LCOV - code coverage report
Current view: top level - sql/storage - store.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4049 4663 86.8 %
Date: 2024-12-19 20:05:57 Functions: 207 218 95.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "sql_types.h"
      15             : #include "sql_storage.h"
      16             : #include "store_dependency.h"
      17             : #include "store_sequence.h"
      18             : #include "mutils.h"
      19             : 
      20             : #include "bat/bat_utils.h"
      21             : #include "bat/bat_storage.h"
      22             : #include "bat/bat_table.h"
      23             : #include "bat/bat_logger.h"
      24             : 
      25             : /* version 05.23.03 of catalog */
      26             : #define CATALOG_VERSION 52303   /* first in Aug2024 */
      27             : 
      28             : ulng
      29         303 : store_function_counter(sqlstore *store)
      30             : {
      31         303 :         ulng ts = ATOMIC_INC(&store->function_counter);
      32         303 :         return ts;
      33             : }
      34             : 
      35             : static ulng
      36      336471 : store_timestamp(sqlstore *store)
      37             : {
      38      336471 :         ulng ts = ATOMIC_INC(&store->timestamp);
      39      336471 :         return ts;
      40             : }
      41             : 
      42             : ulng
      43      405567 : store_get_timestamp(sqlstore *store)
      44             : {
      45      405567 :         ulng ts = ATOMIC_GET(&store->timestamp);
      46      405567 :         return ts;
      47             : }
      48             : 
      49             : static ulng
      50       38267 : store_transaction_id(sqlstore *store)
      51             : {
      52       38267 :         ulng tid = ATOMIC_INC(&store->transaction);
      53       38267 :         return tid;
      54             : }
      55             : 
      56             : ulng
      57     2229009 : store_oldest(sqlstore *store, sql_trans *tr)
      58             : {
      59     2229009 :         if (tr && tr->ts == (ulng) ATOMIC_GET(&store->oldest)) {
      60       29166 :                 sql_trans *otr = store->active->h->data;
      61       29166 :                 if (otr == tr && store->active->h->next) {
      62       24647 :                         otr = store->active->h->next->data;
      63       24647 :                         return otr->ts;
      64             :                 }
      65             :         }
      66     2204362 :         return (ulng) ATOMIC_GET(&store->oldest);
      67             : }
      68             : 
      69             : static ulng
      70        2833 : store_oldest_pending(sqlstore *store)
      71             : {
      72        2833 :         assert(store->oldest_pending != TRANSACTION_ID_BASE);
      73        2833 :         return store->oldest_pending;
      74             : }
      75             : 
      76             : static inline bool
      77      148375 : instore(sqlid id)
      78             : {
      79         228 :         if (id >= 2000 && id <= 2166)
      80       15582 :                 return true;
      81             :         return false;
      82             : }
      83             : 
      84             : static void
      85        1297 : id_destroy(sqlstore *store, void *p)
      86             : {
      87        1297 :         (void)store;
      88        1297 :         GDKfree(p);
      89        1297 : }
      90             : 
      91             : static void
      92      738963 : dep_destroy(sqlstore *store, sql_dependency_change *dep)
      93             : {
      94      738963 :         (void)store;
      95      738963 :         GDKfree(dep);
      96      738969 : }
      97             : 
      98             : static void
      99        1337 : type_destroy(sqlstore *store, sql_type *t)
     100             : {
     101        1337 :         (void)store;
     102        1337 :         assert(t->base.refcnt > 0);
     103        1337 :         if (ATOMIC_DEC(&t->base.refcnt) > 0)
     104             :                 return;
     105        1334 :         _DELETE(t->impl);
     106        1334 :         _DELETE(t->base.name);
     107        1334 :         _DELETE(t);
     108             : }
     109             : 
     110             : void
     111      502964 : arg_destroy(sql_store store, sql_arg *a)
     112             : {
     113      502964 :         (void)store;
     114      502964 :         _DELETE(a->name);
     115      502964 :         _DELETE(a);
     116      502964 : }
     117             : 
     118             : static void
     119      175663 : func_destroy(sqlstore *store, sql_func *f)
     120             : {
     121      175663 :         assert(f->base.refcnt > 0);
     122      175663 :         if (ATOMIC_DEC(&f->base.refcnt) > 0)
     123             :                 return;
     124      174948 :         if (f->lang == FUNC_LANG_SQL && f->instantiated) {
     125             :                 /* clean backend code */
     126         301 :                 backend_freecode(sql_shared_module_name, 0, f->imp);
     127             :         }
     128      174948 :         if (f->res)
     129      148311 :                 list_destroy2(f->res, store);
     130      174948 :         list_destroy2(f->ops, store);
     131      174948 :         _DELETE(f->imp);
     132      174948 :         _DELETE(f->mod);
     133      174948 :         _DELETE(f->query);
     134      174948 :         _DELETE(f->base.name);
     135      174948 :         _DELETE(f);
     136             : }
     137             : 
     138             : static void
     139         528 : seq_destroy(sqlstore *store, sql_sequence *s)
     140             : {
     141         528 :         (void)store;
     142         528 :         assert(s->base.refcnt > 0);
     143         528 :         if (ATOMIC_DEC(&s->base.refcnt) > 0)
     144             :                 return;
     145         352 :         _DELETE(s->base.name);
     146         352 :         _DELETE(s);
     147             : }
     148             : 
     149             : static void
     150       25988 : kc_destroy(sqlstore *store, sql_kc *kc)
     151             : {
     152       25988 :         (void)store;
     153       25988 :         _DELETE(kc);
     154       25988 : }
     155             : 
     156             : static void
     157       36604 : key_destroy(sqlstore *store, sql_key *k)
     158             : {
     159       36604 :         assert(k->base.refcnt > 0);
     160       36604 :         if (ATOMIC_DEC(&k->base.refcnt) > 0)
     161             :                 return;
     162       10992 :         list_destroy2(k->columns, store);
     163       10992 :         _DELETE(k->check);
     164       10992 :         k->columns = NULL;
     165       10992 :         _DELETE(k->base.name);
     166       10992 :         _DELETE(k);
     167             : }
     168             : 
     169             : void
     170       30086 : idx_destroy(sqlstore *store, sql_idx * i)
     171             : {
     172       30086 :         assert(i->base.refcnt > 0);
     173       30086 :         if (ATOMIC_DEC(&i->base.refcnt) > 0)
     174             :                 return;
     175       12726 :         list_destroy2(i->columns, store);
     176       12726 :         i->columns = NULL;
     177             : 
     178       12726 :         if (ATOMIC_PTR_GET(&i->data))
     179       11132 :                 store->storage_api.destroy_idx(store, i);
     180       12726 :         ATOMIC_PTR_DESTROY(&i->data);
     181       12726 :         _DELETE(i->base.name);
     182       12726 :         _DELETE(i);
     183             : }
     184             : 
     185             : static void
     186        1076 : trigger_destroy(sqlstore *store, sql_trigger *t)
     187             : {
     188        1076 :         assert(t->base.refcnt > 0);
     189        1076 :         if (ATOMIC_DEC(&t->base.refcnt) > 0)
     190             :                 return;
     191             :         /* remove trigger from schema */
     192         490 :         if (t->columns) {
     193         486 :                 list_destroy2(t->columns, store);
     194         486 :                 t->columns = NULL;
     195             :         }
     196         490 :         _DELETE(t->old_name);
     197         490 :         _DELETE(t->new_name);
     198         490 :         _DELETE(t->condition);
     199         490 :         _DELETE(t->statement);
     200         490 :         _DELETE(t->base.name);
     201         490 :         _DELETE(t);
     202             : }
     203             : 
     204             : void
     205      490004 : column_destroy(sqlstore *store, sql_column *c)
     206             : {
     207      490004 :         assert(c->base.refcnt > 0);
     208      490004 :         if (ATOMIC_DEC(&c->base.refcnt) > 0)
     209             :                 return;
     210      471935 :         if (ATOMIC_PTR_GET(&c->data))
     211      170687 :                 store->storage_api.destroy_col(store, c);
     212      471935 :         ATOMIC_PTR_DESTROY(&c->data);
     213      471935 :         _DELETE(c->min);
     214      471935 :         _DELETE(c->max);
     215      471935 :         _DELETE(c->def);
     216      471935 :         _DELETE(c->storage_type);
     217      471935 :         _DELETE(c->base.name);
     218      471935 :         _DELETE(c);
     219             : }
     220             : 
     221             : static void
     222          95 : int_destroy(sqlstore *store, int *v)
     223             : {
     224          95 :         (void)store;
     225          95 :         _DELETE(v);
     226          95 : }
     227             : 
     228             : void
     229      311155 : table_destroy(sqlstore *store, sql_table *t)
     230             : {
     231      311155 :         assert(t->base.refcnt > 0);
     232      311155 :         if (ATOMIC_DEC(&t->base.refcnt) > 0)
     233             :                 return;
     234       61148 :         if (isTable(t))
     235       26910 :                 store->storage_api.destroy_del(store, t);
     236       61148 :         ATOMIC_PTR_DESTROY(&t->data);
     237             :         /* cleanup its parts */
     238       61148 :         list_destroy2(t->members, store);
     239       61148 :         ol_destroy(t->idxs, store);
     240       61148 :         ol_destroy(t->keys, store);
     241       61148 :         ol_destroy(t->triggers, store);
     242       61148 :         ol_destroy(t->columns, store);
     243       61148 :         if (isPartitionedByExpressionTable(t)) {
     244          86 :                 if (t->part.pexp->cols)
     245          86 :                         list_destroy2(t->part.pexp->cols, store);
     246          86 :                 _DELETE(t->part.pexp->exp);
     247          86 :                 _DELETE(t->part.pexp);
     248             :         }
     249       61148 :         _DELETE(t->query);
     250       61148 :         _DELETE(t->base.name);
     251       61148 :         _DELETE(t);
     252             : }
     253             : 
     254             : void
     255         441 : part_value_destroy(sql_store store, sql_part_value *pv)
     256             : {
     257         441 :         (void)store;
     258         441 :         _DELETE(pv->value);
     259         441 :         _DELETE(pv);
     260         441 : }
     261             : 
     262             : static void
     263        2724 : part_destroy(sqlstore *store, sql_part *p)
     264             : {
     265        2724 :         assert(p->base.refcnt > 0);
     266        2724 :         if (ATOMIC_DEC(&p->base.refcnt) > 0)
     267             :                 return;
     268        1243 :         if (p->part.range.maxvalue) {
     269         522 :                 _DELETE(p->part.range.minvalue);
     270         522 :                 _DELETE(p->part.range.maxvalue);
     271         721 :         } else if (p->part.values)
     272         147 :                 list_destroy2(p->part.values, store);
     273        1243 :         _DELETE(p->base.name);
     274        1243 :         _DELETE(p);
     275             : }
     276             : 
     277             : static void
     278        2801 : schema_destroy(sqlstore *store, sql_schema *s)
     279             : {
     280        2801 :         assert(s->base.refcnt > 0);
     281        2801 :         if (ATOMIC_DEC(&s->base.refcnt) > 0)
     282             :                 return;
     283             :         /* cleanup its parts */
     284        2600 :         os_destroy(s->parts, store);
     285        2600 :         os_destroy(s->triggers, store);
     286        2600 :         os_destroy(s->idxs, store);
     287        2600 :         os_destroy(s->keys, store);
     288        2600 :         os_destroy(s->seqs, store);
     289        2600 :         os_destroy(s->tables, store);
     290        2600 :         os_destroy(s->funcs, store);
     291        2600 :         os_destroy(s->types, store);
     292        2600 :         _DELETE(s->base.name);
     293        2600 :         _DELETE(s);
     294             : }
     295             : 
     296             : static void
     297       21874 : predicate_destroy(sqlstore *store, pl *p)
     298             : {
     299       21874 :         (void) store;
     300       21874 :         if (p->r) {
     301        1896 :                 VALclear(&p->r->data);
     302        1896 :                 _DELETE(p->r);
     303             :         }
     304       21874 :         if (p->f) {
     305          11 :                 VALclear(&p->f->data);
     306          11 :                 _DELETE(p->f);
     307             :         }
     308       21874 :         _DELETE(p);
     309       21874 : }
     310             : 
     311             : int
     312       21874 : sql_trans_add_predicate(sql_trans* tr, sql_column *c, unsigned int cmp, atom *r, atom *f, bool anti, bool semantics)
     313             : {
     314       21874 :         pl *p = ZNEW(pl);
     315             : 
     316       21874 :         if (!p)
     317             :                 return LOG_ERR;
     318       21874 :         p->c = c;
     319       21874 :         p->cmp = cmp;
     320       21874 :         p->anti = anti;
     321       21874 :         p->semantics = semantics;
     322       21874 :         p->r = r;
     323       21874 :         p->f = f;
     324       21874 :         if (!tr->predicates && !(tr->predicates = list_create((fdestroy) &predicate_destroy))) {
     325           0 :                 predicate_destroy(tr->store, p);
     326           0 :                 return LOG_ERR;
     327             :         }
     328       21874 :         if (!list_append(tr->predicates, p)) {
     329           0 :                 predicate_destroy(tr->store, p);
     330           0 :                 return LOG_ERR;
     331             :         }
     332             :         return LOG_OK;
     333             : }
     334             : 
     335             : int
     336      592899 : sql_trans_add_dependency(sql_trans* tr, sqlid id, sql_dependency_change_type tp)
     337             : {
     338      592899 :         sql_dependency_change *dep = MNEW(sql_dependency_change);
     339             : 
     340      592899 :         if (!dep)
     341             :                 return LOG_ERR;
     342      592899 :         *dep = (sql_dependency_change) {
     343             :                 .objid = id,
     344             :                 .type = tp
     345             :         };
     346      592899 :         if (!tr->dependencies && !(tr->dependencies = list_create((fdestroy) &dep_destroy))) {
     347           0 :                 _DELETE(dep);
     348           0 :                 return LOG_ERR;
     349             :         }
     350      592899 :         if (!list_append(tr->dependencies, dep)) {
     351           0 :                 _DELETE(dep);
     352           0 :                 return LOG_ERR;
     353             :         }
     354             :         return LOG_OK;
     355             : }
     356             : 
     357             : int
     358      146073 : sql_trans_add_dependency_change(sql_trans *tr, sqlid id, sql_dependency_change_type tp)
     359             : {
     360      146073 :         sql_dependency_change *dep = MNEW(sql_dependency_change);
     361             : 
     362      146072 :         if (!dep)
     363             :                 return LOG_ERR;
     364      146072 :         *dep = (sql_dependency_change) {
     365             :                 .objid = id,
     366             :                 .type = tp
     367             :         };
     368      146072 :         if (!tr->depchanges && !(tr->depchanges = list_create((fdestroy) &dep_destroy))) {
     369           0 :                 _DELETE(dep);
     370           0 :                 return LOG_ERR;
     371             :         }
     372      146072 :         if (!list_append(tr->depchanges, dep)) {
     373           0 :                 _DELETE(dep);
     374           0 :                 return LOG_ERR;
     375             :         }
     376             :         return LOG_OK;
     377             : }
     378             : 
     379             : static void
     380        2126 : load_keycolumn(sql_trans *tr, sql_key *k, res_table *rt_keycols/*, oid rid*/)
     381             : {
     382        2126 :         sql_kc *kc = ZNEW(sql_kc);
     383        2126 :         sql_schema *syss = find_sql_schema(tr, "sys");
     384        2126 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     385        2126 :         sqlstore *store = tr->store;
     386             : 
     387        2126 :         str v = (char*)store->table_api.table_fetch_value(rt_keycols, find_sql_column(objects, "name"));
     388        2126 :         kc->c = find_sql_column(k->t, v);
     389        2126 :         list_append(k->columns, kc);
     390        2126 :         assert(kc->c);
     391        2126 : }
     392             : 
     393             : static sql_key *
     394        2087 : load_key(sql_trans *tr, sql_table *t, res_table *rt_keys, res_table *rt_keycols/*, oid rid*/)
     395             : {
     396        2087 :         sql_schema *syss = find_sql_schema(tr, "sys");
     397        2087 :         sql_table *keys = find_sql_table(tr, syss, "keys");
     398        2087 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     399        2087 :         sqlstore *store = tr->store;
     400             : 
     401        2087 :         key_type ktype = (key_type) *(int*) store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "type"));
     402        2087 :         sql_key *nk = (ktype != fkey)?(sql_key*)ZNEW(sql_ukey):(sql_key*)ZNEW(sql_fkey);
     403        2087 :         sqlid kid = *(sqlid*) store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "id"));
     404        2087 :         str v = (char*) store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "name"));
     405             : 
     406        2087 :         base_init(NULL, &nk->base, kid, 0, v);
     407        2087 :         nk->type = ktype;
     408        2087 :         nk->columns = list_create((fdestroy) &kc_destroy);
     409        2087 :         nk->t = t;
     410             : 
     411        2087 :         switch (ktype) {
     412           6 :         case ckey: {
     413           6 :                 str ch = (char*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "check"));
     414          12 :                 if (!strNil(ch))
     415           6 :                         nk->check =_STRDUP(ch);
     416             :         }       break;
     417        2045 :         case ukey:
     418             :         case unndkey:
     419             :         case pkey: {
     420        2045 :                 sql_ukey *uk = (sql_ukey *) nk;
     421             : 
     422        2045 :                 if (ktype == pkey)
     423        1269 :                         t->pkey = uk;
     424             :                 break;
     425             :         }
     426          36 :         case fkey: {
     427          36 :                 sql_fkey *fk = (sql_fkey *) nk;
     428          36 :                 int action = *(int*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "action"));
     429          36 :                 fk->on_delete = action & 255;
     430          36 :                 fk->on_update = (action>>8) & 255;
     431             : 
     432          36 :                 fk->rkey = *(sqlid*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "rkey"));
     433          36 :                 break;
     434             :         }
     435             :         }
     436             : 
     437        4213 :         for ( ; rt_keycols->cur_row < rt_keycols->nr_rows; rt_keycols->cur_row++) {
     438        4107 :                 sqlid nid = *(sqlid*)store->table_api.table_fetch_value(rt_keycols, find_sql_column(objects, "id"));
     439        4107 :                 if (nid != nk->base.id)
     440             :                         break;
     441        2126 :                 load_keycolumn(tr, nk, rt_keycols);
     442             :         }
     443             : 
     444             :         /* find idx with same name */
     445        2087 :         node *n = ol_find_name(t->idxs, nk->base.name);
     446        2087 :         if (n) {
     447        2081 :                 nk->idx = (sql_idx*)n->data;
     448        2081 :                 nk->idx->key = nk;
     449             :         }
     450        2087 :         return nk;
     451             : }
     452             : 
     453             : static void
     454        2162 : load_idxcolumn(sql_trans *tr, sql_idx * i, res_table *rt_idxcols/*, oid rid*/)
     455             : {
     456        2162 :         sql_kc *kc = ZNEW(sql_kc);
     457        2162 :         sql_schema *syss = find_sql_schema(tr, "sys");
     458        2162 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     459        2162 :         sqlstore *store = tr->store;
     460        2162 :         str v;
     461             : 
     462        2162 :         v = (char*)store->table_api.table_fetch_value(rt_idxcols, find_sql_column(objects, "name"));
     463        2162 :         kc->c = find_sql_column(i->t, v);
     464        2162 :         assert(kc->c);
     465        2162 :         list_append(i->columns, kc);
     466        2162 : }
     467             : 
     468             : static sql_idx *
     469        2113 : load_idx(sql_trans *tr, sql_table *t, res_table *rt_idx, res_table *rt_idxcols/*, oid rid*/)
     470             : {
     471        2113 :         sql_idx *ni = ZNEW(sql_idx);
     472        2113 :         sql_schema *syss = find_sql_schema(tr, "sys");
     473        2113 :         sql_table *idxs = find_sql_table(tr, syss, "idxs");
     474        2113 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     475        2113 :         sqlstore *store = tr->store;
     476             : 
     477        2113 :         sqlid iid = *(sqlid*)store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "id"));
     478        2113 :         str v = (char*)store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "name"));
     479        2113 :         base_init(NULL, &ni->base, iid, 0, v);
     480        2113 :         ni->type = (idx_type) *(int*) store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "type"));
     481        2113 :         ni->columns = list_create((fdestroy) &kc_destroy);
     482        2113 :         ni->t = t;
     483        2113 :         ni->key = NULL;
     484        2113 :         ATOMIC_PTR_INIT(&ni->data, NULL);
     485             : 
     486        2113 :         if (isTable(ni->t) && idx_has_column(ni->type))
     487        2061 :                 store->storage_api.create_idx(tr, ni);
     488             : 
     489        4275 :         for ( ; rt_idxcols->cur_row < rt_idxcols->nr_rows; rt_idxcols->cur_row++) {
     490        4169 :                 sqlid nid = *(sqlid*)store->table_api.table_fetch_value(rt_idxcols, find_sql_column(objects, "id"));
     491        4169 :                 if (nid != ni->base.id)
     492             :                         break;
     493        2162 :                 load_idxcolumn(tr, ni, rt_idxcols);
     494             :         }
     495        2113 :         return ni;
     496             : }
     497             : 
     498             : static void
     499           0 : load_triggercolumn(sql_trans *tr, sql_trigger * i, res_table *rt_triggercols)
     500             : {
     501           0 :         sql_kc *kc = ZNEW(sql_kc);
     502           0 :         sql_schema *syss = find_sql_schema(tr, "sys");
     503           0 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     504           0 :         sqlstore *store = tr->store;
     505             : 
     506           0 :         str v = (char*)store->table_api.table_fetch_value(rt_triggercols, find_sql_column(objects, "name"));
     507           0 :         kc->c = find_sql_column(i->t, v);
     508           0 :         list_append(i->columns, kc);
     509           0 :         assert(kc->c);
     510           0 : }
     511             : 
     512             : static sql_trigger *
     513          19 : load_trigger(sql_trans *tr, sql_table *t, res_table *rt_triggers, res_table *rt_triggercols)
     514             : {
     515          19 :         sql_trigger *nt = ZNEW(sql_trigger);
     516          19 :         sql_schema *syss = find_sql_schema(tr, "sys");
     517          19 :         sql_table *triggers = find_sql_table(tr, syss, "triggers");
     518          19 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     519          19 :         sqlstore *store = tr->store;
     520             : 
     521          19 :         sqlid tid = *(sqlid*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "id"));
     522          19 :         str v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "name"));
     523          19 :         base_init(NULL, &nt->base, tid, 0, v);
     524             : 
     525          19 :         nt->time = *(sht*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "time"));
     526          19 :         nt->orientation = *(sht*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "orientation"));
     527          19 :         nt->event = *(sht*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "event"));
     528             : 
     529          19 :         v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "old_name"));
     530          38 :         if (!strNil(v))
     531           0 :                 nt->old_name =_STRDUP(v);
     532          19 :         v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "new_name"));
     533          38 :         if (!strNil(v))
     534          19 :                 nt->new_name =_STRDUP(v);
     535          19 :         v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "condition"));
     536          38 :         if (!strNil(v))
     537           0 :                 nt->condition =_STRDUP(v);
     538          19 :         v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "statement"));
     539          38 :         if (!strNil(v))
     540          19 :                 nt->statement =_STRDUP(v);
     541             : 
     542          19 :         nt->t = t;
     543          19 :         if (t)
     544          19 :                 nt->columns = list_create((fdestroy) &kc_destroy);
     545             : 
     546          19 :         if (rt_triggercols) {
     547          19 :                 for ( ; rt_triggercols->cur_row < rt_triggercols->nr_rows; rt_triggercols->cur_row++) {
     548           0 :                         sqlid nid = *(sqlid*)store->table_api.table_fetch_value(rt_triggercols, find_sql_column(objects, "id"));
     549           0 :                         if (nid != nt->base.id)
     550             :                                 break;
     551           0 :                         load_triggercolumn(tr, nt, rt_triggercols);
     552             :                 }
     553             :         }
     554          19 :         return nt;
     555             : }
     556             : 
     557             : static sql_column *
     558      102651 : load_column(sql_trans *tr, sql_table *t, res_table *rt_cols)
     559             : {
     560      102651 :         sql_column *c = ZNEW(sql_column);
     561      102651 :         sql_schema *syss = find_sql_schema(tr, "sys");
     562      102651 :         sql_table *columns = find_sql_table(tr, syss, "_columns");
     563      102651 :         sqlstore *store = tr->store;
     564      102651 :         str v, def, tpe, st;
     565      102651 :         int sz, d;
     566             : 
     567      102651 :         sqlid cid = *(sqlid*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "id"));
     568      102651 :         v = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "name"));
     569      102651 :         base_init(NULL, &c->base, cid, 0, v);
     570             : 
     571      102651 :         sz = *(int*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "type_digits"));
     572      102651 :         d = *(int*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "type_scale"));
     573      102651 :         tpe = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "type"));
     574      102651 :         if (tpe && strcmp(tpe, "clob") == 0)
     575         610 :                 tpe = "varchar";
     576      102651 :         if (!sql_find_subtype(&c->type, tpe, sz, d)) {
     577          30 :                 sql_type *lt = sql_trans_bind_type(tr, t->s, tpe);
     578          30 :                 if (lt == NULL) {
     579           0 :                         TRC_ERROR(SQL_STORE, "SQL type '%s' is missing\n", tpe);
     580           0 :                         return NULL;
     581             :                 }
     582          30 :                 sql_init_subtype(&c->type, lt, sz, d);
     583             :         }
     584      102651 :         c->def = NULL;
     585      102651 :         def = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "default"));
     586      205302 :         if (!strNil(def))
     587         258 :                 c->def =_STRDUP(def);
     588      102651 :         c->null = *(bit*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "null"));
     589      102651 :         c->colnr = *(int*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "number"));
     590      102651 :         c->unique = 0;
     591      102651 :         c->storage_type = NULL;
     592      102651 :         st = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "storage"));
     593      205302 :         if (!strNil(st))
     594           4 :                 c->storage_type =_STRDUP(st);
     595      102651 :         ATOMIC_PTR_INIT(&c->data, NULL);
     596      102651 :         c->t = t;
     597      102651 :         if (isTable(c->t))
     598       10493 :                 store->storage_api.create_col(tr, c);
     599      102651 :         TRC_DEBUG(SQL_STORE, "Load column: %s\n", c->base.name);
     600      102651 :         if (!c->null)
     601        3648 :                 store->storage_api.col_not_null(tr, c, !c->null);
     602             :         return c;
     603             : }
     604             : 
     605             : static int
     606         268 : col_set_range(sql_trans *tr, sql_part *pt, bool add_range)
     607             : {
     608         268 :                 sql_table *t = find_sql_table_id(tr, pt->t->s /* schema of both member and merge tbale */, pt->member);
     609         268 :                 sql_column *c = t? find_sql_column(t, pt->t->part.pcol->base.name):NULL;
     610             : 
     611         268 :                 if (c) {
     612         257 :                         sqlstore *store = tr->store;
     613         257 :                         return store->storage_api.col_set_range(tr, c, pt, add_range);
     614             :                 }
     615             :                 return 0;
     616             : }
     617             : 
     618             : static int
     619          78 : load_range_partition(sql_trans *tr, sql_schema *syss, sql_part *pt)
     620             : {
     621          78 :         oid rid;
     622          78 :         rids *rs;
     623          78 :         sqlstore *store = tr->store;
     624          78 :         sql_table *ranges = find_sql_table(tr, syss, "range_partitions");
     625          78 :         assert(ranges);
     626             : 
     627          78 :         rs = store->table_api.rids_select(tr, find_sql_column(ranges, "table_id"), &pt->member, &pt->member, NULL);
     628          78 :         if (rs == NULL)
     629             :                 return -1;
     630          78 :         if ((rid = store->table_api.rids_next(rs)) != oid_nil) {
     631          78 :                 ptr cbat;
     632          78 :                 const char *v;
     633             : 
     634          78 :                 pt->with_nills = (bit) store->table_api.column_find_bte(tr, find_sql_column(ranges, "with_nulls"), rid);
     635          78 :                 v = store->table_api.column_find_string_start(tr, find_sql_column(ranges, "minimum"), rid, &cbat);
     636          78 :                 pt->part.range.minvalue =_STRDUP(v);
     637          78 :                 pt->part.range.minlength = strLen(v);
     638          78 :                 store->table_api.column_find_string_end(cbat);
     639          78 :                 v = store->table_api.column_find_string_start(tr, find_sql_column(ranges, "maximum"), rid, &cbat);
     640          78 :                 pt->part.range.maxvalue =_STRDUP(v);
     641          78 :                 pt->part.range.maxlength = strLen(v);
     642          78 :                 store->table_api.column_find_string_end(cbat);
     643             :         }
     644          78 :         store->table_api.rids_destroy(rs);
     645          78 :         return 0;
     646             : }
     647             : 
     648             : static int
     649          33 : load_value_partition(sql_trans *tr, sql_schema *syss, sql_part *pt)
     650             : {
     651          33 :         sqlstore *store = tr->store;
     652          33 :         list *vals = NULL;
     653          33 :         oid rid;
     654          33 :         sql_table *values = find_sql_table(tr, syss, "value_partitions");
     655          33 :         assert(values);
     656             : 
     657          33 :         rids *rs = store->table_api.rids_select(tr, find_sql_column(values, "table_id"), &pt->member, &pt->member, NULL);
     658          33 :         if (rs == NULL)
     659             :                 return -1;
     660             : 
     661          33 :         if (!rs)
     662             :                 return -1;
     663          33 :         vals = list_create((fdestroy) &part_value_destroy);
     664          33 :         if (!vals) {
     665           0 :                 store->table_api.rids_destroy(rs);
     666           0 :                 return -1;
     667             :         }
     668             : 
     669         140 :         for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
     670         107 :                 ptr cbat;
     671             : 
     672         107 :                 const char *v = store->table_api.column_find_string_start(tr, find_sql_column(values, "value"), rid, &cbat);
     673         107 :                 if (strNil(v)) { /* check for null value */
     674          11 :                         pt->with_nills = true;
     675             :                 } else {
     676          96 :                         sql_part_value *nextv = ZNEW(sql_part_value);
     677          96 :                         nextv->value =_STRDUP(v);
     678          96 :                         nextv->length = strLen(v);
     679          96 :                         list_append(vals, nextv);
     680             :                 }
     681         107 :                 store->table_api.column_find_string_end(cbat);
     682             :         }
     683          33 :         store->table_api.rids_destroy(rs);
     684          33 :         pt->part.values = vals;
     685          33 :         return 0;
     686             : }
     687             : 
     688             : static sql_part*
     689         215 : load_part(sql_trans *tr, sql_table *mt, oid rid)
     690             : {
     691         215 :         sql_part *pt = ZNEW(sql_part);
     692         215 :         sql_schema *syss = find_sql_schema(tr, "sys");
     693         215 :         sql_table *objects = find_sql_table(tr, syss, "objects");
     694         215 :         sqlid id;
     695         215 :         sqlstore *store = tr->store;
     696         215 :         const char *v;
     697         215 :         ptr cbat;
     698             : 
     699         215 :         assert(isMergeTable(mt) || isReplicaTable(mt));
     700         215 :         id = store->table_api.column_find_sqlid(tr, find_sql_column(objects, "id"), rid);
     701         215 :         if (is_int_nil(id)) { /* upgrade case, the id it's not initialized */
     702           0 :                 id = store_next_oid(store);
     703           0 :                 store->table_api.column_update_value(tr, find_sql_column(objects, "id"), rid, &id);
     704             :         }
     705         215 :         v = store->table_api.column_find_string_start(tr, find_sql_column(objects, "name"), rid, &cbat);
     706         215 :         base_init(NULL, &pt->base, id, 0, v);
     707         215 :         store->table_api.column_find_string_end(cbat);
     708         215 :         pt->t = mt;
     709         215 :         pt->member = store->table_api.column_find_sqlid(tr, find_sql_column(objects, "sub"), rid);
     710         215 :         list_append(mt->members, pt);
     711         215 :         return pt;
     712             : }
     713             : 
     714             : void
     715           0 : sql_trans_update_tables(sql_trans* tr, sql_schema *s)
     716             : {
     717           0 :         (void)tr;
     718           0 :         (void)s;
     719           0 : }
     720             : 
     721             : sql_base *
     722      314260 : dup_base(sql_base *b)
     723             : {
     724      314260 :         ATOMIC_INC(&b->refcnt);
     725      314260 :         return b;
     726             : }
     727             : 
     728             : static sql_table *
     729       13387 : load_table(sql_trans *tr, sql_schema *s, res_table *rt_tables, res_table *rt_parts,
     730             :                 res_table *rt_cols, res_table *rt_idx, res_table *rt_idxcols,
     731             :                 res_table *rt_keys, res_table *rt_keycols,
     732             :                 res_table *rt_triggers, res_table *rt_triggercols,
     733             :                 sqlid tid)
     734             : {
     735       13387 :         sqlstore *store = tr->store;
     736       13387 :         sql_table *t = ZNEW(sql_table);
     737       13387 :         sql_schema *syss = find_sql_schema(tr, "sys");
     738       13387 :         sql_table *tables = find_sql_table(tr, syss, "_tables");
     739       13387 :         sql_table *cols = find_sql_table(tr, syss, "_columns");
     740       13387 :         sql_table *idxs = find_sql_table(tr, syss, "idxs");
     741       13387 :         sql_table *keys = find_sql_table(tr, syss, "keys");
     742       13387 :         sql_table *triggers = find_sql_table(tr, syss, "triggers");
     743       13387 :         sqlid pcolid = int_nil;
     744       13387 :         str v, exp = NULL;
     745             : 
     746       13387 :         sqlid ntid = *(sqlid*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "id"));
     747       13387 :         assert(tid == ntid);
     748       13387 :         v = (char*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "name"));
     749       13387 :         base_init(NULL, &t->base, tid, 0, v);
     750       13387 :         t->query = NULL;
     751       13387 :         v = (char*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "query"));
     752       26774 :         if (!strNil(v))
     753       10432 :                 t->query =_STRDUP(v);
     754       13387 :         t->type = *(sht*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "type"));
     755       13387 :         t->system = *(bit*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "system"));
     756       13387 :         t->commit_action = (ca_t)*(sht*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "commit_action"));
     757       13387 :         t->persistence = SQL_PERSIST;
     758       13387 :         if (t->commit_action)
     759           0 :                 t->persistence = SQL_GLOBAL_TEMP;
     760       13387 :         if (isRemote(t))
     761          34 :                 t->persistence = SQL_REMOTE;
     762       13387 :         t->access = *(sht*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "access"));
     763             : 
     764       13387 :         t->pkey = NULL;
     765       13387 :         t->s = s;
     766       13387 :         t->sz = COLSIZE;
     767             : 
     768       13387 :         t->columns = ol_new(NULL, (destroy_fptr) &column_destroy, store);
     769       13387 :         t->idxs = ol_new(NULL, (destroy_fptr) &idx_destroy, store);
     770       13387 :         t->keys = ol_new(NULL, (destroy_fptr) &key_destroy, store);
     771       13387 :         t->triggers = ol_new(NULL, (destroy_fptr) &trigger_destroy, store);
     772       13387 :         if (isMergeTable(t) || isReplicaTable(t))
     773         101 :                 t->members = list_create((fdestroy) &part_destroy);
     774       13387 :         ATOMIC_PTR_INIT(&t->data, NULL);
     775             : 
     776       13387 :         if (isTable(t)) {
     777        2854 :                 if (store->storage_api.create_del(tr, t) != LOG_OK) {
     778           0 :                         TRC_ERROR(SQL_STORE, "Load table '%s' is missing 'deletes'", t->base.name);
     779           0 :                         ATOMIC_PTR_DESTROY(&t->data);
     780           0 :                         return NULL;
     781             :                 }
     782             :         }
     783             : 
     784       13387 :         TRC_DEBUG(SQL_STORE, "Load table: %s\n", t->base.name);
     785             : 
     786       13387 :         sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
     787       13387 :         assert(partitions);
     788             : 
     789       13387 :         if (rt_parts->cur_row < rt_parts->nr_rows) {
     790        1863 :                 ntid = *(sqlid*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "table_id"));
     791        1863 :                 if (ntid == tid) {
     792          51 :                         t->properties |= *(bte*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "type"));
     793             : 
     794          51 :                         if (isPartitionedByColumnTable(t)) {
     795          42 :                                 pcolid = *(sqlid*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "column_id"));
     796             :                         } else {
     797           9 :                                 v = (char*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "expression"));
     798          18 :                                 assert(!strNil(v));
     799           9 :                                 exp =_STRDUP(v);
     800             :                         }
     801          51 :                         rt_parts->cur_row++;
     802             :                 }
     803             :         }
     804             : 
     805       13387 :         assert((!isRangePartitionTable(t) && !isListPartitionTable(t)) || (!exp && !is_int_nil(pcolid)) || (exp && is_int_nil(pcolid)));
     806       13387 :         if (isPartitionedByExpressionTable(t)) {
     807           9 :                 t->part.pexp = ZNEW(sql_expression);
     808           9 :                 t->part.pexp->exp = exp;
     809           9 :                 t->part.pexp->type = *sql_bind_localtype("void"); /* initialized at initialize_sql_parts */
     810           9 :                 t->part.pexp->cols = list_create((fdestroy) &int_destroy);
     811             :         }
     812      116038 :         for ( ; rt_cols->cur_row < rt_cols->nr_rows; rt_cols->cur_row++) {
     813      115932 :                 ntid = *(sqlid*)store->table_api.table_fetch_value(rt_cols, find_sql_column(cols, "table_id"));
     814      131196 :                 while (instore(ntid)) {
     815       15264 :                         rt_cols->cur_row++;
     816       15264 :                         ntid = *(sqlid*)store->table_api.table_fetch_value(rt_cols, find_sql_column(cols, "table_id"));
     817             :                 }
     818             : 
     819      115932 :                 if (ntid != t->base.id)
     820             :                         break;
     821      102651 :                 sql_column* next = load_column(tr, t, rt_cols);
     822      102651 :                 if (next == NULL) {
     823           0 :                         table_destroy(store, t);
     824           0 :                         return NULL;
     825             :                 }
     826      102651 :                 if (ol_add(t->columns, &next->base)) {
     827           0 :                         table_destroy(store, t);
     828           0 :                         return NULL;
     829             :                 }
     830      102651 :                 if (pcolid == next->base.id)
     831          42 :                         t->part.pcol = next;
     832             :         }
     833             : 
     834       13387 :         if (!isKindOfTable(t))
     835             :                 return t;
     836             : 
     837             :         /* load idx's first as the may be needed by the keys */
     838        5102 :         for ( ; rt_idx->cur_row < rt_idx->nr_rows; rt_idx->cur_row++) {
     839        4221 :                 ntid = *(sqlid*)store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "table_id"));
     840             : 
     841        4221 :                 if (ntid != t->base.id)
     842             :                         break;
     843        2113 :                 sql_idx *i = load_idx(tr, t, rt_idx, rt_idxcols);
     844             : 
     845        4226 :                 if (!i || ol_add(t->idxs, &i->base) ||
     846        2113 :                     os_add(s->idxs, tr, i->base.name, dup_base(&i->base))) {
     847           0 :                         table_destroy(store, t);
     848           0 :                         return NULL;
     849             :                 }
     850             :         }
     851             : 
     852        5076 :         for ( ; rt_keys->cur_row < rt_keys->nr_rows; rt_keys->cur_row++) {
     853        4179 :                 ntid = *(sqlid*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "table_id"));
     854             : 
     855        4179 :                 if (ntid != t->base.id)
     856             :                         break;
     857        2087 :                 sql_key *k = load_key(tr, t, rt_keys, rt_keycols);
     858             : 
     859        4174 :                 if (!k || ol_add(t->keys, &k->base) ||
     860        2087 :                     os_add(s->keys, tr, k->base.name, dup_base(&k->base)) ||
     861        2087 :                         (isGlobal(t) && os_add(tr->cat->objects, tr, k->base.name, dup_base(&k->base)))) {
     862           0 :                         table_destroy(store, t);
     863           0 :                         return NULL;
     864             :                 }
     865             :         }
     866             : 
     867             :         /* after loading keys and idxs, update properties derived from indexes that require keys */
     868        2989 :         if (ol_length(t->idxs))
     869        3416 :                 for (node *n = ol_first_node(t->idxs); n; n = n->next)
     870        2113 :                         create_sql_idx_done(tr, n->data);
     871             : 
     872        3114 :         for ( ; rt_triggers->cur_row < rt_triggers->nr_rows; rt_triggers->cur_row++) {
     873         627 :                 ntid = *(sqlid*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "table_id"));
     874             : 
     875         627 :                 if (ntid < t->base.id && instore(ntid)) /* skip triggers on system tables ugh */
     876         106 :                         continue;
     877         521 :                 if (ntid != t->base.id)
     878             :                         break;
     879          19 :                 sql_trigger *k = load_trigger(tr, t, rt_triggers, rt_triggercols);
     880             : 
     881          38 :                 if (!k || ol_add(t->triggers, &k->base) ||
     882          19 :                     os_add(s->triggers, tr, k->base.name, dup_base(&k->base))) {
     883           0 :                         table_destroy(store, t);
     884           0 :                         return NULL;
     885             :                 }
     886             :         }
     887             :         return t;
     888             : }
     889             : 
     890             : static sql_type *
     891         432 : load_type(sql_trans *tr, sql_schema *s, oid rid)
     892             : {
     893         432 :         sqlstore *store = tr->store;
     894         432 :         sql_type *t = ZNEW(sql_type);
     895         432 :         sql_schema *syss = find_sql_schema(tr, "sys");
     896         432 :         sql_table *types = find_sql_table(tr, syss, "types");
     897         432 :         sqlid tid;
     898         432 :         const char *v;
     899         432 :         ptr cbat;
     900             : 
     901         432 :         tid = store->table_api.column_find_sqlid(tr, find_sql_column(types, "id"), rid);
     902         432 :         v = store->table_api.column_find_string_start(tr, find_sql_column(types, "sqlname"), rid, &cbat);
     903         432 :         base_init(NULL, &t->base, tid, 0, v);
     904         432 :         store->table_api.column_find_string_end(cbat);
     905         432 :         v = store->table_api.column_find_string_start(tr, find_sql_column(types, "systemname"), rid, &cbat);
     906         432 :         t->impl =_STRDUP(v);
     907         432 :         store->table_api.column_find_string_end(cbat);
     908         432 :         t->digits = store->table_api.column_find_int(tr, find_sql_column(types, "digits"), rid);
     909         432 :         t->scale = store->table_api.column_find_int(tr, find_sql_column(types, "scale"), rid);
     910         432 :         t->radix = store->table_api.column_find_int(tr, find_sql_column(types, "radix"), rid);
     911         432 :         t->eclass = (sql_class)store->table_api.column_find_int(tr, find_sql_column(types, "eclass"), rid);
     912         432 :         t->localtype = ATOMindex(t->impl);
     913         432 :         t->s = s;
     914         432 :         return t;
     915             : }
     916             : 
     917             : static sql_arg *
     918      157177 : load_arg(sql_trans *tr, sql_func *f, oid rid)
     919             : {
     920      157177 :         sqlstore *store = tr->store;
     921      157177 :         sql_arg *a = ZNEW(sql_arg);
     922      157177 :         unsigned int digits, scale;
     923      157177 :         sql_schema *syss = find_sql_schema(tr, "sys");
     924      157177 :         sql_table *args = find_sql_table(tr, syss, "args");
     925      157177 :         const char *v, *tpe;
     926      157177 :         ptr cbat;
     927             : 
     928      157177 :         v = store->table_api.column_find_string_start(tr, find_sql_column(args, "name"), rid, &cbat);
     929      157177 :         a->name =_STRDUP(v);
     930      157177 :         store->table_api.column_find_string_end(cbat);
     931      157177 :         a->inout = store->table_api.column_find_bte(tr, find_sql_column(args, "inout"), rid);
     932      157177 :         digits = store->table_api.column_find_int(tr, find_sql_column(args, "type_digits"), rid);
     933      157177 :         scale = store->table_api.column_find_int(tr, find_sql_column(args, "type_scale"), rid);
     934             : 
     935      157177 :         tpe = store->table_api.column_find_string_start(tr, find_sql_column(args, "type"), rid, &cbat);
     936      157177 :         if (tpe && strcmp(tpe, "clob") == 0)
     937        2566 :                 tpe = "varchar";
     938      157177 :         if (!sql_find_subtype(&a->type, tpe, digits, scale)) {
     939        6344 :                 sql_type *lt = sql_trans_bind_type(tr, f->s, tpe);
     940        6344 :                 if (lt == NULL) {
     941           0 :                         TRC_ERROR(SQL_STORE, "SQL type '%s' is missing\n", tpe);
     942           0 :                         store->table_api.column_find_string_end(cbat);
     943           0 :                         return NULL;
     944             :                 }
     945        6344 :                 sql_init_subtype(&a->type, lt, digits, scale);
     946             :         }
     947      157177 :         store->table_api.column_find_string_end(cbat);
     948      157177 :         return a;
     949             : }
     950             : 
     951             : static sql_func *
     952       54569 : load_func(sql_trans *tr, sql_schema *s, sqlid fid, subrids *rs)
     953             : {
     954       54569 :         sqlstore *store = tr->store;
     955       54569 :         sql_func *t = ZNEW(sql_func);
     956       54569 :         sql_schema *syss = find_sql_schema(tr, "sys");
     957       54569 :         sql_table *funcs = find_sql_table(tr, syss, "functions");
     958       54569 :         oid rid;
     959       54569 :         bool update_env;        /* hacky way to update env function */
     960       54569 :         const char *v;
     961       54569 :         ptr cbat;
     962             : 
     963       54569 :         rid = store->table_api.column_find_row(tr, find_sql_column(funcs, "id"), &fid, NULL);
     964       54569 :         v = store->table_api.column_find_string_start(tr, find_sql_column(funcs, "name"), rid, &cbat);
     965       54569 :         update_env = strcmp(v, "env") == 0;
     966       54569 :         base_init(NULL, &t->base, fid, 0, v);
     967       54569 :         store->table_api.column_find_string_end(cbat);
     968       54569 :         v = store->table_api.column_find_string_start(tr, find_sql_column(funcs, "func"), rid, &cbat);
     969       54569 :         update_env = update_env && strstr(v, "EXTERNAL NAME sql.sql_environment") != NULL;
     970       54569 :         if (update_env) {
     971             :                 /* see creation of env in sql_create_env()
     972             :                  * also see upgrade code in sql_upgrades.c */
     973             :                 v = "CREATE FUNCTION env() RETURNS TABLE( name varchar(1024), value varchar(2048)) EXTERNAL NAME inspect.\"getEnvironment\";";
     974             :         }
     975       54569 :         t->imp =_STRDUP(v);
     976       54569 :         store->table_api.column_find_string_end(cbat);
     977       54569 :         if (update_env) {
     978             :                 v = "inspect";
     979             :         } else {
     980       54569 :                 v = store->table_api.column_find_string_start(tr, find_sql_column(funcs, "mod"), rid, &cbat);
     981             :         }
     982       54569 :         if (strcmp(v, "pyapi") == 0 ||         /* pyapi module no longer used */
     983       54569 :                 strcmp(v, "pyapi3map") == 0) /* pyapi3map module no longer used */
     984           0 :                 t->mod =_STRDUP("pypapi3");
     985             :         else
     986       54569 :                 t->mod =_STRDUP(v);
     987       54569 :         if (!update_env)
     988       54569 :                 store->table_api.column_find_string_end(cbat);
     989       54569 :         t->lang = (sql_flang) store->table_api.column_find_int(tr, find_sql_column(funcs, "language"), rid);
     990       54569 :         t->instantiated = t->lang != FUNC_LANG_SQL && t->lang != FUNC_LANG_MAL;
     991       54569 :         t->type = (sql_ftype) store->table_api.column_find_int(tr, find_sql_column(funcs, "type"), rid);
     992       54569 :         t->side_effect = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "side_effect"), rid);
     993       54569 :         t->varres = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "varres"), rid);
     994       54569 :         t->vararg = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "vararg"), rid);
     995       54569 :         t->system = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "system"), rid);
     996       54569 :         t->semantics = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "semantics"), rid);
     997       54569 :         t->res = NULL;
     998       54569 :         t->s = s;
     999       54569 :         t->fix_scale = SCALE_EQ;
    1000       54569 :         t->sa = NULL;
    1001       54569 :         if (t->lang != FUNC_LANG_INT) {
    1002       54569 :                 t->query = t->imp;
    1003       54569 :                 t->imp = NULL;
    1004             :         }
    1005             :         /* convert old PYTHON2 and PYTHON2_MAP to PYTHON and PYTHON_MAP
    1006             :          * see also function sql_update_jun2020() in sql_upgrades.c */
    1007       54569 :         if ((int) t->lang == 7 || (int) t->lang == 8)             /* MAP_PY old FUNC_LANG_PY2 */
    1008           0 :                 t->lang = FUNC_LANG_PY;
    1009       54569 :         else if ((int) t->lang == 9 || (int) t->lang == 11)       /* old FUNC_LANG_MAP_PY2 or MAP_PY3 */
    1010           0 :                 t->lang = FUNC_LANG_PY;
    1011       54569 :         if (LANG_EXT(t->lang)) { /* instantiate functions other than sql and mal */
    1012          76 :                 switch(t->type) {
    1013          10 :                 case F_AGGR:
    1014          10 :                         t->imp =_STRDUP("eval_aggr");
    1015          10 :                         break;
    1016           0 :                 case F_LOADER:
    1017           0 :                         t->imp =_STRDUP("eval_loader");
    1018           0 :                         break;
    1019          66 :                 default: /* for every other function type at the moment */
    1020          66 :                         t->imp =_STRDUP("eval");
    1021             :                 }
    1022             :         }
    1023             : 
    1024       54569 :         TRC_DEBUG(SQL_STORE, "Load function: %s\n", t->base.name);
    1025             : 
    1026       54569 :         t->ops = list_create((fdestroy) &arg_destroy);
    1027       54569 :         if (rs) {
    1028      210260 :                 for (rid = store->table_api.subrids_next(rs); !is_oid_nil(rid); rid = store->table_api.subrids_next(rs)) {
    1029      157177 :                         sql_arg *a = load_arg(tr, t, rid);
    1030             : 
    1031      157177 :                         if (a == NULL)
    1032             :                                 return NULL;
    1033      157177 :                         if (a->inout == ARG_OUT) {
    1034       72219 :                                 if (!t->res)
    1035       46161 :                                         t->res = list_create((fdestroy) &arg_destroy);
    1036       72219 :                                 list_append(t->res, a);
    1037             :                         } else {
    1038       84958 :                                 list_append(t->ops, a);
    1039             :                         }
    1040             :                 }
    1041             :         }
    1042             :         return t;
    1043             : }
    1044             : 
    1045             : static sql_sequence *
    1046          36 : load_seq(sql_trans *tr, sql_schema * s, oid rid)
    1047             : {
    1048          36 :         sqlstore *store = tr->store;
    1049          36 :         sql_sequence *seq = ZNEW(sql_sequence);
    1050          36 :         sql_schema *syss = find_sql_schema(tr, "sys");
    1051          36 :         sql_table *seqs = find_sql_table(tr, syss, "sequences");
    1052          36 :         sqlid sid;
    1053          36 :         const char *v;
    1054          36 :         ptr cbat;
    1055             : 
    1056          36 :         sid = store->table_api.column_find_sqlid(tr, find_sql_column(seqs, "id"), rid);
    1057          36 :         v = store->table_api.column_find_string_start(tr, find_sql_column(seqs, "name"), rid, &cbat);
    1058          36 :         base_init(NULL, &seq->base, sid, 0, v);
    1059          36 :         store->table_api.column_find_string_end(cbat);
    1060          36 :         seq->start = store->table_api.column_find_lng(tr, find_sql_column(seqs, "start"), rid);
    1061          36 :         seq->minvalue = store->table_api.column_find_lng(tr, find_sql_column(seqs, "minvalue"), rid);
    1062          36 :         seq->maxvalue = store->table_api.column_find_lng(tr, find_sql_column(seqs, "maxvalue"), rid);
    1063          36 :         seq->increment = store->table_api.column_find_lng(tr, find_sql_column(seqs, "increment"), rid);
    1064          36 :         seq->cacheinc = store->table_api.column_find_lng(tr, find_sql_column(seqs, "cacheinc"), rid);
    1065          36 :         seq->cycle = (bit) store->table_api.column_find_bte(tr, find_sql_column(seqs, "cycle"), rid);
    1066          36 :         seq->s = s;
    1067          36 :         return seq;
    1068             : }
    1069             : 
    1070             : static void
    1071        1350 : sql_trans_update_schema(sql_trans *tr, oid rid)
    1072             : {
    1073        1350 :         sqlstore *store = tr->store;
    1074        1350 :         sql_schema *s = NULL, *syss = find_sql_schema(tr, "sys");
    1075        1350 :         sql_table *ss = find_sql_table(tr, syss, "schemas");
    1076        1350 :         sqlid sid;
    1077        1350 :         str v;
    1078             : 
    1079        1350 :         sid = store->table_api.column_find_sqlid(tr, find_sql_column(ss, "id"), rid);
    1080        1350 :         s = find_sql_schema_id(tr, sid);
    1081             : 
    1082        1350 :         if (s==NULL)
    1083             :                 return ;
    1084             : 
    1085        1350 :         TRC_DEBUG(SQL_STORE, "Update schema: %s %d\n", s->base.name, s->base.id);
    1086             : 
    1087        1350 :         v = store->table_api.column_find_value(tr, find_sql_column(ss, "name"), rid);
    1088        1350 :         if (!v)
    1089             :                 return; /* TODO do better than this */
    1090        1350 :         _DELETE(s->base.name);
    1091        1350 :         base_init(NULL, &s->base, sid, 0, v);
    1092        1350 :         _DELETE(v);
    1093        1350 :         s->auth_id = store->table_api.column_find_sqlid(tr, find_sql_column(ss, "authorization"), rid);
    1094        1350 :         s->system = (bit) store->table_api.column_find_bte(tr, find_sql_column(ss, "system"), rid);
    1095        1350 :         s->owner = store->table_api.column_find_sqlid(tr, find_sql_column(ss, "owner"), rid);
    1096             : }
    1097             : 
    1098             : static sql_schema *
    1099         669 : load_schema(sql_trans *tr, res_table *rt_schemas, res_table *rt_tables, res_table *rt_parts,
    1100             :                     res_table *rt_cols, res_table *rt_idx, res_table *rt_idxcols,
    1101             :                     res_table *rt_keys, res_table *rt_keycols,
    1102             :                     res_table *rt_triggers, res_table *rt_triggercols)
    1103             : {
    1104         669 :         sqlstore *store = tr->store;
    1105         669 :         sql_schema *s = NULL, *syss = find_sql_schema(tr, "sys");
    1106         669 :         sql_table *ss = find_sql_table(tr, syss, "schemas");
    1107         669 :         sql_table *types = find_sql_table(tr, syss, "types");
    1108         669 :         sql_table *tables = find_sql_table(tr, syss, "_tables");
    1109         669 :         sql_table *funcs = find_sql_table(tr, syss, "functions");
    1110         669 :         sql_table *seqs = find_sql_table(tr, syss, "sequences");
    1111         669 :         sql_column *type_schema, *type_id, *table_schema, *table_id;
    1112         669 :         sql_column *func_schema, *func_id, *seq_schema, *seq_id;
    1113         669 :         rids *rs;
    1114             : 
    1115         669 :         sqlid sid = *(sqlid*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "id"));
    1116         669 :         if (instore(sid)) {
    1117         212 :                 s = find_sql_schema_id(tr, sid);
    1118             : 
    1119         212 :                 if (s==NULL) {
    1120           0 :                         char *name = (char*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "name"));
    1121           0 :                         s = find_sql_schema(tr, name);
    1122           0 :                         if (s == NULL) {
    1123           0 :                                 GDKerror("SQL schema missing or incompatible, rebuild from archive");
    1124           0 :                                 return NULL;
    1125             :                         }
    1126             :                 }
    1127         212 :                 s->base.id = sid;
    1128             :         } else {
    1129         457 :                 s = ZNEW(sql_schema);
    1130         457 :                 if (s == NULL)
    1131             :                         return NULL;
    1132         457 :                 char *name = (char*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "name"));
    1133         457 :                 base_init(NULL, &s->base, sid, 0, name);
    1134         457 :                 s->auth_id = *(sqlid*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "authorization"));
    1135         457 :                 s->system = *(bte*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "system"));
    1136         457 :                 s->owner = *(sqlid*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "owner"));
    1137             : 
    1138         457 :                 s->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
    1139         457 :                 s->types = os_new(NULL, (destroy_fptr) &type_destroy, false, true, true, false, store);
    1140         457 :                 s->funcs = os_new(NULL, (destroy_fptr) &func_destroy, false, false, false, false, store);
    1141         457 :                 s->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
    1142         457 :                 s->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
    1143         457 :                 s->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
    1144         457 :                 s->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
    1145         457 :                 s->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
    1146             :         }
    1147             : 
    1148         669 :         TRC_DEBUG(SQL_STORE, "Load schema: %s %d\n", s->base.name, s->base.id);
    1149             : 
    1150         669 :         sqlid tmpid = FUNC_OIDS;
    1151             : 
    1152             :         /* first load simple types */
    1153         669 :         type_schema = find_sql_column(types, "schema_id");
    1154         669 :         type_id = find_sql_column(types, "id");
    1155         669 :         rs = store->table_api.rids_select(tr, type_schema, &s->base.id, &s->base.id, type_id, &tmpid, NULL, NULL);
    1156         669 :         if (!rs) {
    1157           0 :                 schema_destroy(store, s);
    1158           0 :                 return NULL;
    1159             :         }
    1160        1101 :         for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
    1161         432 :                 sql_type *t = load_type(tr, s, rid);
    1162         432 :                 if (os_add(s->types, tr, t->base.name, &t->base)) {
    1163           0 :                         schema_destroy(store, s);
    1164           0 :                         store->table_api.rids_destroy(rs);
    1165           0 :                         return NULL;
    1166             :                 }
    1167             :         }
    1168         669 :         store->table_api.rids_destroy(rs);
    1169             : 
    1170             :         /* second tables */
    1171         669 :         table_schema = find_sql_column(tables, "schema_id");
    1172         669 :         table_id = find_sql_column(tables, "id");
    1173       16951 :         for ( ; rt_tables->cur_row < rt_tables->nr_rows; rt_tables->cur_row++) {
    1174       16172 :                 sqlid nsid = *(sqlid*)store->table_api.table_fetch_value(rt_tables, table_schema);
    1175       16172 :                 sqlid tid = *(sqlid*)store->table_api.table_fetch_value(rt_tables, table_id);
    1176       16172 :                 if (nsid > s->base.id)
    1177             :                         break;
    1178       15613 :                 if (nsid < s->base.id)
    1179           0 :                         assert(0);
    1180       29000 :                 if (!instore(tid)) {
    1181       13387 :                         sql_table *t = load_table(tr, s, rt_tables, rt_parts,
    1182             :                                         rt_cols, rt_idx, rt_idxcols, rt_keys, rt_keycols, rt_triggers, rt_triggercols, tid);
    1183       13387 :                         if (t == NULL && store->debug&8) /* try to continue without this table */
    1184           0 :                                 continue;
    1185           0 :                         if (t == NULL) {
    1186           0 :                                 schema_destroy(store, s);
    1187           0 :                                 return NULL;
    1188             :                         }
    1189       13387 :                         if (os_add(s->tables, tr, t->base.name, &t->base)) {
    1190           0 :                                 schema_destroy(store, s);
    1191           0 :                                 return NULL;
    1192             :                         }
    1193             :                 }
    1194             :         }
    1195             : 
    1196             :         /* next functions which could use these types */
    1197         669 :         func_schema = find_sql_column(funcs, "schema_id");
    1198         669 :         func_id = find_sql_column(funcs, "id");
    1199         669 :         rs = store->table_api.rids_select(tr, func_schema, &s->base.id, &s->base.id, func_id, &tmpid, NULL, NULL);
    1200         669 :         if (rs == NULL) {
    1201           0 :                 schema_destroy(store, s);
    1202           0 :                 return NULL;
    1203             :         }
    1204         669 :         if (!store->table_api.rids_empty(rs)) {
    1205         443 :                 sql_table *args = find_sql_table(tr, syss, "args");
    1206         443 :                 sql_column *arg_func_id = find_sql_column(args, "func_id");
    1207         443 :                 sql_column *arg_number = find_sql_column(args, "number");
    1208         443 :                 subrids *nrs = store->table_api.subrids_create(tr, rs, func_id, arg_func_id, arg_number);
    1209         443 :                 if (!nrs) {
    1210           0 :                         store->table_api.rids_destroy(rs);
    1211           0 :                         schema_destroy(store, s);
    1212           0 :                         return NULL;
    1213             :                 }
    1214         443 :                 sqlid fid;
    1215         443 :                 sql_func *f;
    1216             : 
    1217       53526 :                 for (fid = store->table_api.subrids_nextid(nrs); fid >= 0; fid = store->table_api.subrids_nextid(nrs)) {
    1218       53083 :                         f = load_func(tr, s, fid, nrs);
    1219       53083 :                         if (f == NULL) {
    1220           0 :                                 store->table_api.subrids_destroy(nrs);
    1221           0 :                                 store->table_api.rids_destroy(rs);
    1222           0 :                                 schema_destroy(store, s);
    1223           0 :                                 return NULL;
    1224             :                         }
    1225       53083 :                         if (os_add(s->funcs, tr, f->base.name, &f->base)) {
    1226           0 :                                 schema_destroy(store, s);
    1227           0 :                                 return NULL;
    1228             :                         }
    1229             :                 }
    1230             :                 /* Handle all procedures without arguments (no args) */
    1231         443 :                 rs = store->table_api.rids_diff(tr, rs, func_id, nrs, arg_func_id);
    1232         443 :                 if (!rs) {
    1233           0 :                         store->table_api.subrids_destroy(nrs);
    1234           0 :                         schema_destroy(store, s);
    1235           0 :                         return NULL;
    1236             :                 }
    1237        1929 :                 for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
    1238        1486 :                         fid = store->table_api.column_find_sqlid(tr, func_id, rid);
    1239        1486 :                         f = load_func(tr, s, fid, NULL);
    1240        1486 :                         if (f == NULL) {
    1241           0 :                                 store->table_api.subrids_destroy(nrs);
    1242           0 :                                 store->table_api.rids_destroy(rs);
    1243           0 :                                 schema_destroy(store, s);
    1244           0 :                                 return NULL;
    1245             :                         }
    1246        1486 :                         if (os_add(s->funcs, tr, f->base.name, &f->base)) {
    1247           0 :                                 store->table_api.subrids_destroy(nrs);
    1248           0 :                                 store->table_api.rids_destroy(rs);
    1249           0 :                                 schema_destroy(store, s);
    1250           0 :                                 return NULL;
    1251             :                         }
    1252             :                 }
    1253         443 :                 store->table_api.subrids_destroy(nrs);
    1254             :         }
    1255         669 :         store->table_api.rids_destroy(rs);
    1256             : 
    1257             :         /* last sequence numbers */
    1258         669 :         seq_schema = find_sql_column(seqs, "schema_id");
    1259         669 :         seq_id = find_sql_column(seqs, "id");
    1260         669 :         rs = store->table_api.rids_select(tr, seq_schema, &s->base.id, &s->base.id, seq_id, &tmpid, NULL, NULL);
    1261         669 :         if (rs == NULL) {
    1262           0 :                 schema_destroy(store, s);
    1263           0 :                 return NULL;
    1264             :         }
    1265         705 :         for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
    1266          36 :                 sql_sequence *seq = load_seq(tr, s, rid);
    1267          36 :                 if (os_add(s->seqs, tr, seq->base.name, &seq->base)) {
    1268           0 :                         schema_destroy(store, s);
    1269           0 :                         store->table_api.rids_destroy(rs);
    1270           0 :                         return NULL;
    1271             :                 }
    1272             :         }
    1273         669 :         store->table_api.rids_destroy(rs);
    1274             : 
    1275         669 :         struct os_iter oi;
    1276         669 :         os_iterator(&oi, s->tables, tr, NULL);
    1277       16282 :         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    1278       15613 :                 sql_table *t = (sql_table*)b;
    1279       15613 :                 if (isMergeTable(t) || isReplicaTable(t)) {
    1280         101 :                         sql_table *objects = find_sql_table(tr, syss, "objects");
    1281         101 :                         sql_column *mt_nr = find_sql_column(objects, "nr");
    1282         101 :                         sql_column *mt_sub = find_sql_column(objects, "sub");
    1283         101 :                         rids *rs = store->table_api.rids_select(tr, mt_nr, &t->base.id, &t->base.id, NULL);
    1284         101 :                         if (rs == NULL) {
    1285           0 :                                 schema_destroy(store, s);
    1286           0 :                                 return NULL;
    1287             :                         }
    1288         101 :                         rs = store->table_api.rids_orderby(tr, rs, mt_sub);
    1289         101 :                         if (rs == NULL) {
    1290           0 :                                 schema_destroy(store, s);
    1291           0 :                                 return NULL;
    1292             :                         }
    1293         316 :                         for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
    1294         215 :                                 sql_part *pt = load_part(tr, t, rid);
    1295         215 :                                 if (isRangePartitionTable(t)) {
    1296          78 :                                         if (load_range_partition(tr, syss, pt) < 0) {
    1297           0 :                                                 schema_destroy(store, s);
    1298           0 :                                                 return NULL;
    1299             :                                         }
    1300         137 :                                 } else if (isListPartitionTable(t)) {
    1301          33 :                                         load_value_partition(tr, syss, pt);
    1302             :                                 }
    1303         215 :                                 if (os_add(s->parts, tr, pt->base.name, dup_base(&pt->base))) {
    1304           0 :                                         schema_destroy(store, s);
    1305           0 :                                         store->table_api.rids_destroy(rs);
    1306           0 :                                         return NULL;
    1307             :                                 }
    1308             :                         }
    1309         101 :                         store->table_api.rids_destroy(rs);
    1310             :                 }
    1311             :         }
    1312             :         return s;
    1313             : }
    1314             : 
    1315             : int
    1316         225 : sql_trans_update_schemas(sql_trans* tr)
    1317             : {
    1318         225 :         sqlstore *store = tr->store;
    1319         225 :         sql_schema *syss = find_sql_schema(tr, "sys");
    1320         225 :         sql_table *sysschema = find_sql_table(tr, syss, "schemas");
    1321         225 :         sql_column *sysschema_ids = find_sql_column(sysschema, "id");
    1322         225 :         rids *schemas = store->table_api.rids_select(tr, sysschema_ids, NULL, NULL);
    1323         225 :         oid rid;
    1324             : 
    1325         225 :         if (schemas == NULL)
    1326             :                 return -1;
    1327         225 :         TRC_DEBUG(SQL_STORE, "Update schemas\n");
    1328             : 
    1329        1575 :         for (rid = store->table_api.rids_next(schemas); !is_oid_nil(rid); rid = store->table_api.rids_next(schemas)) {
    1330        1350 :                 sql_trans_update_schema(tr, rid);
    1331             :         }
    1332         225 :         store->table_api.rids_destroy(schemas);
    1333         225 :         return 0;
    1334             : }
    1335             : 
    1336             : static bool
    1337         106 : load_trans(sql_trans* tr)
    1338             : {
    1339         106 :         sqlstore *store = tr->store;
    1340         106 :         sql_schema *syss = find_sql_schema(tr, "sys");
    1341         106 :         sql_table *sysschema = find_sql_table(tr, syss, "schemas");
    1342         106 :         sql_table *systables = find_sql_table(tr, syss, "_tables");
    1343         106 :         sql_table *sysparts = find_sql_table(tr, syss, "table_partitions");
    1344         106 :         sql_table *syscols = find_sql_table(tr, syss, "_columns");
    1345         106 :         sql_table *sysidx = find_sql_table(tr, syss, "idxs");
    1346         106 :         sql_table *syskeys = find_sql_table(tr, syss, "keys");
    1347         106 :         sql_table *systriggers = find_sql_table(tr, syss, "triggers");
    1348         106 :         sql_table *sysobjects = find_sql_table(tr, syss, "objects");
    1349         106 :         sql_column *sysschema_ids = find_sql_column(sysschema, "id");
    1350         106 :         bool ok = true;
    1351             : 
    1352         106 :         TRC_DEBUG(SQL_STORE, "Load transaction\n");
    1353         106 :         assert(sysschema);
    1354         106 :         assert(systables);
    1355         106 :         assert(sysparts);
    1356         106 :         assert(syscols);
    1357         106 :         assert(sysidx);
    1358         106 :         assert(syskeys);
    1359         106 :         assert(systriggers);
    1360         106 :         assert(sysobjects);
    1361         106 :         assert(sysschema_ids);
    1362             : 
    1363         106 :         res_table *rt_schemas = store->table_api.table_orderby(tr, sysschema, NULL, NULL, NULL, NULL, sysschema_ids, NULL);
    1364         106 :         res_table *rt_tables = store->table_api.table_orderby(tr, systables, NULL, NULL, NULL, NULL,
    1365             :                         find_sql_column(systables, "schema_id"),
    1366             :                         find_sql_column(systables, "id"), NULL);
    1367         106 :         res_table *rt_parts = store->table_api.table_orderby(tr, sysparts,
    1368             :                         find_sql_column(sysparts, "table_id"),
    1369             :                         find_sql_column(systables, "id"),
    1370             :                         NULL, NULL,
    1371             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id */
    1372             :                         find_sql_column(sysparts, "table_id"), NULL);
    1373         106 :         res_table *rt_cols = store->table_api.table_orderby(tr, syscols,
    1374             :                         find_sql_column(syscols, "table_id"),
    1375             :                         find_sql_column(systables, "id"),
    1376             :                         NULL, NULL,
    1377             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id */
    1378             :                         find_sql_column(syscols, "table_id"),
    1379             :                         find_sql_column(syscols, "number"), NULL);
    1380             : 
    1381         106 :         res_table *rt_idx = store->table_api.table_orderby(tr, sysidx,
    1382             :                         find_sql_column(sysidx, "table_id"),
    1383             :                         find_sql_column(systables, "id"),
    1384             :                         NULL, NULL,
    1385             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id */
    1386             :                         find_sql_column(sysidx, "table_id"),
    1387             :                         find_sql_column(sysidx, "id"), NULL);
    1388         106 :         res_table *rt_idxcols = store->table_api.table_orderby(tr, sysobjects,
    1389             :                         find_sql_column(sysobjects, "id"),
    1390             :                         find_sql_column(sysidx, "id"),
    1391             :                         find_sql_column(sysidx, "table_id"),
    1392             :                         find_sql_column(systables, "id"),
    1393             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id, table_id */
    1394             :                         find_sql_column(sysidx, "table_id"),
    1395             :                         find_sql_column(sysobjects, "id"),
    1396             :                         find_sql_column(sysobjects, "nr"), NULL);
    1397         106 :         res_table *rt_keys = store->table_api.table_orderby(tr, syskeys,
    1398             :                         find_sql_column(syskeys, "table_id"),
    1399             :                         find_sql_column(systables, "id"),
    1400             :                         NULL, NULL,
    1401             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id */
    1402             :                         find_sql_column(syskeys, "table_id"),
    1403             :                         find_sql_column(syskeys, "id"), NULL);
    1404         106 :         res_table *rt_keycols = store->table_api.table_orderby(tr, sysobjects,
    1405             :                         find_sql_column(sysobjects, "id"),
    1406             :                         find_sql_column(syskeys, "id"),
    1407             :                         find_sql_column(syskeys, "table_id"),
    1408             :                         find_sql_column(systables, "id"),
    1409             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id, table_id */
    1410             :                         find_sql_column(syskeys, "table_id"),
    1411             :                         find_sql_column(sysobjects, "id"),
    1412             :                         find_sql_column(sysobjects, "nr"), NULL);
    1413         106 :         res_table *rt_tabletriggers = store->table_api.table_orderby(tr, systriggers,
    1414             :                         find_sql_column(systriggers, "table_id"),
    1415             :                         find_sql_column(systables, "id"),
    1416             :                         NULL, NULL,
    1417             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id */
    1418             :                         find_sql_column(systriggers, "table_id"),
    1419             :                         find_sql_column(systriggers, "id"), NULL);
    1420         106 :         res_table *rt_triggercols = store->table_api.table_orderby(tr, sysobjects,
    1421             :                         find_sql_column(sysobjects, "id"),
    1422             :                         find_sql_column(systriggers, "id"),
    1423             :                         find_sql_column(systriggers, "table_id"),
    1424             :                         find_sql_column(systables, "id"),
    1425             :                         find_sql_column(systables, "schema_id"), /* order also on schema_id, table_id */
    1426             :                         find_sql_column(systriggers, "table_id"),
    1427             :                         find_sql_column(sysobjects, "id"),
    1428             :                         find_sql_column(sysobjects, "nr"), NULL);
    1429         106 :         res_table *rt_triggers = store->table_api.table_orderby(tr, systriggers,
    1430             :                         NULL, NULL, NULL, NULL,
    1431             :                         find_sql_column(systriggers, "id"),
    1432             :                         find_sql_column(systriggers, "table_id"), NULL);
    1433         881 :         for ( ; rt_schemas->cur_row < rt_schemas->nr_rows; rt_schemas->cur_row++) {
    1434         669 :                 sql_schema *ns = load_schema(tr, rt_schemas, rt_tables, rt_parts,
    1435             :                                 rt_cols, rt_idx, rt_idxcols, rt_keys, rt_keycols, rt_tabletriggers, rt_triggercols);
    1436         669 :                 if (ns == NULL) {
    1437           0 :                         ok = false;
    1438           0 :                         goto finish;
    1439             :                 }
    1440        1126 :                 if (!instore(ns->base.id)) {
    1441         457 :                         if (os_add(tr->cat->schemas, tr, ns->base.name, &ns->base)) {
    1442           0 :                                 ok = false;
    1443           0 :                                 goto finish;
    1444             :                         }
    1445         457 :                         if (isTempSchema(ns))
    1446           0 :                                 tr->tmp = ns;
    1447             :                 }
    1448             :         }
    1449         106 :         if (rt_triggers) {
    1450         231 :                 for ( ; rt_triggers->cur_row < rt_triggers->nr_rows; rt_triggers->cur_row++) {
    1451         125 :                         sqlid ntid = *(sqlid*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(systriggers, "table_id"));
    1452         125 :                         if (ntid != int_nil)
    1453         125 :                                 continue;
    1454           0 :                         sql_trigger *k = load_trigger(tr, NULL, rt_triggers, NULL);
    1455             : 
    1456           0 :                         if (!k || os_add(syss->triggers, tr, k->base.name, &k->base)) {
    1457           0 :                                 ok = false;
    1458           0 :                                 goto finish;
    1459             :                         }
    1460             :                 }
    1461             :         }
    1462             : 
    1463         106 : finish:
    1464         106 :         store->table_api.table_result_destroy(rt_schemas);
    1465         106 :         store->table_api.table_result_destroy(rt_tables);
    1466         106 :         store->table_api.table_result_destroy(rt_parts);
    1467         106 :         store->table_api.table_result_destroy(rt_cols);
    1468         106 :         store->table_api.table_result_destroy(rt_idx);
    1469         106 :         store->table_api.table_result_destroy(rt_idxcols);
    1470         106 :         store->table_api.table_result_destroy(rt_keys);
    1471         106 :         store->table_api.table_result_destroy(rt_keycols);
    1472         106 :         store->table_api.table_result_destroy(rt_tabletriggers);
    1473         106 :         store->table_api.table_result_destroy(rt_triggercols);
    1474         106 :         store->table_api.table_result_destroy(rt_triggers);
    1475         106 :         return ok;
    1476             : }
    1477             : 
    1478             : static sqlid
    1479     1389919 : next_oid(sqlstore *store)
    1480             : {
    1481     1389919 :         sqlid id = 0;
    1482     1389919 :         MT_lock_set(&store->lock);
    1483     1389919 :         id = store->obj_id++;
    1484     1389919 :         assert(id < 2000000000);
    1485     1389919 :         MT_lock_unset(&store->lock);
    1486     1389919 :         return id;
    1487             : }
    1488             : 
    1489             : sqlid
    1490       23354 : store_next_oid(sqlstore *store)
    1491             : {
    1492       23354 :         return next_oid(store);
    1493             : }
    1494             : 
    1495             : static int
    1496         225 : insert_schemas(sql_trans *tr)
    1497             : {
    1498         225 :         int res = LOG_OK;
    1499         225 :         sqlstore *store = tr->store;
    1500         225 :         sql_schema *syss = find_sql_schema(tr, "sys");
    1501         225 :         sql_table *sysschema = find_sql_table(tr, syss, "schemas");
    1502         225 :         sql_table *systable = find_sql_table(tr, syss, "_tables");
    1503         225 :         sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    1504         225 :         node *o;
    1505             : 
    1506         225 :         struct os_iter si;
    1507         225 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
    1508         900 :         for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
    1509         675 :                 sql_schema *s = (sql_schema*)b;
    1510         675 :                 char *strnil = (char*)ATOMnilptr(TYPE_str);
    1511             : 
    1512         675 :                 if (isDeclaredSchema(s))
    1513         225 :                         continue;
    1514         450 :                 if ((res = store->table_api.table_insert(tr, sysschema, &s->base.id, &s->base.name, &s->auth_id, &s->owner, &s->system)))
    1515           0 :                         return res;
    1516         450 :                 struct os_iter oi;
    1517         450 :                 os_iterator(&oi, s->tables, tr, NULL);
    1518        5175 :                 for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    1519        4725 :                         sql_table *t = (sql_table*)b;
    1520        4725 :                         sht ca = t->commit_action;
    1521             : 
    1522        4725 :                         if ((res = store->table_api.table_insert(tr, systable, &t->base.id, &t->base.name, &s->base.id, &strnil, &t->type, &t->system, &ca, &t->access)))
    1523           0 :                                 return res;
    1524       37125 :                         for (o = t->columns->l->h; o; o = o->next) {
    1525       32400 :                                 sql_column *c = o->data;
    1526             : 
    1527       32400 :                                 if ((res = store->table_api.table_insert(tr, syscolumn, &c->base.id, &c->base.name, &c->type.type->base.name, &c->type.digits, &c->type.scale,
    1528       32400 :                                                                                 &t->base.id, (c->def) ? &c->def : &strnil, &c->null, &c->colnr, (c->storage_type)? &c->storage_type : &strnil)))
    1529           0 :                                         return res;
    1530             :                         }
    1531             :                 }
    1532             :         }
    1533             :         return res;
    1534             : }
    1535             : 
    1536             : static int
    1537         225 : insert_types(sql_trans *tr, sql_table *systype)
    1538             : {
    1539         225 :         int res = LOG_OK;
    1540         225 :         sqlstore *store = tr->store;
    1541        7194 :         for (node *n = types->h; n; n = n->next) {
    1542        6969 :                 sql_type *t = n->data;
    1543        6969 :                 int radix = t->radix, eclass = (int) t->eclass;
    1544        6969 :                 sqlid next_schema = t->s ? t->s->base.id : 0;
    1545             : 
    1546        6969 :                 if ((res = store->table_api.table_insert(tr, systype, &t->base.id, &t->impl, &t->base.name, &t->digits, &t->scale, &radix, &eclass, &next_schema)))
    1547           0 :                         return res;
    1548             :         }
    1549             :         return res;
    1550             : }
    1551             : 
    1552             : static int
    1553      320280 : insert_args(sql_trans *tr, sql_table *sysarg, list *args, sqlid funcid, const char *arg_def, int *number)
    1554             : {
    1555      320280 :         int res = LOG_OK;
    1556      320280 :         sqlstore *store = tr->store;
    1557      747150 :         for (node *n = args->h; n; n = n->next) {
    1558      426870 :                 sql_arg *a = n->data;
    1559      426870 :                 sqlid id = next_oid(tr->store);
    1560      426870 :                 int next_number = (*number)++;
    1561      426870 :                 char buf[32], *next_name;
    1562             : 
    1563      426870 :                 if (a->name) {
    1564           0 :                         next_name = a->name;
    1565             :                 } else {
    1566      426870 :                         snprintf(buf, sizeof(buf), arg_def, next_number);
    1567      426870 :                         next_name = buf;
    1568             :                 }
    1569      426870 :                 if ((res = store->table_api.table_insert(tr, sysarg, &id, &funcid, &next_name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &next_number)))
    1570           0 :                         return res;
    1571             :         }
    1572             :         return res;
    1573             : }
    1574             : 
    1575             : static int
    1576         225 : insert_functions(sql_trans *tr, sql_table *sysfunc, list *funcs_list, sql_table *sysarg)
    1577             : {
    1578         225 :         int res = LOG_OK;
    1579         225 :         sqlstore *store = tr->store;
    1580      212115 :         for (node *n = funcs_list->h; n; n = n->next) {
    1581      211890 :                 sql_func *f = n->data;
    1582      211890 :                 int number = 0, ftype = (int) f->type, flang = (int) FUNC_LANG_INT;
    1583      211890 :                 sqlid next_schema = f->s ? f->s->base.id : 0;
    1584      211890 :                 bit se = f->side_effect, vares = f->varres, varg = f->vararg, system = f->system, sem = f->semantics;
    1585             : 
    1586      211890 :                 if (f->private) /* don't serialize private functions because they cannot be seen by users */
    1587       51525 :                         continue;
    1588      160365 :                 if ((res = store->table_api.table_insert(tr, sysfunc, &f->base.id, &f->base.name, &f->imp, &f->mod, &flang, &ftype, &se, &vares, &varg, &next_schema, &system, &sem)))
    1589           0 :                         return res;
    1590      160365 :                 if (f->res && (res = insert_args(tr, sysarg, f->res, f->base.id, "res_%d", &number)))
    1591           0 :                         return res;
    1592      160365 :                 if (f->ops && (res = insert_args(tr, sysarg, f->ops, f->base.id, "arg_%d", &number)))
    1593           0 :                         return res;
    1594             :         }
    1595             :         return res;
    1596             : }
    1597             : 
    1598             : static int
    1599      314194 : table_next_column_nr(sql_table *t)
    1600             : {
    1601      314194 :         int nr = ol_length(t->columns);
    1602      314194 :         if (nr) {
    1603      272751 :                 node *n = ol_last_node(t->columns);
    1604      272751 :                 if (n) {
    1605      272751 :                         sql_column *c = n->data;
    1606             : 
    1607      272751 :                         nr = c->colnr+1;
    1608             :                 }
    1609             :         }
    1610      314194 :         return nr;
    1611             : }
    1612             : 
    1613             : static sql_column *
    1614       47664 : bootstrap_create_column(sql_trans *tr, sql_table *t, const char *name, sqlid id, const char *sqltype, unsigned int digits)
    1615             : {
    1616       47664 :         sqlstore *store = tr->store;
    1617       47664 :         sql_column *col = ZNEW(sql_column);
    1618             : 
    1619       47664 :         if (store->obj_id <= id)
    1620        8937 :                 store->obj_id = id+1;
    1621       47664 :         TRC_DEBUG(SQL_STORE, "Create column: %s\n", name);
    1622             : 
    1623       47664 :         base_init(NULL, &col->base, id, t->base.new, name);
    1624       47664 :         assert(col->base.id > 0);
    1625       47664 :         sql_find_subtype(&col->type, sqltype, digits, 0);
    1626       47664 :         col->def = NULL;
    1627       47664 :         col->null = 1;
    1628       47664 :         col->colnr = table_next_column_nr(t);
    1629       47664 :         col->t = t;
    1630       47664 :         col->unique = 0;
    1631       47664 :         col->storage_type = NULL;
    1632       47664 :         if (ol_add(t->columns, &col->base))
    1633             :                 return NULL;
    1634             : 
    1635       47664 :         ATOMIC_PTR_INIT(&col->data, NULL);
    1636       47664 :         if (isTable(col->t))
    1637       47664 :                 store->storage_api.create_col(tr, col);
    1638             :         return col;
    1639             : }
    1640             : 
    1641             : static sql_table *
    1642       75513 : create_sql_table_with_id(allocator *sa, sqlid id, const char *name, sht type, bit system, int persistence, int commit_action, bte properties)
    1643             : {
    1644       75513 :         sql_table *t = SA_ZNEW(sa, sql_table);
    1645             : 
    1646       75513 :         assert((persistence==SQL_PERSIST ||
    1647             :                 persistence==SQL_DECLARED_TABLE ||
    1648             :                 commit_action) && commit_action>=0);
    1649       75513 :         assert(id);
    1650       75513 :         base_init(sa, &t->base, id, true, name);
    1651       75513 :         t->type = type;
    1652       75513 :         t->system = system;
    1653       75513 :         t->persistence = (temp_t)persistence;
    1654       75513 :         t->commit_action = (ca_t)commit_action;
    1655       75513 :         t->query = NULL;
    1656       75513 :         t->access = 0;
    1657       75513 :         t->columns = ol_new(sa, (destroy_fptr) &column_destroy, NULL);
    1658       75513 :         t->idxs = ol_new(sa, (destroy_fptr) &idx_destroy, NULL);
    1659       75513 :         t->keys = ol_new(sa, (destroy_fptr) &key_destroy, NULL);
    1660       75513 :         t->triggers = ol_new(sa, (destroy_fptr) &trigger_destroy, NULL);
    1661       75513 :         if (isMergeTable(t) || isReplicaTable(t))
    1662         635 :                 t->members = list_new(sa, (fdestroy) &part_destroy);
    1663       75513 :         t->pkey = NULL;
    1664       75513 :         t->sz = COLSIZE;
    1665       75513 :         t->s = NULL;
    1666       75513 :         t->properties = properties;
    1667       75513 :         memset(&t->part, 0, sizeof(t->part));
    1668       75513 :         ATOMIC_PTR_INIT(&t->data, NULL);
    1669       75513 :         return t;
    1670             : }
    1671             : 
    1672             : sql_table *
    1673       32678 : create_sql_table(sqlstore *store, allocator *sa, const char *name, sht type, bit system, int persistence, int commit_action, bte properties)
    1674             : {
    1675       32678 :         return create_sql_table_with_id(sa, next_oid(store), name, type, system, persistence, commit_action, properties);
    1676             : }
    1677             : 
    1678             : static void
    1679      603168 : dup_sql_type(sql_trans *tr, sql_schema *s, sql_subtype *oc, sql_subtype *nc)
    1680             : {
    1681      603168 :         nc->digits = oc->digits;
    1682      603168 :         nc->scale = oc->scale;
    1683      603168 :         nc->type = oc->type;
    1684      603168 :         if (s && nc->type->s) { /* user type */
    1685       13735 :                 sql_type *lt = NULL;
    1686             : 
    1687       13735 :                 if (s->base.id == nc->type->s->base.id) {
    1688             :                         /* Current user type belongs to current schema. So search there for current user type. */
    1689        8741 :                         lt = find_sql_type(tr, s, nc->type->base.name);
    1690             :                 } else {
    1691             :                         /* Current user type belongs to another schema in the current transaction. Search there for current user type. */
    1692        4994 :                         lt = sql_trans_bind_type(tr, NULL, nc->type->base.name);
    1693             :                 }
    1694       13735 :                 if (lt == NULL)
    1695           0 :                         GDKfatal("SQL type %s missing", nc->type->base.name);
    1696       13735 :                 sql_init_subtype(nc, lt, nc->digits, nc->scale);
    1697             :         }
    1698      603168 : }
    1699             : 
    1700             : static sql_column *
    1701       24464 : dup_sql_column(allocator *sa, sql_table *t, sql_column *c)
    1702             : {
    1703       24464 :         sql_column *col = SA_ZNEW(sa, sql_column);
    1704             : 
    1705       48928 :         base_init(sa, &col->base, c->base.id, t->persistence==SQL_DECLARED_TABLE?false:c->base.new, c->base.name);
    1706       24464 :         col->type = c->type; /* Both types belong to the same transaction, so no dup_sql_type call is needed */
    1707       24464 :         col->def = NULL;
    1708       24464 :         if (c->def)
    1709        1730 :                 col->def = SA_STRDUP(sa, c->def);
    1710       24464 :         col->null = c->null;
    1711       24464 :         col->colnr = c->colnr;
    1712       24464 :         col->t = t;
    1713       24464 :         col->unique = c->unique;
    1714       24464 :         col->storage_type = NULL;
    1715       24464 :         if (c->storage_type)
    1716           2 :                 col->storage_type = SA_STRDUP(sa, c->storage_type);
    1717       24464 :         if (ol_add(t->columns, &col->base))
    1718           0 :                 return NULL;
    1719             :         return col;
    1720             : }
    1721             : 
    1722             : static sql_part *
    1723           7 : dup_sql_part(allocator *sa, sql_table *mt, sql_part *op)
    1724             : {
    1725           7 :         sql_part *p = SA_ZNEW(sa, sql_part);
    1726             : 
    1727          14 :         base_init(sa, &p->base, op->base.id, mt->persistence==SQL_DECLARED_TABLE?false:op->base.new, op->base.name);
    1728           7 :         p->with_nills = op->with_nills;
    1729             : 
    1730           7 :         if (isRangePartitionTable(mt)) {
    1731           3 :                 p->part.range.minvalue = SA_NEW_ARRAY(sa, char, op->part.range.minlength);
    1732           3 :                 p->part.range.maxvalue = SA_NEW_ARRAY(sa, char, op->part.range.maxlength);
    1733           3 :                 memcpy(p->part.range.minvalue, op->part.range.minvalue, op->part.range.minlength);
    1734           3 :                 memcpy(p->part.range.maxvalue, op->part.range.maxvalue, op->part.range.maxlength);
    1735           3 :                 p->part.range.minlength = op->part.range.minlength;
    1736           3 :                 p->part.range.maxlength = op->part.range.maxlength;
    1737           4 :         } else if (isListPartitionTable(mt)) {
    1738           4 :                 p->part.values = list_new(sa, (fdestroy) &part_value_destroy);
    1739          16 :                 for (node *n = op->part.values->h ; n ; n = n->next) {
    1740          12 :                         sql_part_value *prev = (sql_part_value*) n->data, *nextv = SA_ZNEW(sa, sql_part_value);
    1741          12 :                         nextv->value = SA_NEW_ARRAY(sa, char, prev->length);
    1742          12 :                         memcpy(nextv->value, prev->value, prev->length);
    1743          12 :                         nextv->length = prev->length;
    1744          12 :                         list_append(p->part.values, nextv);
    1745             :                 }
    1746             :         }
    1747           7 :         list_append(mt->members, p);
    1748           7 :         p->t = mt;
    1749           7 :         p->member = op->member;
    1750           7 :         assert(p->member);
    1751           7 :         return p;
    1752             : }
    1753             : 
    1754             : sql_table *
    1755        1600 : dup_sql_table(allocator *sa, sql_table *t)
    1756             : {
    1757        1600 :         node *n;
    1758        1600 :         sql_table *nt = create_sql_table_with_id(sa, t->base.id, t->base.name, t->type, t->system, SQL_DECLARED_TABLE, t->commit_action, t->properties);
    1759             : 
    1760        1600 :         nt->base.new = t->base.new;
    1761             : 
    1762        1600 :         nt->access = t->access;
    1763        1600 :         nt->query = (t->query) ? SA_STRDUP(sa, t->query) : NULL;
    1764        1600 :         nt->s = t->s;
    1765             : 
    1766        1600 :         if (isPartitionedByExpressionTable(nt)) {
    1767           7 :                 nt->part.pexp = SA_ZNEW(sa, sql_expression);
    1768           7 :                 nt->part.pexp->exp = SA_STRDUP(sa, t->part.pexp->exp);
    1769           7 :                 nt->part.pexp->type = t->part.pexp->type; /* No dup_sql_type call needed */
    1770           7 :                 nt->part.pexp->cols = SA_LIST(sa, (fdestroy) &int_destroy);
    1771          20 :                 for (n = t->part.pexp->cols->h; n; n = n->next) {
    1772          13 :                         int *nid = SA_NEW(sa, int);
    1773          13 :                         *nid = *(int *) n->data;
    1774          13 :                         list_append(nt->part.pexp->cols, nid);
    1775             :                 }
    1776             :         }
    1777             : 
    1778       26064 :         for (n = t->columns->l->h; n; n = n->next) {
    1779       24464 :                 sql_column *c = n->data;
    1780       24464 :                 sql_column *dup = dup_sql_column(sa, nt, c);
    1781       24464 :                 if (isPartitionedByColumnTable(nt) && c->base.id == t->part.pcol->base.id)
    1782          16 :                         nt->part.pcol = dup;
    1783             :         }
    1784             : 
    1785        1600 :         if (t->members)
    1786          37 :                 for (n = t->members->h; n; n = n->next)
    1787           7 :                         dup_sql_part(sa, nt, n->data);
    1788        1600 :         return nt;
    1789             : }
    1790             : 
    1791             : static sql_table *
    1792        6951 : bootstrap_create_table(sql_trans *tr, sql_schema *s, const char *name, sqlid id)
    1793             : {
    1794        6951 :         sqlstore *store = tr->store;
    1795        6951 :         int istmp = isTempSchema(s);
    1796        6951 :         int persistence = istmp?SQL_GLOBAL_TEMP:SQL_PERSIST;
    1797        4965 :         sht commit_action = istmp?CA_PRESERVE:CA_COMMIT;
    1798        6951 :         sql_table *t;
    1799             : 
    1800        6951 :         if (store->obj_id <= id)
    1801         993 :                 store->obj_id = id+1;
    1802        6951 :         t = create_sql_table_with_id(NULL, id, name, tt_table, 1, persistence, commit_action, 0);
    1803        6951 :         t->bootstrap = 1;
    1804             : 
    1805        6951 :         TRC_DEBUG(SQL_STORE, "Create table: %s\n", name);
    1806             : 
    1807        6951 :         t->base.new = s->base.new;
    1808        6951 :         t->query = NULL;
    1809        6951 :         t->s = s;
    1810        6951 :         if (isTable(t) && store->storage_api.create_del(tr, t) != LOG_OK) {
    1811           0 :                 table_destroy(store, t);
    1812           0 :                 return NULL;
    1813             :         }
    1814        6951 :         if (os_add(s->tables, tr, name, &t->base)) {
    1815           0 :                 table_destroy(store, t);
    1816           0 :                 return NULL;
    1817             :         }
    1818             :         return t;
    1819             : }
    1820             : 
    1821             : static sql_schema *
    1822         993 : bootstrap_create_schema(sql_trans *tr, const char *name, sqlid id, sqlid auth_id, int owner)
    1823             : {
    1824         993 :         sqlstore *store = tr->store;
    1825         993 :         sql_schema *s = ZNEW(sql_schema);
    1826             : 
    1827         993 :         if (store->obj_id <= id)
    1828         331 :                 store->obj_id = id+1;
    1829         993 :         TRC_DEBUG(SQL_STORE, "Create schema: %s %d %d\n", name, auth_id, owner);
    1830             : 
    1831         993 :         if (strcmp(name, dt_schema) == 0) {
    1832         331 :                 base_init(NULL, &s->base, (sqlid) FUNC_OIDS - 1, true, name);
    1833             :         } else {
    1834         662 :                 base_init(NULL, &s->base, id, true, name);
    1835             :         }
    1836         993 :         s->base.new = store->first;
    1837         993 :         s->auth_id = auth_id;
    1838         993 :         s->owner = owner;
    1839         993 :         s->system = TRUE;
    1840         993 :         s->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
    1841         993 :         s->types = os_new(NULL, (destroy_fptr) &type_destroy, false, true, true, false, store);
    1842         993 :         s->funcs = os_new(NULL, (destroy_fptr) &func_destroy, false, false, false, false, store);
    1843         993 :         s->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
    1844         993 :         s->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
    1845         993 :         s->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
    1846         993 :         s->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
    1847         993 :         s->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
    1848         993 :         if (os_add(tr->cat->schemas, tr, s->base.name, &s->base)) {
    1849             :                 return NULL;
    1850             :         }
    1851         993 :         if (isTempSchema(s))
    1852         331 :                 tr->tmp = s;
    1853             : 
    1854         993 :         s->store = tr->store;
    1855         993 :         return s;
    1856             : }
    1857             : 
    1858             : /* TODO clean this */
    1859             : static inline int
    1860       68259 : dep_hash(sql_dependency_change *dep)
    1861             : {
    1862       68259 :         return (int) BATatoms[TYPE_int].atomHash(&dep->objid);
    1863             : }
    1864             : 
    1865             : static void
    1866      174922 : dep_hash_clear(sql_hash *h)
    1867             : {
    1868      174922 :         if (h == NULL || h->sa || h->entries == 0)
    1869             :                 return;
    1870       24618 :         for (int i = 0; i < h->size; i++) {
    1871       23872 :                 sql_hash_e *e = h->buckets[i];
    1872             : 
    1873       25630 :                 while (e) {
    1874        1758 :                         sql_hash_e *next = e->chain;
    1875             : 
    1876        1758 :                         _DELETE(e->value);
    1877        1758 :                         _DELETE(e);
    1878        1758 :                         e = next;
    1879             :                 }
    1880       23872 :                 h->buckets[i] = NULL;
    1881             :         }
    1882         746 :         h->entries = 0;
    1883             : }
    1884             : 
    1885             : static void
    1886         662 : dep_hash_destroy(sql_hash *h)
    1887             : {
    1888         662 :         if (h == NULL || h->sa)
    1889             :                 return;
    1890       21780 :         for (int i = 0; i < h->size; i++) {
    1891       21120 :                 sql_hash_e *e = h->buckets[i];
    1892             : 
    1893       21120 :                 while (e) {
    1894           0 :                         sql_hash_e *next = e->chain;
    1895             : 
    1896           0 :                         _DELETE(e->value);
    1897           0 :                         _DELETE(e);
    1898           0 :                         e = next;
    1899             :                 }
    1900             :         }
    1901         660 :         _DELETE(h->buckets);
    1902         660 :         _DELETE(h);
    1903             : }
    1904             : 
    1905             : static sqlstore *
    1906         332 : store_load(sqlstore *store, allocator *pa)
    1907             : {
    1908         332 :         sql_trans *tr;
    1909         332 :         sql_table *t, *types, *functions, *arguments;
    1910         332 :         sql_schema *s;
    1911         332 :         lng lng_store_oid;
    1912             : 
    1913         332 :         assert(pa);
    1914         332 :         store->sa = pa;
    1915             : 
    1916         332 :         store->first = store->logger_api.log_isnew(store);
    1917             : 
    1918         332 :         if (store->first && store->readonly) {
    1919             :                 /* cannot initialize database in readonly mode */
    1920           1 :                 TRC_CRITICAL(SQL_STORE, "Cannot initialize store in readonly mode\n");
    1921           1 :                 return NULL;
    1922             :         }
    1923             : 
    1924         331 :         types_init(store->sa); /* initialize global lists of types and functions, TODO: needs to move */
    1925             : 
    1926             :         /* we store some spare oids */
    1927         331 :         store->obj_id = FUNC_OIDS;
    1928             : 
    1929         331 :         tr = sql_trans_create(store, NULL, NULL);
    1930         331 :         if (!tr) {
    1931           0 :                 TRC_CRITICAL(SQL_STORE, "Failed to start a transaction while loading the storage\n");
    1932           0 :                 return NULL;
    1933             :         }
    1934         331 :         tr->store = store;
    1935         331 :         tr->active = 1;
    1936             : 
    1937             :         /* for now use malloc and free */
    1938         331 :         store->active = list_create(NULL);
    1939         331 :         store->dependencies = hash_new(NULL, 32, (fkeyvalue)&dep_hash);
    1940         331 :         store->depchanges = hash_new(NULL, 32, (fkeyvalue)&dep_hash);
    1941         331 :         store->sequences = hash_new(NULL, 32, (fkeyvalue)&seq_hash);
    1942         331 :         store->seqchanges = list_create(NULL);
    1943         331 :         if (!store->active || !store->dependencies || !store->depchanges || !store->sequences || !store->seqchanges) {
    1944           0 :                 goto critical;
    1945             :         }
    1946             : 
    1947         331 :         s = bootstrap_create_schema(tr, "sys", 2000, ROLE_SYSADMIN, USER_MONETDB);
    1948         331 :         if (s == NULL) {
    1949           0 :                 goto critical;
    1950             :         }
    1951         331 :         if (!store->first)
    1952         106 :                 s->base.new = 0;
    1953             : 
    1954         662 :         if ((t = bootstrap_create_table(tr, s, "schemas", 2001)) == NULL ||
    1955         662 :                 bootstrap_create_column(tr, t, "id", 2002, "int", 31) == NULL ||
    1956         662 :                 bootstrap_create_column(tr, t, "name", 2003, "varchar", 1024) == NULL ||
    1957         662 :                 bootstrap_create_column(tr, t, "authorization", 2004, "int", 31) == NULL ||
    1958         662 :                 bootstrap_create_column(tr, t, "owner", 2005, "int", 31) == NULL ||
    1959         331 :                 bootstrap_create_column(tr, t, "system", 2006, "boolean", 1) == NULL ||
    1960             : 
    1961         662 :                 (types = t = bootstrap_create_table(tr, s, "types", 2007)) == NULL ||
    1962         662 :                 bootstrap_create_column(tr, t, "id", 2008, "int", 31) == NULL ||
    1963         662 :                 bootstrap_create_column(tr, t, "systemname", 2009, "varchar", 256) == NULL ||
    1964         662 :                 bootstrap_create_column(tr, t, "sqlname", 2010, "varchar", 1024) == NULL ||
    1965         662 :                 bootstrap_create_column(tr, t, "digits", 2011, "int", 31) == NULL ||
    1966         662 :                 bootstrap_create_column(tr, t, "scale", 2012, "int", 31) == NULL ||
    1967         662 :                 bootstrap_create_column(tr, t, "radix", 2013, "int", 31) == NULL ||
    1968         662 :                 bootstrap_create_column(tr, t, "eclass", 2014, "int", 31) == NULL ||
    1969         331 :                 bootstrap_create_column(tr, t, "schema_id", 2015, "int", 31) == NULL ||
    1970             : 
    1971         662 :                 (functions = t = bootstrap_create_table(tr, s, "functions", 2016)) == NULL ||
    1972         662 :                 bootstrap_create_column(tr, t, "id", 2017, "int", 31) == NULL ||
    1973         662 :                 bootstrap_create_column(tr, t, "name", 2018, "varchar", 256) == NULL ||
    1974         662 :                 bootstrap_create_column(tr, t, "func", 2019, "varchar", 8196) == NULL ||
    1975         662 :                 bootstrap_create_column(tr, t, "mod", 2020, "varchar", 8196) == NULL ||
    1976             : 
    1977             :                 /* language asm=0, sql=1, R=2, C=3, J=4 */
    1978         662 :                 bootstrap_create_column(tr, t, "language", 2021, "int", 31) == NULL ||
    1979             : 
    1980             :                 /* func, proc, aggr or filter */
    1981         662 :                 bootstrap_create_column(tr, t, "type", 2022, "int", 31) == NULL ||
    1982         662 :                 bootstrap_create_column(tr, t, "side_effect", 2023, "boolean", 1) == NULL ||
    1983         662 :                 bootstrap_create_column(tr, t, "varres", 2024, "boolean", 1) == NULL ||
    1984         662 :                 bootstrap_create_column(tr, t, "vararg", 2025, "boolean", 1) == NULL ||
    1985         662 :                 bootstrap_create_column(tr, t, "schema_id", 2026, "int", 31) == NULL ||
    1986         662 :                 bootstrap_create_column(tr, t, "system", 2027, "boolean", 1) == NULL ||
    1987         331 :                 bootstrap_create_column(tr, t, "semantics", 2162, "boolean", 1) == NULL ||
    1988             : 
    1989         662 :                 (arguments = t = bootstrap_create_table(tr, s, "args", 2028)) == NULL ||
    1990         662 :                 bootstrap_create_column(tr, t, "id", 2029, "int", 31) == NULL ||
    1991         662 :                 bootstrap_create_column(tr, t, "func_id", 2030, "int", 31) == NULL ||
    1992         662 :                 bootstrap_create_column(tr, t, "name", 2031, "varchar", 256) == NULL ||
    1993         662 :                 bootstrap_create_column(tr, t, "type", 2032, "varchar", 1024) == NULL ||
    1994         662 :                 bootstrap_create_column(tr, t, "type_digits", 2033, "int", 31) == NULL ||
    1995         662 :                 bootstrap_create_column(tr, t, "type_scale", 2034, "int", 31) == NULL ||
    1996         662 :                 bootstrap_create_column(tr, t, "inout", 2035, "tinyint", 7) == NULL ||
    1997         331 :                 bootstrap_create_column(tr, t, "number", 2036, "int", 31) == NULL ||
    1998             : 
    1999         662 :                 (t = bootstrap_create_table(tr, s, "sequences", 2037)) == NULL ||
    2000         662 :                 bootstrap_create_column(tr, t, "id", 2038, "int", 31) == NULL ||
    2001         662 :                 bootstrap_create_column(tr, t, "schema_id", 2039, "int", 31) == NULL ||
    2002         662 :                 bootstrap_create_column(tr, t, "name", 2040, "varchar", 256) == NULL ||
    2003         662 :                 bootstrap_create_column(tr, t, "start", 2041, "bigint", 63) == NULL ||
    2004         662 :                 bootstrap_create_column(tr, t, "minvalue", 2042, "bigint", 63) == NULL ||
    2005         662 :                 bootstrap_create_column(tr, t, "maxvalue", 2043, "bigint", 63) == NULL ||
    2006         662 :                 bootstrap_create_column(tr, t, "increment", 2044, "bigint", 63) == NULL ||
    2007         662 :                 bootstrap_create_column(tr, t, "cacheinc", 2045, "bigint", 63) == NULL ||
    2008         331 :                 bootstrap_create_column(tr, t, "cycle", 2046, "boolean", 1) == NULL ||
    2009             : 
    2010         662 :                 (t = bootstrap_create_table(tr, s, "table_partitions", 2047)) == NULL ||
    2011         662 :                 bootstrap_create_column(tr, t, "id", 2048, "int", 31) == NULL ||
    2012         662 :                 bootstrap_create_column(tr, t, "table_id", 2049, "int", 31) == NULL ||
    2013         662 :                 bootstrap_create_column(tr, t, "column_id", 2050, "int", 31) == NULL ||
    2014         662 :                 bootstrap_create_column(tr, t, "expression", 2051, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
    2015         331 :                 bootstrap_create_column(tr, t, "type", 2052, "tinyint", 7) == NULL ||
    2016             : 
    2017         662 :                 (t = bootstrap_create_table(tr, s, "range_partitions", 2053)) == NULL ||
    2018         662 :                 bootstrap_create_column(tr, t, "table_id", 2054, "int", 31) == NULL ||
    2019         662 :                 bootstrap_create_column(tr, t, "partition_id", 2055, "int", 31) == NULL ||
    2020         662 :                 bootstrap_create_column(tr, t, "minimum", 2056, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
    2021         662 :                 bootstrap_create_column(tr, t, "maximum", 2057, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
    2022         331 :                 bootstrap_create_column(tr, t, "with_nulls", 2058, "boolean", 1) == NULL ||
    2023             : 
    2024         662 :                 (t = bootstrap_create_table(tr, s, "value_partitions", 2059)) == NULL ||
    2025         662 :                 bootstrap_create_column(tr, t, "table_id", 2060, "int", 31) == NULL ||
    2026         662 :                 bootstrap_create_column(tr, t, "partition_id", 2061, "int", 31) == NULL ||
    2027         331 :                 bootstrap_create_column(tr, t, "value", 2062, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
    2028             : 
    2029         662 :                 (t = bootstrap_create_table(tr, s, "dependencies", 2063)) == NULL ||
    2030         662 :                 bootstrap_create_column(tr, t, "id", 2064, "int", 31) == NULL ||
    2031         662 :                 bootstrap_create_column(tr, t, "depend_id", 2065, "int", 31) == NULL ||
    2032         331 :                 bootstrap_create_column(tr, t, "depend_type", 2066, "smallint", 15) == NULL ||
    2033             : 
    2034             : 
    2035         662 :                 (t = bootstrap_create_table(tr, s, "_tables", 2067)) == NULL ||
    2036         662 :                 bootstrap_create_column(tr, t, "id", 2068, "int", 31) == NULL ||
    2037         662 :                 bootstrap_create_column(tr, t, "name", 2069, "varchar", 1024) == NULL ||
    2038         662 :                 bootstrap_create_column(tr, t, "schema_id", 2070, "int", 31) == NULL ||
    2039         662 :                 bootstrap_create_column(tr, t, "query", 2071, "varchar", 1 << 20) == NULL||
    2040         662 :                 bootstrap_create_column(tr, t, "type", 2072, "smallint", 15) == NULL ||
    2041         662 :                 bootstrap_create_column(tr, t, "system", 2073, "boolean", 1) == NULL ||
    2042         662 :                 bootstrap_create_column(tr, t, "commit_action", 2074, "smallint", 15) == NULL ||
    2043         331 :                 bootstrap_create_column(tr, t, "access", 2075, "smallint", 15) == NULL ||
    2044             : 
    2045         662 :                 (t = bootstrap_create_table(tr, s, "_columns", 2076)) == NULL ||
    2046         662 :                 bootstrap_create_column(tr, t, "id", 2077, "int", 31) == NULL ||
    2047         662 :                 bootstrap_create_column(tr, t, "name", 2078, "varchar", 1024) == NULL ||
    2048         662 :                 bootstrap_create_column(tr, t, "type", 2079, "varchar", 1024) == NULL ||
    2049         662 :                 bootstrap_create_column(tr, t, "type_digits", 2080, "int", 31) == NULL ||
    2050         662 :                 bootstrap_create_column(tr, t, "type_scale", 2081, "int", 31) == NULL ||
    2051         662 :                 bootstrap_create_column(tr, t, "table_id", 2082, "int", 31) == NULL ||
    2052         662 :                 bootstrap_create_column(tr, t, "default", 2083, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
    2053         662 :                 bootstrap_create_column(tr, t, "null", 2084, "boolean", 1) == NULL ||
    2054         662 :                 bootstrap_create_column(tr, t, "number", 2085, "int", 31) == NULL ||
    2055         331 :                 bootstrap_create_column(tr, t, "storage", 2086, "varchar", 2048) == NULL ||
    2056             : 
    2057         662 :                 (t = bootstrap_create_table(tr, s, "keys", 2087)) == NULL ||
    2058         662 :                 bootstrap_create_column(tr, t, "id", 2088, "int", 31) == NULL ||
    2059         662 :                 bootstrap_create_column(tr, t, "table_id", 2089, "int", 31) == NULL ||
    2060         662 :                 bootstrap_create_column(tr, t, "type", 2090, "int", 31) == NULL ||
    2061         662 :                 bootstrap_create_column(tr, t, "name", 2091, "varchar", 1024) == NULL ||
    2062         662 :                 bootstrap_create_column(tr, t, "rkey", 2092, "int", 31) == NULL ||
    2063         662 :                 bootstrap_create_column(tr, t, "action", 2093, "int", 31) == NULL ||
    2064         331 :                 bootstrap_create_column(tr, t, "check", 2165, "varchar", 2048) == NULL ||
    2065             : 
    2066         662 :                 (t = bootstrap_create_table(tr, s, "idxs", 2094)) == NULL ||
    2067         662 :                 bootstrap_create_column(tr, t, "id", 2095, "int", 31) == NULL ||
    2068         662 :                 bootstrap_create_column(tr, t, "table_id", 2096, "int", 31) == NULL ||
    2069         662 :                 bootstrap_create_column(tr, t, "type", 2097, "int", 31) == NULL ||
    2070         331 :                 bootstrap_create_column(tr, t, "name", 2098, "varchar", 1024) == NULL ||
    2071             : 
    2072         662 :                 (t = bootstrap_create_table(tr, s, "triggers", 2099)) == NULL ||
    2073         662 :                 bootstrap_create_column(tr, t, "id", 2100, "int", 31) == NULL ||
    2074         662 :                 bootstrap_create_column(tr, t, "name", 2101, "varchar", 1024) == NULL ||
    2075         662 :                 bootstrap_create_column(tr, t, "table_id", 2102, "int", 31) == NULL ||
    2076         662 :                 bootstrap_create_column(tr, t, "time", 2103, "smallint", 15) == NULL ||
    2077         662 :                 bootstrap_create_column(tr, t, "orientation", 2104, "smallint", 15) == NULL ||
    2078         662 :                 bootstrap_create_column(tr, t, "event", 2105, "smallint", 15) == NULL ||
    2079         662 :                 bootstrap_create_column(tr, t, "old_name", 2106, "varchar", 1024) == NULL ||
    2080         662 :                 bootstrap_create_column(tr, t, "new_name", 2107, "varchar", 1024) == NULL ||
    2081         662 :                 bootstrap_create_column(tr, t, "condition", 2108, "varchar", 2048) == NULL ||
    2082         331 :                 bootstrap_create_column(tr, t, "statement", 2109, "varchar", 2048) == NULL ||
    2083             : 
    2084         662 :                 (t = bootstrap_create_table(tr, s, "objects", 2110)) == NULL ||
    2085         662 :                 bootstrap_create_column(tr, t, "id", 2111, "int", 31) == NULL ||
    2086         662 :                 bootstrap_create_column(tr, t, "name", 2112, "varchar", 1024) == NULL ||
    2087         662 :                 bootstrap_create_column(tr, t, "nr", 2113, "int", 31) == NULL ||
    2088         331 :                 bootstrap_create_column(tr, t, "sub", 2163, "int", 31) == NULL) {
    2089           0 :                 goto critical;
    2090             :         }
    2091             : 
    2092         331 :         if ((s = bootstrap_create_schema(tr, "tmp", 2114, ROLE_SYSADMIN, USER_MONETDB)) == NULL) {
    2093           0 :                 goto critical;
    2094             :         }
    2095         331 :         store->tmp = s;
    2096             : 
    2097         662 :         if ((t = bootstrap_create_table(tr, s, "_tables", 2115)) == NULL ||
    2098         662 :                 bootstrap_create_column(tr, t, "id", 2116, "int", 31) == NULL ||
    2099         662 :                 bootstrap_create_column(tr, t, "name", 2117, "varchar", 1024) == NULL ||
    2100         662 :                 bootstrap_create_column(tr, t, "schema_id", 2118, "int", 31) == NULL ||
    2101         662 :                 bootstrap_create_column(tr, t, "query", 2119, "varchar", 1 << 20) == NULL ||
    2102         662 :                 bootstrap_create_column(tr, t, "type", 2120, "smallint", 15) == NULL ||
    2103         662 :                 bootstrap_create_column(tr, t, "system", 2121, "boolean", 1) == NULL ||
    2104         662 :                 bootstrap_create_column(tr, t, "commit_action", 2122, "smallint", 15) == NULL ||
    2105         331 :                 bootstrap_create_column(tr, t, "access", 2123, "smallint", 15) == NULL ||
    2106             : 
    2107         662 :                 (t = bootstrap_create_table(tr, s, "_columns", 2124)) == NULL ||
    2108         662 :                 bootstrap_create_column(tr, t, "id", 2125, "int", 31) == NULL ||
    2109         662 :                 bootstrap_create_column(tr, t, "name", 2126, "varchar", 1024) == NULL ||
    2110         662 :                 bootstrap_create_column(tr, t, "type", 2127, "varchar", 1024) == NULL ||
    2111         662 :                 bootstrap_create_column(tr, t, "type_digits", 2128, "int", 31) == NULL ||
    2112         662 :                 bootstrap_create_column(tr, t, "type_scale", 2129, "int", 31) == NULL ||
    2113         662 :                 bootstrap_create_column(tr, t, "table_id", 2130, "int", 31) == NULL ||
    2114         662 :                 bootstrap_create_column(tr, t, "default", 2131, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
    2115         662 :                 bootstrap_create_column(tr, t, "null", 2132, "boolean", 1) == NULL ||
    2116         662 :                 bootstrap_create_column(tr, t, "number", 2133, "int", 31) == NULL ||
    2117         331 :                 bootstrap_create_column(tr, t, "storage", 2134, "varchar", 2048) == NULL ||
    2118             : 
    2119         662 :                 (t = bootstrap_create_table(tr, s, "keys", 2135)) == NULL ||
    2120         662 :                 bootstrap_create_column(tr, t, "id", 2136, "int", 31) == NULL ||
    2121         662 :                 bootstrap_create_column(tr, t, "table_id", 2137, "int", 31) == NULL ||
    2122         662 :                 bootstrap_create_column(tr, t, "type", 2138, "int", 31) == NULL ||
    2123         662 :                 bootstrap_create_column(tr, t, "name", 2139, "varchar", 1024) == NULL ||
    2124         662 :                 bootstrap_create_column(tr, t, "rkey", 2140, "int", 31) == NULL ||
    2125         662 :                 bootstrap_create_column(tr, t, "action", 2141, "int", 31) == NULL ||
    2126         331 :                 bootstrap_create_column(tr, t, "check", 2166, "varchar", 2048) == NULL ||
    2127             : 
    2128         662 :                 (t = bootstrap_create_table(tr, s, "idxs", 2142)) == NULL ||
    2129         662 :                 bootstrap_create_column(tr, t, "id", 2143, "int", 31) == NULL ||
    2130         662 :                 bootstrap_create_column(tr, t, "table_id", 2144, "int", 31) == NULL ||
    2131         662 :                 bootstrap_create_column(tr, t, "type", 2145, "int", 31) == NULL ||
    2132         331 :                 bootstrap_create_column(tr, t, "name", 2146, "varchar", 1024) == NULL ||
    2133             : 
    2134         662 :                 (t = bootstrap_create_table(tr, s, "triggers", 2147)) == NULL ||
    2135         662 :                 bootstrap_create_column(tr, t, "id", 2148, "int", 31) == NULL ||
    2136         662 :                 bootstrap_create_column(tr, t, "name", 2149, "varchar", 1024) == NULL ||
    2137         662 :                 bootstrap_create_column(tr, t, "table_id", 2150, "int", 31) == NULL ||
    2138         662 :                 bootstrap_create_column(tr, t, "time", 2151, "smallint", 15) == NULL ||
    2139         662 :                 bootstrap_create_column(tr, t, "orientation", 2152, "smallint", 15) == NULL ||
    2140         662 :                 bootstrap_create_column(tr, t, "event", 2153, "smallint", 15) == NULL ||
    2141         662 :                 bootstrap_create_column(tr, t, "old_name", 2154, "varchar", 1024) == NULL ||
    2142         662 :                 bootstrap_create_column(tr, t, "new_name", 2155, "varchar", 1024) == NULL ||
    2143         662 :                 bootstrap_create_column(tr, t, "condition", 2156, "varchar", 2048) == NULL ||
    2144         331 :                 bootstrap_create_column(tr, t, "statement", 2157, "varchar", 2048) == NULL ||
    2145             : 
    2146         662 :                 (t = bootstrap_create_table(tr, s, "objects", 2158)) == NULL ||
    2147         662 :                 bootstrap_create_column(tr, t, "id", 2159, "int", 31) == NULL ||
    2148         662 :                 bootstrap_create_column(tr, t, "name", 2160, "varchar", 1024) == NULL ||
    2149         662 :                 bootstrap_create_column(tr, t, "nr", 2161, "int", 31) == NULL ||
    2150         331 :                 bootstrap_create_column(tr, t, "sub", 2164, "int", 31) == NULL) {
    2151           0 :                 goto critical;
    2152             :         }
    2153             : 
    2154         331 :         if (bootstrap_create_schema(tr, dt_schema, -1, ROLE_SYSADMIN, USER_MONETDB) == NULL) {
    2155           0 :                 goto critical;
    2156             :         }
    2157             : 
    2158         331 :         if (store->first) {
    2159         225 :                 if (insert_types(tr, types) || insert_functions(tr, functions, funcs, arguments) || insert_schemas(tr)) {
    2160           0 :                         TRC_CRITICAL(SQL_STORE, "Cannot load catalog\n");
    2161           0 :                         sql_trans_destroy(tr);
    2162           0 :                         return NULL;
    2163             :                 }
    2164             :         } else {
    2165         106 :                 tr->active = 0;
    2166             :         }
    2167             : 
    2168         331 :         if (sql_trans_commit(tr) != SQL_OK) {
    2169           0 :                 TRC_CRITICAL(SQL_STORE, "Cannot commit initial transaction\n");
    2170           0 :                 sql_trans_destroy(tr);
    2171           0 :                 return NULL;
    2172             :         }
    2173         331 :         tr->ts = store_timestamp(store);
    2174             : 
    2175         331 :         store->logger_api.get_sequence(store, OBJ_SID, &lng_store_oid);
    2176         331 :         store->prev_oid = (sqlid)lng_store_oid;
    2177         331 :         if (store->obj_id < store->prev_oid)
    2178         106 :                 store->obj_id = store->prev_oid;
    2179             : 
    2180             :         /* load remaining schemas, tables, columns etc */
    2181         331 :         tr->active = 1;
    2182         331 :         if (!store->first && !load_trans(tr)) {
    2183           0 :                 TRC_CRITICAL(SQL_STORE, "Cannot load catalog tables\n");
    2184           0 :                 sql_trans_destroy(tr);
    2185           0 :                 return NULL;
    2186             :         }
    2187         331 :         if (sql_trans_commit(tr) != SQL_OK) {
    2188           0 :                 TRC_CRITICAL(SQL_STORE, "Cannot commit loaded objects transaction\n");
    2189           0 :                 sql_trans_destroy(tr);
    2190           0 :                 return NULL;
    2191             :         }
    2192         331 :         tr->active = 0;
    2193         331 :         sql_trans_destroy(tr);
    2194         331 :         store->initialized = 1;
    2195         331 :         return store;
    2196             : 
    2197           0 :   critical:
    2198           0 :         TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
    2199           0 :         sql_trans_destroy(tr);
    2200           0 :         return NULL;
    2201             : }
    2202             : 
    2203             : sqlstore *
    2204         332 : store_init(int debug, store_type store_tpe, int readonly, int singleuser)
    2205             : {
    2206         332 :         allocator *pa;
    2207         332 :         sqlstore *store = MNEW(sqlstore);
    2208             : 
    2209         332 :         if (debug&2)
    2210           0 :                 GDKtracer_set_layer_level("sql_all", "debug");
    2211             : 
    2212         332 :         if (!store) {
    2213           0 :                 TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
    2214           0 :                 return NULL;
    2215             :         }
    2216             : 
    2217         332 :         if (!(pa = sa_create(NULL))) {
    2218           0 :                 TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
    2219           0 :                 _DELETE(store);
    2220           0 :                 return NULL;
    2221             :         }
    2222             : 
    2223         332 :         *store = (sqlstore) {
    2224             :                 .readonly = readonly,
    2225             :                 .singleuser = singleuser,
    2226             :                 .debug = debug,
    2227             :                 .transaction = ATOMIC_VAR_INIT(TRANSACTION_ID_BASE),
    2228             :                 .nr_active = ATOMIC_VAR_INIT(0),
    2229             :                 .timestamp = ATOMIC_VAR_INIT(0),
    2230             :                 .lastactive = ATOMIC_VAR_INIT(0),
    2231             :                 .function_counter = ATOMIC_VAR_INIT(0),
    2232             :                 .oldest = ATOMIC_VAR_INIT(0),
    2233             :                 .sa = pa,
    2234             :         };
    2235             : 
    2236         332 :         (void)store_timestamp(store); /* increment once */
    2237         332 :         MT_lock_init(&store->lock, "sqlstore_lock");
    2238         332 :         MT_lock_init(&store->commit, "sqlstore_commit");
    2239         332 :         MT_lock_init(&store->flush, "sqlstore_flush");
    2240       21580 :         for(int i = 0; i<NR_TABLE_LOCKS; i++)
    2241       21248 :                 MT_lock_init(&store->table_locks[i], "sqlstore_table");
    2242      170316 :         for(int i = 0; i<NR_COLUMN_LOCKS; i++)
    2243      169984 :                 MT_lock_init(&store->column_locks[i], "sqlstore_column");
    2244             : 
    2245         332 :         MT_lock_set(&store->flush);
    2246         332 :         MT_lock_set(&store->lock);
    2247             : 
    2248             :         /* initialize empty bats */
    2249         332 :         switch (store_tpe) {
    2250         332 :         case store_bat:
    2251             :         case store_mem:
    2252         332 :                 if (bat_utils_init() == -1) {
    2253           0 :                         TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
    2254           0 :                         MT_lock_unset(&store->lock);
    2255           0 :                         MT_lock_unset(&store->flush);
    2256           0 :                         store_exit(store);
    2257           0 :                         return NULL;
    2258             :                 }
    2259         332 :                 bat_storage_init(&store->storage_api);
    2260         332 :                 bat_table_init(&store->table_api);
    2261         332 :                 bat_logger_init(&store->logger_api);
    2262         332 :                 break;
    2263             :         default:
    2264             :                 break;
    2265             :         }
    2266         332 :         store->active_type = store_tpe;
    2267         332 :         int v = 1;
    2268         664 :         if (!store->logger_api.create ||
    2269         332 :             store->logger_api.create(store, debug, "sql_logs", CATALOG_VERSION*v) != LOG_OK) {
    2270           0 :                 MT_lock_unset(&store->lock);
    2271           0 :                 MT_lock_unset(&store->flush);
    2272           0 :                 store_exit(store);
    2273           0 :                 return NULL;
    2274             :         }
    2275             : 
    2276             :         /* create the initial store structure or re-load previous data */
    2277         332 :         MT_lock_unset(&store->lock);
    2278         332 :         MT_lock_unset(&store->flush);
    2279         332 :         if (!store_load(store, pa)) {
    2280             :                 /* zap current change list */
    2281           1 :                 store->changes = NULL;
    2282           1 :                 store_exit(store);
    2283           1 :                 return NULL;
    2284             :         }
    2285             :         return store;
    2286             : }
    2287             : 
    2288             : void
    2289         331 : store_exit(sqlstore *store)
    2290             : {
    2291         331 :         allocator *sa = store->sa;
    2292         331 :         MT_lock_set(&store->commit);
    2293         331 :         MT_lock_set(&store->flush);
    2294         331 :         MT_lock_set(&store->lock);
    2295             : 
    2296         331 :         TRC_DEBUG(SQL_STORE, "Store locked\n");
    2297             : 
    2298         331 :         if (store->cat) {
    2299         330 :                 while (ATOMIC_GET(&store->nr_active) > 0) {
    2300           0 :                         const int sleeptime = 100;
    2301           0 :                         MT_lock_unset(&store->flush);
    2302           0 :                         MT_lock_unset(&store->lock);
    2303           0 :                         MT_lock_unset(&store->commit);
    2304           0 :                         MT_sleep_ms(sleeptime);
    2305           0 :                         MT_lock_set(&store->commit);
    2306           0 :                         MT_lock_set(&store->lock);
    2307         330 :                         MT_lock_set(&store->flush);
    2308             :                 }
    2309         330 :                 if (!list_empty(store->changes)) {
    2310          32 :                         ulng oldest = store_timestamp(store)+1;
    2311          89 :                         for(node *n=store->changes->h; n; n = n->next) {
    2312          57 :                                 sql_change *c = n->data;
    2313             : 
    2314          57 :                                 if (c->cleanup && !c->cleanup(store, c, oldest)) {
    2315             :                                         /* try again with newer oldest, should cleanup any pending issues */
    2316           0 :                                         if (!c->cleanup(store, c, oldest+1))
    2317           0 :                                                 TRC_DEBUG(SQL_STORE, "not deleted\n");
    2318             :                                         else
    2319           0 :                                                 _DELETE(c);
    2320             :                                 } else
    2321          57 :                                         _DELETE(c);
    2322             :                         }
    2323             :                 }
    2324         330 :                 MT_lock_unset(&store->commit);
    2325         330 :                 list_destroy(store->changes);
    2326         330 :                 os_destroy(store->cat->objects, store);
    2327         330 :                 os_destroy(store->cat->schemas, store);
    2328         330 :                 _DELETE(store->cat);
    2329             :         } else {
    2330           1 :                 MT_lock_unset(&store->commit);
    2331             :         }
    2332         331 :         store->logger_api.destroy(store);
    2333             : 
    2334         331 :         list_destroy(store->active);
    2335         331 :         dep_hash_destroy(store->dependencies);
    2336         331 :         dep_hash_destroy(store->depchanges);
    2337         331 :         list_destroy(store->seqchanges);
    2338         331 :         seq_hash_destroy(store->sequences);
    2339             : 
    2340         331 :         TRC_DEBUG(SQL_STORE, "Store unlocked\n");
    2341         331 :         MT_lock_unset(&store->flush);
    2342         331 :         MT_lock_unset(&store->lock);
    2343         331 :         sa_destroy(sa);
    2344         331 :         MT_lock_destroy(&store->lock);
    2345         331 :         MT_lock_destroy(&store->commit);
    2346         331 :         MT_lock_destroy(&store->flush);
    2347       21515 :         for(int i = 0; i<NR_TABLE_LOCKS; i++)
    2348       21184 :                 MT_lock_destroy(&store->table_locks[i]);
    2349      169803 :         for(int i = 0; i<NR_COLUMN_LOCKS; i++)
    2350      169472 :                 MT_lock_destroy(&store->column_locks[i]);
    2351         331 :         _DELETE(store);
    2352         331 : }
    2353             : 
    2354             : /* call locked! */
    2355             : static int
    2356        2833 : store_apply_deltas(sqlstore *store)
    2357             : {
    2358        2833 :         int res = LOG_OK;
    2359             : 
    2360        2833 :         store_lock(store);
    2361        2833 :         ulng oldest = store_oldest_pending(store);
    2362        2833 :         store_unlock(store);
    2363        2833 :         TRC_DEBUG(SQL_STORE, "Store apply deltas (" ULLFMT ")\n", oldest-1);
    2364        2833 :         if (oldest)
    2365        2833 :             res = store->logger_api.flush(store, oldest-1);
    2366        2833 :         return res;
    2367             : }
    2368             : 
    2369             : void
    2370           0 : store_suspend_log(sqlstore *store)
    2371             : {
    2372           0 :         MT_lock_set(&store->lock);
    2373           0 :         MT_lock_unset(&store->lock);
    2374           0 : }
    2375             : 
    2376             : void
    2377           0 : store_resume_log(sqlstore *store)
    2378             : {
    2379           0 :         MT_lock_set(&store->flush);
    2380           0 :         MT_lock_unset(&store->flush);
    2381           0 : }
    2382             : 
    2383             : static void
    2384      149704 : id_hash_clear_older(sql_hash *h, ulng oldest)
    2385             : {
    2386      149704 :         if (h->entries == 0)
    2387             :                 return;
    2388     1408704 :         for (int i = 0; i < h->size; i++) {
    2389     1366016 :                 sql_hash_e *e = h->buckets[i], *last = NULL, *first = NULL;
    2390             : 
    2391     1911203 :                 while (e) {
    2392      545187 :                         sql_hash_e *next = e->chain;
    2393      545187 :                         sql_dependency_change *dc = e->value;
    2394             : 
    2395      545187 :                         if (dc->ts < oldest) {
    2396       40884 :                                 _DELETE(e->value);
    2397       40884 :                                 _DELETE(e);
    2398       40884 :                                 h->entries--;
    2399             :                         } else {
    2400      504303 :                                 if (last)
    2401      280080 :                                         last->chain = e;
    2402             :                                 else
    2403             :                                         first = e;
    2404             :                                 last = e;
    2405             :                         }
    2406             :                         e = next;
    2407             :                 }
    2408     1366016 :                 if (last)
    2409      224223 :                         last->chain = NULL;
    2410     1366016 :                 h->buckets[i] = first;
    2411             :         }
    2412             : }
    2413             : 
    2414             : static void
    2415      162313 : store_pending_changes(sqlstore *store, ulng oldest, sql_trans *tr)
    2416             : {
    2417      162313 :         ulng oldest_changes = store_get_timestamp(store);
    2418      162313 :         if (!list_empty(store->changes)) { /* lets first cleanup old stuff */
    2419     1026009 :                 for(node *n=store->changes->h; n; ) {
    2420      975408 :                         node *next = n->next;
    2421      975408 :                         sql_change *c = n->data;
    2422             : 
    2423      975408 :                         assert(c->cleanup);
    2424      975408 :                         if (c->cleanup(store, c, oldest)) {
    2425      181139 :                                 list_remove_node(store->changes, store, n);
    2426      181139 :                                 _DELETE(c);
    2427      794269 :                         } else if (!c->handled && c->ts < oldest_changes) {
    2428      975408 :                                 oldest_changes = c->ts;
    2429             :                         }
    2430             :                         n = next;
    2431             :                 }
    2432             :         }
    2433      162313 :         if (ATOMIC_GET(&store->nr_active) < 2) { /* one or no transaction running */
    2434       87461 :                 dep_hash_clear(store->dependencies);
    2435       87461 :                 dep_hash_clear(store->depchanges);
    2436             :         } else {
    2437       74852 :                 ulng stoldest = store_oldest(store, tr);
    2438       74852 :                 id_hash_clear_older(store->dependencies, stoldest);
    2439       74852 :                 id_hash_clear_older(store->depchanges, stoldest);
    2440             :         }
    2441      162313 :         store->oldest_pending = oldest_changes;
    2442      162313 : }
    2443             : 
    2444             : #define IDLE_TIME       30                      /* in seconds */
    2445             : 
    2446             : void
    2447         330 : store_manager(sqlstore *store)
    2448             : {
    2449         330 :         MT_thread_setworking("sleeping");
    2450             : 
    2451             :         // In the main loop we always hold the lock except when sleeping or doing cleanups
    2452         330 :         MT_lock_set(&store->flush);
    2453             : 
    2454       16781 :         for (;;) {
    2455       16781 :                 const int idle = ATOMIC_GET(&GDKdebug) & TESTINGMASK ? 5000 : IDLE_TIME * 1000000;
    2456             :                 /* if debug bit 1024 is set, attempt immediate log activation
    2457             :                  * and clear the bit */
    2458       16781 :                 if (store->debug&(128|1024) || ATOMIC_GET(&store->lastactive) + idle < (ATOMIC_BASE_TYPE) GDKusec()) {
    2459       13994 :                         store->debug &= ~1024;
    2460       13994 :                         MT_lock_unset(&store->flush);
    2461       13994 :                         store_lock(store);
    2462       13994 :                         if (ATOMIC_GET(&store->nr_active) == 0) {
    2463        4724 :                                 ulng oldest = store_timestamp(store)+1;
    2464        4724 :                                 store_pending_changes(store, oldest, NULL);
    2465             :                         }
    2466       13994 :                         store_unlock(store);
    2467       13994 :                         MT_lock_set(&store->flush);
    2468       13994 :                         store->logger_api.activate(store); /* rotate to new log file */
    2469       13994 :                         ATOMIC_SET(&store->lastactive, GDKusec());
    2470             :                 }
    2471             : 
    2472       16781 :                 if (GDKexiting())
    2473             :                         break;
    2474       16781 :                 const int sleeptime = 100;
    2475       16781 :                 MT_lock_unset(&store->flush);
    2476       16781 :                 MT_sleep_ms(sleeptime);
    2477       16800 :                 for (;;) {
    2478       16790 :                         MT_lock_set(&store->commit);
    2479       16790 :                         if (MT_lock_try(&store->flush))
    2480             :                                 break;
    2481          10 :                         MT_lock_unset(&store->commit);
    2482          10 :                         MT_sleep_ms(sleeptime);
    2483             :                 }
    2484             : 
    2485       16780 :                 if (GDKexiting()) {
    2486         329 :                         MT_lock_unset(&store->commit);
    2487         329 :                         break;
    2488             :                 }
    2489             : 
    2490       16451 :                 if (store->logger_api.changes(store) <= 0) {
    2491       13618 :                         TRC_DEBUG(SQL_STORE, "Store flusher, no changes\n");
    2492       13618 :                         MT_lock_unset(&store->commit);
    2493       13618 :                         continue;
    2494             :                 }
    2495        2833 :                 MT_lock_unset(&store->commit);
    2496             : 
    2497        2833 :                 MT_thread_setworking("flushing");
    2498        2833 :                 if (store_apply_deltas(store) != LOG_OK) {
    2499           0 :                         MT_lock_unset(&store->flush);
    2500           0 :                         if (!GDKexiting())
    2501           0 :                                 GDKfatal("write-ahead logging failure");
    2502             :                 }
    2503             : 
    2504        2833 :                 if (GDKexiting())
    2505             :                         break;
    2506        2833 :                 MT_thread_setworking("sleeping");
    2507        2833 :                 TRC_DEBUG(SQL_STORE, "Store flusher done\n");
    2508             :         }
    2509             : 
    2510             :         // End of loop, end of lock
    2511         329 :         MT_lock_unset(&store->flush);
    2512         329 : }
    2513             : 
    2514             : void
    2515      652732 : store_lock(sqlstore *store)
    2516             : {
    2517      652732 :         MT_lock_set(&store->lock);
    2518             :         /* tell GDK allocation functions to ignore limits */
    2519      652739 :         MT_thread_setworking("store locked");
    2520      652739 : }
    2521             : 
    2522             : void
    2523      652739 : store_unlock(sqlstore *store)
    2524             : {
    2525      652739 :         TRC_DEBUG(SQL_STORE, "Store unlocked\n");
    2526             :         /* tell GDK allocation functions to honor limits again */
    2527      652739 :         MT_thread_setworking("store unlocked");
    2528      652739 :         MT_lock_unset(&store->lock);
    2529      652738 : }
    2530             : 
    2531             : int
    2532      724615 : store_readonly(sqlstore *store)
    2533             : {
    2534      724615 :         return store->readonly;
    2535             : }
    2536             : 
    2537             : // Helper function for tar_write_header.
    2538             : // Our stream.h makes sure __attribute__ exists.
    2539             : static void __attribute__((__format__(__printf__, 3, 4)))
    2540       16704 : tar_write_header_field(char **cursor_ptr, size_t size, const char *fmt, ...)
    2541             : {
    2542       16704 :         va_list ap;
    2543             : 
    2544       16704 :         va_start(ap, fmt);
    2545       16704 :         (void)vsnprintf(*cursor_ptr, size + 1, fmt, ap);
    2546       16704 :         va_end(ap);
    2547             : 
    2548             :         /* At first reading you might wonder why add `size` instead
    2549             :          * of the byte count returned by vsnprintf. The reason is
    2550             :          * that we want to move `*cursor_ptr` to the start of the next
    2551             :          * field, not to the unused part of this field.
    2552             :          */
    2553       16704 :         *cursor_ptr += size;
    2554       16704 : }
    2555             : 
    2556             : #define TAR_BLOCK_SIZE (512)
    2557             : 
    2558             : // Write a tar header to the given stream.
    2559             : static gdk_return __attribute__((__warn_unused_result__))
    2560        1044 : tar_write_header(stream *tarfile, const char *path, time_t mtime, size_t size)
    2561             : {
    2562        1044 :         char buf[TAR_BLOCK_SIZE] = {0};
    2563        1044 :         char *cursor = buf;
    2564        1044 :         char *chksum;
    2565             : 
    2566             :         // We set the uid/gid fields to 0 and the uname/gname fields to "".
    2567             :         // When unpacking as a normal user, they are ignored and the files are
    2568             :         // owned by that user. When unpacking as root it is reasonable that
    2569             :         // the resulting files are owned by root.
    2570             : 
    2571             :         // The following is taken directly from the definition found
    2572             :         // in /usr/include/tar.h on a Linux system.
    2573        1044 :         tar_write_header_field(&cursor, 100, "%s", path);   // name[100]
    2574        1044 :         tar_write_header_field(&cursor, 8, "0000644");      // mode[8]
    2575        1044 :         tar_write_header_field(&cursor, 8, "%07o", 0U);      // uid[8]
    2576        1044 :         tar_write_header_field(&cursor, 8, "%07o", 0U);      // gid[8]
    2577        1044 :         tar_write_header_field(&cursor, 12, "%011zo", size);      // size[12]
    2578        1044 :         tar_write_header_field(&cursor, 12, "%011lo", (unsigned long)mtime); // mtime[12]
    2579        1044 :         chksum = cursor; // use this later to set the computed checksum
    2580        1044 :         tar_write_header_field(&cursor, 8, "%8s", ""); // chksum[8]
    2581        1044 :         *cursor++ = '0'; // typeflag REGTYPE
    2582        1044 :         tar_write_header_field(&cursor, 100, "%s", "");  // linkname[100]
    2583        1044 :         tar_write_header_field(&cursor, 6, "%s", "ustar"); // magic[6]
    2584        1044 :         tar_write_header_field(&cursor, 2, "%02o", 0U); // version, not null terminated
    2585        1044 :         tar_write_header_field(&cursor, 32, "%s", ""); // uname[32]
    2586        1044 :         tar_write_header_field(&cursor, 32, "%s", ""); // gname[32]
    2587        1044 :         tar_write_header_field(&cursor, 8, "%07o", 0U); // devmajor[8]
    2588        1044 :         tar_write_header_field(&cursor, 8, "%07o", 0U); // devminor[8]
    2589        1044 :         tar_write_header_field(&cursor, 155, "%s", ""); // prefix[155]
    2590             : 
    2591        1044 :         assert(cursor - buf == 500);
    2592             : 
    2593             :         unsigned sum = 0;
    2594      535572 :         for (int i = 0; i < TAR_BLOCK_SIZE; i++)
    2595      534528 :                 sum += (unsigned char) buf[i];
    2596             : 
    2597        1044 :         tar_write_header_field(&chksum, 8, "%06o", sum);
    2598             : 
    2599        1044 :         if (mnstr_write(tarfile, buf, TAR_BLOCK_SIZE, 1) != 1) {
    2600           0 :                 GDKerror("error writing tar header %s: %s", path, mnstr_peek_error(tarfile));
    2601           0 :                 return GDK_FAIL;
    2602             :         }
    2603             : 
    2604             :         return GDK_SUCCEED;
    2605             : }
    2606             : 
    2607             : /* Write data to the stream, padding it with zeroes up to the next
    2608             :  * multiple of TAR_BLOCK_SIZE.  Make sure all writes are in multiples
    2609             :  * of TAR_BLOCK_SIZE.
    2610             :  */
    2611             : static gdk_return __attribute__((__warn_unused_result__))
    2612        1059 : tar_write(stream *outfile, const char *data, size_t size)
    2613             : {
    2614        1059 :         const size_t tail = size % TAR_BLOCK_SIZE;
    2615        1059 :         const size_t bulk = size - tail;
    2616             : 
    2617        1059 :         if (bulk) {
    2618         490 :                 size_t written = mnstr_write(outfile, data, 1, bulk);
    2619         490 :                 if (written != bulk) {
    2620           0 :                         GDKerror("Wrote only %zu bytes instead of first %zu", written, bulk);
    2621           0 :                         return GDK_FAIL;
    2622             :                 }
    2623             :         }
    2624             : 
    2625        1059 :         if (tail) {
    2626        1044 :                 char buf[TAR_BLOCK_SIZE] = {0};
    2627        1044 :                 memcpy(buf, data + bulk, tail);
    2628        1044 :                 size_t written = mnstr_write(outfile, buf, 1, TAR_BLOCK_SIZE);
    2629        1044 :                 if (written != TAR_BLOCK_SIZE) {
    2630           0 :                         GDKerror("Wrote only %zu tail bytes instead of %d", written, TAR_BLOCK_SIZE);
    2631           0 :                         return GDK_FAIL;
    2632             :                 }
    2633             :         }
    2634             : 
    2635             :         return GDK_SUCCEED;
    2636             : }
    2637             : 
    2638             : static gdk_return __attribute__((__warn_unused_result__))
    2639          15 : tar_write_data(stream *tarfile, const char *path, time_t mtime, const char *data, size_t size)
    2640             : {
    2641          15 :         gdk_return res;
    2642             : 
    2643          15 :         res = tar_write_header(tarfile, path, mtime, size);
    2644          15 :         if (res != GDK_SUCCEED)
    2645             :                 return res;
    2646             : 
    2647          15 :         return tar_write(tarfile, data, size);
    2648             : }
    2649             : 
    2650             : static gdk_return __attribute__((__warn_unused_result__))
    2651        1029 : tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream *contents, size_t size, char *buf, size_t bufsize)
    2652             : {
    2653        1029 :         size_t file_size;
    2654        1029 :         size_t to_read;
    2655             : 
    2656        1029 :         file_size = getFileSize(contents);
    2657        1029 :         if (file_size < size) {
    2658           0 :                 GDKerror("Have to copy %zd bytes but only %zd exist in %s", size, file_size, path);
    2659           0 :                 return GDK_FAIL;
    2660             :         }
    2661             : 
    2662        1029 :         assert( (bufsize % TAR_BLOCK_SIZE) == 0);
    2663        1029 :         assert(bufsize >= TAR_BLOCK_SIZE);
    2664             : 
    2665             : 
    2666        1029 :         if (tar_write_header(tarfile, path, mtime, size) != GDK_SUCCEED)
    2667             :                 return GDK_FAIL;
    2668             : 
    2669             :         to_read = size;
    2670             : 
    2671        2063 :         while (to_read > 0) {
    2672        1034 :                 size_t chunk = (to_read <= bufsize) ? to_read : bufsize;
    2673        1034 :                 ssize_t nbytes = mnstr_read(contents, buf, 1, chunk);
    2674        1034 :                 if (nbytes != (ssize_t)chunk) {
    2675           0 :                         GDKerror("Read only %zd/%zd bytes of component %s: %s", nbytes, chunk, path, mnstr_peek_error(contents));
    2676           0 :                         return GDK_FAIL;
    2677             :                 }
    2678        1034 :                 if (tar_write(tarfile, buf, chunk) != GDK_SUCCEED)
    2679             :                         return GDK_FAIL;
    2680        1034 :                 to_read -= chunk;
    2681             :         }
    2682             : 
    2683             :         return GDK_SUCCEED;
    2684             : }
    2685             : 
    2686             : static gdk_return __attribute__((__warn_unused_result__))
    2687           5 : hot_snapshot_write_tar(stream *out, const char *prefix, char *plan)
    2688             : {
    2689           5 :         if (plan == NULL)
    2690             :                 return GDK_FAIL;
    2691             : 
    2692           5 :         gdk_return ret = GDK_FAIL;
    2693           5 :         const char *p = plan; // our cursor in the plan
    2694           5 :         time_t timestamp = 1234567890; // dummy date, Sat 14 Feb 2009 12:31:30 AM CET
    2695             :         // Name convention: _path for the absolute path
    2696             :         // and _name for the corresponding local relative path
    2697           5 :         char abs_src_path[2 * FILENAME_MAX];
    2698           5 :         char *src_name = abs_src_path;
    2699           5 :         char dest_path[100]; // size imposed by tar format.
    2700           5 :         char *dest_name = dest_path + snprintf(dest_path, sizeof(dest_path), "%s/", prefix);
    2701           5 :         stream *infile = NULL;
    2702           5 :         const char *bufsize_env_var = "hot_snapshot_buffer_size";
    2703           5 :         int bufsize = GDKgetenv_int(bufsize_env_var, 1024 * 1024);
    2704           5 :         char *buffer = NULL;
    2705             : 
    2706           5 :         if (bufsize < TAR_BLOCK_SIZE || (bufsize % TAR_BLOCK_SIZE) != 0) {
    2707           0 :                 GDKerror("invalid value for setting %s=%d: must be a multiple of %d",
    2708             :                         bufsize_env_var, bufsize, TAR_BLOCK_SIZE);
    2709           0 :                 goto end;
    2710             :         }
    2711           5 :         buffer = GDKmalloc(bufsize);
    2712           5 :         if (!buffer) {
    2713           0 :                 GDKerror("could not allocate buffer");
    2714           0 :                 goto end;
    2715             :         }
    2716             : 
    2717           5 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2718             : 
    2719           5 :         int len;
    2720           5 :         if (sscanf(p, "%[^\n]\n%n", abs_src_path, &len) != 1) {
    2721           0 :                 GDKerror("internal error: first line of plan is malformed");
    2722           0 :                 goto end;
    2723             :         }
    2724           5 :         p += len;
    2725           5 :         src_name = abs_src_path + len - 1; // - 1 because len includes the trailing newline
    2726           5 :         *src_name++ = DIR_SEP;
    2727             : 
    2728           5 :         char command;
    2729           5 :         long size;
    2730        1049 :         while (sscanf(p, "%c %ld %100s\n%n", &command, &size, src_name, &len) == 3) {
    2731        1044 :                 GDK_CHECK_TIMEOUT_BODY(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(end, qry_ctx));
    2732        1044 :                 p += len;
    2733        1044 :                 strcpy(dest_name, src_name);
    2734        1044 :                 if (size < 0) {
    2735           0 :                         GDKerror("malformed snapshot plan for %s: size %ld < 0", src_name, size);
    2736           0 :                         goto end;
    2737             :                 }
    2738        1044 :                 switch (command) {
    2739        1029 :                         case 'c':
    2740        1029 :                                 infile = open_rstream(abs_src_path);
    2741        1029 :                                 if (!infile) {
    2742           0 :                                         GDKerror("%s", mnstr_peek_error(NULL));
    2743           0 :                                         goto end;
    2744             :                                 }
    2745        1029 :                                 if (tar_copy_stream(out, dest_path, timestamp, infile, size, buffer, (size_t)bufsize) != GDK_SUCCEED)
    2746           0 :                                         goto end;
    2747        1029 :                                 close_stream(infile);
    2748        1029 :                                 infile = NULL;
    2749        1029 :                                 break;
    2750          15 :                         case 'w':
    2751          15 :                                 if (tar_write_data(out, dest_path, timestamp, p, size) != GDK_SUCCEED)
    2752           0 :                                         goto end;
    2753          15 :                                 p += size;
    2754          15 :                                 break;
    2755           0 :                         default:
    2756           0 :                                 GDKerror("Unknown command in snapshot plan: %c (%s)", command, src_name);
    2757           0 :                                 goto end;
    2758             :                 }
    2759        1044 :                 mnstr_flush(out, MNSTR_FLUSH_ALL);
    2760             :         }
    2761             : 
    2762             :         // write a trailing block of zeros. If it succeeds, this function succeeds.
    2763           5 :         char a;
    2764           5 :         a = '\0';
    2765           5 :         ret = tar_write(out, &a, 1);
    2766           5 :         if (ret == GDK_SUCCEED)
    2767           5 :                 ret = tar_write(out, &a, 1);
    2768             : 
    2769           0 : end:
    2770           5 :         free(plan);
    2771           5 :         GDKfree(buffer);
    2772           5 :         if (infile)
    2773           0 :                 close_stream(infile);
    2774             :         return ret;
    2775             : }
    2776             : 
    2777             : /* Pick a name for the temporary tar file. Make sure it has the same extension
    2778             :  * so as not to confuse the streams library.
    2779             :  *
    2780             :  * This function is not entirely safe as compared to for example mkstemp.
    2781             :  */
    2782             : static str __attribute__((__warn_unused_result__))
    2783           5 : pick_tmp_name(str filename)
    2784             : {
    2785           5 :         str name = GDKmalloc(strlen(filename) + 10);
    2786           5 :         if (name == NULL) {
    2787           0 :                 GDKerror("malloc failed");
    2788           0 :                 return NULL;
    2789             :         }
    2790           5 :         strcpy(name, filename);
    2791             : 
    2792             :         // Look for an extension.
    2793             :         // Make sure it's part of the basename
    2794             : 
    2795           5 :         char *ext = strrchr(name, '.');
    2796           5 :         char *sep = strrchr(name, DIR_SEP);
    2797           5 :         char *slash = strrchr(name, '/'); // on Windows, / and \ both work
    2798           5 :         if (ext != NULL) {
    2799             :                 // is ext actually after sep and slash?
    2800           5 :                 if ((sep != NULL && sep > ext) || (slash != NULL && slash > ext))
    2801             :                         ext = NULL;
    2802             :         }
    2803             : 
    2804           5 :         if (ext == NULL) {
    2805           0 :                 return strcat(name, "..tmp");
    2806             :         } else {
    2807           5 :                 const char tmp[] = "..tmp.";
    2808           5 :                 size_t tmplen = strlen(tmp);
    2809           5 :                 memmove(ext + tmplen, ext, strlen(ext) + 1);
    2810           5 :                 memmove(ext, tmp, tmplen);
    2811             :         }
    2812             : 
    2813           5 :         return name;
    2814             : }
    2815             : 
    2816             : lng
    2817           5 : store_hot_snapshot_to_stream(sqlstore *store, stream *tar_stream)
    2818             : {
    2819           5 :         int locked = 0;
    2820           5 :         lng result = 0;
    2821           5 :         buffer *plan_buf = NULL;
    2822           5 :         stream *plan_stream = NULL;
    2823           5 :         gdk_return r;
    2824             : 
    2825           5 :         if (!store->logger_api.get_snapshot_files) {
    2826           0 :                 GDKerror("backend does not support hot snapshots");
    2827           0 :                 goto end;
    2828             :         }
    2829             : 
    2830           5 :         plan_buf = buffer_create(64 * 1024);
    2831           5 :         if (!plan_buf) {
    2832           0 :                 GDKerror("Failed to allocate plan buffer");
    2833           0 :                 goto end;
    2834             :         }
    2835           5 :         plan_stream = buffer_wastream(plan_buf, "write_snapshot_plan");
    2836           5 :         if (!plan_stream) {
    2837           0 :                 GDKerror("Failed to allocate buffer stream");
    2838           0 :                 goto end;
    2839             :         }
    2840             : 
    2841           5 :         MT_lock_set(&store->flush);
    2842           5 :         MT_lock_set(&store->lock);
    2843           5 :         BBPtmlock();
    2844           5 :         locked = 1;
    2845           5 :         if (GDKexiting())
    2846           0 :                 goto end;
    2847             : 
    2848           5 :         r = store->logger_api.get_snapshot_files(store, plan_stream);
    2849           5 :         if (r != GDK_SUCCEED)
    2850           0 :                 goto end; // should already have set a GDK error
    2851           5 :         close_stream(plan_stream);
    2852           5 :         plan_stream = NULL;
    2853           5 :         MT_lock_unset(&store->lock);
    2854           5 :         locked = 2;
    2855           5 :         r = hot_snapshot_write_tar(tar_stream, GDKgetenv("gdk_dbname"), buffer_get_buf(plan_buf));
    2856           5 :         if (r != GDK_SUCCEED)
    2857           0 :                 goto end;
    2858             : 
    2859             :         // the original idea was to return a sort of sequence number of the
    2860             :         // database that identifies exactly which version has been snapshotted
    2861             :         // but no such number is available:
    2862             :         // logger_functions.read_last_transaction_id is not implemented
    2863             :         // anywhere.
    2864             :         //
    2865             :         // So we return a random positive integer instead.
    2866             :         result = 42;
    2867             : 
    2868           5 : end:
    2869           5 :         if (locked) {
    2870           5 :                 BBPtmunlock();
    2871           5 :                 if (locked == 1)
    2872           0 :                         MT_lock_unset(&store->lock);
    2873           5 :                 MT_lock_unset(&store->flush);
    2874             :         }
    2875           5 :         if (plan_stream)
    2876           0 :                 close_stream(plan_stream);
    2877           5 :         if (plan_buf)
    2878           5 :                 buffer_destroy(plan_buf);
    2879           5 :         return result;
    2880             : }
    2881             : 
    2882             : 
    2883             : lng
    2884           5 : store_hot_snapshot(sqlstore *store, str tarfile)
    2885             : {
    2886           5 :         lng result = 0;
    2887           5 :         struct stat st = {0};
    2888           5 :         char *tmppath = NULL;
    2889           5 :         char *dirpath = NULL;
    2890           5 :         int do_remove = 0;
    2891           5 :         int dir_fd = -1;
    2892           5 :         stream *tar_stream = NULL;
    2893           5 :         buffer *plan_buf = NULL;
    2894           5 :         stream *plan_stream = NULL;
    2895             : 
    2896           5 :         if (!store->logger_api.get_snapshot_files) {
    2897           0 :                 GDKerror("backend does not support hot snapshots");
    2898           0 :                 goto end;
    2899             :         }
    2900             : 
    2901           5 :         if (!MT_path_absolute(tarfile)) {
    2902           0 :                 GDKerror("Hot snapshot requires an absolute path");
    2903           0 :                 goto end;
    2904             :         }
    2905             : 
    2906           5 :         if (MT_stat(tarfile, &st) == 0) {
    2907           0 :                 GDKerror("File already exists: %s", tarfile);
    2908           0 :                 goto end;
    2909             :         }
    2910             : 
    2911           5 :         tmppath = pick_tmp_name(tarfile);
    2912           5 :         if (tmppath == NULL) {
    2913           0 :                 goto end;
    2914             :         }
    2915           5 :         tar_stream = open_wstream(tmppath);
    2916           5 :         if (!tar_stream) {
    2917           0 :                 GDKerror("%s", mnstr_peek_error(NULL));
    2918           0 :                 goto end;
    2919             :         }
    2920           5 :         do_remove = 1;
    2921             : 
    2922             : #ifdef HAVE_FSYNC
    2923             :         // The following only makes sense on POSIX, where fsync'ing a file
    2924             :         // guarantees the bytes of the file to go to disk, but not necessarily
    2925             :         // guarantees the existence of the file in a directory to be persistent.
    2926             :         // Hence the fsync-the-parent ceremony.
    2927             : 
    2928             :         // Set dirpath to the directory containing the tar file.
    2929             :         // Call realpath(2) to make the path absolute so it has at least
    2930             :         // one DIR_SEP in it. Realpath requires the file to exist so
    2931             :         // we feed it tmppath rather than tarfile.
    2932           5 :         dirpath = GDKmalloc(PATH_MAX);
    2933           5 :         if (dirpath == NULL) {
    2934           0 :                 GDKsyserror("malloc failed");
    2935           0 :                 goto end;
    2936             :         }
    2937           5 :         if (realpath(tmppath, dirpath) == NULL) {
    2938           0 :                 GDKsyserror("couldn't resolve path %s: %s", tarfile, strerror(errno));
    2939           0 :                 goto end;
    2940             :         }
    2941           5 :         *strrchr(dirpath, DIR_SEP) = '\0';
    2942             : 
    2943             :         // Open the directory so we can call fsync on it.
    2944             :         // We use raw posix calls because this is not available in the streams library
    2945             :         // and I'm not quite sure what a generic streams-api should look like.
    2946           5 :         dir_fd = open(dirpath, O_RDONLY); // ERROR no o_rdonly
    2947           5 :         if (dir_fd < 0) {
    2948           0 :                 GDKsyserror("couldn't open directory %s", dirpath);
    2949           0 :                 goto end;
    2950             :         }
    2951             : 
    2952             :         // Fsync the directory beforehand too.
    2953             :         // Postgres believes this is necessary for durability.
    2954           5 :         if (fsync(dir_fd) < 0) {
    2955           0 :                 GDKsyserror("First fsync on %s failed", dirpath);
    2956           0 :                 goto end;
    2957             :         }
    2958             : #else
    2959             :         (void)dirpath;
    2960             : #endif
    2961             : 
    2962           5 :         result = store_hot_snapshot_to_stream(store, tar_stream);
    2963           5 :         if (result == 0)
    2964           0 :                 goto end;
    2965             : 
    2966             :         // Now sync and atomically rename the temp file to the real file,
    2967             :         // also fsync'ing the directory
    2968           5 :         mnstr_fsync(tar_stream);
    2969           5 :         close_stream(tar_stream);
    2970           5 :         tar_stream = NULL;
    2971           5 :         if (MT_rename(tmppath, tarfile) < 0) {
    2972           0 :                 GDKsyserror("rename %s to %s failed", tmppath, tarfile);
    2973           0 :                 goto end;
    2974             :         }
    2975           5 :         do_remove = 0;
    2976             : #ifdef HAVE_FSYNC
    2977             :         // More POSIX fsync-the-parent-dir ceremony
    2978           5 :         if (fsync(dir_fd) < 0) {
    2979           0 :                 GDKsyserror("fsync on dir %s failed", dirpath);
    2980           0 :                 goto end;
    2981             :         }
    2982             : #endif
    2983           5 : end:
    2984           5 :         GDKfree(dirpath);
    2985           5 :         if (dir_fd >= 0)
    2986           5 :                 close(dir_fd);
    2987           5 :         if (tar_stream)
    2988           0 :                 close_stream(tar_stream);
    2989           5 :         if (plan_stream)
    2990             :                 close_stream(plan_stream);
    2991           5 :         if (plan_buf)
    2992             :                 buffer_destroy(plan_buf);
    2993           5 :         if (do_remove)
    2994           0 :                 (void) MT_remove(tmppath);      // Best effort, ignore the result
    2995           5 :         GDKfree(tmppath);
    2996           5 :         return result;
    2997             : }
    2998             : 
    2999             : static int
    3000       56585 : column_dup(sql_trans *tr, sql_column *oc, sql_table *t, sql_column **cres)
    3001             : {
    3002       56585 :         sqlstore *store = tr->store;
    3003       56585 :         sql_column *c = ZNEW(sql_column);
    3004       56585 :         int res = LOG_OK;
    3005             : 
    3006       56585 :         base_init(NULL, &c->base, oc->base.id, 0, oc->base.name);
    3007       56585 :         c->type = oc->type;
    3008       56585 :         c->def = NULL;
    3009       56585 :         if (oc->def)
    3010         520 :                 c->def =_STRDUP(oc->def);
    3011       56585 :         c->null = oc->null;
    3012       56585 :         c->colnr = oc->colnr;
    3013       56585 :         c->unique = oc->unique;
    3014       56585 :         c->t = t;
    3015       56585 :         c->storage_type = NULL;
    3016       56585 :         if (oc->storage_type)
    3017          85 :                 c->storage_type =_STRDUP(oc->storage_type);
    3018       56585 :         ATOMIC_PTR_INIT(&c->data, NULL);
    3019             : 
    3020       56585 :         if (isTable(c->t)) {
    3021       55420 :                 if (isTempTable(c->t)) {
    3022       35850 :                         if ((res = store->storage_api.create_col(tr, c))) {
    3023             :                                 ATOMIC_PTR_DESTROY(&c->data);
    3024             :                                 return res;
    3025             :                         }
    3026             :                 } else {
    3027       19570 :                         ATOMIC_PTR_SET(&c->data, store->storage_api.col_dup(oc));
    3028             :                 }
    3029             :         }
    3030       56585 :         *cres = c;
    3031       56585 :         return res;
    3032             : }
    3033             : 
    3034             : static sql_kc *
    3035       21284 : kc_dup(sql_kc *kc, sql_table *t)
    3036             : {
    3037       21284 :         sql_kc *nkc = ZNEW(sql_kc);
    3038       21284 :         sql_column *c = find_sql_column(t, kc->c->base.name);
    3039             : 
    3040       21284 :         assert(c);
    3041       21284 :         nkc->c = c;
    3042       21284 :         c->unique = kc->c->unique;
    3043       21284 :         return nkc;
    3044             : }
    3045             : 
    3046             : static int
    3047        8697 : key_dup(sql_trans *tr, sql_key *k, sql_table *t, sql_key **kres)
    3048             : {
    3049        8697 :         sql_key *nk = (k->type != fkey) ? (sql_key *) ZNEW(sql_ukey) : (sql_key *) ZNEW(sql_fkey);
    3050        8697 :         node *n;
    3051        8697 :         int res = LOG_OK;
    3052             : 
    3053        8697 :         base_init(NULL, &nk->base, k->base.id?k->base.id:next_oid(tr->store), 0, k->base.name);
    3054        8697 :         nk->type = k->type;
    3055        8697 :         nk->columns = list_create((fdestroy) &kc_destroy);
    3056        8697 :         nk->t = t;
    3057        8697 :         nk->idx = NULL;
    3058             : 
    3059        8697 :         if (k->idx) {
    3060        8643 :                 node *n = ol_find_name(t->idxs, nk->base.name);
    3061        8643 :                 nk->idx = (sql_idx *)n->data;
    3062        8643 :                 nk->idx->key = nk;
    3063             :         }
    3064             : 
    3065        8697 :         if (nk->type != fkey) {
    3066        6785 :                 sql_ukey *tk = (sql_ukey *) nk;
    3067             : 
    3068        6785 :                 if (nk->type == pkey)
    3069        4579 :                         t->pkey = tk;
    3070             : 
    3071        6785 :                 if (nk->type == ckey)
    3072          54 :                         nk->check = _STRDUP(k->check);
    3073             :         } else {
    3074        1912 :                 sql_fkey *fk = (sql_fkey *) nk;
    3075        1912 :                 sql_fkey *ok = (sql_fkey *) k;
    3076             : 
    3077        1912 :                 fk->rkey = ok->rkey;
    3078        1912 :                 fk->on_delete = ok->on_delete;
    3079        1912 :                 fk->on_update = ok->on_update;
    3080             :         }
    3081             : 
    3082       18401 :         for (n = k->columns->h; n; n = n->next) {
    3083        9704 :                 sql_kc *okc = n->data;
    3084             : 
    3085        9704 :                 list_append(nk->columns, kc_dup(okc, t));
    3086             :         }
    3087             : 
    3088        8697 :         if (isGlobal(t) &&
    3089        8630 :                         ((res = os_add(t->s->keys, tr, nk->base.name, dup_base(&nk->base))) ||
    3090        8630 :                      (res = os_add(tr->cat->objects, tr, nk->base.name, dup_base(&nk->base))))) {
    3091           0 :                 return res;
    3092             :         }
    3093        8697 :         *kres = nk;
    3094        8697 :         return res;
    3095             : }
    3096             : 
    3097             : static int
    3098        3242 : idx_dup(sql_trans *tr, sql_idx * i, sql_table *t, sql_idx **ires)
    3099             : {
    3100        3242 :         sqlstore *store = tr->store;
    3101        3242 :         sql_idx *ni = ZNEW(sql_idx);
    3102        3242 :         node *n;
    3103        3242 :         int res = LOG_OK;
    3104             : 
    3105        3242 :         base_init(NULL, &ni->base, i->base.id, 0, i->base.name);
    3106             : 
    3107        3242 :         ni->columns = list_create((fdestroy) &kc_destroy);
    3108        3242 :         ni->t = t;
    3109        3242 :         ni->type = i->type;
    3110        3242 :         ni->key = NULL;
    3111        3242 :         ATOMIC_PTR_INIT(&ni->data, NULL);
    3112             : 
    3113        3242 :         if (isTable(i->t)) {
    3114        3189 :                 if (isTempTable(i->t)) {
    3115          86 :                         if ((res = store->storage_api.create_idx(tr, ni))) {
    3116             :                                 ATOMIC_PTR_DESTROY(&ni->data);
    3117             :                                 return res;
    3118             :                         }
    3119             :                 } else {
    3120        3103 :                         ATOMIC_PTR_SET(&ni->data, store->storage_api.idx_dup(i));
    3121             :                 }
    3122             :         }
    3123             : 
    3124        6935 :         for (n = i->columns->h; n; n = n->next) {
    3125        3693 :                 sql_kc *okc = n->data;
    3126             : 
    3127        3693 :                 list_append(ni->columns, kc_dup(okc, t));
    3128             :         }
    3129        3242 :         if (isGlobal(t) && (res = os_add(t->s->idxs, tr, ni->base.name, dup_base(&ni->base)))) {
    3130             :                 ATOMIC_PTR_DESTROY(&ni->data);
    3131             :                 return res;
    3132             :         }
    3133        3242 :         *ires = ni;
    3134        3242 :         return res;
    3135             : }
    3136             : 
    3137             : static int
    3138         495 : part_dup(sql_trans *tr, sql_part *op, sql_table *mt, sql_part **pres)
    3139             : {
    3140         495 :         sql_part *p = ZNEW(sql_part);
    3141         495 :         int res = LOG_OK;
    3142             : 
    3143         495 :         assert(isMergeTable(mt) || isReplicaTable(mt));
    3144         495 :         base_init(NULL, &p->base, op->base.id, 0, op->base.name);
    3145         495 :         p->with_nills = op->with_nills;
    3146         495 :         p->t = mt;
    3147         495 :         p->member = op->member;
    3148             : 
    3149         495 :         if (isRangePartitionTable(mt)) {
    3150         262 :                 p->part.range.minvalue = NEW_ARRAY(char, op->part.range.minlength);
    3151         262 :                 p->part.range.maxvalue = NEW_ARRAY(char, op->part.range.maxlength);
    3152         262 :                 memcpy(p->part.range.minvalue, op->part.range.minvalue, op->part.range.minlength);
    3153         262 :                 memcpy(p->part.range.maxvalue, op->part.range.maxvalue, op->part.range.maxlength);
    3154         262 :                 p->part.range.minlength = op->part.range.minlength;
    3155         262 :                 p->part.range.maxlength = op->part.range.maxlength;
    3156         233 :         } else if (isListPartitionTable(mt)) {
    3157          62 :                 p->part.values = list_create((fdestroy) &part_value_destroy);
    3158         243 :                 for (node *n = op->part.values->h ; n ; n = n->next) {
    3159         181 :                         sql_part_value *prev = (sql_part_value*) n->data, *nextv = ZNEW(sql_part_value);
    3160         181 :                         nextv->value = NEW_ARRAY(char, prev->length);
    3161         181 :                         memcpy(nextv->value, prev->value, prev->length);
    3162         181 :                         nextv->length = prev->length;
    3163         181 :                         list_append(p->part.values, nextv);
    3164             :                 }
    3165             :         }
    3166         495 :         if (isGlobal(mt) && (res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
    3167             :                 return res;
    3168         495 :         *pres = p;
    3169         495 :         return res;
    3170             : }
    3171             : 
    3172             : static int
    3173         128 : trigger_dup(sql_trans *tr, sql_trigger *i, sql_table *t, sql_trigger **tres)
    3174             : {
    3175         128 :         sql_trigger *nt = ZNEW(sql_trigger);
    3176         128 :         int res = LOG_OK;
    3177             : 
    3178         128 :         base_init(NULL, &nt->base, i->base.id, 0, i->base.name);
    3179             : 
    3180         128 :         nt->columns = list_create((fdestroy) &kc_destroy);
    3181         128 :         nt->t = t;
    3182         128 :         nt->time = i->time;
    3183         128 :         nt->orientation = i->orientation;
    3184         128 :         nt->event = i->event;
    3185         128 :         nt->old_name = nt->new_name = nt->condition = NULL;
    3186         128 :         if (i->old_name)
    3187          39 :                 nt->old_name =_STRDUP(i->old_name);
    3188         128 :         if (i->new_name)
    3189          55 :                 nt->new_name =_STRDUP(i->new_name);
    3190         128 :         if (i->condition)
    3191           0 :                 nt->condition =_STRDUP(i->condition);
    3192         128 :         nt->statement =_STRDUP(i->statement);
    3193             : 
    3194         128 :         for (node *n = i->columns->h; n; n = n->next) {
    3195           0 :                 sql_kc *okc = n->data;
    3196             : 
    3197           0 :                 list_append(nt->columns, kc_dup(okc, t));
    3198             :         }
    3199         128 :         if (isGlobal(t) && (res = os_add(t->s->triggers, tr, nt->base.name, dup_base(&nt->base))))
    3200             :                 return res;
    3201         128 :         *tres = nt;
    3202         128 :         return res;
    3203             : }
    3204             : 
    3205             : static int
    3206        6663 : table_dup(sql_trans *tr, sql_table *ot, sql_schema *s, const char *name,
    3207             :                   sql_table **tres, bool dup_global_as_global)
    3208             : {
    3209        6663 :         sqlstore *store = tr->store;
    3210        6663 :         sql_table *t = ZNEW(sql_table);
    3211        6663 :         node *n;
    3212        6663 :         int res = LOG_OK;
    3213             : 
    3214        6663 :         if (t == NULL)
    3215             :                 return LOG_ERR;
    3216        6663 :         base_init(NULL, &t->base, ot->base.id, 0, name?name:ot->base.name);
    3217        6663 :         t->type = ot->type;
    3218        6663 :         t->system = ot->system;
    3219        6663 :         t->bootstrap = ot->bootstrap;
    3220        6663 :         t->persistence = (s || dup_global_as_global)?ot->persistence:SQL_LOCAL_TEMP;
    3221        6663 :         t->commit_action = ot->commit_action;
    3222        6663 :         t->access = ot->access;
    3223        6663 :         t->query = (ot->query) ?_STRDUP(ot->query) : NULL;
    3224        6663 :         t->properties = ot->properties;
    3225             : 
    3226        6663 :         t->columns = ol_new(NULL, (destroy_fptr) &column_destroy, store);
    3227        6663 :         t->idxs = ol_new(NULL, (destroy_fptr) &idx_destroy, store);
    3228        6663 :         t->keys = ol_new(NULL, (destroy_fptr) &key_destroy, store);
    3229        6663 :         t->triggers = ol_new(NULL, (destroy_fptr) &trigger_destroy, store);
    3230        6663 :         if (ot->members)
    3231         572 :                 t->members = list_create((fdestroy) &part_destroy);
    3232             : 
    3233        6663 :         t->pkey = NULL;
    3234        6663 :         t->s = s ? s : tr->tmp;
    3235        6663 :         t->sz = ot->sz;
    3236        6663 :         ATOMIC_PTR_INIT(&t->data, NULL);
    3237             : 
    3238        6663 :         if (isPartitionedByExpressionTable(ot)) {
    3239          50 :                 t->part.pexp = ZNEW(sql_expression);
    3240          50 :                 t->part.pexp->exp =_STRDUP(ot->part.pexp->exp);
    3241          50 :                 t->part.pexp->type = ot->part.pexp->type;
    3242          50 :                 t->part.pexp->cols = list_create((fdestroy) &int_destroy);
    3243         107 :                 for (n = ot->part.pexp->cols->h; n; n = n->next) {
    3244          57 :                         int *nid = MNEW(int);
    3245          57 :                         *nid = *(int *) n->data;
    3246          57 :                         list_append(t->part.pexp->cols, nid);
    3247             :                 }
    3248             :         }
    3249        6663 :         if (ot->columns)
    3250       63248 :                 for (n = ol_first_node(ot->columns); n; n = n->next) {
    3251       56585 :                         sql_column *c = NULL;
    3252             : 
    3253       56585 :                         if ((res = column_dup(tr, n->data, t, &c)) || (res = ol_add(t->columns, &c->base)))
    3254           0 :                                 goto cleanup;
    3255       56585 :                         if (isPartitionedByColumnTable(ot) && ot->part.pcol->base.id == c->base.id)
    3256         250 :                                 t->part.pcol = c;
    3257             :                 }
    3258        6663 :         if (ot->idxs)
    3259        9905 :                 for (n = ol_first_node(ot->idxs); n; n = n->next) {
    3260        3242 :                         sql_idx *i = NULL;
    3261             : 
    3262        3242 :                         if ((res = idx_dup(tr, n->data, t, &i)) || (res = ol_add(t->idxs, &i->base)))
    3263           0 :                                 goto cleanup;
    3264             :                 }
    3265        6663 :         if (ot->keys)
    3266        8491 :                 for (n = ol_first_node(ot->keys); n; n = n->next) {
    3267        1828 :                         sql_key *k = NULL;
    3268             : 
    3269        1828 :                         if ((res = key_dup(tr, n->data, t, &k)) || (res = ol_add(t->keys, &k->base)))
    3270           0 :                                 goto cleanup;
    3271             :                 }
    3272        6663 :         if (ot->triggers)
    3273        6791 :                 for (n = ol_first_node(ot->triggers); n; n = n->next) {
    3274         128 :                         sql_trigger *tri = NULL;
    3275             : 
    3276         128 :                         if ((res = trigger_dup(tr, n->data, t, &tri)) || (res = ol_add(t->triggers, &tri->base)))
    3277           0 :                                 goto cleanup;
    3278             :                 }
    3279        6663 :         if (ot->members)
    3280        1067 :                 for (n = ot->members->h; n; n = n->next) {
    3281         495 :                         sql_part *pt = NULL;
    3282             : 
    3283         495 :                         if ((res = part_dup(tr, n->data, t, &pt)))
    3284           0 :                                 goto cleanup;
    3285         495 :                         list_append(t->members, pt);
    3286             :                 }
    3287        6663 :         if (isTable(t)) {
    3288        6083 :                 if (isTempTable(t)) {
    3289        4480 :                         if ((res = store->storage_api.create_del(tr, t)))
    3290           0 :                                 goto cleanup;
    3291             :                 } else {
    3292        1603 :                         ATOMIC_PTR_SET(&t->data, store->storage_api.del_dup(ot));
    3293             :                 }
    3294             :         }
    3295        6663 :         if ((res = os_add(isLocalTemp(t) ? tr->localtmps : t->s->tables, tr, t->base.name, &t->base)))
    3296          10 :                 goto cleanup;
    3297             : 
    3298        6653 : cleanup:
    3299          10 :         if (res) {
    3300             :                 ATOMIC_PTR_DESTROY(&t->data);
    3301             :                 t = NULL;
    3302             :         }
    3303        6663 :         *tres = t;
    3304        6663 :         return res;
    3305             : }
    3306             : 
    3307             : sql_table *
    3308        4454 : globaltmp_instantiate(sql_trans *tr, sql_table *ot)
    3309             : {
    3310        4454 :         assert(isGlobal(ot)&& isTempTable(ot));
    3311        4454 :         sql_table *t = NULL;
    3312        4454 :         if (table_dup(tr, ot, NULL, NULL, &t, false) == LOG_OK)
    3313        4454 :                 return t;
    3314             :         return NULL;
    3315             : }
    3316             : 
    3317             : static int
    3318      275645 : new_table(sql_trans *tr, sql_table *t, sql_table **tres)
    3319             : {
    3320      275645 :         int res = LOG_OK;
    3321      275645 :         if (!isGlobalTemp(t))
    3322      275513 :                 t = find_sql_table(tr, t->s, t->base.name); /* could have changed by depending changes */
    3323             : 
    3324      275645 :         if (!isLocalTemp(t) && !isNew(t) && !os_obj_intransaction(t->s->tables, tr, &t->base))
    3325        2167 :                 res = table_dup(tr, t, t->s, NULL, tres, true);
    3326             :         else
    3327      273478 :                 *tres = t;
    3328      275645 :         return res;
    3329             : }
    3330             : 
    3331             : static sql_arg *
    3332      346895 : arg_dup(sql_trans *tr, sql_schema *s, sql_arg *oa)
    3333             : {
    3334      346895 :         sql_arg *a = ZNEW(sql_arg);
    3335             : 
    3336      346895 :         if (a) {
    3337      346895 :                 a->name =_STRDUP(oa->name);
    3338      346895 :                 a->inout = oa->inout;
    3339      346895 :                 dup_sql_type(tr, s, &(oa->type), &(a->type));
    3340             :         }
    3341      346895 :         return a;
    3342             : }
    3343             : 
    3344             : static int
    3345          13 : func_dup(sql_trans *tr, sql_func *of, sql_schema *s)
    3346             : {
    3347          13 :         sql_func *f = ZNEW(sql_func);
    3348             : 
    3349             :         /* 'func_dup' is aimed at FUNC_LANG_SQL functions ONLY, so f->imp and f->instantiated won't be set */
    3350          13 :         base_init(NULL, &f->base, of->base.id, 0, of->base.name);
    3351          13 :         f->mod =_STRDUP(of->mod);
    3352          13 :         f->type = of->type;
    3353          13 :         f->lang = of->lang;
    3354          13 :         f->semantics = of->semantics;
    3355          13 :         f->side_effect = of->side_effect;
    3356          13 :         f->varres = of->varres;
    3357          13 :         f->vararg = of->vararg;
    3358          13 :         f->fix_scale = of->fix_scale;
    3359          13 :         f->system = of->system;
    3360          13 :         f->private = of->private;
    3361          13 :         f->query = (of->query)?_STRDUP(of->query):NULL;
    3362          13 :         f->s = s;
    3363          13 :         f->sa = NULL;
    3364             : 
    3365          13 :         f->ops = list_create((fdestroy) &arg_destroy);
    3366          30 :         for (node *n=of->ops->h; n; n = n->next)
    3367          17 :                 list_append(f->ops, arg_dup(tr, s, n->data));
    3368          13 :         if (of->res) {
    3369          11 :                 f->res = list_create((fdestroy) &arg_destroy);
    3370          22 :                 for (node *n=of->res->h; n; n = n->next)
    3371          11 :                         list_append(f->res, arg_dup(tr, s, n->data));
    3372             :         }
    3373             : 
    3374          13 :         return os_add(s->funcs, tr, f->base.name, &f->base);
    3375             : }
    3376             : 
    3377             : static int
    3378       20405 : store_reset_sql_functions(sql_trans *tr, sqlid id)
    3379             : {
    3380       20405 :         sqlstore *store = tr->store;
    3381       20405 :         int res = LOG_OK, sql_lang = (int) FUNC_LANG_SQL; /* functions other than SQL don't require to be instantiated again */
    3382       20405 :         sql_schema *syss = find_sql_schema(tr, "sys");
    3383       20405 :         sql_table *deps = find_sql_table(tr, syss, "dependencies");
    3384       20405 :         rids *sql_funcs = NULL, *depends = NULL, *joined = NULL;
    3385             : 
    3386             :         /* Find dependencies from the object */
    3387       20405 :         depends = store->table_api.rids_select(tr, find_sql_column(deps, "id"), &id, &id, NULL);
    3388       20405 :         if (depends == NULL)
    3389             :                 return -1;
    3390       20405 :         if (store->table_api.rids_empty(depends)) { /* nothing depends on the object, return */
    3391       19605 :                 store->table_api.rids_destroy(depends);
    3392       19605 :                 return res;
    3393             :         }
    3394             :         /* Get SQL functions */
    3395         800 :         sql_table *funcs = find_sql_table(tr, syss, "functions");
    3396         800 :         sql_column *func_id = find_sql_column(funcs, "id");
    3397         800 :         if (!(sql_funcs = store->table_api.rids_select(tr, find_sql_column(funcs, "language"), &sql_lang, &sql_lang, NULL))) {
    3398           0 :                 store->table_api.rids_destroy(depends);
    3399           0 :                 return -1;
    3400             :         }
    3401             :         /* Do the semijoin */
    3402         800 :         joined = store->table_api.rids_semijoin(tr, sql_funcs, func_id, depends, find_sql_column(deps, "depend_id"));
    3403         800 :         store->table_api.rids_destroy(depends);
    3404         800 :         if (!joined) {
    3405           0 :                 store->table_api.rids_destroy(sql_funcs);
    3406           0 :                 return -1;
    3407             :         }
    3408             : 
    3409        1157 :         for (oid rid = store->table_api.rids_next(joined); !is_oid_nil(rid); rid = store->table_api.rids_next(joined)) {
    3410         357 :                 sqlid fid = store->table_api.column_find_sqlid(tr, func_id, rid);
    3411         357 :                 sql_func *f = sql_trans_find_func(tr, fid); /* could have changed by depending changes */
    3412             :                 /* if it is on the same transaction, then don't dup it again */
    3413         357 :                 if (isNew(f) || os_obj_intransaction(f->s->funcs, tr, &f->base)) {
    3414         344 :                         if (f->instantiated) {
    3415             :                                 /* clean backend code */
    3416           0 :                                 backend_freecode(sql_shared_module_name, 0, f->imp);
    3417           0 :                                 f->instantiated = FALSE;
    3418           0 :                                 _DELETE(f->imp);
    3419             :                         }
    3420          13 :                 } else if ((res = func_dup(tr, f, f->s))) {
    3421           0 :                         store->table_api.rids_destroy(joined);
    3422           0 :                         return res;
    3423             :                 }
    3424             :         }
    3425         800 :         store->table_api.rids_destroy(joined);
    3426         800 :         return res;
    3427             : }
    3428             : 
    3429             : int
    3430        6869 : sql_trans_copy_key( sql_trans *tr, sql_table *t, sql_key *k, sql_key **kres)
    3431             : {
    3432        6869 :         sqlstore *store = tr->store;
    3433        6906 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    3434        6869 :         sql_table *syskey = find_sql_table(tr, syss, "keys");
    3435        6869 :         sql_table *syskc = find_sql_table(tr, syss, "objects");
    3436        6869 :         int neg = -1, action = -1, nr, res = LOG_OK;
    3437        6869 :         node *n;
    3438        6869 :         sql_key *nk;
    3439        6869 :         sql_table *dup = NULL;
    3440             : 
    3441        6869 :         if ((res = new_table(tr, t, &dup)))
    3442             :                 return res;
    3443        6869 :         t = dup;
    3444        6869 :         if ((res = key_dup(tr, k, t, &nk)))
    3445             :                 return res;
    3446        6869 :         sql_fkey *fk = (sql_fkey*)nk;
    3447        6869 :         if ((res = ol_add(t->keys, &nk->base)))
    3448             :                 return res;
    3449             : 
    3450        6869 :         if (nk->type == fkey)
    3451         925 :                 action = (fk->on_update<<8) + fk->on_delete;
    3452             : 
    3453        6869 :         char *strnil = (char*)ATOMnilptr(TYPE_str);
    3454        6869 :         if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action
    3455             :         , (nk->type == ckey)? &nk->check : &strnil )))
    3456             :                 return res;
    3457             : 
    3458        6869 :         if (nk->type == fkey) {
    3459         925 :                 sql_key *rkey = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    3460         925 :                 if (!rkey)
    3461             :                         return LOG_ERR;
    3462             : 
    3463         924 :                 if ((res = sql_trans_create_dependency(tr, rkey->base.id, nk->base.id, FKEY_DEPENDENCY)))
    3464             :                         return res;
    3465             :                 /* TODO this has to be cleaned out once the sql_cat.c cleanup is done */
    3466         924 :                 if (!isNew(rkey) && (res = sql_trans_add_dependency(tr, rkey->base.id, ddl)))
    3467             :                         return res;
    3468         924 :                 if (!isNew(rkey) && (res = sql_trans_add_dependency(tr, rkey->t->base.id, ddl))) /* this dependency is needed for merge tables */
    3469             :                         return res;
    3470         924 :                 if (!isNew(rkey) && isGlobal(rkey->t) && !isGlobalTemp(rkey->t) && (res = sql_trans_add_dependency(tr, rkey->t->base.id, dml))) /* disallow concurrent updates on other key */
    3471             :                         return res;
    3472         924 :                 if ((res = store_reset_sql_functions(tr, rkey->t->base.id))) /* reset sql functions depending on the table */
    3473             :                         return res;
    3474             :         }
    3475             : 
    3476       14367 :         for (n = nk->columns->h, nr = 0; n; n = n->next, nr++) {
    3477        7499 :                 sql_kc *kc = n->data;
    3478             : 
    3479        7499 :                 if ((res = store->table_api.table_insert(tr, syskc, &nk->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))))
    3480           0 :                         return res;
    3481             : 
    3482        7499 :                 if (nk->type == fkey) {
    3483         956 :                         if ((res = sql_trans_create_dependency(tr, kc->c->base.id, nk->base.id, FKEY_DEPENDENCY)))
    3484           0 :                                 return res;
    3485        6543 :                 } else if (nk->type == ukey || nk->type == ckey) {
    3486        2356 :                         if ((res = sql_trans_create_dependency(tr, kc->c->base.id, nk->base.id, KEY_DEPENDENCY)))
    3487           0 :                                 return res;
    3488        4187 :                 } else if (nk->type == pkey) {
    3489        4179 :                         if ((res = sql_trans_create_dependency(tr, kc->c->base.id, nk->base.id, KEY_DEPENDENCY)))
    3490           0 :                                 return res;
    3491        4179 :                         if ((res = sql_trans_alter_null(tr, kc->c, 0)))
    3492           0 :                                 return res;
    3493             :                 }
    3494             : 
    3495             :                 /* TODO this has to be cleaned out too */
    3496        7499 :                 if (!isNew(kc->c) && (res = sql_trans_add_dependency(tr, kc->c->base.id, ddl)))
    3497           0 :                         return res;
    3498             :         }
    3499        6868 :         if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
    3500             :                 return res;
    3501             : 
    3502             :         /* TODO this has to be cleaned out too */
    3503        6868 :         if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl))) /* this dependency is needed for merge tables */
    3504             :                 return res;
    3505        6868 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml))) /* disallow concurrent updates on t */
    3506             :                 return res;
    3507        6868 :         if (kres)
    3508           0 :                 *kres = nk;
    3509             :         return res;
    3510             : }
    3511             : 
    3512             : int
    3513        7166 : sql_trans_copy_idx( sql_trans *tr, sql_table *t, sql_idx *i, sql_idx **ires)
    3514             : {
    3515        7166 :         sqlstore *store = tr->store;
    3516        7216 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    3517        7166 :         sql_table *sysidx = find_sql_table(tr, syss, "idxs");
    3518        7166 :         sql_table *sysic = find_sql_table(tr, syss, "objects");
    3519        7166 :         node *n;
    3520        7166 :         int nr, res = LOG_OK, ncols = list_length(i->columns);
    3521        7166 :         sql_table *dup = NULL;
    3522             : 
    3523        7166 :         if ((res = new_table(tr, t, &dup)))
    3524             :                 return res;
    3525        7163 :         t = dup;
    3526        7163 :         sql_idx *ni = ZNEW(sql_idx);
    3527        7163 :         base_init(NULL, &ni->base, i->base.id?i->base.id:next_oid(tr->store), true, i->base.name);
    3528        7163 :         ni->columns = list_create((fdestroy) &kc_destroy);
    3529        7163 :         ni->t = t;
    3530        7163 :         ni->type = i->type;
    3531        7163 :         ni->key = NULL;
    3532        7163 :         ATOMIC_PTR_INIT(&ni->data, NULL);
    3533             : 
    3534       15050 :         for (n = i->columns->h, nr = 0; n; n = n->next, nr++) {
    3535        7887 :                 sql_kc *okc = n->data, *ic;
    3536             : 
    3537        7887 :                 list_append(ni->columns, ic = kc_dup(okc, t));
    3538        7887 :                 if (i->key && hash_index(i->type))
    3539        6514 :                         ic->c->unique = (ncols == 1) ? 2 : MAX(ic->c->unique, 1);
    3540        7887 :                 if ((res = store->table_api.table_insert(tr, sysic, &ni->base.id, &ic->c->base.name, &nr, ATOMnilptr(TYPE_int)))) {
    3541           0 :                         idx_destroy(store, ni);
    3542           0 :                         return res;
    3543             :                 }
    3544        7887 :                 if ((res = sql_trans_create_dependency(tr, ic->c->base.id, ni->base.id, INDEX_DEPENDENCY))) {
    3545           0 :                         idx_destroy(store, ni);
    3546           0 :                         return res;
    3547             :                 }
    3548             :         }
    3549        7163 :         if ((res = ol_add(t->idxs, &ni->base)))
    3550             :                 return res;
    3551             : 
    3552        7163 :         if (isGlobal(t) && (res = os_add(t->s->idxs, tr, ni->base.name, dup_base(&ni->base))))
    3553             :                 return res;
    3554        7163 :         if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
    3555             :                 return res;
    3556             : 
    3557             :         /* this dependency is needed for merge tables */
    3558        7163 :         if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl)))
    3559             :                 return res;
    3560        7163 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml)))
    3561             :                 return res;
    3562             : 
    3563        7163 :         if (isDeclaredTable(i->t))
    3564        7163 :                 if (!isDeclaredTable(t) && isTable(ni->t) && idx_has_column(ni->type))
    3565        6961 :                         if ((res = store->storage_api.create_idx(tr, ni))) {
    3566             :                                 ATOMIC_PTR_DESTROY(&ni->data);
    3567             :                                 return res;
    3568             :                         }
    3569        7163 :         if (!isDeclaredTable(t))
    3570        7163 :                 if ((res = store->table_api.table_insert(tr, sysidx, &ni->base.id, &t->base.id, &ni->type, &ni->base.name))) {
    3571             :                         ATOMIC_PTR_DESTROY(&ni->data);
    3572             :                         return res;
    3573             :                 }
    3574             : 
    3575        7163 :         if (ires)
    3576           0 :                 *ires = ni;
    3577             :         return res;
    3578             : }
    3579             : 
    3580             : int
    3581           0 : sql_trans_copy_trigger( sql_trans *tr, sql_table *t, sql_trigger *tri, sql_trigger **tres)
    3582             : {
    3583           0 :         sqlstore *store = tr->store;
    3584           0 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    3585           0 :         sql_table *systr = find_sql_table(tr, syss, "triggers");
    3586           0 :         sql_table *sysic = find_sql_table(tr, syss, "objects");
    3587           0 :         node *n;
    3588           0 :         int nr, res = LOG_OK;
    3589           0 :         sql_trigger *nt = ZNEW(sql_trigger);
    3590           0 :         char *strnil = (char*)ATOMnilptr(TYPE_str);
    3591             : 
    3592           0 :         base_init(NULL, &nt->base, tri->base.id?tri->base.id:next_oid(tr->store), true, tri->base.name);
    3593           0 :         nt->columns = list_create((fdestroy) &kc_destroy);
    3594           0 :         nt->t = t;
    3595           0 :         nt->time = tri->time;
    3596           0 :         nt->orientation = tri->orientation;
    3597           0 :         nt->event = tri->event;
    3598           0 :         nt->old_name = nt->new_name = nt->condition = NULL;
    3599           0 :         if (tri->old_name)
    3600           0 :                 nt->old_name =_STRDUP(tri->old_name);
    3601           0 :         if (tri->new_name)
    3602           0 :                 nt->new_name =_STRDUP(tri->new_name);
    3603           0 :         if (tri->condition)
    3604           0 :                 nt->condition =_STRDUP(tri->condition);
    3605           0 :         nt->statement =_STRDUP(tri->statement);
    3606             : 
    3607           0 :         for (n = tri->columns->h, nr = 0; n; n = n->next, nr++) {
    3608           0 :                 sql_kc *okc = n->data, *ic;
    3609             : 
    3610           0 :                 list_append(nt->columns, ic = kc_dup(okc, t));
    3611           0 :                 if ((res = store->table_api.table_insert(tr, sysic, &nt->base.id, &ic->c->base.name, &nr, ATOMnilptr(TYPE_int)))) {
    3612           0 :                         trigger_destroy(store, nt);
    3613           0 :                         return res;
    3614             :                 }
    3615           0 :                 if ((res = sql_trans_create_dependency(tr, ic->c->base.id, nt->base.id, TRIGGER_DEPENDENCY))) {
    3616           0 :                         trigger_destroy(store, nt);
    3617           0 :                         return res;
    3618             :                 }
    3619             :         }
    3620           0 :         if ((res = ol_add(t->triggers, &nt->base)))
    3621             :                 return res;
    3622             : 
    3623           0 :         assert(isGlobal(t));
    3624           0 :         if ((res = os_add(t->s->triggers, tr, nt->base.name, dup_base(&nt->base))))
    3625             :                 return res;
    3626           0 :         if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
    3627             :                 return res;
    3628             : 
    3629           0 :         if (!isDeclaredTable(t))
    3630           0 :                 if ((res = store->table_api.table_insert(tr, systr, &nt->base.id, &nt->base.name, &t->base.id, &nt->time, &nt->orientation,
    3631           0 :                                 &nt->event, (nt->old_name)?&nt->old_name:&strnil, (nt->new_name)?&nt->new_name:&strnil,
    3632           0 :                                 (nt->condition)?&nt->condition:&strnil, &nt->statement))) {
    3633             :                         return res;
    3634             :                 }
    3635             : 
    3636           0 :         if (tres)
    3637           0 :                 *tres = nt;
    3638             :         return res;
    3639             : }
    3640             : 
    3641             : static int
    3642      266100 : type_digits(sql_subtype *type)
    3643             : {
    3644      266100 :         int digits = type->digits;
    3645             : 
    3646      266100 :         if (digits && type->type->eclass == EC_NUM) {
    3647      108403 :                 if(type->type->localtype == TYPE_bte) {
    3648             :                         digits = 7;
    3649             :                 } else if(type->type->localtype == TYPE_sht) {
    3650             :                         digits = 15;
    3651             :                 } else if(type->type->localtype == TYPE_int) {
    3652             :                         digits = 31;
    3653             :                 } else if(type->type->localtype == TYPE_lng) {
    3654             :                         digits = 63;
    3655             : #ifdef HAVE_HGE
    3656             :                 } else if(type->type->localtype == TYPE_hge) {
    3657      266100 :                         digits = 127;
    3658             : #endif
    3659             :                 }
    3660             :         }
    3661      266100 :         return digits;
    3662             : }
    3663             : 
    3664             : int
    3665      256275 : sql_trans_copy_column( sql_trans *tr, sql_table *t, sql_column *c, sql_column **cres)
    3666             : {
    3667      256275 :         sqlstore *store = tr->store;
    3668      256392 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    3669      256275 :         sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    3670      256275 :         sql_table *dup = NULL;
    3671      256275 :         int res = LOG_OK;
    3672             : 
    3673      256275 :         if ((res = new_table(tr, t, &dup)))
    3674             :                 return res;
    3675      256273 :         t = dup;
    3676      256273 :         sql_column *col = ZNEW(sql_column);
    3677      256273 :         base_init(NULL, &col->base, c->base.id?c->base.id:next_oid(tr->store), true, c->base.name);
    3678      256273 :         dup_sql_type(tr, t->s, &(c->type), &(col->type));
    3679      256273 :         col->def = NULL;
    3680      256273 :         if (c->def)
    3681        1391 :                 col->def =_STRDUP(c->def);
    3682      256273 :         col->null = c->null;
    3683      256273 :         col->colnr = c->colnr;
    3684      256273 :         col->unique = c->unique;
    3685      256273 :         col->t = t;
    3686      256273 :         col->storage_type = NULL;
    3687      256273 :         if (c->storage_type)
    3688           0 :                 col->storage_type =_STRDUP(c->storage_type);
    3689             : 
    3690      256273 :         if ((res = ol_add(t->columns, &col->base)))
    3691             :                 return res;
    3692             : 
    3693             :         /* this dependency is needed for merge tables */
    3694      256273 :         if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl)))
    3695             :                 return res;
    3696      256273 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml)))
    3697             :                 return res;
    3698             : 
    3699      256273 :         ATOMIC_PTR_INIT(&col->data, NULL);
    3700      256273 :         if (isDeclaredTable(c->t))
    3701      256273 :                 if (isTable(t))
    3702       51914 :                         if ((res = store->storage_api.create_col(tr, col))) {
    3703             :                                 ATOMIC_PTR_DESTROY(&col->data);
    3704             :                                 return res;
    3705             :                         }
    3706             : 
    3707      256273 :         if (!isDeclaredTable(t)) {
    3708      256273 :                 char *strnil = (char*)ATOMnilptr(TYPE_str);
    3709      256273 :                 int digits = type_digits(&col->type);
    3710      256273 :                 if ((res = store->table_api.table_insert(tr, syscolumn, &col->base.id, &col->base.name, &col->type.type->base.name,
    3711             :                                         &digits, &col->type.scale, &t->base.id,
    3712      256273 :                                         (col->def) ? &col->def : &strnil, &col->null, &col->colnr,
    3713      256273 :                                         (col->storage_type) ? &col->storage_type : &strnil))) {
    3714             :                         ATOMIC_PTR_DESTROY(&col->data);
    3715           0 :                         return res;
    3716             :                 }
    3717      256273 :                 if (c->type.type->s) { /* column depends on type */
    3718         188 :                         if ((res = sql_trans_create_dependency(tr, c->type.type->base.id, col->base.id, TYPE_DEPENDENCY))) {
    3719             :                                 ATOMIC_PTR_DESTROY(&col->data);
    3720             :                                 return res;
    3721             :                         }
    3722         188 :                         if (!isNew(c->type.type) && (res = sql_trans_add_dependency(tr, c->type.type->base.id, ddl))) {
    3723             :                                 ATOMIC_PTR_DESTROY(&col->data);
    3724             :                                 return res;
    3725             :                         }
    3726             :                 }
    3727             :         }
    3728      256273 :         if (cres)
    3729      256165 :                 *cres = col;
    3730             :         return res;
    3731             : }
    3732             : 
    3733             : static int
    3734      158302 : clean_predicates_and_propagate_to_parent(sql_trans *tr)
    3735             : {
    3736      158302 :         int res = LOG_OK;
    3737             : 
    3738      158302 :         if (!list_empty(tr->predicates)) {
    3739        6003 :                 if (tr->parent) { /* propagate to the parent */
    3740           4 :                         for(node *n=tr->predicates->h; n && res == LOG_OK ; n = n->next) {
    3741           2 :                                 pl *p = (pl*) n->data;
    3742           2 :                                 atom *e1 = p->r ? atom_copy(NULL, p->r) : NULL, *e2 = p->f ? atom_copy(NULL, p->f) : NULL;
    3743             : 
    3744           2 :                                 res = sql_trans_add_predicate(tr->parent, p->c, p->cmp, e1, e2, p->anti, p->semantics);
    3745             :                         }
    3746             :                 }
    3747        6003 :                 list_destroy(tr->predicates);
    3748        6003 :                 tr->predicates = NULL;
    3749             :         }
    3750      158301 :         if (!list_empty(tr->dependencies)) {
    3751        2730 :                 if (tr->parent) { /* propagate to the parent */
    3752           6 :                         for(node *n=tr->dependencies->h; n && res == LOG_OK ; n = n->next) {
    3753           4 :                                 sql_dependency_change *dp = (sql_dependency_change*)n->data;
    3754           4 :                                 res = sql_trans_add_dependency(tr->parent, dp->objid, dp->type);
    3755             :                         }
    3756             :                 }
    3757        2730 :                 list_destroy(tr->dependencies);
    3758        2730 :                 tr->dependencies = NULL;
    3759             :         }
    3760      158300 :         if (!list_empty(tr->depchanges)) {
    3761       56669 :                 if (tr->parent) { /* propagate to the parent */
    3762           6 :                         for(node *n=tr->depchanges->h; n && res == LOG_OK ; n = n->next) {
    3763           3 :                                 sql_dependency_change *dp = (sql_dependency_change*)n->data;
    3764           3 :                                 res = sql_trans_add_dependency_change(tr->parent, dp->objid, dp->type);
    3765             :                         }
    3766             :                 }
    3767       56669 :                 list_destroy(tr->depchanges);
    3768       56672 :                 tr->depchanges = NULL;
    3769             :         }
    3770      158301 :         return res;
    3771             : }
    3772             : 
    3773             : static void
    3774       63345 : sql_trans_rollback(sql_trans *tr, bool commit_lock)
    3775             : {
    3776       63345 :         sqlstore *store = tr->store;
    3777       63345 :         if (!list_empty(tr->changes)) {
    3778        2052 :                 struct os_iter oi;
    3779        2052 :                 os_iterator(&oi, tr->localtmps, tr, NULL);
    3780        3226 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    3781        1174 :                         sql_table *t = (sql_table *) b;
    3782        1174 :                         if (t->commit_action == CA_DROP && !b->deleted) {
    3783           3 :                                 (void) sql_trans_drop_table_id(tr, t->s, b->id, DROP_RESTRICT);// TODO transaction_layer_revamp: fix result code sql_trans_drop_table_id
    3784             :                         }
    3785             :                 }
    3786             :                 /* revert the change list */
    3787        2052 :                 list *nl = tr->changes;
    3788        2052 :                 list_revert(nl);
    3789             : 
    3790             :                 /* rollback */
    3791        2052 :                 if (!commit_lock)
    3792        1141 :                         MT_lock_set(&store->commit);
    3793        2052 :                 store_lock(store);
    3794        2052 :                 ulng oldest = store_oldest(store, tr);
    3795        2052 :                 ulng commit_ts = store_get_timestamp(store); /* use most recent timestamp such that we can cleanup safely */
    3796       13857 :                 for(node *n=nl->h; n; n = n->next) {
    3797       11805 :                         sql_change *c = n->data;
    3798             : 
    3799       11805 :                         if (!c)
    3800           0 :                                 continue;
    3801       11805 :                         if (c->commit)
    3802       11805 :                                 c->commit(tr, c, 0 /* ie rollback */, oldest);
    3803       11805 :                         c->ts = commit_ts;
    3804             :                 }
    3805        2052 :                 store_pending_changes(store, oldest, tr);
    3806       13857 :                 for(node *n=nl->h; n; n = n->next) {
    3807       11805 :                         sql_change *c = n->data;
    3808             : 
    3809       11805 :                         if (!c)
    3810           0 :                                 continue;
    3811       11805 :                         if (!c->cleanup) {
    3812           0 :                                 _DELETE(c);
    3813       11805 :                         } else if (c->cleanup && !c->cleanup(store, c, oldest)) {
    3814             :                                 /* TODO change to node stealing (no allocs here) */
    3815        8613 :                                 store->changes = list_add(store->changes, c);
    3816             :                         } else
    3817       11805 :                                 _DELETE(c);
    3818             :                 }
    3819        2052 :                 store_unlock(store);
    3820        2052 :                 if (!commit_lock)
    3821        1141 :                         MT_lock_unset(&store->commit);
    3822        2052 :                 list_destroy(tr->changes);
    3823        2052 :                 tr->changes = NULL;
    3824        2052 :                 tr->logchanges = 0;
    3825             :         } else {
    3826       61293 :                 if (commit_lock || MT_lock_try(&store->commit)) {
    3827       44890 :                         store_lock(store);
    3828       44890 :                         ulng oldest = store_oldest(store, tr);
    3829       44890 :                         store_pending_changes(store, oldest, tr);
    3830       44890 :                         store_unlock(store);
    3831       44890 :                         if (!commit_lock)
    3832       44890 :                                 MT_lock_unset(&store->commit);
    3833             :                 }
    3834             :         }
    3835             : 
    3836       63344 :         if (!list_empty(tr->predicates)) {
    3837        1177 :                 list_destroy(tr->predicates);
    3838        1177 :                 tr->predicates = NULL;
    3839             :         }
    3840       63344 :         if (!list_empty(tr->dependencies)) {
    3841         183 :                 list_destroy(tr->dependencies);
    3842         183 :                 tr->dependencies = NULL;
    3843             :         }
    3844       63344 :         if (!list_empty(tr->depchanges)) {
    3845         972 :                 list_destroy(tr->depchanges);
    3846         972 :                 tr->depchanges = NULL;
    3847             :         }
    3848       63344 : }
    3849             : 
    3850             : sql_trans *
    3851       38267 : sql_trans_destroy(sql_trans *tr)
    3852             : {
    3853       38267 :         sql_trans *res = tr->parent;
    3854             : 
    3855       38267 :         TRC_DEBUG(SQL_STORE, "Destroy transaction: %p\n", tr);
    3856       38267 :         _DELETE(tr->name);
    3857       38267 :         assert(!tr->active || tr->parent);
    3858       38267 :         if (!list_empty(tr->changes))
    3859          19 :                 sql_trans_rollback(tr, false);
    3860       38267 :         sqlstore *store = tr->store;
    3861       38267 :         os_destroy(tr->localtmps, store);
    3862       38267 :         MT_lock_destroy(&tr->lock);
    3863       38267 :         if (!list_empty(tr->dropped))
    3864           0 :                 list_destroy(tr->dropped);
    3865       38267 :         _DELETE(tr);
    3866       38267 :         return res;
    3867             : }
    3868             : 
    3869             : static sql_trans *
    3870       38267 : sql_trans_create_(sqlstore *store, sql_trans *parent, const char *name)
    3871             : {
    3872       38267 :         if (name && !parent)            /* unlikely */
    3873             :                 return NULL;
    3874             : 
    3875       38267 :         sql_trans *tr = ZNEW(sql_trans);
    3876             : 
    3877       38267 :         if (!tr)
    3878             :                 return NULL;
    3879       38267 :         MT_lock_init(&tr->lock, "trans_lock");
    3880       38267 :         tr->parent = parent;
    3881       38267 :         if (name) {
    3882          62 :                 _DELETE(parent->name);
    3883          62 :                 parent->name = _STRDUP(name);
    3884             :         }
    3885             : 
    3886       38267 :         if (!parent) {
    3887       38205 :                 tr->localtmps = os_new(NULL, (destroy_fptr) &table_destroy, true, true, false, false, store);
    3888             :         }
    3889             :         else {
    3890          62 :                 tr->localtmps = os_dup(parent->localtmps);
    3891             :         }
    3892             : 
    3893       38267 :         store_lock(store);
    3894       38267 :         tr->store = store;
    3895       38267 :         tr->tid = store_transaction_id(store);
    3896       38267 :         tr->cat = store->cat;
    3897       38267 :         if (!tr->cat) {
    3898         331 :                 store->cat = tr->cat = ZNEW(sql_catalog);
    3899         331 :                 store->cat->schemas = os_new(NULL, (destroy_fptr) &schema_destroy, false, true, true, true, store);
    3900         331 :                 store->cat->objects = os_new(NULL, (destroy_fptr) &key_destroy, false, false, true, false, store);
    3901         331 :                 ATOMIC_INIT(&store->cat->schema_version, 0);
    3902             :         }
    3903       38267 :         tr->tmp = store->tmp;
    3904       38267 :         TRC_DEBUG(SQL_STORE, "New transaction: %p\n", tr);
    3905       38267 :         store_unlock(store);
    3906       38267 :         return tr;
    3907             : }
    3908             : 
    3909             : static int
    3910          40 : schema_dup(sql_trans *tr, sql_schema *s, const char *name, sql_schema **rs)
    3911             : {
    3912          40 :         sql_schema *ns = ZNEW(sql_schema);
    3913          40 :         int res = LOG_OK;
    3914             : 
    3915          40 :         base_init(NULL, &ns->base, s->base.id, 0, name);
    3916          40 :         ns->auth_id = s->auth_id;
    3917          40 :         ns->owner = s->owner;
    3918          40 :         ns->system = s->system;
    3919             : 
    3920          40 :         sqlstore *store = tr->store;
    3921          40 :         assert(!isTempSchema(s)); // TODO transaction_layer_revamp: check if this is really true
    3922          40 :         ns->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
    3923          40 :         ns->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
    3924          40 :         ns->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
    3925          40 :         ns->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
    3926          40 :         ns->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
    3927          40 :         ns->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
    3928             : 
    3929             :         /* table_dup will dup keys, idxs, triggers and parts */
    3930          40 :         struct os_iter oi;
    3931          40 :         os_iterator(&oi, s->tables, tr, NULL);
    3932          41 :         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    3933           1 :                 sql_table *t = NULL;
    3934           1 :                 if ((res = table_dup(tr, (sql_table*)b, ns, NULL, &t, true))) {
    3935           0 :                         schema_destroy(tr->store, ns);
    3936           0 :                         return res;
    3937             :                 }
    3938             :         }
    3939             : 
    3940             :         /* we can share the funcs and types */
    3941          40 :         ns->funcs = os_dup(s->funcs);
    3942          40 :         ns->types = os_dup(s->types);
    3943          40 :         ns->store = s->store;
    3944          40 :         ns->internal = NULL;
    3945          40 :         *rs = ns;
    3946          40 :         return res;
    3947             : }
    3948             : 
    3949             : sql_trans *
    3950         393 : sql_trans_create(sqlstore *store, sql_trans *parent, const char *name)
    3951             : {
    3952         393 :         sql_trans *tr = sql_trans_create_(store, parent, name);
    3953         393 :         if (tr) {
    3954         393 :                 tr->ts = store_timestamp(store);
    3955         393 :                 tr->active = 1;
    3956             :         }
    3957         393 :         return tr;
    3958             : }
    3959             : 
    3960             : static int
    3961        6804 : sql_trans_valid(sql_trans *tr)
    3962             : {
    3963        6804 :         int ok = LOG_OK;
    3964        6804 :         sqlstore *store = tr->store;
    3965             : 
    3966        6804 :         if (!list_empty(tr->predicates)) {
    3967             :                 /* for each predicate check if that table/column has changes */
    3968       26922 :                 for(node *n = tr->predicates->h; n; n = n->next) {
    3969       20981 :                         pl *p = n->data;
    3970       20981 :                         sql_column *c = p->c;
    3971             : 
    3972       20981 :                         if (c->t && isTable(c->t) && !isNew(c) && !isTempTable(c->t)) {
    3973       20979 :                                 if ((ok = store->storage_api.tab_validate(tr, c->t, 0)))
    3974             :                                         break;
    3975             :                         }
    3976             :                 }
    3977             :         }
    3978        6804 :         return ok;
    3979             : }
    3980             : 
    3981             : static inline int
    3982       68166 : transaction_add_hash_entry(sql_hash *h, sqlid id, sql_dependency_change_type tpe, ulng ts)
    3983             : {
    3984       68166 :         sql_dependency_change *next_change = MNEW(sql_dependency_change);
    3985             : 
    3986       68166 :         if (!next_change)
    3987             :                 return LOG_ERR;
    3988       68166 :         *next_change = (sql_dependency_change) {
    3989             :                 .objid = id,
    3990             :                 .type = tpe,
    3991             :                 .ts = ts
    3992             :         };
    3993             : 
    3994       68166 :         int key = h->key(next_change);
    3995       68166 :         sql_hash_e *he = h->buckets[key&(h->size-1)];
    3996             : 
    3997      234669 :         for (; he ; he = he->chain) { /* find if the entry is already present */
    3998      192027 :                 sql_dependency_change *schange = (sql_dependency_change*) he->value;
    3999             : 
    4000      192027 :                 if (schange->objid == id && schange->ts == ts && schange->type == tpe) {
    4001       25524 :                         _DELETE(next_change);
    4002       25524 :                         return LOG_OK;
    4003             :                 }
    4004             :         }
    4005             : 
    4006       42642 :         if (!hash_add(h, key, next_change)) {
    4007           0 :                 _DELETE(next_change);
    4008           0 :                 return LOG_ERR;
    4009             :         }
    4010             :         return LOG_OK;
    4011             : }
    4012             : 
    4013             : static int
    4014       58662 : transaction_check_dependencies_and_removals(sql_trans *tr)
    4015             : {
    4016       58662 :         int ok = LOG_OK;
    4017       58662 :         sqlstore *store = tr->store;
    4018             : 
    4019             :         /* test dependencies and removals crossed for conflicts */
    4020       58662 :         if (!list_empty(tr->dependencies) && !hash_empty(store->depchanges)) {
    4021          68 :                 for (node *n = tr->dependencies->h; n && ok == LOG_OK; n = n->next) {
    4022          42 :                         sql_dependency_change *lchange = (sql_dependency_change*) n->data;
    4023          42 :                         int key = store->depchanges->key(lchange);
    4024          42 :                         sql_hash_e *he = store->depchanges->buckets[key&(store->depchanges->size-1)];
    4025             : 
    4026          67 :                         for (; he && ok == LOG_OK; he = he->chain) {
    4027          25 :                                 sql_dependency_change *schange = (sql_dependency_change*) he->value;
    4028             : 
    4029             :                                 /* conflict only if transactions overlap */
    4030          25 :                                 if (schange->ts >= tr->ts && lchange->objid == schange->objid && lchange->type == schange->type)
    4031          25 :                                         ok = LOG_CONFLICT;
    4032             :                         }
    4033             :                 }
    4034             :         }
    4035       58662 :         if (ok == LOG_OK && !list_empty(tr->depchanges) && !hash_empty(store->dependencies)) {
    4036          87 :                 for (node *n = tr->depchanges->h; n && ok == LOG_OK; n = n->next) {
    4037          51 :                         sql_dependency_change *lchange = (sql_dependency_change*) n->data;
    4038          51 :                         int key = store->dependencies->key(lchange);
    4039          51 :                         sql_hash_e *he = store->dependencies->buckets[key&(store->dependencies->size-1)];
    4040             : 
    4041          89 :                         for (; he && ok == LOG_OK; he = he->chain) {
    4042          38 :                                 sql_dependency_change *schange = (sql_dependency_change*) he->value;
    4043             : 
    4044             :                                 /* conflict only if transactions overlap */
    4045          38 :                                 if (schange->ts >= tr->ts && lchange->objid == schange->objid && lchange->type == schange->type)
    4046          38 :                                         ok = LOG_CONFLICT;
    4047             :                         }
    4048             :                 }
    4049             :         }
    4050       58662 :         return ok;
    4051             : }
    4052             : 
    4053             : int
    4054      159211 : sql_trans_commit(sql_trans *tr)
    4055             : {
    4056      159211 :         int ok = LOG_OK;
    4057      159211 :         sqlstore *store = tr->store;
    4058             : 
    4059      159211 :         if (!list_empty(tr->changes)) {
    4060       66325 :                 struct os_iter oi;
    4061       66325 :                 os_iterator(&oi, tr->localtmps, tr, NULL);
    4062       88173 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    4063       21848 :                         sql_table *t = (sql_table *) b;
    4064       21848 :                         if (t->commit_action == CA_DROP && !b->deleted) {
    4065       21848 :                                 (void) sql_trans_drop_table_id(tr, t->s, b->id, DROP_RESTRICT);;// TODO transaction_layer_revamp: fix result code sql_trans_drop_table_id
    4066             :                         }
    4067             :                 }
    4068             : 
    4069       66325 :                 bool flush = false;
    4070       66325 :                 ulng commit_ts = 0, oldest = 0, log_file_id = 0;
    4071             : 
    4072       66325 :                 MT_lock_set(&store->commit);
    4073             : 
    4074       66325 :                 if (!tr->parent && !list_empty(tr->predicates)) {
    4075        6804 :                         ok = sql_trans_valid(tr);
    4076        6804 :                         if (ok != LOG_OK) {
    4077         863 :                                 sql_trans_rollback(tr, true);
    4078         863 :                                 MT_lock_unset(&store->commit);
    4079        1774 :                                 return ok == LOG_CONFLICT ? SQL_CONFLICT : SQL_ERR;
    4080             :                         }
    4081             :                 }
    4082             : 
    4083      130907 :                 if (!tr->parent &&
    4084      128136 :                         (!list_empty(tr->dependencies) || !list_empty(tr->depchanges))) {
    4085       58662 :                         ok = transaction_check_dependencies_and_removals(tr);
    4086       58662 :                         if (ok != LOG_OK) {
    4087          48 :                                 sql_trans_rollback(tr, true);
    4088          48 :                                 MT_lock_unset(&store->commit);
    4089          48 :                                 return ok == LOG_CONFLICT ? SQL_CONFLICT : SQL_ERR;
    4090             :                         }
    4091             :                 }
    4092             : 
    4093             :                 /* log changes should only be done if there is something to log */
    4094       65414 :                 const bool log = !tr->parent && tr->logchanges > 0;
    4095             : 
    4096       62493 :                 if (log) {
    4097       62493 :                         const lng min_changes = ATOMIC_GET(&GDKdebug) & TESTINGMASK ? 5 : 1000000;
    4098       62493 :                         flush = (tr->logchanges > min_changes && list_empty(store->changes));
    4099             :                 }
    4100             : 
    4101        5571 :                 if (flush)
    4102        5571 :                         MT_lock_set(&store->flush);
    4103       65414 :                 if (log) {
    4104       62493 :                         ok = store->logger_api.log_tstart(store, flush, &log_file_id); /* wal start */
    4105             :                         /* log */
    4106      521705 :                         for(node *n=tr->changes->h; n && ok == LOG_OK; n = n->next) {
    4107      459212 :                                 sql_change *c = n->data;
    4108             : 
    4109      459212 :                                 if (c->log && ok == LOG_OK)
    4110      253555 :                                         ok = c->log(tr, c);
    4111             :                         }
    4112       62493 :                         if (ok == LOG_OK && !list_empty(store->seqchanges)) {
    4113         631 :                                 sequences_lock(store);
    4114        1397 :                                 for(node *n = store->seqchanges->h; n; ) {
    4115         766 :                                         node *next = n->next;
    4116         766 :                                         log_store_sequence(store, n->data);
    4117         766 :                                         list_remove_node(store->seqchanges, NULL, n);
    4118         766 :                                         n = next;
    4119             :                                 }
    4120         631 :                                 sequences_unlock(store);
    4121             :                         }
    4122       62493 :                         if (ok == LOG_OK && store->prev_oid != store->obj_id) {
    4123        6135 :                                 if (!flush)
    4124        2105 :                                         MT_lock_set(&store->flush);
    4125        6135 :                                 ok = store->logger_api.log_tsequence(store, OBJ_SID, store->obj_id);
    4126        6135 :                                 if (!flush)
    4127        2105 :                                         MT_lock_unset(&store->flush);
    4128             :                         }
    4129       62493 :                         store->prev_oid = store->obj_id;
    4130             : 
    4131             : 
    4132       62493 :                         if (ok == LOG_OK)
    4133       62493 :                                 ok = store->logger_api.log_tend(store); /* wal end */
    4134             :                 }
    4135       65414 :                 store_lock(store);
    4136             : 
    4137       65414 :                 if (tr->parent) {
    4138          17 :                         commit_ts = oldest = tr->parent->tid;
    4139          17 :                         tr->parent->logchanges += tr->logchanges;
    4140             :                 } else {
    4141       65397 :                         commit_ts = store_timestamp(store);
    4142       65397 :                         oldest = store_oldest(store, tr);
    4143             :                 }
    4144       65414 :                 tr->logchanges = 0;
    4145       65414 :                 TRC_DEBUG(SQL_STORE, "Forwarding changes (" ULLFMT ", " ULLFMT ") -> " ULLFMT "\n", tr->tid, tr->ts, commit_ts);
    4146             :                 /* apply committed changes */
    4147       65414 :                 if (ATOMIC_GET(&store->nr_active) == 1 && !tr->parent)
    4148       65414 :                         oldest = commit_ts;
    4149       65414 :                 store_pending_changes(store, oldest, tr);
    4150      608803 :                 for(node *n=tr->changes->h; n && ok == LOG_OK; n = n->next) {
    4151      543389 :                         sql_change *c = n->data;
    4152             : 
    4153      543389 :                         if (c->commit && ok == LOG_OK)
    4154      543389 :                                 ok = c->commit(tr, c, commit_ts, oldest);
    4155             :                         else
    4156           0 :                                 c->obj->new = 0;
    4157      543389 :                         c->ts = commit_ts;
    4158             :                 }
    4159             :                 /* propagate transaction dependencies to the storage only if other transactions are running */
    4160       65414 :                 if (ok == LOG_OK && !tr->parent && ATOMIC_GET(&store->nr_active) > 1) {
    4161       42529 :                         if (!list_empty(tr->dependencies)) {
    4162         253 :                                 for (node *n = tr->dependencies->h; n && ok == LOG_OK; n = n->next) {
    4163         191 :                                         sql_dependency_change *lchange = (sql_dependency_change*) n->data;
    4164         191 :                                         ok = transaction_add_hash_entry(store->dependencies, lchange->objid, lchange->type, commit_ts);
    4165             :                                 }
    4166             :                         }
    4167       42529 :                         if (!list_empty(tr->depchanges)) {
    4168      110435 :                                 for (node *n = tr->depchanges->h; n && ok == LOG_OK; n = n->next) {
    4169       67975 :                                         sql_dependency_change *lchange = (sql_dependency_change*) n->data;
    4170       67975 :                                         ok = transaction_add_hash_entry(store->depchanges, lchange->objid, lchange->type, commit_ts);
    4171             :                                 }
    4172             :                         }
    4173             :                 }
    4174             :                 /* garbage collect */
    4175      608803 :                 for(node *n=tr->changes->h; n && ok == LOG_OK; ) {
    4176      543389 :                         node *next = n->next;
    4177      543389 :                         sql_change *c = n->data;
    4178             : 
    4179      543389 :                         n->data = NULL;
    4180      543389 :                         if (c) {
    4181      543389 :                                 if (!c->cleanup || c->cleanup(store, c, oldest)) {
    4182      370769 :                                         _DELETE(c);
    4183      172620 :                                 } else if (tr->parent) { /* need to keep everything */
    4184          37 :                                         tr->parent->changes = list_add(tr->parent->changes, c);
    4185             :                                 } else {
    4186      172583 :                                         store->changes = list_add(store->changes, c);
    4187             :                                 }
    4188             :                         }
    4189             :                         n = next;
    4190             :                 }
    4191       65414 :                 tr->active = 2; /* small hack enabling to signal that this transaction has committed */
    4192       65414 :                 tr->ts = commit_ts; /* fix profiler output */
    4193       65414 :                 store_unlock(store);
    4194             :                 /* flush the log structure */
    4195       65414 :                 if (log) {
    4196       62493 :                         if (!flush)
    4197       56922 :                                 MT_lock_unset(&store->commit); /* release the commit log when flushing to disk */
    4198       62493 :                         if (ok == LOG_OK)
    4199       62493 :                                 ok = store->logger_api.log_tflush(store, log_file_id, commit_ts); /* flush/sync */
    4200       62493 :                         if (!flush)
    4201       56922 :                                 MT_lock_set(&store->commit); /* release the commit log when flushing to disk */
    4202       56922 :                         if (flush)
    4203        5571 :                                 MT_lock_unset(&store->flush);
    4204             :                 }
    4205       65414 :                 MT_lock_unset(&store->commit);
    4206       65414 :                 if (ok == LOG_OK) {
    4207       65414 :                         list_destroy(tr->changes);
    4208       65414 :                         tr->changes = NULL;
    4209             :                 }
    4210       92888 :         } else if (ATOMIC_GET(&store->nr_active) == 1) { /* just me cleanup */
    4211       45233 :                 MT_lock_set(&store->commit);
    4212       45233 :                 store_lock(store);
    4213       45233 :                 ulng oldest = store_timestamp(store);
    4214       45233 :                 store_pending_changes(store, oldest, tr);
    4215       45233 :                 store_unlock(store);
    4216       45233 :                 MT_lock_unset(&store->commit);
    4217             :         }
    4218             : 
    4219      110647 :         if (ok == LOG_OK)
    4220      158302 :                 ok = clean_predicates_and_propagate_to_parent(tr);
    4221             : 
    4222      158302 :         return (ok==LOG_OK)?SQL_OK:SQL_ERR;
    4223             : }
    4224             : 
    4225             : static sql_table *
    4226           5 : find_table_by_columnid(sql_trans *tr, const char *schema, sqlid id)
    4227             : {
    4228           5 :         sqlstore *store = tr->store;
    4229           5 :         sql_table *syscolumn = find_sql_table(tr, find_sql_schema(tr, schema), "_columns");
    4230             : 
    4231           5 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"), &id, NULL);
    4232           5 :         if (!is_oid_nil(rid)) {
    4233           5 :                 sqlid tid = store->table_api.column_find_sqlid(tr, find_sql_column(syscolumn, "table_id"), rid);
    4234           5 :                 return sql_trans_find_table(tr, tid);
    4235             :         }
    4236             :         return NULL;
    4237             : }
    4238             : 
    4239             : static int
    4240        5155 : sql_trans_drop_all_dependencies(sql_trans *tr, sqlid id, sql_dependency type)
    4241             : {
    4242        5155 :         sqlid dep_id=0, t_id = -1;
    4243        5155 :         sht dep_type = 0;
    4244        5155 :         list *dep = sql_trans_get_dependents(tr, id, type, NULL);
    4245        5155 :         node *n;
    4246        5155 :         int res = LOG_OK;
    4247             : 
    4248        5155 :         if (!dep)
    4249             :                 return -1;
    4250             : 
    4251        5155 :         n = dep->h;
    4252             : 
    4253        5526 :         while (n && !res) {
    4254         371 :                 dep_id = *(sqlid*) n->data;
    4255         371 :                 dep_type = (sql_dependency) *(sht*) n->next->data;
    4256             : 
    4257         371 :                 if (!list_find_id(tr->dropped, dep_id)) {
    4258             : 
    4259         367 :                         switch (dep_type) {
    4260           0 :                                 case SCHEMA_DEPENDENCY:
    4261           0 :                                         res = sql_trans_drop_schema(tr, dep_id, DROP_CASCADE);
    4262           0 :                                         break;
    4263          47 :                                 case TABLE_DEPENDENCY:
    4264             :                                 case VIEW_DEPENDENCY: {
    4265          47 :                                         sql_table *t = sql_trans_find_table(tr, dep_id);
    4266          47 :                                         if (t)
    4267          47 :                                                 res = sql_trans_drop_table_id(tr, t->s, dep_id, DROP_CASCADE);
    4268             :                                         } break;
    4269           0 :                                 case COLUMN_DEPENDENCY: {
    4270           0 :                                         if ((t_id = sql_trans_get_dependency_type(tr, dep_id, TABLE_DEPENDENCY)) > 0) {
    4271           0 :                                                 sql_table *t = sql_trans_find_table(tr, dep_id);
    4272           0 :                                                 if (t && ol_length(t->columns) == 1) /* only column left, drop the table instead */
    4273           0 :                                                         res = sql_trans_drop_table_id(tr, t->s, t->base.id, DROP_CASCADE);
    4274           0 :                                                 else if (t)
    4275           0 :                                                         res = sql_trans_drop_column(tr, t, dep_id, DROP_CASCADE);
    4276             :                                         }
    4277             :                                         } break;
    4278           2 :                                 case TRIGGER_DEPENDENCY: {
    4279           2 :                                         sql_trigger *t = sql_trans_find_trigger(tr, dep_id);
    4280           2 :                                         if (t && !list_find_id(tr->dropped, t->t->base.id)) /* table not yet dropped */
    4281           2 :                                                  res = sql_trans_drop_trigger(tr, t->t->s, dep_id, DROP_CASCADE);
    4282             :                                         } break;
    4283         278 :                                 case KEY_DEPENDENCY:
    4284             :                                 case FKEY_DEPENDENCY: {
    4285         278 :                                         sql_key *k = sql_trans_find_key(tr, dep_id);
    4286         278 :                                         if (k && !list_find_id(tr->dropped, k->t->base.id)) /* table not yet dropped */
    4287         277 :                                                 res = sql_trans_drop_key(tr, k->t->s, dep_id, DROP_CASCADE);
    4288             :                                         } break;
    4289           8 :                                 case INDEX_DEPENDENCY: {
    4290           8 :                                         sql_idx *i = sql_trans_find_idx(tr, dep_id);
    4291           8 :                                         if (i && !list_find_id(tr->dropped, i->t->base.id)) /* table not yet dropped */
    4292           8 :                                                 res = sql_trans_drop_idx(tr, i->t->s, dep_id, DROP_CASCADE);
    4293             :                                         } break;
    4294          18 :                                 case PROC_DEPENDENCY:
    4295             :                                 case FUNC_DEPENDENCY: {
    4296          18 :                                         sql_func *f = sql_trans_find_func(tr, dep_id);
    4297          18 :                                         if (f)
    4298          18 :                                                 res = sql_trans_drop_func(tr, f->s, dep_id, DROP_CASCADE);
    4299             :                                         } break;
    4300          14 :                                 case TYPE_DEPENDENCY: {
    4301             :                                         /* Unlike other dependencies, for type dependencies,
    4302             :                                            the dependent object depends on the type, rather the other way around.
    4303             :                                            At this moment, only functions or columns depend on types, so try both */
    4304          14 :                                         sql_table *t = NULL;
    4305          14 :                                         sql_func *f = sql_trans_find_func(tr, dep_id);
    4306          14 :                                         if (f) {
    4307           9 :                                                 res = sql_trans_drop_func(tr, f->s, dep_id, DROP_CASCADE);
    4308           5 :                                         } else if ((t = find_table_by_columnid(tr, "sys", dep_id)) ||
    4309           0 :                                                            (t = find_table_by_columnid(tr, "tmp", dep_id))) {
    4310           5 :                                                 if (ol_length(t->columns) == 1) /* only column left, drop the table instead */
    4311           2 :                                                         res = sql_trans_drop_table_id(tr, t->s, t->base.id, DROP_CASCADE);
    4312             :                                                 else
    4313           3 :                                                         res = sql_trans_drop_column(tr, t, dep_id, DROP_CASCADE);
    4314             :                                         }
    4315             :                                         } break;
    4316             :                                 case USER_DEPENDENCY:  /*TODO schema and users dependencies*/
    4317             :                                         break;
    4318             :                         }
    4319             :                 }
    4320             : 
    4321         371 :                 n = n->next->next;
    4322             :         }
    4323        5155 :         list_destroy(dep);
    4324        5155 :         return res;
    4325             : }
    4326             : 
    4327             : static int
    4328        2646 : sys_drop_ic(sql_trans *tr, sql_idx * i, sql_kc *kc)
    4329             : {
    4330        2646 :         sqlstore *store = tr->store;
    4331        2701 :         sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
    4332        2646 :         sql_table *sysic = find_sql_table(tr, syss, "objects");
    4333        2646 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(sysic, "id"), &i->base.id, find_sql_column(sysic, "name"), kc->c->base.name, NULL);
    4334        2646 :         int res = LOG_OK;
    4335             : 
    4336        2646 :         if (is_oid_nil(rid))
    4337             :                 return -1;
    4338        2646 :         if ((res = store->table_api.table_delete(tr, sysic, rid)))
    4339             :                 return res;
    4340             :         return res;
    4341             : }
    4342             : 
    4343             : static int
    4344       36454 : sql_trans_drop_any_comment(sql_trans *tr, sqlid id)
    4345             : {
    4346       36454 :         sqlstore *store = tr->store;
    4347       36454 :         sql_table *comments;
    4348       36454 :         sql_column *id_col;
    4349       36454 :         oid row;
    4350             : 
    4351       36454 :         comments = find_sql_table(tr, find_sql_schema(tr, "sys"), "comments");
    4352       36454 :         if (!comments) /* for example during upgrades */
    4353             :                 return 0;
    4354             : 
    4355       36454 :         id_col = find_sql_column(comments, "id");
    4356       36454 :         assert(id_col);
    4357             : 
    4358       36454 :         row = store->table_api.column_find_row(tr, id_col, &id, NULL);
    4359       36454 :         if (!is_oid_nil(row) && store->table_api.table_delete(tr, comments, row))
    4360             :                 return -2;
    4361             :         return 0;
    4362             : }
    4363             : 
    4364             : static int
    4365        2164 : sys_drop_idx(sql_trans *tr, sql_idx * i, int drop_action)
    4366             : {
    4367        2164 :         sqlstore *store = tr->store;
    4368        2164 :         node *n;
    4369        2208 :         sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
    4370        2164 :         sql_table *sysidx = find_sql_table(tr, syss, "idxs");
    4371        2164 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(sysidx, "id"), &i->base.id, NULL);
    4372        2164 :         int res = LOG_OK;
    4373             : 
    4374        2164 :         if (is_oid_nil(rid))
    4375             :                 return -1;
    4376        2164 :         if ((res = store->table_api.table_delete(tr, sysidx, rid)))
    4377             :                 return res;
    4378        2164 :         if ((res = sql_trans_drop_any_comment(tr, i->base.id)))
    4379             :                 return res;
    4380        4810 :         for (n = i->columns->h; n; n = n->next) {
    4381        2646 :                 sql_kc *ic = n->data;
    4382             : 
    4383        2646 :                 if (i->key && hash_index(i->type)) { /* update new column's unique value */
    4384        1526 :                         int unique = 0;
    4385        1526 :                         sqlid cid = ic->c->base.id;
    4386        1526 :                         struct os_iter oi;
    4387             : 
    4388        1526 :                         os_iterator(&oi, i->t->s->idxs, tr, NULL);
    4389       44099 :                         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    4390       42573 :                                 sql_idx *ti = (sql_idx*)b;
    4391             : 
    4392       42573 :                                 if (ti->base.id != i->base.id && ti->key && hash_index(ti->type)) {
    4393       35082 :                                         bool found = false;
    4394       76303 :                                         for (node *m = ti->columns->h; m && !found; m = m->next) {
    4395       41221 :                                                 sql_kc *tic = m->data;
    4396             : 
    4397       41221 :                                                 found |= tic->c->base.id == cid;
    4398             :                                         }
    4399       35082 :                                         if (found)
    4400          21 :                                                 unique = MAX(unique, list_length(ti->columns) == 1 ? 2 : 1);
    4401             :                                 }
    4402             :                         }
    4403        1526 :                         ic->c->unique = unique;
    4404             :                 }
    4405        2646 :                 if ((res = sys_drop_ic(tr, i, ic)))
    4406           0 :                         return res;
    4407             :         }
    4408             : 
    4409        2164 :         i->base.deleted = 1;
    4410        2164 :         if (!isNew(i) && !isTempTable(i->t))
    4411        1962 :                 if ((res = store->storage_api.drop_idx(tr, (sql_idx*)dup_base(&i->base))))
    4412             :                         return res;
    4413             : 
    4414             :         /* remove idx from schema and table */
    4415        2164 :         if (isGlobal(i->t) && (res = os_del(i->t->s->idxs, tr, i->base.name, dup_base(&i->base))))
    4416             :                 return res;
    4417        2164 :         if (!isNew(i) && (res = sql_trans_add_dependency_change(tr, i->base.id, ddl)))
    4418             :                 return res;
    4419        2164 :         if ((res = sql_trans_drop_dependencies(tr, i->base.id)))
    4420             :                 return res;
    4421             : 
    4422        2164 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, i->base.id, INDEX_DEPENDENCY)))
    4423             :                 return res;
    4424             :         return res;
    4425             : }
    4426             : 
    4427             : static int
    4428        2326 : sys_drop_kc(sql_trans *tr, sql_key *k, sql_kc *kc)
    4429             : {
    4430        2326 :         sqlstore *store = tr->store;
    4431        2357 :         sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
    4432        2326 :         sql_table *syskc = find_sql_table(tr, syss, "objects");
    4433        2326 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(syskc, "id"), &k->base.id, find_sql_column(syskc, "name"), kc->c->base.name, NULL);
    4434        2326 :         int res = LOG_OK;
    4435             : 
    4436        2326 :         if (is_oid_nil(rid))
    4437             :                 return -1;
    4438        2326 :         if ((res = store->table_api.table_delete(tr, syskc, rid)))
    4439             :                 return res;
    4440             :         return res;
    4441             : }
    4442             : 
    4443             : static int
    4444        1912 : sys_drop_key(sql_trans *tr, sql_key *k, int drop_action)
    4445             : {
    4446        1912 :         sqlstore *store = tr->store;
    4447        1912 :         node *n;
    4448        1943 :         sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
    4449        1912 :         sql_table *syskey = find_sql_table(tr, syss, "keys");
    4450        1912 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(syskey, "id"), &k->base.id, NULL);
    4451        1912 :         int res = LOG_OK;
    4452             : 
    4453        1912 :         if (is_oid_nil(rid))
    4454             :                 return -1;
    4455        1912 :         if ((res = store->table_api.table_delete(tr, syskey, rid)))
    4456             :                 return res;
    4457             : 
    4458        4238 :         for (n = k->columns->h; n; n = n->next) {
    4459        2326 :                 sql_kc *kc = n->data;
    4460        2326 :                 if ((res = sys_drop_kc(tr, k, kc)))
    4461           0 :                         return res;
    4462             :         }
    4463             :         /* remove key from schema */
    4464        1912 :         if (isGlobal(k->t) && (res = os_del(k->t->s->keys, tr, k->base.name, dup_base(&k->base))))
    4465             :                 return res;
    4466        1912 :         if (isGlobal(k->t) && (res = os_del(tr->cat->objects, tr, k->base.name, dup_base(&k->base))))
    4467             :                 return res;
    4468        1912 :         if (k->t->pkey == (sql_ukey*)k)
    4469         942 :                 k->t->pkey = NULL;
    4470             : 
    4471        1912 :         if (!isNew(k) && (res = sql_trans_add_dependency_change(tr, k->base.id, ddl)))
    4472             :                 return res;
    4473        1912 :         if ((res = sql_trans_drop_dependencies(tr, k->base.id)))
    4474             :                 return res;
    4475             : 
    4476        2145 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, k->base.id, (k->type == fkey) ? FKEY_DEPENDENCY : KEY_DEPENDENCY)))
    4477             :                 return res;
    4478             :         return res;
    4479             : }
    4480             : 
    4481             : static int
    4482           0 : sys_drop_tc(sql_trans *tr, sql_trigger * i, sql_kc *kc)
    4483             : {
    4484           0 :         sqlstore *store = tr->store;
    4485           0 :         sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
    4486           0 :         sql_table *systc = find_sql_table(tr, syss, "objects");
    4487           0 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(systc, "id"), &i->base.id, find_sql_column(systc, "name"), kc->c->base.name, NULL);
    4488           0 :         int res = LOG_OK;
    4489             : 
    4490           0 :         if (is_oid_nil(rid))
    4491             :                 return -1;
    4492           0 :         if ((res = store->table_api.table_delete(tr, systc, rid)))
    4493             :                 return res;
    4494             :         return res;
    4495             : }
    4496             : 
    4497             : static int
    4498         177 : sys_drop_sequence(sql_trans *tr, sql_sequence * seq, int drop_action)
    4499             : {
    4500         177 :         sqlstore *store = tr->store;
    4501         177 :         sql_schema *syss = find_sql_schema(tr, "sys");
    4502         177 :         sql_table *sysseqs = find_sql_table(tr, syss, "sequences");
    4503         177 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(sysseqs, "id"), &seq->base.id, NULL);
    4504         177 :         int res = LOG_OK;
    4505             : 
    4506         177 :         if (is_oid_nil(rid))
    4507             :                 return -1;
    4508             : 
    4509         177 :         if ((res = store->table_api.table_delete(tr, sysseqs, rid)))
    4510             :                 return res;
    4511         177 :         if (!isNew(seq) && (res = sql_trans_add_dependency_change(tr, seq->base.id, ddl)))
    4512             :                 return res;
    4513         177 :         if ((res = sql_trans_drop_dependencies(tr, seq->base.id)))
    4514             :                 return res;
    4515         177 :         if ((res = sql_trans_drop_any_comment(tr, seq->base.id)))
    4516             :                 return res;
    4517         177 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, seq->base.id, SEQ_DEPENDENCY)))
    4518             :                 return res;
    4519             :         return res;
    4520             : }
    4521             : 
    4522             : static int
    4523       29129 : sys_drop_default_object(sql_trans *tr, sql_column *col, int drop_action)
    4524             : {
    4525       29129 :         const char next_value_for[] = "next value for ";
    4526       29129 :         int res = LOG_OK;
    4527             : 
    4528             :         /* Drop sequence for generated column if it's the case */
    4529       29129 :         if (col->def && !strncmp(col->def, next_value_for, strlen(next_value_for))) {
    4530         167 :                 sql_schema *s = NULL;
    4531         167 :                 sql_sequence *seq = NULL;
    4532         167 :                 char *schema = NULL, *seq_name = NULL;
    4533             : 
    4534         167 :                 extract_schema_and_sequence_name(NULL, col->def + strlen(next_value_for), &schema, &seq_name);
    4535         167 :                 if (!schema || !seq_name || !(s = find_sql_schema(tr, schema))) {
    4536             :                         /* didn't find the schema so no generated sequence */
    4537           0 :                         _DELETE(schema);
    4538           0 :                         _DELETE(seq_name);
    4539           0 :                         return res;
    4540             :                 }
    4541             : 
    4542         167 :                 seq = find_sql_sequence(tr, s, seq_name);
    4543         167 :                 _DELETE(schema);
    4544         167 :                 _DELETE(seq_name);
    4545         167 :                 if (seq && sql_trans_get_dependency_type(tr, seq->base.id, BEDROPPED_DEPENDENCY) > 0) {
    4546         146 :                         if ((res = sys_drop_sequence(tr, seq, drop_action)))
    4547             :                                 return res;
    4548         146 :                         if ((res = os_del(s->seqs, tr, seq->base.name, dup_base(&seq->base))))
    4549             :                                 return res;
    4550             :                 }
    4551             :         }
    4552             :         return res;
    4553             : }
    4554             : 
    4555             : static int
    4556       34113 : sql_trans_drop_obj_priv(sql_trans *tr, sqlid obj_id)
    4557             : {
    4558       34113 :         sqlstore *store = tr->store;
    4559       34113 :         sql_schema *sys = find_sql_schema(tr, "sys");
    4560       34113 :         sql_table *privs = find_sql_table(tr, sys, "privileges");
    4561       34113 :         int res = LOG_OK;
    4562             : 
    4563       34113 :         assert(sys && privs);
    4564             :         /* select privileges of this obj_id */
    4565       34113 :         rids *A = store->table_api.rids_select(tr, find_sql_column(privs, "obj_id"), &obj_id, &obj_id, NULL);
    4566       34113 :         if (A == NULL)
    4567             :                 return LOG_ERR;
    4568             :         /* remove them */
    4569       34367 :         for(oid rid = store->table_api.rids_next(A); !is_oid_nil(rid) && res == LOG_OK; rid = store->table_api.rids_next(A))
    4570         254 :                 res = store->table_api.table_delete(tr, privs, rid);
    4571       34113 :         store->table_api.rids_destroy(A);
    4572       34113 :         return res;
    4573             : }
    4574             : 
    4575             : static int
    4576         103 : sys_drop_trigger(sql_trans *tr, sql_trigger * i)
    4577             : {
    4578         103 :         sqlstore *store = tr->store;
    4579         103 :         node *n;
    4580         206 :         sql_schema *syss = find_sql_schema(tr, (!i->t || isGlobal(i->t))?"sys":"tmp");
    4581         103 :         sql_table *systrigger = find_sql_table(tr, syss, "triggers");
    4582         103 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(systrigger, "id"), &i->base.id, NULL);
    4583         103 :         int res = LOG_OK;
    4584             : 
    4585         103 :         if (is_oid_nil(rid))
    4586             :                 return -1;
    4587         103 :         if ((res = store->table_api.table_delete(tr, systrigger, rid)))
    4588             :                 return res;
    4589             : 
    4590         100 :         if (i->t) {
    4591          97 :                 for (n = i->columns->h; n; n = n->next) {
    4592           0 :                         sql_kc *tc = n->data;
    4593             : 
    4594           0 :                         if ((res = sys_drop_tc(tr, i, tc)))
    4595           0 :                                 return res;
    4596             :                 }
    4597             :         }
    4598             :         /* remove trigger from schema */
    4599         100 :         if ((res = os_del(i->t?i->t->s->triggers:syss->triggers, tr, i->base.name, dup_base(&i->base))))
    4600             :                 return res;
    4601         100 :         if (!isNew(i) && (res = sql_trans_add_dependency_change(tr, i->base.id, ddl)))
    4602             :                 return res;
    4603         100 :         if ((res = sql_trans_drop_dependencies(tr, i->base.id)))
    4604             :                 return res;
    4605             :         return res;
    4606             : }
    4607             : 
    4608             : static int
    4609       29106 : sys_drop_column(sql_trans *tr, sql_column *col, int drop_action)
    4610             : {
    4611       29106 :         sqlstore *store = tr->store;
    4612       29189 :         sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
    4613       29106 :         sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    4614       29106 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"), &col->base.id, NULL);
    4615       29106 :         int res = LOG_OK;
    4616             : 
    4617       29106 :         if (is_oid_nil(rid))
    4618             :                 return -1;
    4619       29106 :         if ((res = store->table_api.table_delete(tr, syscolumn, rid)))
    4620             :                 return res;
    4621       29106 :         if (!isNew(col) && (res = sql_trans_add_dependency_change(tr, col->base.id, ddl)))
    4622             :                 return res;
    4623       29106 :         if ((res = sql_trans_drop_dependencies(tr, col->base.id)))
    4624             :                 return res;
    4625       29106 :         if ((res = sql_trans_drop_any_comment(tr, col->base.id)))
    4626             :                 return res;
    4627       29106 :         if ((res = sql_trans_drop_obj_priv(tr, col->base.id)))
    4628             :                 return res;
    4629       29106 :         if ((res = sys_drop_default_object(tr, col, drop_action)))
    4630             :                 return res;
    4631             : 
    4632       29106 :         col->base.deleted = 1;
    4633       29106 :         if (!isNew(col) && !isTempTable(col->t))
    4634       17912 :                 if ((res = store->storage_api.drop_col(tr, (sql_column*)dup_base(&col->base))))
    4635             :                         return res;
    4636             : 
    4637       29106 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, col->base.id, COLUMN_DEPENDENCY)))
    4638             :                 return res;
    4639       29106 :         if (col->type.type->s && (res = sql_trans_drop_dependency(tr, col->type.type->base.id, col->base.id, TYPE_DEPENDENCY)))
    4640             :                 return res;
    4641             :         return res;
    4642             : }
    4643             : 
    4644             : static int
    4645        4111 : sys_drop_keys(sql_trans *tr, sql_table *t, int drop_action)
    4646             : {
    4647        4111 :         node *n;
    4648        4111 :         int res = LOG_OK;
    4649             : 
    4650        4111 :         if (ol_length(t->keys))
    4651        2554 :                 for (n = ol_first_node(t->keys); n; n = n->next) {
    4652        1489 :                         sql_key *k = n->data;
    4653             : 
    4654        1489 :                         if ((res = sys_drop_key(tr, k, drop_action)))
    4655           0 :                                 return res;
    4656             :                 }
    4657             :         return res;
    4658             : }
    4659             : 
    4660             : static int
    4661        4111 : sys_drop_idxs(sql_trans *tr, sql_table *t, int drop_action)
    4662             : {
    4663        4111 :         node *n;
    4664        4111 :         int res = LOG_OK;
    4665             : 
    4666        4111 :         if (ol_length(t->idxs))
    4667        2671 :                 for (n = ol_first_node(t->idxs); n; n = n->next) {
    4668        1582 :                         sql_idx *k = n->data;
    4669             : 
    4670        1582 :                         if ((res = sys_drop_idx(tr, k, drop_action)))
    4671           0 :                                 return res;
    4672             :                 }
    4673             :         return res;
    4674             : }
    4675             : 
    4676             : static int
    4677        4111 : sys_drop_triggers(sql_trans *tr, sql_table *t)
    4678             : {
    4679        4111 :         node *n;
    4680        4111 :         int res = LOG_OK;
    4681             : 
    4682        4111 :         if (ol_length(t->triggers))
    4683          21 :                 for (n = ol_first_node(t->triggers); n; n = n->next) {
    4684          12 :                         sql_trigger *i = n->data;
    4685             : 
    4686          12 :                         if ((res = sys_drop_trigger(tr, i)))
    4687           0 :                                 return res;
    4688             :                 }
    4689             :         return res;
    4690             : }
    4691             : 
    4692             : static int
    4693        4111 : sys_drop_columns(sql_trans *tr, sql_table *t, int drop_action)
    4694             : {
    4695        4111 :         node *n;
    4696        4111 :         int res = LOG_OK;
    4697             : 
    4698        4111 :         if (ol_length(t->columns))
    4699       33147 :                 for (n = t->columns->l->h; n; n = n->next) {
    4700       29036 :                         sql_column *c = n->data;
    4701             : 
    4702       29036 :                         if ((res = sys_drop_column(tr, c, drop_action)))
    4703           0 :                                 return res;
    4704             :                 }
    4705             :         return res;
    4706             : }
    4707             : 
    4708             : static int
    4709         281 : sys_drop_part(sql_trans *tr, sql_part *pt, int drop_action)
    4710             : {
    4711         281 :         sqlstore *store = tr->store;
    4712         281 :         sql_table *mt = pt->t;
    4713         281 :         sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
    4714         281 :         sql_table *sysobj = find_sql_table(tr, syss, "objects");
    4715         281 :         oid obj_oid = store->table_api.column_find_row(tr, find_sql_column(sysobj, "id"), &pt->base.id, NULL);
    4716         281 :         int res = LOG_OK;
    4717             : 
    4718         281 :         (void)drop_action;
    4719         281 :         if (is_oid_nil(obj_oid))
    4720             :                 return -1;
    4721             : 
    4722         281 :         if ((res = store->table_api.table_delete(tr, sysobj, obj_oid)))
    4723             :                 return res;
    4724         281 :         if (isRangePartitionTable(mt)) {
    4725          93 :                 if (isPartitionedByColumnTable(pt->t))
    4726          80 :                         col_set_range(tr, pt, false);
    4727          93 :                 sql_table *ranges = find_sql_table(tr, syss, "range_partitions");
    4728          93 :                 assert(ranges);
    4729          93 :                 oid rid = store->table_api.column_find_row(tr, find_sql_column(ranges, "table_id"), &pt->member, NULL);
    4730          93 :                 if ((res = store->table_api.table_delete(tr, ranges, rid)))
    4731             :                         return res;
    4732         188 :         } else if (isListPartitionTable(mt)) {
    4733          25 :                 sql_table *values = find_sql_table(tr, syss, "value_partitions");
    4734          25 :                 assert(values);
    4735          25 :                 rids *rs = store->table_api.rids_select(tr, find_sql_column(values, "table_id"), &pt->member, &pt->member, NULL);
    4736          25 :                 if (rs == NULL)
    4737             :                         return LOG_ERR;
    4738         107 :                 for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
    4739          82 :                         if ((res = store->table_api.table_delete(tr, values, rid))) {
    4740           0 :                                 store->table_api.rids_destroy(rs);
    4741           0 :                                 return res;
    4742             :                         }
    4743             :                 }
    4744          25 :                 store->table_api.rids_destroy(rs);
    4745             :         }
    4746             :         /* merge table depends on part table */
    4747         281 :         if (!isNew(pt) && (res = sql_trans_add_dependency_change(tr, mt->base.id, ddl)))
    4748             :                 return res;
    4749         281 :         if ((res = sql_trans_drop_dependency(tr, pt->member, mt->base.id, TABLE_DEPENDENCY)))
    4750             :                 return res;
    4751             : 
    4752         281 :         if ((res = os_del(mt->s->parts, tr, pt->base.name, dup_base(&pt->base))))
    4753             :                 return res;
    4754             :         return res;
    4755             : }
    4756             : 
    4757             : static int
    4758         195 : sys_drop_members(sql_trans *tr, sql_table *t, int drop_action)
    4759             : {
    4760         195 :         int res = LOG_OK;
    4761             : 
    4762         195 :         if (!list_empty(t->members)) {
    4763         172 :                 for (node *n = t->members->h; n; ) {
    4764          96 :                         sql_part *pt = n->data;
    4765             : 
    4766          96 :                         n = n->next;
    4767          96 :                         if ((res = sys_drop_part(tr, pt, drop_action)))
    4768           0 :                                 return res;
    4769             :                 }
    4770             :         }
    4771             :         return res;
    4772             : }
    4773             : 
    4774             : static int
    4775          15 : sys_drop_parts(sql_trans *tr, sql_table *t, int drop_action)
    4776             : {
    4777          15 :         int res = LOG_OK;
    4778             : 
    4779          30 :         for(sql_part *pt = partition_find_part(tr, t, NULL); pt; pt = partition_find_part(tr, t, pt)) {
    4780          15 :                 if ((res = sql_trans_del_table(tr, pt->t, t, drop_action)))
    4781           0 :                         return res;
    4782             :         }
    4783             :         return res;
    4784             : }
    4785             : 
    4786             : static int
    4787        4111 : sys_drop_table(sql_trans *tr, sql_table *t, int drop_action)
    4788             : {
    4789        4111 :         sqlstore *store = tr->store;
    4790        4161 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    4791        4111 :         sql_table *systable = find_sql_table(tr, syss, "_tables");
    4792        4111 :         sql_column *syscol = find_sql_column(systable, "id");
    4793        4111 :         oid rid = store->table_api.column_find_row(tr, syscol, &t->base.id, NULL);
    4794        4111 :         int res = LOG_OK;
    4795             : 
    4796        4111 :         if (is_oid_nil(rid))
    4797             :                 return -1;
    4798             : 
    4799        4111 :         if ((res = store->table_api.table_delete(tr, systable, rid)))
    4800             :                 return res;
    4801        4111 :         if ((res = sys_drop_keys(tr, t, drop_action)))
    4802             :                 return res;
    4803        4111 :         if ((res = sys_drop_idxs(tr, t, drop_action)))
    4804             :                 return res;
    4805        4111 :         if ((res = sys_drop_triggers(tr, t)))
    4806             :                 return res;
    4807             : 
    4808        4111 :         if (partition_find_part(tr, t, NULL))
    4809          15 :                 if ((res = sys_drop_parts(tr, t, drop_action)))
    4810             :                         return res;
    4811             : 
    4812        4111 :         if (isMergeTable(t) || isReplicaTable(t))
    4813         195 :                 if ((res = sys_drop_members(tr, t, drop_action)))
    4814             :                         return res;
    4815             : 
    4816        4111 :         if (isRangePartitionTable(t) || isListPartitionTable(t)) {
    4817          66 :                 sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
    4818          66 :                 assert(partitions);
    4819          66 :                 sql_column *pcols = find_sql_column(partitions, "table_id");
    4820          66 :                 assert(pcols);
    4821          66 :                 rids *rs = store->table_api.rids_select(tr, pcols, &t->base.id, &t->base.id, NULL);
    4822          66 :                 if (!rs)
    4823             :                         return -1;
    4824          66 :                 oid poid;
    4825          66 :                 if (rs == NULL)
    4826             :                         return LOG_ERR;
    4827          66 :                 if ((poid = store->table_api.rids_next(rs)) != oid_nil) {
    4828          66 :                         if ((res = store->table_api.table_delete(tr, partitions, poid))) {
    4829           0 :                                 store->table_api.rids_destroy(rs);
    4830           0 :                                 return res;
    4831             :                         }
    4832             :                 }
    4833          66 :                 store->table_api.rids_destroy(rs);
    4834             :         }
    4835             : 
    4836        4111 :         if ((res = sql_trans_drop_any_comment(tr, t->base.id)))
    4837             :                 return res;
    4838        4111 :         if (!isNew(t) && (res = sql_trans_add_dependency_change(tr, t->base.id, ddl)))
    4839             :                 return res;
    4840        4111 :         if ((res = sql_trans_drop_dependencies(tr, t->base.id)))
    4841             :                 return res;
    4842        4111 :         if ((res = sql_trans_drop_obj_priv(tr, t->base.id)))
    4843             :                 return res;
    4844        4111 :         if ((res = sys_drop_columns(tr, t, drop_action)))
    4845             :                 return res;
    4846             : 
    4847        4111 :         if (isTable(t) && !isNew(t))
    4848        3339 :                 if ((res = store->storage_api.drop_del(tr, t)))
    4849             :                         return res;
    4850             : 
    4851        4173 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, t->base.id, !isView(t) ? TABLE_DEPENDENCY : VIEW_DEPENDENCY)))
    4852             :                 return res;
    4853             :         return res;
    4854             : }
    4855             : 
    4856             : static int
    4857           3 : sys_drop_type(sql_trans *tr, sql_type *type, int drop_action)
    4858             : {
    4859           3 :         sqlstore *store = tr->store;
    4860           3 :         sql_schema *syss = find_sql_schema(tr, "sys");
    4861           3 :         sql_table *sys_tab_type = find_sql_table(tr, syss, "types");
    4862           3 :         sql_column *sys_type_col = find_sql_column(sys_tab_type, "id");
    4863           3 :         oid rid = store->table_api.column_find_row(tr, sys_type_col, &type->base.id, NULL);
    4864           3 :         int res = LOG_OK;
    4865             : 
    4866           3 :         if (is_oid_nil(rid))
    4867             :                 return -1;
    4868             : 
    4869           3 :         if ((res = store->table_api.table_delete(tr, sys_tab_type, rid)))
    4870             :                 return res;
    4871           3 :         if (!isNew(type) && (res = sql_trans_add_dependency_change(tr, type->base.id, ddl)))
    4872             :                 return res;
    4873           3 :         if ((res = sql_trans_drop_dependencies(tr, type->base.id)))
    4874             :                 return res;
    4875             : 
    4876           3 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, type->base.id, TYPE_DEPENDENCY)))
    4877             :                 return res;
    4878             :         return res;
    4879             : }
    4880             : 
    4881             : static int
    4882         736 : sys_drop_func(sql_trans *tr, sql_func *func, int drop_action)
    4883             : {
    4884         736 :         sqlstore *store = tr->store;
    4885         736 :         sql_schema *syss = find_sql_schema(tr, "sys");
    4886         736 :         sql_table *sys_tab_func = find_sql_table(tr, syss, "functions");
    4887         736 :         sql_column *sys_func_col = find_sql_column(sys_tab_func, "id");
    4888         736 :         oid rid_func = store->table_api.column_find_row(tr, sys_func_col, &func->base.id, NULL);
    4889         736 :         if (is_oid_nil(rid_func))
    4890             :                 return -1;
    4891         736 :         sql_table *sys_tab_args = find_sql_table(tr, syss, "args");
    4892         736 :         sql_column *sys_args_col = find_sql_column(sys_tab_args, "func_id");
    4893         736 :         rids *args = store->table_api.rids_select(tr, sys_args_col, &func->base.id, &func->base.id, NULL);
    4894         736 :         int res = LOG_OK;
    4895             : 
    4896         736 :         if (args == NULL)
    4897             :                 return LOG_ERR;
    4898        2735 :         for (oid r = store->table_api.rids_next(args); !is_oid_nil(r); r = store->table_api.rids_next(args)) {
    4899        2000 :                 if ((res = store->table_api.table_delete(tr, sys_tab_args, r))) {
    4900           1 :                         store->table_api.rids_destroy(args);
    4901           1 :                         return res;
    4902             :                 }
    4903             :         }
    4904         735 :         store->table_api.rids_destroy(args);
    4905             : 
    4906         735 :         assert(!is_oid_nil(rid_func));
    4907         735 :         if ((res = store->table_api.table_delete(tr, sys_tab_func, rid_func)))
    4908             :                 return res;
    4909             : 
    4910         735 :         if (!isNew(func) && (res = sql_trans_add_dependency_change(tr, func->base.id, ddl)))
    4911             :                 return res;
    4912         735 :         if ((res = sql_trans_drop_dependencies(tr, func->base.id)))
    4913             :                 return res;
    4914         735 :         if ((res = sql_trans_drop_any_comment(tr, func->base.id)))
    4915             :                 return res;
    4916         735 :         if ((res = sql_trans_drop_obj_priv(tr, func->base.id)))
    4917             :                 return res;
    4918             : 
    4919         812 :         if (drop_action && (res = sql_trans_drop_all_dependencies(tr, func->base.id, !IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY)))
    4920             :                 return res;
    4921         735 :         if (!func->vararg && func->ops) {
    4922        1751 :                 for (node *n = func->ops->h; n; n = n->next) {
    4923        1019 :                         sql_arg *a = n->data;
    4924             : 
    4925        1019 :                         if (a->type.type->s && (res = sql_trans_drop_dependency(tr, a->type.type->base.id, func->base.id, TYPE_DEPENDENCY)))
    4926           0 :                                 return res;
    4927             :                 }
    4928             :         }
    4929         735 :         if (!func->varres && func->res) {
    4930        1627 :                 for (node *n = func->res->h; n; n = n->next) {
    4931         980 :                         sql_arg *a = n->data;
    4932             : 
    4933         980 :                         if (a->type.type->s && (res = sql_trans_drop_dependency(tr, a->type.type->base.id, func->base.id, TYPE_DEPENDENCY)))
    4934           0 :                                 return res;
    4935             :                 }
    4936             :         }
    4937             :         return res;
    4938             : }
    4939             : 
    4940             : static int
    4941         161 : sys_drop_types(sql_trans *tr, sql_schema *s, int drop_action)
    4942             : {
    4943         161 :         int res = LOG_OK;
    4944         161 :         struct os_iter oi;
    4945         161 :         os_iterator(&oi, s->types, tr, NULL);
    4946         161 :         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    4947           0 :                 sql_type *t = (sql_type*)b;
    4948             : 
    4949           0 :                 if ((res = sys_drop_type(tr, t, drop_action)))
    4950           0 :                         return res;
    4951             :         }
    4952             :         return res;
    4953             : }
    4954             : 
    4955             : static int
    4956         161 : sys_drop_tables(sql_trans *tr, sql_schema *s, int drop_action)
    4957             : {
    4958         161 :         int res = LOG_OK;
    4959         161 :         struct os_iter oi;
    4960         161 :         os_iterator(&oi, s->tables, tr, NULL);
    4961         208 :         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    4962          47 :                 sql_table *t = (sql_table*)b;
    4963             : 
    4964          47 :                 if ((res = sys_drop_table(tr, t, drop_action)))
    4965           0 :                         return res;
    4966             :         }
    4967             :         return res;
    4968             : }
    4969             : 
    4970             : static int
    4971         161 : sys_drop_funcs(sql_trans *tr, sql_schema *s, int drop_action)
    4972             : {
    4973         161 :         int res = LOG_OK;
    4974         161 :         struct os_iter oi;
    4975         161 :         os_iterator(&oi, s->funcs, tr, NULL);
    4976         181 :         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    4977          20 :                 sql_func *f = (sql_func*)b;
    4978             : 
    4979          20 :                 if ((res = sys_drop_func(tr, f, drop_action)))
    4980           0 :                         return res;
    4981             :         }
    4982             :         return res;
    4983             : }
    4984             : 
    4985             : static int
    4986         161 : sys_drop_sequences(sql_trans *tr, sql_schema *s, int drop_action)
    4987             : {
    4988         161 :         int res = LOG_OK;
    4989         161 :         struct os_iter oi;
    4990         161 :         os_iterator(&oi, s->seqs, tr, NULL);
    4991         162 :         for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    4992           1 :                 sql_sequence *seq = (sql_sequence*)b;
    4993             : 
    4994           1 :                 if ((res = sys_drop_sequence(tr, seq, drop_action)))
    4995           0 :                         return res;
    4996             :         }
    4997             :         return res;
    4998             : }
    4999             : 
    5000             : int
    5001         906 : sql_trans_create_type(sql_trans *tr, sql_schema *s, const char *sqlname, unsigned int digits, unsigned int scale, int radix, const char *impl)
    5002             : {
    5003         906 :         sqlstore *store = tr->store;
    5004         906 :         sql_type *t;
    5005         906 :         sql_table *systype;
    5006         906 :         int localtype = ATOMindex(impl);
    5007         906 :         sql_class eclass = EC_EXTERNAL;
    5008         906 :         int eclass_cast = (int) eclass, res = LOG_OK;
    5009             : 
    5010         906 :         if (localtype < 0)
    5011             :                 return -4;
    5012         906 :         t = ZNEW(sql_type);
    5013         906 :         systype = find_sql_table(tr, find_sql_schema(tr, "sys"), "types");
    5014         906 :         base_init(NULL, &t->base, next_oid(tr->store), true, sqlname);
    5015         906 :         t->impl =_STRDUP(impl);
    5016         906 :         t->digits = digits;
    5017         906 :         t->scale = scale;
    5018         906 :         t->radix = radix;
    5019         906 :         t->eclass = eclass;
    5020         906 :         t->localtype = localtype;
    5021         906 :         t->s = s;
    5022             : 
    5023         906 :         if ((res = os_add(s->types, tr, t->base.name, &t->base)))
    5024             :                 return res;
    5025         905 :         if ((res = store->table_api.table_insert(tr, systype, &t->base.id, &t->impl, &t->base.name, &t->digits, &t->scale, &radix, &eclass_cast, &s->base.id)))
    5026             :                 return res;
    5027             :         return res;
    5028             : }
    5029             : 
    5030             : int
    5031           3 : sql_trans_drop_type(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
    5032             : {
    5033           3 :         sql_type *t = sql_trans_find_type(tr, s, id);
    5034           3 :         int res = LOG_OK;
    5035             : 
    5036           3 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    5037           1 :                 sqlid* local_id = MNEW(sqlid);
    5038           1 :                 if (!local_id)
    5039             :                         return -1;
    5040             : 
    5041           1 :                 if (!tr->dropped) {
    5042           1 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    5043           1 :                         if (!tr->dropped) {
    5044           0 :                                 _DELETE(local_id);
    5045           0 :                                 return -1;
    5046             :                         }
    5047             :                 }
    5048           1 :                 *local_id = t->base.id;
    5049           1 :                 list_append(tr->dropped, local_id);
    5050             :         }
    5051             : 
    5052           3 :         if ((res = sys_drop_type(tr, t, drop_action)))
    5053             :                 return res;
    5054           3 :         if ((res = os_del(s->types, tr, t->base.name, dup_base(&t->base))))
    5055             :                 return res;
    5056             : 
    5057           3 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    5058           1 :                 list_destroy(tr->dropped);
    5059           1 :                 tr->dropped = NULL;
    5060             :         }
    5061             :         return res;
    5062             : }
    5063             : 
    5064             : sql_func *
    5065      120340 : create_sql_func(sqlstore *store, allocator *sa, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod,
    5066             :                                 const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect)
    5067             : {
    5068      120340 :         sql_func *t = SA_ZNEW(sa, sql_func);
    5069             : 
    5070      120340 :         base_init(sa, &t->base, next_oid(store), true, func);
    5071      120340 :         assert(mod);
    5072      120340 :         t->imp = (impl)?SA_STRDUP(sa, impl):NULL;
    5073      120340 :         t->mod = SA_STRDUP(sa, mod);
    5074      120340 :         t->type = type;
    5075      120340 :         t->lang = lang;
    5076      120340 :         t->instantiated = lang != FUNC_LANG_SQL && lang != FUNC_LANG_MAL;
    5077      120340 :         t->semantics = TRUE;
    5078      120340 :         t->side_effect = side_effect;
    5079      120340 :         t->varres = varres;
    5080      120340 :         t->vararg = vararg;
    5081      120340 :         t->ops = args;
    5082      120340 :         t->res = res;
    5083      120340 :         t->query = (query)?SA_STRDUP(sa, query):NULL;
    5084      120340 :         t->fix_scale = SCALE_EQ;
    5085      120340 :         t->s = NULL;
    5086      120340 :         t->system = system;
    5087      120340 :         return t;
    5088             : }
    5089             : 
    5090             : int
    5091      120742 : sql_trans_create_func(sql_func **fres, sql_trans *tr, sql_schema *s, const char *func, list *args, list *ffres, sql_ftype type, sql_flang lang,
    5092             :                                           const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect)
    5093             : {
    5094      120742 :         sqlstore *store = tr->store;
    5095      120742 :         sql_schema *syss = find_sql_schema(tr, "sys");
    5096      120742 :         sql_table *sysfunc = find_sql_table(tr, syss, "functions");
    5097      120742 :         sql_table *sysarg = find_sql_table(tr, syss, "args");
    5098      120742 :         node *n;
    5099      120742 :         int number = 0, ftype = (int) type, flang = (int) lang, res = LOG_OK;
    5100      120742 :         bit semantics = TRUE;
    5101             : 
    5102      120742 :         sql_func *t = ZNEW(sql_func);
    5103      120742 :         base_init(NULL, &t->base, next_oid(tr->store), true, func);
    5104      120742 :         assert(mod);
    5105      120742 :         t->imp = (impl)?_STRDUP(impl):NULL;
    5106      120742 :         t->mod =_STRDUP(mod);
    5107      120742 :         t->type = type;
    5108      120742 :         t->lang = lang;
    5109      120742 :         t->instantiated = lang != FUNC_LANG_SQL && lang != FUNC_LANG_MAL;
    5110      120742 :         t->semantics = semantics;
    5111      120742 :         t->side_effect = side_effect;
    5112      120742 :         t->varres = varres;
    5113      120742 :         t->vararg = vararg;
    5114      120742 :         t->ops = list_create((fdestroy) &arg_destroy);
    5115      120742 :         t->fix_scale = SCALE_EQ;
    5116      120742 :         t->system = system;
    5117      309351 :         for (n=args->h; n; n = n->next)
    5118      188609 :                 list_append(t->ops, arg_dup(tr, s, n->data));
    5119      120742 :         if (ffres) {
    5120      102448 :                 t->res = list_create((fdestroy) &arg_destroy);
    5121      260706 :                 for (n=ffres->h; n; n = n->next)
    5122      158258 :                         list_append(t->res, arg_dup(tr, s, n->data));
    5123             :         }
    5124      120742 :         t->query = (query)?_STRDUP(query):NULL;
    5125      120742 :         t->s = s;
    5126             : 
    5127      120742 :         if ((res = os_add(s->funcs, tr, t->base.name, &t->base)))
    5128             :                 return res;
    5129      120741 :         if ((res = store->table_api.table_insert(tr, sysfunc, &t->base.id, &t->base.name, query?(char**)&query:&t->imp, &t->mod, &flang, &ftype, &side_effect,
    5130             :                         &varres, &vararg, &s->base.id, &system, &semantics)))
    5131             :                 return res;
    5132      278998 :         if (t->res) for (n = t->res->h; n; n = n->next, number++) {
    5133      158257 :                 sql_arg *a = n->data;
    5134      158257 :                 sqlid id = next_oid(tr->store);
    5135      158257 :                 if ((res = store->table_api.table_insert(tr, sysarg, &id, &t->base.id, &a->name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &number)))
    5136           0 :                         return res;
    5137             :         }
    5138      309350 :         if (t->ops) for (n = t->ops->h; n; n = n->next, number++) {
    5139      188609 :                 sql_arg *a = n->data;
    5140      188609 :                 sqlid id = next_oid(tr->store);
    5141      188609 :                 if ((res = store->table_api.table_insert(tr, sysarg, &id, &t->base.id, &a->name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &number)))
    5142           0 :                         return res;
    5143             :         }
    5144      120741 :         *fres = t;
    5145      120741 :         return res;
    5146             : }
    5147             : 
    5148             : int
    5149         673 : sql_trans_drop_func(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
    5150             : {
    5151         673 :         sql_base *b = os_find_id(s->funcs, tr, id);
    5152         673 :         int res = LOG_OK;
    5153             : 
    5154         673 :         if (!b)
    5155             :                 return res;
    5156             : 
    5157         673 :         sql_func *func = (sql_func*)b;
    5158         673 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    5159          69 :                 sqlid *local_id = MNEW(sqlid);
    5160          69 :                 if (!local_id)
    5161             :                         return -1;
    5162             : 
    5163          69 :                 if (! tr->dropped) {
    5164          42 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    5165          42 :                         if (!tr->dropped) {
    5166           0 :                                 _DELETE(local_id);
    5167           0 :                                 return -1;
    5168             :                         }
    5169             :                 }
    5170          69 :                 *local_id = func->base.id;
    5171          69 :                 list_append(tr->dropped, local_id);
    5172             :         }
    5173             : 
    5174         673 :         if ((res = sys_drop_func(tr, func, DROP_CASCADE)))
    5175             :                 return res;
    5176         672 :         if ((res = os_del(s->funcs, tr, func->base.name, dup_base(&func->base))))
    5177             :                 return res;
    5178             : 
    5179         672 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    5180          42 :                 list_destroy(tr->dropped);
    5181          42 :                 tr->dropped = NULL;
    5182             :         }
    5183             :         return res;
    5184             : }
    5185             : 
    5186             : static int
    5187          43 : build_drop_func_list_item(sql_trans *tr, sql_schema *s, sqlid id)
    5188             : {
    5189          43 :         sql_base *b = os_find_id(s->funcs, tr, id);
    5190          43 :         int res = LOG_OK;
    5191             : 
    5192          43 :         if (b) {
    5193          43 :                 sql_func *func = (sql_func*)b;
    5194          43 :                 if ((res = sys_drop_func(tr, func, DROP_CASCADE)))
    5195             :                         return res;
    5196          43 :                 if ((res = os_del(s->funcs, tr, func->base.name, dup_base(&func->base))))
    5197             :                         return res;
    5198             :         }
    5199             :         return res;
    5200             : }
    5201             : 
    5202             : int
    5203          31 : sql_trans_drop_all_func(sql_trans *tr, sql_schema *s, list *list_func, int drop_action)
    5204             : {
    5205          31 :         list *to_drop = NULL;
    5206          31 :         int res = LOG_OK;
    5207             : 
    5208          31 :         (void) drop_action;
    5209          31 :         if (!tr->dropped && !(tr->dropped = list_create((fdestroy) &id_destroy)))
    5210             :                 return -1;
    5211             : 
    5212          74 :         for (node *n = list_func->h; n ; n = n->next ) {
    5213          43 :                 sql_func *func = (sql_func *) n->data;
    5214             : 
    5215          43 :                 if (!list_find_id(tr->dropped, func->base.id)) {
    5216          43 :                         sqlid *local_id = MNEW(sqlid);
    5217          43 :                         if (!local_id) {
    5218           0 :                                 list_destroy(tr->dropped);
    5219           0 :                                 tr->dropped = NULL;
    5220           0 :                                 if (to_drop)
    5221           0 :                                         list_destroy(to_drop);
    5222           0 :                                 return -1;
    5223             :                         }
    5224          43 :                         if (!to_drop && !(to_drop = list_create(NULL))) {
    5225           0 :                                 list_destroy(tr->dropped);
    5226           0 :                                 tr->dropped = NULL;
    5227           0 :                                 return -1;
    5228             :                         }
    5229          43 :                         *local_id = func->base.id;
    5230          43 :                         list_append(tr->dropped, local_id);
    5231          43 :                         list_append(to_drop, func);
    5232             :                 }
    5233             :         }
    5234             : 
    5235          31 :         if (to_drop) {
    5236          74 :                 for (node *n = to_drop->h; n ; n = n->next ) {
    5237          43 :                         sql_func *func = (sql_func *) n->data;
    5238          43 :                         if ((res = build_drop_func_list_item(tr, s, func->base.id))) {
    5239           0 :                                 list_destroy(tr->dropped);
    5240           0 :                                 tr->dropped = NULL;
    5241           0 :                                 list_destroy(to_drop);
    5242           0 :                                 return res;
    5243             :                         }
    5244             :                 }
    5245          31 :                 list_destroy(to_drop);
    5246             :         }
    5247             : 
    5248          31 :         list_destroy(tr->dropped);
    5249          31 :         tr->dropped = NULL;
    5250          31 :         return res;
    5251             : }
    5252             : 
    5253             : int
    5254        1117 : sql_trans_create_schema(sql_trans *tr, const char *name, sqlid auth_id, sqlid owner, sqlid *schema_id_ptr)
    5255             : {
    5256        1117 :         sqlstore *store = tr->store;
    5257        1117 :         sql_schema *s = ZNEW(sql_schema);
    5258        1117 :         sql_table *sysschema = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
    5259        1117 :         int res = LOG_OK;
    5260             : 
    5261        1117 :         base_init(NULL, &s->base, next_oid(tr->store), true, name);
    5262        1117 :         s->auth_id = auth_id;
    5263        1117 :         s->owner = owner;
    5264        1117 :         s->system = FALSE;
    5265        1117 :         assert(!isTempSchema(s)); // TODO transaction_layer_revamp: check if this is really true
    5266        1117 :         s->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
    5267        1117 :         s->types = os_new(NULL, (destroy_fptr) &type_destroy, false, true, true, false, store);
    5268        1117 :         s->funcs = os_new(NULL, (destroy_fptr) &func_destroy, false, false, false, false, store);
    5269        1117 :         s->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
    5270        1117 :         s->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
    5271        1117 :         s->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
    5272        1117 :         s->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
    5273        1117 :         s->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
    5274        1117 :         s->store = tr->store;
    5275             : 
    5276        1117 :         if ((res = store->table_api.table_insert(tr, sysschema, &s->base.id, &s->base.name, &s->auth_id, &s->owner, &s->system))) {
    5277           0 :                 schema_destroy(store, s);
    5278           0 :                 return res;
    5279             :         }
    5280        1117 :         if ((res = os_add(tr->cat->schemas, tr, s->base.name, &s->base)))
    5281             :                 return res;
    5282        1116 :         if ((res = sql_trans_add_dependency(tr, s->auth_id, ddl)))
    5283             :                 return res;
    5284        1116 :         if ((res = sql_trans_add_dependency(tr, s->owner, ddl)))
    5285             :                 return res;
    5286        1116 :         if (schema_id_ptr)
    5287          33 :                 *schema_id_ptr = s->base.id;
    5288             :         return res;
    5289             : }
    5290             : 
    5291             : int
    5292           8 : sql_trans_rename_schema(sql_trans *tr, sqlid id, const char *new_name)
    5293             : {
    5294           8 :         sqlstore *store = tr->store;
    5295           8 :         table_functions table_api = store->table_api;
    5296           8 :         sql_table *schemas = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
    5297           8 :         sql_schema *s = find_sql_schema_id(tr, id), *ns = NULL;
    5298           8 :         oid rid;
    5299           8 :         int res = LOG_OK;
    5300             : 
    5301          16 :         assert(!strNil(new_name));
    5302             : 
    5303           8 :         rid = table_api.column_find_row(tr, find_sql_column(schemas, "id"), &id, NULL);
    5304           8 :         assert(!is_oid_nil(rid));
    5305           8 :         if ((res = table_api.column_update_value(tr, find_sql_column(schemas, "name"), rid, (void*) new_name)))
    5306             :                 return res;
    5307             : 
    5308           8 :         if (!isNew(s) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
    5309             :                 return res;
    5310             : 
    5311             :         /* delete schema, add schema */
    5312           8 :         if ((res = os_del(tr->cat->schemas, tr, s->base.name, dup_base(&s->base))))
    5313             :                 return res;
    5314             : 
    5315           8 :         if ((res = schema_dup(tr, s, new_name, &ns)) ||
    5316           8 :                 (res = os_add(tr->cat->schemas, tr, ns->base.name, &ns->base))) {
    5317           0 :                 return res;
    5318             :         }
    5319             : 
    5320             :         return res;
    5321             : }
    5322             : 
    5323             : int
    5324          32 : sql_trans_change_schema_authorization(sql_trans *tr, sqlid id, sqlid auth_id)
    5325             : {
    5326          32 :         sqlstore *store = tr->store;
    5327          32 :         sql_table *sysschema = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
    5328          32 :         sql_schema *s = find_sql_schema_id(tr, id), *ns = NULL;
    5329          32 :         oid rid;
    5330          32 :         int res = LOG_OK;
    5331             : 
    5332          32 :         assert(auth_id);
    5333          32 :         s->auth_id = auth_id;
    5334             : 
    5335          32 :         rid = store->table_api.column_find_row(tr, find_sql_column(sysschema, "id"), &id, NULL);
    5336          32 :         assert(!is_oid_nil(rid));
    5337          32 :         if ((res = store->table_api.column_update_value(tr, find_sql_column(sysschema, "authorization"), rid, &auth_id)))
    5338             :                 return res;
    5339             : 
    5340          32 :         if (!isNew(s) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
    5341             :                 return res;
    5342             :         /* delete schema, add schema */
    5343          32 :         if ((res = os_del(tr->cat->schemas, tr, s->base.name, dup_base(&s->base))))
    5344             :                 return res;
    5345          32 :         if ((res = schema_dup(tr, s, s->base.name, &ns)) || (res = os_add(tr->cat->schemas, tr, ns->base.name, &ns->base))) {
    5346           0 :                 return res;
    5347             :         }
    5348             :         return res;
    5349             : }
    5350             : 
    5351             : int
    5352         161 : sql_trans_drop_schema(sql_trans *tr, sqlid id, int drop_action)
    5353             : {
    5354         161 :         sqlstore *store = tr->store;
    5355         161 :         sql_schema *s = find_sql_schema_id(tr, id);
    5356         161 :         sql_table *sysschema = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
    5357         161 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(sysschema, "id"), &s->base.id, NULL);
    5358         161 :         int res = LOG_OK;
    5359             : 
    5360         161 :         if (is_oid_nil(rid))
    5361             :                 return 0;
    5362         161 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    5363          81 :                 sqlid* local_id = MNEW(sqlid);
    5364          81 :                 if (!local_id)
    5365             :                         return -1;
    5366             : 
    5367          81 :                 if (!tr->dropped) {
    5368          81 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    5369          81 :                         if (!tr->dropped) {
    5370           0 :                                 _DELETE(local_id);
    5371           0 :                                 return -1;
    5372             :                         }
    5373             :                 }
    5374          81 :                 *local_id = s->base.id;
    5375          81 :                 list_append(tr->dropped, local_id);
    5376             :         }
    5377             : 
    5378         161 :         if ((res = store->table_api.table_delete(tr, sysschema, rid)))
    5379             :                 return res;
    5380         161 :         if (!isNew(s) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
    5381             :                 return res;
    5382         161 :         if ((res = sys_drop_funcs(tr, s, drop_action)))
    5383             :                 return res;
    5384         161 :         if ((res = sys_drop_tables(tr, s, drop_action)))
    5385             :                 return res;
    5386         161 :         if ((res = sys_drop_types(tr, s, drop_action)))
    5387             :                 return res;
    5388         161 :         if ((res = sys_drop_sequences(tr, s, drop_action)))
    5389             :                 return res;
    5390         161 :         if ((res = sql_trans_drop_any_comment(tr, s->base.id)))
    5391             :                 return res;
    5392         161 :         if ((res = sql_trans_drop_obj_priv(tr, s->base.id)))
    5393             :                 return res;
    5394             : 
    5395         161 :         if ((res = os_del(tr->cat->schemas, tr, s->base.name, dup_base(&s->base))))
    5396             :                 return res;
    5397             : 
    5398         161 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    5399          81 :                 list_destroy(tr->dropped);
    5400          81 :                 tr->dropped = NULL;
    5401             :         }
    5402             :         return res;
    5403             : }
    5404             : 
    5405             : static int
    5406         495 : sql_trans_propagate_dependencies_parents(sql_trans *tr, sql_table *mt, bool *child_of_partitioned)
    5407             : {
    5408         495 :         int res = LOG_OK;
    5409         495 :         sql_part *pt = NULL;
    5410             : 
    5411        1020 :         for (; mt; mt = pt?pt->t:NULL) {
    5412         510 :                 if ((res = store_reset_sql_functions(tr, mt->base.id))) /* reset sql functions depending on the table */
    5413           0 :                         return res;
    5414         510 :                 if (!isNew(mt) && (res = sql_trans_add_dependency(tr, mt->base.id, ddl))) /* protect from another transaction changing the table's schema */
    5415           0 :                         return res;
    5416         510 :                 if (child_of_partitioned)
    5417         620 :                         *child_of_partitioned |= (isRangePartitionTable(mt) || isListPartitionTable(mt));
    5418         510 :                 pt = partition_find_part(tr, mt, NULL);
    5419             :         }
    5420             :         return res;
    5421             : }
    5422             : 
    5423             : static int
    5424         514 : sql_trans_propagate_dependencies_children(sql_trans *tr, sql_table *pt, bool child_of_partitioned)
    5425             : {
    5426         514 :         int res = LOG_OK;
    5427             : 
    5428         514 :         if (THRhighwater()) /* for now throw malloc failure error */
    5429             :                 return -1;
    5430             : 
    5431         514 :         if ((res = store_reset_sql_functions(tr, pt->base.id))) /* reset sql functions depending on the table */
    5432             :                 return res;
    5433         514 :         if (!isNew(pt)) {
    5434         354 :                 if ((res = sql_trans_add_dependency(tr, pt->base.id, ddl))) /* protect from another transaction changing the table's schema */
    5435             :                         return res;
    5436         354 :                 if ((res = sql_trans_add_dependency_change(tr, pt->base.id, ddl))) /* protect from being added twice */
    5437             :                         return res;
    5438         354 :                 if (child_of_partitioned && isTable(pt) && (res = sql_trans_add_dependency(tr, pt->base.id, dml))) /* disallow concurrent updates on pt */
    5439             :                         return res;
    5440             :         }
    5441         514 :         if ((isMergeTable(pt) || isReplicaTable(pt)) && !list_empty(pt->members)) {
    5442          33 :                 for (node *nt = pt->members->h; nt; nt = nt->next) {
    5443          19 :                         sql_part *pd = nt->data;
    5444          19 :                         sql_table *t = find_sql_table_id(tr, pt->s, pd->member);
    5445             : 
    5446          19 :                         child_of_partitioned |= (isRangePartitionTable(t) || isListPartitionTable(t));
    5447          19 :                         if ((res = sql_trans_propagate_dependencies_children(tr, t, child_of_partitioned)))
    5448           0 :                                 return res;
    5449             :                 }
    5450             :         }
    5451             :         return res;
    5452             : }
    5453             : 
    5454             : int
    5455         302 : sql_trans_add_table(sql_trans *tr, sql_table *mt, sql_table *pt)
    5456             : {
    5457         302 :         sqlstore *store = tr->store;
    5458         302 :         sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
    5459         302 :         sql_table *sysobj = find_sql_table(tr, syss, "objects");
    5460         302 :         int res = LOG_OK;
    5461         302 :         sql_table *dup = NULL;
    5462         302 :         bool child_of_partitioned = false;
    5463             : 
    5464             :         /* merge table depends on part table */
    5465         302 :         if ((res = sql_trans_create_dependency(tr, pt->base.id, mt->base.id, TABLE_DEPENDENCY)))
    5466             :                 return res;
    5467         302 :         assert(isMergeTable(mt) || isReplicaTable(mt));
    5468             : 
    5469         302 :         if ((res = new_table(tr, mt, &dup)))
    5470             :                 return res;
    5471         299 :         mt = dup;
    5472         299 :         if (!mt->members)
    5473           0 :                 mt->members = list_create((fdestroy) &part_destroy);
    5474         299 :         sql_part *p = ZNEW(sql_part);
    5475         299 :         p->t = mt;
    5476         299 :         p->member = pt->base.id;
    5477             : 
    5478         299 :         base_init(NULL, &p->base, next_oid(store), true, pt->base.name);
    5479         299 :         list_append(mt->members, p);
    5480         299 :         if ((res = store->table_api.table_insert(tr, sysobj, &p->base.id, &p->base.name, &mt->base.id, &pt->base.id)))
    5481             :                 return res;
    5482         299 :         if ((res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
    5483             :                 return res;
    5484         299 :         if ((res = sql_trans_propagate_dependencies_parents(tr, mt, &child_of_partitioned)))
    5485             :                 return res;
    5486         299 :         if ((res = sql_trans_propagate_dependencies_children(tr, pt, child_of_partitioned)))
    5487             :                 return res;
    5488             :         return res;
    5489             : }
    5490             : 
    5491             : int
    5492         186 : sql_trans_add_range_partition(sql_trans *tr, sql_table *mt, sql_table *pt, sql_subtype tpe, ptr min, ptr max,
    5493             :                 bit with_nills, int update, sql_part **err)
    5494             : {
    5495         186 :         sqlstore *store = tr->store;
    5496         186 :         sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
    5497         186 :         sql_table *sysobj = find_sql_table(tr, syss, "objects");
    5498         186 :         sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
    5499         186 :         sql_table *ranges = find_sql_table(tr, syss, "range_partitions");
    5500         186 :         sql_part *p;
    5501         186 :         int localtype = tpe.type->localtype, res = LOG_OK;
    5502         186 :         ValRecord vmin, vmax;
    5503         186 :         size_t smin, smax;
    5504         186 :         bit to_insert = with_nills;
    5505         186 :         oid rid;
    5506         186 :         ptr ok;
    5507         186 :         sql_table *dup = NULL;
    5508             : 
    5509         186 :         assert(sysobj);
    5510         186 :         assert(partitions);
    5511         186 :         assert(ranges);
    5512             : 
    5513         186 :         vmin = vmax = (ValRecord) {.vtype = TYPE_void,};
    5514             : 
    5515         186 :         if ((res = new_table(tr, mt, &dup)))
    5516             :                 return res;
    5517         185 :         mt = dup;
    5518         185 :         if (!mt->members)
    5519           0 :                 mt->members = list_create((fdestroy) &part_destroy);
    5520         185 :         if (min) {
    5521         185 :                 ok = VALinit(&vmin, localtype, min);
    5522         185 :                 if (ok && localtype != TYPE_str)
    5523         168 :                         ok = VALconvert(TYPE_str, &vmin);
    5524             :         } else {
    5525           0 :                 ok = VALinit(&vmin, TYPE_str, ATOMnilptr(TYPE_str));
    5526           0 :                 min = (ptr) ATOMnilptr(localtype);
    5527             :         }
    5528         185 :         if (!ok) {
    5529           0 :                 res = -1;
    5530           0 :                 goto finish;
    5531             :         }
    5532         185 :         smin = ATOMlen(localtype, min);
    5533         185 :         if (smin > STORAGE_MAX_VALUE_LENGTH) {
    5534           0 :                 res = -10;
    5535           0 :                 goto finish;
    5536             :         }
    5537             : 
    5538         185 :         if (max) {
    5539         185 :                 ok = VALinit(&vmax, localtype, max);
    5540         185 :                 if (ok && localtype != TYPE_str)
    5541         168 :                         ok = VALconvert(TYPE_str, &vmax);
    5542             :         } else {
    5543           0 :                 ok = VALinit(&vmax, TYPE_str, ATOMnilptr(TYPE_str));
    5544           0 :                 max = (ptr) ATOMnilptr(localtype);
    5545             :         }
    5546         185 :         if (!ok) {
    5547           0 :                 res = -1;
    5548           0 :                 goto finish;
    5549             :         }
    5550         185 :         smax = ATOMlen(localtype, max);
    5551         185 :         if (smax > STORAGE_MAX_VALUE_LENGTH) {
    5552           0 :                 res = -11;
    5553           0 :                 goto finish;
    5554             :         }
    5555             : 
    5556         185 :         if (!update) {
    5557         182 :                 p = ZNEW(sql_part);
    5558         182 :                 base_init(NULL, &p->base, next_oid(store), true, pt->base.name);
    5559         182 :                 assert(isMergeTable(mt) || isReplicaTable(mt));
    5560         182 :                 p->t = mt;
    5561         182 :                 assert(pt);
    5562         182 :                 p->member = pt->base.id;
    5563             :         } else {
    5564           3 :                 node *n = members_find_child_id(mt->members, pt->base.id);
    5565           3 :                 p = (sql_part*) n->data;
    5566             :         }
    5567             : 
    5568             :         /* add range partition values */
    5569         185 :         if (update) {
    5570           3 :                 _DELETE(p->part.range.minvalue);
    5571           3 :                 _DELETE(p->part.range.maxvalue);
    5572             :         }
    5573         185 :         p->part.range.minvalue = NEW_ARRAY(char, smin);
    5574         185 :         p->part.range.maxvalue = NEW_ARRAY(char, smax);
    5575         185 :         memcpy(p->part.range.minvalue, min, smin);
    5576         185 :         memcpy(p->part.range.maxvalue, max, smax);
    5577         185 :         p->part.range.minlength = smin;
    5578         185 :         p->part.range.maxlength = smax;
    5579         185 :         p->with_nills = with_nills;
    5580             : 
    5581         185 :         if (!update) {
    5582         182 :                 *err = list_append_with_validate(mt->members, p, &localtype, sql_range_part_validate_and_insert);
    5583         182 :                 if (*err)
    5584          38 :                         part_destroy(store, p);
    5585             :         } else {
    5586           3 :                 *err = list_transverse_with_validate(mt->members, p, &localtype, sql_range_part_validate_and_insert);
    5587             :         }
    5588         185 :         if (*err) {
    5589          38 :                 res = -12;
    5590          38 :                 goto finish;
    5591             :         }
    5592             : 
    5593         147 :         if (isPartitionedByColumnTable(p->t))
    5594         124 :                 col_set_range(tr, p, true);
    5595             : 
    5596         147 :         if (!update) {
    5597         144 :                 rid = store->table_api.column_find_row(tr, find_sql_column(partitions, "table_id"), &mt->base.id, NULL);
    5598         144 :                 assert(!is_oid_nil(rid));
    5599             : 
    5600             :                 /* add merge table dependency */
    5601         144 :                 if ((res = sql_trans_create_dependency(tr, pt->base.id, mt->base.id, TABLE_DEPENDENCY)))
    5602           0 :                         goto finish;
    5603         144 :                 sqlid id = store->table_api.column_find_sqlid(tr, find_sql_column(partitions, "id"), rid);
    5604         144 :                 if ((res = store->table_api.table_insert(tr, sysobj, &p->base.id, &p->base.name, &mt->base.id, &pt->base.id)))
    5605           0 :                         goto finish;
    5606         144 :                 char *vmin_val = VALget(&vmin);
    5607         144 :                 char *vmax_val = VALget(&vmax);
    5608         144 :                 if ((res = store->table_api.table_insert(tr, ranges, &pt->base.id, &id, &vmin_val, &vmax_val, &to_insert)))
    5609           0 :                         goto finish;
    5610             :         } else {
    5611           3 :                 sql_column *cmin = find_sql_column(ranges, "minimum"), *cmax = find_sql_column(ranges, "maximum"),
    5612           3 :                                    *wnulls = find_sql_column(ranges, "with_nulls");
    5613             : 
    5614           3 :                 rid = store->table_api.column_find_row(tr, find_sql_column(ranges, "table_id"), &pt->base.id, NULL);
    5615           3 :                 assert(!is_oid_nil(rid));
    5616             : 
    5617           3 :                 if ((res = store->table_api.column_update_value(tr, cmin, rid, VALget(&vmin))))
    5618           0 :                         goto finish;
    5619           3 :                 if ((res = store->table_api.column_update_value(tr, cmax, rid, VALget(&vmax))))
    5620           0 :                         goto finish;
    5621           3 :                 if ((res = store->table_api.column_update_value(tr, wnulls, rid, &to_insert)))
    5622           0 :                         goto finish;
    5623             :         }
    5624             : 
    5625         147 :         if (!update && (res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
    5626           0 :                 goto finish;
    5627         147 :         if ((res = sql_trans_propagate_dependencies_parents(tr, mt, NULL)))
    5628           0 :                 goto finish;
    5629         147 :         res = sql_trans_propagate_dependencies_children(tr, pt, true);
    5630             : 
    5631         185 : finish:
    5632         185 :         VALclear(&vmin);
    5633         185 :         VALclear(&vmax);
    5634         185 :         return res;
    5635             : }
    5636             : 
    5637             : int
    5638          54 : sql_trans_add_value_partition(sql_trans *tr, sql_table *mt, sql_table *pt, sql_subtype tpe, list* vals, bit with_nills,
    5639             :                 int update, sql_part **err)
    5640             : {
    5641          54 :         sqlstore *store = tr->store;
    5642          54 :         sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
    5643          54 :         sql_table *sysobj = find_sql_table(tr, syss, "objects");
    5644          54 :         sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
    5645          54 :         sql_table *values = find_sql_table(tr, syss, "value_partitions");
    5646          54 :         sql_part *p;
    5647          54 :         oid rid;
    5648          54 :         int localtype = tpe.type->localtype, i = 0, res = LOG_OK;
    5649          54 :         sql_table *dup = NULL;
    5650             : 
    5651          54 :         assert(sysobj);
    5652          54 :         assert(partitions);
    5653          54 :         assert(values);
    5654             : 
    5655          54 :         if ((res = new_table(tr, mt, &dup)))
    5656             :                 return res;
    5657          54 :         mt = dup;
    5658          54 :         if (!mt->members)
    5659           0 :                 mt->members = list_create((fdestroy) &part_destroy);
    5660          54 :         if (!update) {
    5661          52 :                 p = ZNEW(sql_part);
    5662          52 :                 base_init(NULL, &p->base, next_oid(store), true, pt->base.name);
    5663          52 :                 assert(isMergeTable(mt) || isReplicaTable(mt));
    5664          52 :                 p->t = mt;
    5665          52 :                 assert(pt);
    5666          52 :                 p->member = pt->base.id;
    5667             :         } else {
    5668           2 :                 rids *rs;
    5669           2 :                 node *n = members_find_child_id(mt->members, pt->base.id);
    5670           2 :                 p = (sql_part*) n->data;
    5671             : 
    5672           2 :                 rs = store->table_api.rids_select(tr, find_sql_column(values, "table_id"), &pt->base.id, &pt->base.id, NULL);
    5673           2 :                 if (rs == NULL)
    5674             :                         return LOG_ERR;
    5675           8 :                 for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
    5676           6 :                         if ((res = store->table_api.table_delete(tr, values, rid))) { /* eliminate the old values */
    5677           0 :                                 store->table_api.rids_destroy(rs);
    5678           0 :                                 return res;
    5679             :                         }
    5680             :                 }
    5681           2 :                 store->table_api.rids_destroy(rs);
    5682             :         }
    5683          54 :         p->with_nills = with_nills;
    5684             : 
    5685          54 :         rid = store->table_api.column_find_row(tr, find_sql_column(partitions, "table_id"), &mt->base.id, NULL);
    5686          54 :         assert(!is_oid_nil(rid));
    5687             : 
    5688          54 :         sqlid id = store->table_api.column_find_sqlid(tr, find_sql_column(partitions, "id"), rid);
    5689             : 
    5690          54 :         if (with_nills) { /* store the null value first */
    5691          11 :                 ValRecord vnnil;
    5692          11 :                 if (VALinit(&vnnil, TYPE_str, ATOMnilptr(TYPE_str)) == NULL) {
    5693           0 :                         if (!update)
    5694           0 :                                 part_destroy(store, p);
    5695           0 :                         list_destroy2(vals, store);
    5696           0 :                         return -1;
    5697             :                 }
    5698          11 :                 char *vnnil_val = VALget(&vnnil);
    5699          11 :                 if ((res = store->table_api.table_insert(tr, values, &pt->base.id, &id, &vnnil_val))) {
    5700           0 :                         list_destroy2(vals, store);
    5701           0 :                         return res;
    5702             :                 }
    5703          11 :                 VALclear(&vnnil);
    5704             :         }
    5705             : 
    5706         217 :         for (node *n = vals->h ; n ; n = n->next) {
    5707         163 :                 sql_part_value *next = (sql_part_value*) n->data;
    5708         163 :                 ValRecord vvalue;
    5709         163 :                 ptr ok;
    5710             : 
    5711         163 :                 if (ATOMlen(localtype, next->value) > STORAGE_MAX_VALUE_LENGTH) {
    5712           0 :                         if (!update)
    5713           0 :                                 part_destroy(store, p);
    5714           0 :                         list_destroy2(vals, store);
    5715           0 :                         return -i - 10;
    5716             :                 }
    5717         163 :                 ok = VALinit(&vvalue, localtype, next->value);
    5718         163 :                 if (ok && localtype != TYPE_str)
    5719         163 :                         ok = VALconvert(TYPE_str, &vvalue);
    5720         163 :                 if (!ok) {
    5721           0 :                         if (!update)
    5722           0 :                                 part_destroy(store, p);
    5723           0 :                         VALclear(&vvalue);
    5724           0 :                         list_destroy2(vals, store);
    5725           0 :                         return -i - 10;
    5726             :                 }
    5727         163 :                 char *vvalue_val = VALget(&vvalue);
    5728         163 :                 if ((res = store->table_api.table_insert(tr, values, &pt->base.id, &id, &vvalue_val))) {
    5729           0 :                         VALclear(&vvalue);
    5730           0 :                         list_destroy2(vals, store);
    5731           0 :                         return res;
    5732             :                 }
    5733             : 
    5734         163 :                 VALclear(&vvalue);
    5735         163 :                 i++;
    5736             :         }
    5737             : 
    5738          54 :         if (p->part.values)
    5739           2 :                 list_destroy2(p->part.values, store);
    5740          54 :         p->part.values = vals;
    5741             : 
    5742          54 :         if (!update) {
    5743          52 :                 *err = list_append_with_validate(mt->members, p, &localtype, sql_values_part_validate_and_insert);
    5744          52 :                 if (*err)
    5745           5 :                         part_destroy(store, p);
    5746             :         } else {
    5747           2 :                 *err = list_transverse_with_validate(mt->members, p, &localtype, sql_values_part_validate_and_insert);
    5748             :         }
    5749          54 :         if (*err)
    5750             :                 return -4;
    5751             : 
    5752          49 :         if (!update) {
    5753             :                 /* add merge table dependency */
    5754          47 :                 if ((res = sql_trans_create_dependency(tr, pt->base.id, mt->base.id, TABLE_DEPENDENCY)))
    5755             :                         return res;
    5756          47 :                 if ((res = store->table_api.table_insert(tr, sysobj, &p->base.id, &p->base.name, &mt->base.id, &pt->base.id)))
    5757             :                         return res;
    5758          47 :                 if ((res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
    5759             :                         return res;
    5760             :         }
    5761          49 :         if ((res = sql_trans_propagate_dependencies_parents(tr, mt, NULL)))
    5762             :                 return res;
    5763          49 :         if ((res = sql_trans_propagate_dependencies_children(tr, pt, true)))
    5764             :                 return res;
    5765             :         return res;
    5766             : }
    5767             : 
    5768             : int
    5769          19 : sql_trans_rename_table(sql_trans *tr, sql_schema *s, sqlid id, const char *new_name)
    5770             : {
    5771          19 :         sqlstore *store = tr->store;
    5772          37 :         sql_table *systable = find_sql_table(tr, find_sql_schema(tr, isTempSchema(s) ? "tmp":"sys"), "_tables");
    5773          19 :         sql_table *t = find_sql_table_id(tr, s, id), *dup = NULL;
    5774          19 :         oid rid;
    5775          19 :         int res = LOG_OK;
    5776             : 
    5777          38 :         assert(!strNil(new_name));
    5778             : 
    5779          19 :         rid = store->table_api.column_find_row(tr, find_sql_column(systable, "id"), &id, NULL);
    5780          19 :         assert(!is_oid_nil(rid));
    5781          19 :         if ((res = store->table_api.column_update_value(tr, find_sql_column(systable, "name"), rid, (void*) new_name)))
    5782             :                 return res;
    5783             : 
    5784          17 :         if (isGlobal(t)) {
    5785          16 :                 if (!isNew(t) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
    5786             :                         return res;
    5787          16 :                 if ((res = os_del(s->tables, tr, t->base.name, dup_base(&t->base))))
    5788             :                         return res;
    5789             :         } else {
    5790           1 :                 assert(isTempTable(t));
    5791           1 :                 sql_base *b = os_find_id(tr->localtmps, tr, t->base.id);
    5792           1 :                 if ((res = os_del(tr->localtmps, tr, b->name, dup_base(b))))
    5793             :                         return res;
    5794             :         }
    5795             : 
    5796          16 :         if ((res = table_dup(tr, t, t->s, new_name, &dup, true)))
    5797             :                 return res;
    5798             :         return res;
    5799             : }
    5800             : 
    5801             : int
    5802          26 : sql_trans_set_table_schema(sql_trans *tr, sqlid id, sql_schema *os, sql_schema *ns)
    5803             : {
    5804          26 :         sqlstore *store = tr->store;
    5805          52 :         sql_table *systable = find_sql_table(tr, find_sql_schema(tr, isTempSchema(os) ? "tmp":"sys"), "_tables");
    5806          26 :         sql_base *b = os_find_id(os->tables, tr, id);
    5807          26 :         sql_table *t = (sql_table*)b, *dup = NULL;
    5808          26 :         oid rid;
    5809          26 :         int res = LOG_OK;
    5810             : 
    5811          26 :         rid = store->table_api.column_find_row(tr, find_sql_column(systable, "id"), &t->base.id, NULL);
    5812          26 :         assert(!is_oid_nil(rid));
    5813          26 :         if ((res = store->table_api.column_update_value(tr, find_sql_column(systable, "schema_id"), rid, &(ns->base.id))))
    5814             :                 return res;
    5815             : 
    5816          26 :         if (!isNew(t) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
    5817             :                 return res;
    5818          26 :         if ((res = os_del(os->tables, tr, t->base.name, dup_base(&t->base))))
    5819             :                 return res;
    5820          25 :         return table_dup(tr, t, ns, NULL, &dup, true);
    5821             : }
    5822             : 
    5823             : int
    5824         185 : sql_trans_del_table(sql_trans *tr, sql_table *mt, sql_table *pt, int drop_action)
    5825             : {
    5826         185 :         int res = LOG_OK;
    5827         185 :         sqlstore *store = tr->store;
    5828         185 :         sql_table *dup = NULL, *mt_it;
    5829         185 :         sql_part *mti_part = NULL;
    5830             : 
    5831         185 :         if ((res = new_table(tr, mt, &dup)))
    5832             :                 return res;
    5833         185 :         mt = dup;
    5834         185 :         node *n = members_find_child_id(mt->members, pt->base.id); /* get sqlpart id*/
    5835         185 :         sqlid part_id = ((sql_part*)n->data)->base.id;
    5836         185 :         sql_base *b = os_find_id(mt->s->parts, tr, part_id); /* fetch updated part */
    5837         185 :         sql_part *p = (sql_part*)b;
    5838             : 
    5839         185 :         if ((res = sys_drop_part(tr, p, drop_action)))
    5840             :                 return res;
    5841             :         /*Clean the part from members*/
    5842         185 :         list_remove_node(mt->members, store, n);
    5843             : 
    5844         185 :         if (drop_action == DROP_CASCADE && (res = sql_trans_drop_table_id(tr, mt->s, pt->base.id, drop_action)))
    5845             :                 return res;
    5846         386 :         for (mt_it = mt; mt_it; mt_it = mti_part?mti_part->t:NULL) {
    5847             :                 /* functions depending on parent tables need to be recompiled, ugh */
    5848         193 :                 if ((res = store_reset_sql_functions(tr, mt_it->base.id))) /* reset sql functions depending on the table */
    5849           0 :                         return res;
    5850         193 :                 mti_part = partition_find_part(tr, mt_it, NULL);
    5851             :         }
    5852         185 :         if ((res = store_reset_sql_functions(tr, pt->base.id))) /* reset sql functions depending on the table */
    5853             :                 return res;
    5854             :         return res;
    5855             : }
    5856             : 
    5857             : int
    5858       34284 : sql_trans_create_table(sql_table **tres, sql_trans *tr, sql_schema *s, const char *name, const char *sql, int tt, bit system,
    5859             :                                            int persistence, int commit_action, int sz, bte properties)
    5860             : {
    5861       34284 :         sqlstore *store = tr->store;
    5862       34284 :         sql_table *t = create_sql_table_with_id(NULL, next_oid(tr->store), name, tt, system, persistence, commit_action, properties);
    5863       34356 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    5864       34284 :         sql_table *systable = find_sql_table(tr, syss, "_tables");
    5865       34284 :         sht ca;
    5866       34284 :         int res = LOG_OK;
    5867             : 
    5868             :         /* temps all belong to a special tmp schema and only views/remote have a query */
    5869       34284 :         assert( (isTable(t) ||
    5870             :                 (!isTempTable(t) || (strcmp(s->base.name, "tmp") == 0) || isDeclaredTable(t))) || (isView(t) && !sql) || (isRemote(t) && !sql));
    5871             : 
    5872       34284 :         t->query = sql ?_STRDUP(sql) : NULL;
    5873       34284 :         t->s = s;
    5874       34284 :         t->sz = sz;
    5875       34284 :         if (sz < 0)
    5876        1350 :                 t->sz = COLSIZE;
    5877             : 
    5878       34284 :         if ((res = os_add(isGlobal(t)?s->tables:tr->localtmps, tr, t->base.name, &t->base)))
    5879             :                 return res;
    5880             : 
    5881       34280 :         if (isUnloggedTable(t))
    5882           6 :                 t->persistence = SQL_PERSIST; // It's not a temporary
    5883             : 
    5884       34280 :         if (isRemote(t))
    5885         101 :                 t->persistence = SQL_REMOTE;
    5886             : 
    5887       34280 :         if (isTable(t))
    5888       11058 :                 if ((res = store->storage_api.create_del(tr, t))) {
    5889             :                         ATOMIC_PTR_DESTROY(&t->data);
    5890             :                         return res;
    5891             :                 }
    5892       34280 :         if (isPartitionedByExpressionTable(t)) {
    5893          27 :                 t->part.pexp = ZNEW(sql_expression);
    5894          27 :                 t->part.pexp->type = *sql_bind_localtype("void"); /* leave it non-initialized, at the backend the copy of this table will get the type */
    5895          27 :                 t->part.pexp->cols = list_create((fdestroy) &int_destroy);
    5896             :         }
    5897             : 
    5898       34280 :         ca = t->commit_action;
    5899       34280 :         if (!isDeclaredTable(t)) {
    5900       34280 :                 char *strnil = (char*)ATOMnilptr(TYPE_str);
    5901       34280 :                 if ((res = store->table_api.table_insert(tr, systable, &t->base.id, &t->base.name, &s->base.id,
    5902       34280 :                                                                                   (t->query) ? &t->query : &strnil, &t->type, &t->system, &ca, &t->access))) {
    5903           0 :                         ATOMIC_PTR_DESTROY(&t->data);
    5904           0 :                         return res;
    5905             :                 }
    5906             :         }
    5907       34280 :         *tres = t;
    5908       34280 :         return res;
    5909             : }
    5910             : 
    5911             : int
    5912       33810 : sql_trans_set_partition_table(sql_trans *tr, sql_table *t)
    5913             : {
    5914       33810 :         int res = LOG_OK;
    5915       33810 :         sqlstore *store = tr->store;
    5916             : 
    5917       33810 :         if (t && (isRangePartitionTable(t) || isListPartitionTable(t))) {
    5918         104 :                 sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    5919         104 :                 sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
    5920         104 :                 assert(partitions);
    5921         104 :                 sqlid next = next_oid(tr->store);
    5922         104 :                 if (isPartitionedByColumnTable(t)) {
    5923          80 :                         assert(t->part.pcol);
    5924          80 :                         if ((res = store->table_api.table_insert(tr, partitions, &next, &t->base.id, &t->part.pcol->base.id, &ATOMnilptr(TYPE_str), &t->properties)))
    5925           0 :                                 return res;
    5926          24 :                 } else if (isPartitionedByExpressionTable(t)) {
    5927          24 :                         assert(t->part.pexp->exp);
    5928          24 :                         if (strlen(t->part.pexp->exp) > STORAGE_MAX_VALUE_LENGTH)
    5929             :                                 return -4;
    5930          24 :                         if ((res = store->table_api.table_insert(tr, partitions, &next, &t->base.id, ATOMnilptr(TYPE_int), &t->part.pexp->exp, &t->properties)))
    5931             :                                 return res;
    5932             :                 } else {
    5933           0 :                         assert(0);
    5934             :                 }
    5935             :         }
    5936             :         return res;
    5937             : }
    5938             : 
    5939             : sql_key *
    5940        7530 : create_sql_kc(sqlstore *store, allocator *sa, sql_key *k, sql_column *c)
    5941             : {
    5942        7530 :         sql_kc *kc = SA_ZNEW(sa, sql_kc);
    5943             : 
    5944        7530 :         kc->c = c;
    5945        7530 :         list_append(k->columns, kc);
    5946        7530 :         if (k->idx)
    5947         962 :                 create_sql_ic(store, sa, k->idx, c);
    5948        7530 :         if (k->type == pkey)
    5949        4202 :                 c->null = 0;
    5950        7530 :         return k;
    5951             : }
    5952             : 
    5953             : sql_key *
    5954        5970 : create_sql_ukey(sqlstore *store, allocator *sa, sql_table *t, const char *name, key_type kt, const char* check)
    5955             : {
    5956        5970 :         sql_key *nk = NULL;
    5957        5970 :         sql_ukey *tk;
    5958             : 
    5959        5970 :         nk = (kt != fkey) ? (sql_key *) SA_ZNEW(sa, sql_ukey) : (sql_key *) SA_ZNEW(sa, sql_fkey);
    5960        5970 :         tk = (sql_ukey *) nk;
    5961        5970 :         assert(name);
    5962             : 
    5963        5970 :         base_init(sa, &nk->base, next_oid(store), true, name);
    5964        5970 :         nk->type = kt;
    5965        5970 :         nk->columns = SA_LIST(sa, (fdestroy) NULL);
    5966        5970 :         nk->idx = NULL;
    5967        5970 :         nk->t = t;
    5968        5970 :         nk->check = check ? SA_STRDUP(sa, check) : NULL;
    5969             : 
    5970        5970 :         if (nk->type == pkey)
    5971        3884 :                 t->pkey = tk;
    5972        5970 :         if (ol_add(t->keys, &nk->base))
    5973           0 :                 return NULL;
    5974             :         return nk;
    5975             : }
    5976             : 
    5977             : sql_fkey *
    5978         941 : create_sql_fkey(sqlstore *store, allocator *sa, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update)
    5979             : {
    5980         941 :         sql_key *nk;
    5981         941 :         sql_fkey *fk = NULL;
    5982             : 
    5983         941 :         nk = (kt != fkey) ? (sql_key *) SA_ZNEW(sa, sql_ukey) : (sql_key *) SA_ZNEW(sa, sql_fkey);
    5984             : 
    5985         941 :         assert(name);
    5986         941 :         base_init(sa, &nk->base, next_oid(store), true, name);
    5987         941 :         nk->type = kt;
    5988         941 :         nk->columns = SA_LIST(sa, (fdestroy) NULL);
    5989         941 :         nk->t = t;
    5990         941 :         nk->idx = create_sql_idx(store, sa, t, name, (nk->type == fkey) ? join_idx : hash_idx);
    5991         941 :         nk->idx->key = nk;
    5992             : 
    5993         941 :         fk = (sql_fkey *) nk;
    5994             : 
    5995         941 :         fk->on_delete = on_delete;
    5996         941 :         fk->on_update = on_update;
    5997             : 
    5998         941 :         fk->rkey = rkey->base.id;
    5999         941 :         if (ol_add(t->keys, &nk->base))
    6000           0 :                 return NULL;
    6001             :         return (sql_fkey*) nk;
    6002             : }
    6003             : 
    6004             : sql_idx *
    6005        7210 : create_sql_idx(sqlstore *store, allocator *sa, sql_table *t, const char *name, idx_type it)
    6006             : {
    6007        7210 :         sql_idx *ni = SA_ZNEW(sa, sql_idx);
    6008             : 
    6009        7210 :         base_init(sa, &ni->base, next_oid(store), true, name);
    6010        7210 :         ni->columns = SA_LIST(sa, (fdestroy) NULL);
    6011        7210 :         ni->t = t;
    6012        7210 :         ni->type = it;
    6013        7210 :         ni->key = NULL;
    6014        7210 :         if (ol_add(t->idxs, &ni->base))
    6015           0 :                 return NULL;
    6016             :         return ni;
    6017             : }
    6018             : 
    6019             : sql_idx *
    6020        7925 : create_sql_ic(sqlstore *store, allocator *sa, sql_idx *i, sql_column *c)
    6021             : {
    6022        7925 :         sql_kc *ic = SA_ZNEW(sa, sql_kc);
    6023             : 
    6024        7925 :         ic->c = c;
    6025        7925 :         list_append(i->columns, ic);
    6026             : 
    6027        7925 :         (void)store;
    6028        7925 :         return i;
    6029             : }
    6030             : 
    6031             : sql_idx *
    6032        9565 : create_sql_idx_done(sql_trans *tr, sql_idx *i)
    6033             : {
    6034        9565 :         (void) tr;
    6035        9565 :         if (i && i->key && hash_index(i->type)) {
    6036        8202 :                 int ncols = list_length(i->columns);
    6037       17025 :                 for (node *n = i->columns->h ; n ; n = n->next) {
    6038        8823 :                         sql_kc *kc = n->data;
    6039             : 
    6040        8823 :                         kc->c->unique = (ncols == 1) ? 2 : MAX(kc->c->unique, 1);
    6041             :                 }
    6042             :         }
    6043        9565 :         return i;
    6044             : }
    6045             : 
    6046             : static sql_column *
    6047      266530 : create_sql_column_with_id(allocator *sa, sqlid id, sql_table *t, const char *name, sql_subtype *tpe)
    6048             : {
    6049      266530 :         sql_column *col = SA_ZNEW(sa, sql_column);
    6050             : 
    6051      266530 :         base_init(sa, &col->base, id, true, name);
    6052      266530 :         col->type = *tpe;
    6053      266530 :         col->def = NULL;
    6054      266530 :         col->null = 1;
    6055      266530 :         col->colnr = table_next_column_nr(t);
    6056      266530 :         col->t = t;
    6057      266530 :         col->unique = 0;
    6058      266530 :         col->storage_type = NULL;
    6059             : 
    6060      266530 :         if (ol_add(t->columns, &col->base))
    6061             :                 return NULL;
    6062      266530 :         ATOMIC_PTR_INIT(&col->data, NULL);
    6063      266530 :         return col;
    6064             : }
    6065             : 
    6066             : sql_column *
    6067      256703 : create_sql_column(sqlstore *store, allocator *sa, sql_table *t, const char *name, sql_subtype *tpe)
    6068             : {
    6069      256703 :         return create_sql_column_with_id(sa, next_oid(store), t, name, tpe);
    6070             : }
    6071             : 
    6072             : int
    6073        4064 : sql_trans_drop_table(sql_trans *tr, sql_schema *s, const char *name, int drop_action)
    6074             : {
    6075        4064 :         sql_table *t = find_sql_table(tr, s, name);
    6076             : 
    6077        4064 :         if (!t) {
    6078           0 :                 TRC_ERROR(SQL_STORE, "sql_trans_drop_table: Table %s.%s does not exist\n", s->base.name, name);
    6079           0 :                 return -1;
    6080             :         }
    6081             : 
    6082        4064 :         sql_table *gt = t;
    6083        4064 :         if (t && isTempTable(t)) {
    6084         111 :                 gt = (sql_table*)os_find_id(s->tables, tr, t->base.id);
    6085             :         }
    6086             : 
    6087        4064 :         assert(t == gt || !gt || (isTempTable(gt) && !isLocalTemp(gt) && isLocalTemp(t)));
    6088             : 
    6089        4064 :         int res = LOG_OK;
    6090             : 
    6091        4064 :         if ((drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) &&
    6092         530 :             tr->dropped && list_find_id(tr->dropped, t->base.id))
    6093             :                 return res;
    6094             : 
    6095         530 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    6096         530 :                 sqlid *local_id = MNEW(sqlid);
    6097         530 :                 if (!local_id)
    6098             :                         return -1;
    6099             : 
    6100         530 :                 if (! tr->dropped) {
    6101         481 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    6102         481 :                         if (!tr->dropped) {
    6103           0 :                                 _DELETE(local_id);
    6104           0 :                                 return -1;
    6105             :                         }
    6106             :                 }
    6107         530 :                 *local_id = t->base.id;
    6108         530 :                 list_append(tr->dropped, local_id);
    6109             :         }
    6110             : 
    6111        4064 :         if (!isDeclaredTable(t))
    6112        4114 :                 if ((res = sys_drop_table(tr, gt?gt:t, drop_action)))
    6113             :                         return res;
    6114             : 
    6115        4064 :         if (isNew(t))
    6116         171 :                 t->base.deleted = 1;
    6117        4064 :         if (gt && (res = os_del(s->tables, tr, gt->base.name, dup_base(&gt->base))))
    6118             :                 return res;
    6119        4064 :         if (t != gt && (res = os_del(tr->localtmps, tr, t->base.name, dup_base(&t->base))))
    6120             :                 return res;
    6121             : 
    6122        4064 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    6123         481 :                 list_destroy(tr->dropped);
    6124         481 :                 tr->dropped = NULL;
    6125             :         }
    6126             :         return res;
    6127             : }
    6128             : 
    6129             : int
    6130          55 : sql_trans_drop_table_id(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
    6131             : {
    6132          55 :         sql_table *t = find_sql_table_id(tr, s, id);
    6133             : 
    6134          55 :         if (t)
    6135          55 :                 return sql_trans_drop_table(tr, s, t->base.name, drop_action);
    6136             :         else
    6137             :                 return SQL_ERR;
    6138             : }
    6139             : 
    6140             : BUN
    6141       41826 : sql_trans_clear_table(sql_trans *tr, sql_table *t)
    6142             : {
    6143       41826 :         sqlstore *store = tr->store;
    6144       41826 :         return store->storage_api.clear_table(tr, t);
    6145             : }
    6146             : 
    6147             : int
    6148        9827 : sql_trans_create_column(sql_column **rcol, sql_trans *tr, sql_table *t, const char *name, sql_subtype *tpe)
    6149             : {
    6150        9827 :         sqlstore *store = tr->store;
    6151        9827 :         sql_column *col;
    6152        9827 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    6153        9827 :         sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    6154        9827 :         int res = LOG_OK;
    6155             : 
    6156        9827 :         if (!tpe)
    6157             :                 return -1; /* TODO not sure what to do here */
    6158             : 
    6159        9827 :         col = create_sql_column_with_id(NULL, next_oid(tr->store), t, name, tpe);
    6160             : 
    6161        9827 :         if (isTable(col->t))
    6162        5400 :                 if ((res = store->storage_api.create_col(tr, col))) {
    6163             :                         ATOMIC_PTR_DESTROY(&col->data);
    6164             :                         return res;
    6165             :                 }
    6166        9827 :         if (!isDeclaredTable(t)) {
    6167        9827 :                 char *strnil = (char*)ATOMnilptr(TYPE_str);
    6168        9827 :                 int digits = type_digits(&col->type);
    6169        9827 :                 if ((res = store->table_api.table_insert(tr, syscolumn, &col->base.id, &col->base.name, &col->type.type->base.name, &digits, &col->type.scale,
    6170        9827 :                                                                                   &t->base.id, (col->def) ? &col->def : &strnil, &col->null, &col->colnr, (col->storage_type) ? &col->storage_type : &strnil))) {
    6171           0 :                         ATOMIC_PTR_DESTROY(&col->data);
    6172           0 :                         return res;
    6173             :                 }
    6174             :         }
    6175             : 
    6176        9827 :         if (tpe->type->s) {/* column depends on type */
    6177           0 :                 if ((res = sql_trans_create_dependency(tr, tpe->type->base.id, col->base.id, TYPE_DEPENDENCY))) {
    6178             :                         ATOMIC_PTR_DESTROY(&col->data);
    6179             :                         return res;
    6180             :                 }
    6181           0 :                 if (!isNew(tpe->type) && (res = sql_trans_add_dependency(tr, tpe->type->base.id, ddl))) {
    6182             :                         ATOMIC_PTR_DESTROY(&col->data);
    6183             :                         return res;
    6184             :                 }
    6185             :         }
    6186        9827 :         *rcol = col;
    6187        9827 :         return res;
    6188             : }
    6189             : 
    6190             : void
    6191          68 : drop_sql_column(sql_table *t, sqlid id, int drop_action)
    6192             : {
    6193          68 :         node *n = ol_find_id(t->columns, id);
    6194          68 :         sql_column *col = n->data;
    6195             : 
    6196          68 :         col->drop_action = drop_action;
    6197          68 :         col->base.deleted = 1;
    6198             :         //ol_del(t->columns, t->s->store, n);
    6199          68 : }
    6200             : 
    6201             : void
    6202           0 : drop_sql_idx(sql_table *t, sqlid id)
    6203             : {
    6204           0 :         node *n = ol_find_id(t->idxs, id);
    6205           0 :         sql_idx *i = n->data;
    6206             : 
    6207           0 :         i->base.deleted = 1;
    6208             :         //ol_del(t->idxs, t->s->store, n);
    6209           0 : }
    6210             : 
    6211             : void
    6212           0 : drop_sql_key(sql_table *t, sqlid id, int drop_action)
    6213             : {
    6214           0 :         node *n = ol_find_id(t->keys, id);
    6215           0 :         sql_key *k = n->data;
    6216             : 
    6217           0 :         k->drop_action = drop_action;
    6218           0 :         k->base.deleted = 1;
    6219             :         //ol_del(t->keys, t->s->store, n);
    6220           0 : }
    6221             : 
    6222             : int
    6223          13 : sql_trans_rename_column(sql_trans *tr, sql_table *t, sqlid id, const char *old_name, const char *new_name)
    6224             : {
    6225          13 :         sqlstore *store = tr->store;
    6226          13 :         sql_table *syscolumn = find_sql_table(tr, find_sql_schema(tr, isGlobal(t)?"sys":"tmp"), "_columns");
    6227          13 :         oid rid;
    6228          13 :         int res = LOG_OK;
    6229          13 :         sql_table *dup = NULL;
    6230          13 :         node *n;
    6231             : 
    6232          26 :         assert(!strNil(new_name));
    6233             : 
    6234          13 :         rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"), &id, NULL);
    6235          13 :         assert(!is_oid_nil(rid));
    6236          13 :         if ((res = store->table_api.column_update_value(tr, find_sql_column(syscolumn, "name"), rid, (void*) new_name)))
    6237             :                 return res;
    6238             : 
    6239          13 :         if ((res = new_table(tr, t, &dup)))
    6240             :                 return res;
    6241          13 :         t = dup;
    6242          13 :         if (!(n = ol_find_name(t->columns, old_name)))
    6243             :                 return -1;
    6244          13 :         sql_column *c = n->data;
    6245             : 
    6246          13 :         if (!isNew(c) && (res = sql_trans_add_dependency_change(tr, c->t->base.id, ddl)))
    6247             :                 return res;
    6248          13 :         if (!isNew(c) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
    6249             :                 return res;
    6250             : 
    6251          13 :         _DELETE(c->base.name);
    6252          13 :         c->base.name =_STRDUP(new_name);
    6253          13 :         if (ol_rehash(t->columns, old_name, n) == NULL)
    6254             :                 return -1;
    6255             :         return res;
    6256             : }
    6257             : 
    6258             : static int
    6259         646 : new_column(sql_trans *tr, sql_column *col, sql_column **cres)
    6260             : {
    6261         646 :         int res = LOG_OK;
    6262         646 :         sql_table *t = NULL;
    6263             : 
    6264         646 :         if ((res = new_table(tr, col->t, &t)))
    6265             :                 return res;
    6266         646 :         *cres = find_sql_column(t, col->base.name);
    6267         646 :         return res;
    6268             : }
    6269             : 
    6270             : int
    6271          71 : sql_trans_drop_column(sql_trans *tr, sql_table *t, sqlid id, int drop_action)
    6272             : {
    6273          71 :         sqlstore *store = tr->store;
    6274          71 :         node *n = NULL;
    6275          71 :         sql_table *syscolumn = find_sql_table(tr, find_sql_schema(tr, isGlobal(t)?"sys":"tmp"), "_columns");
    6276          71 :         sql_column *col = NULL, *cid = find_sql_column(syscolumn, "id"), *cnr = find_sql_column(syscolumn, "number");
    6277          71 :         int res = LOG_OK;
    6278          71 :         sql_table *dup = NULL;
    6279             : 
    6280          71 :         if ((res = new_table(tr, t, &dup)))
    6281             :                 return res;
    6282          70 :         t = dup;
    6283         537 :         for (node *nn = t->columns->l->h ; nn ; nn = nn->next) {
    6284         467 :                 sql_column *next = (sql_column *) nn->data;
    6285         467 :                 if (next->base.id == id) {
    6286             :                         n = nn;
    6287             :                         col = next;
    6288         397 :                 } else if (col) { /* if the column to be dropped was found, decrease the column number for others after it */
    6289          92 :                         next->colnr--;
    6290             : 
    6291          92 :                         if (!isDeclaredTable(t)) {
    6292          92 :                                 oid rid = store->table_api.column_find_row(tr, cid, &next->base.id, NULL);
    6293          92 :                                 assert(!is_oid_nil(rid));
    6294          92 :                                 if ((res = store->table_api.column_update_value(tr, cnr, rid, &next->colnr)))
    6295           0 :                                         return res;
    6296             :                         }
    6297             :                 }
    6298             :         }
    6299             : 
    6300          70 :         assert(n && col); /* the column to be dropped must have been found */
    6301             : 
    6302          70 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    6303          11 :                 sqlid *local_id = MNEW(sqlid);
    6304          11 :                 if (!local_id)
    6305             :                         return -1;
    6306             : 
    6307          11 :                 if (! tr->dropped) {
    6308           8 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    6309           8 :                         if (!tr->dropped) {
    6310           0 :                                 _DELETE(local_id);
    6311           0 :                                 return -1;
    6312             :                         }
    6313             :                 }
    6314          11 :                 *local_id = col->base.id;
    6315          11 :                 list_append(tr->dropped, local_id);
    6316             :         }
    6317             : 
    6318          70 :         if (!isNew(col) && (res = sql_trans_add_dependency_change(tr, col->t->base.id, ddl)))
    6319             :                 return res;
    6320          70 :         if (!isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml)))
    6321             :                 return res;
    6322          70 :         if ((res = sys_drop_column(tr, col, drop_action)))
    6323             :                 return res;
    6324             : 
    6325          70 :         if (isNew(col)) { /* remove create from changes */
    6326           7 :                 trans_del(tr, &col->base);
    6327           7 :                 if (!isNew(col->t))
    6328           1 :                         column_destroy(store, col);
    6329             :         }
    6330          70 :         ol_del(t->columns, store, n);
    6331             : 
    6332          70 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    6333           8 :                 list_destroy(tr->dropped);
    6334           8 :                 tr->dropped = NULL;
    6335             :         }
    6336             :         return res;
    6337             : }
    6338             : 
    6339             : int
    6340        4726 : sql_trans_alter_null(sql_trans *tr, sql_column *col, int isnull)
    6341             : {
    6342        4726 :         int res = LOG_OK;
    6343        4726 :         sqlstore *store = tr->store;
    6344             : 
    6345        4726 :         if (col->null != isnull) {
    6346         565 :                 sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
    6347         565 :                 sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    6348         565 :                 oid rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"),
    6349         565 :                                           &col->base.id, NULL);
    6350         565 :                 sql_column *dup = NULL;
    6351             : 
    6352         565 :                 if (is_oid_nil(rid))
    6353           1 :                         return -1;
    6354         565 :                 if ((res = store->table_api.column_update_value(tr, find_sql_column(syscolumn, "null"), rid, &isnull)))
    6355             :                         return res;
    6356             : 
    6357         564 :                 if ((res = new_column(tr, col, &dup)))
    6358             :                         return res;
    6359         564 :                 col = dup;
    6360         564 :                 dup->null = isnull;
    6361             : 
    6362             :                 /* disallow concurrent updates on the column if not null is set */
    6363             :                 /* this dependency is needed for merge tables */
    6364         564 :                 if (!isNew(col) && (res = sql_trans_add_dependency(tr, col->t->base.id, ddl)))
    6365             :                         return res;
    6366         564 :                 if (!isnull && !isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml)))
    6367             :                         return res;
    6368         564 :                 if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */
    6369             :                         return res;
    6370         564 :                 if (isNew(col) || isnull) /* new ie can still change, or persistent only widen semantics */
    6371         459 :                         store->storage_api.col_not_null(tr, col, !isnull);
    6372             :         }
    6373             :         return res;
    6374             : }
    6375             : 
    6376             : int
    6377        2309 : sql_trans_alter_access(sql_trans *tr, sql_table *t, sht access)
    6378             : {
    6379        2309 :         int res = LOG_OK;
    6380        2309 :         sqlstore *store = tr->store;
    6381             : 
    6382        2309 :         if (t->access != access) {
    6383        2309 :                 sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    6384        2309 :                 sql_table *systable = find_sql_table(tr, syss, "_tables");
    6385        2309 :                 oid rid = store->table_api.column_find_row(tr, find_sql_column(systable, "id"),
    6386        2309 :                                           &t->base.id, NULL);
    6387        2309 :                 sql_table *dup = NULL;
    6388             : 
    6389        2309 :                 if (is_oid_nil(rid))
    6390           0 :                         return -1;
    6391        2309 :                 if ((res = store->table_api.column_update_value(tr, find_sql_column(systable, "access"), rid, &access)))
    6392             :                         return res;
    6393        2309 :                 if ((res = new_table(tr, t, &dup)))
    6394             :                         return res;
    6395        2309 :                 t = dup;
    6396        2309 :                 t->access = access;
    6397        2309 :                 if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml)))
    6398             :                         return res;
    6399        2309 :                 if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
    6400             :                         return res;
    6401             :         }
    6402             :         return res;
    6403             : }
    6404             : 
    6405             : int
    6406          23 : sql_trans_alter_default(sql_trans *tr, sql_column *col, char *val)
    6407             : {
    6408          23 :         int res = LOG_OK;
    6409          23 :         sqlstore *store = tr->store;
    6410             : 
    6411          23 :         if ((col->def || val) && (!col->def || !val || strcmp(col->def, val) != 0)) {
    6412          19 :                 void *p = val ? val : (void *) ATOMnilptr(TYPE_str);
    6413          23 :                 sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
    6414          23 :                 sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    6415          23 :                 sql_column *col_ids = find_sql_column(syscolumn, "id");
    6416          23 :                 sql_column *col_dfs = find_sql_column(syscolumn, "default");
    6417          23 :                 oid rid = store->table_api.column_find_row(tr, col_ids, &col->base.id, NULL);
    6418          23 :                 sql_column *dup = NULL;
    6419             : 
    6420          23 :                 if (is_oid_nil(rid))
    6421           0 :                         return -1;
    6422          23 :                 if ((res = sys_drop_default_object(tr, col, 0)))
    6423             :                         return res;
    6424          23 :                 if ((res = store->table_api.column_update_value(tr, col_dfs, rid, p)))
    6425             :                         return res;
    6426             : 
    6427          23 :                 if ((res = new_column(tr, col, &dup)))
    6428             :                         return res;
    6429          23 :                 _DELETE(dup->def);
    6430          23 :                 if (val)
    6431          17 :                         dup->def =_STRDUP(val);
    6432          23 :                 if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */
    6433             :                         return res;
    6434             :         }
    6435             :         return res;
    6436             : }
    6437             : 
    6438             : int
    6439          59 : sql_trans_alter_storage(sql_trans *tr, sql_column *col, char *storage)
    6440             : {
    6441          59 :         int res = LOG_OK;
    6442          59 :         sqlstore *store = tr->store;
    6443             : 
    6444          59 :         if ((col->storage_type || storage) && (!col->storage_type || !storage || strcmp(col->storage_type, storage) != 0)) {
    6445          59 :                 void *p = storage ? storage : (void *) ATOMnilptr(TYPE_str);
    6446          59 :                 sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
    6447          59 :                 sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
    6448          59 :                 sql_column *col_ids = find_sql_column(syscolumn, "id");
    6449          59 :                 sql_column *col_dfs = find_sql_column(syscolumn, "storage");
    6450          59 :                 oid rid = store->table_api.column_find_row(tr, col_ids, &col->base.id, NULL);
    6451          59 :                 sql_column *dup = NULL;
    6452             : 
    6453          59 :                 if (is_oid_nil(rid))
    6454           0 :                         return -1;
    6455          59 :                 if ((res = store->table_api.column_update_value(tr, col_dfs, rid, p)))
    6456             :                         return res;
    6457             : 
    6458          59 :                 if ((res = new_column(tr, col, &dup)))
    6459             :                         return res;
    6460          59 :                 _DELETE(dup->storage_type);
    6461          59 :                 if (storage)
    6462          58 :                         dup->storage_type =_STRDUP(storage);
    6463          59 :                 if (!isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml)))
    6464             :                         return res;
    6465          59 :                 if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */
    6466             :                         return res;
    6467             :         }
    6468             :         return res;
    6469             : }
    6470             : 
    6471             : int
    6472       21612 : sql_trans_is_sorted( sql_trans *tr, sql_column *col )
    6473             : {
    6474       21612 :         sqlstore *store = tr->store;
    6475       21612 :         if (col && isTable(col->t) && store->storage_api.sorted_col && store->storage_api.sorted_col(tr, col))
    6476             :                 return 1;
    6477             :         return 0;
    6478             : }
    6479             : 
    6480             : int
    6481        7814 : sql_trans_is_unique( sql_trans *tr, sql_column *col )
    6482             : {
    6483        7814 :         sqlstore *store = tr->store;
    6484        7814 :         if (col && isTable(col->t) && store->storage_api.unique_col && store->storage_api.unique_col(tr, col))
    6485             :                 return 1;
    6486             :         return 0;
    6487             : }
    6488             : 
    6489             : int
    6490        2048 : sql_trans_is_duplicate_eliminated( sql_trans *tr, sql_column *col )
    6491             : {
    6492        2048 :         sqlstore *store = tr->store;
    6493        2048 :         if (col && isTable(col->t) && store->storage_api.double_elim_col)
    6494        2048 :                 return store->storage_api.double_elim_col(tr, col);
    6495             :         return 0;
    6496             : }
    6497             : 
    6498             : int
    6499     4065230 : sql_trans_col_stats( sql_trans *tr, sql_column *col, bool *nonil, bool *unique, double *unique_est, ValPtr min, ValPtr max )
    6500             : {
    6501     4065230 :         sqlstore *store = tr->store;
    6502     4065230 :         if (col && isTable(col->t) && store->storage_api.col_stats)
    6503     3761318 :                 return store->storage_api.col_stats(tr, col, nonil, unique, unique_est, min, max);
    6504             :         return 0;
    6505             : }
    6506             : 
    6507             : size_t
    6508           0 : sql_trans_dist_count( sql_trans *tr, sql_column *col )
    6509             : {
    6510           0 :         sqlstore *store = tr->store;
    6511             : 
    6512           0 :         if (col && isTable(col->t)) {
    6513           0 :                 if (!col->dcount)
    6514           0 :                         col->dcount = store->storage_api.dcount_col(tr, col);
    6515           0 :                 return col->dcount;
    6516             :         }
    6517             :         return 0;
    6518             : }
    6519             : 
    6520             : int
    6521          87 : sql_trans_ranges( sql_trans *tr, sql_column *col, void **min, void **max )
    6522             : {
    6523          87 :         sqlstore *store = tr->store;
    6524             : 
    6525          87 :         *min = NULL;
    6526          87 :         *max = NULL;
    6527          87 :         if (col && isTable(col->t)) {
    6528          87 :                 if (!col->min || !col->max)
    6529          19 :                         (void) store->storage_api.min_max_col(tr, col);
    6530          87 :                 *min = col->min;
    6531          87 :                 *max = col->max;
    6532             :         }
    6533          87 :         return *min != NULL && *max != NULL;
    6534             : }
    6535             : 
    6536             : int
    6537         225 : sql_trans_create_ukey(sql_key **kres, sql_trans *tr, sql_table *t, const char *name, key_type kt, const char* check)
    6538             : {
    6539             : /* can only have keys between persistent tables */
    6540         225 :         sqlstore *store = tr->store;
    6541         225 :         int neg = -1, action = -1, res = LOG_OK;
    6542         225 :         sql_key *nk;
    6543         225 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    6544         225 :         sql_table *syskey = find_sql_table(tr, syss, "keys");
    6545         225 :         sql_ukey *uk = NULL;
    6546         225 :         sql_table *dup = NULL;
    6547             : 
    6548         225 :         if (isTempTable(t))
    6549             :                 return -1; /* TODO not sure here */
    6550             : 
    6551         225 :         if ((res = new_table(tr, t, &dup)))
    6552             :                 return res;
    6553         225 :         t = dup;
    6554         225 :         nk = (kt != fkey) ? (sql_key *) ZNEW(sql_ukey)
    6555         225 :         : (sql_key *) ZNEW(sql_fkey);
    6556             : 
    6557         225 :         assert(name);
    6558         225 :         base_init(NULL, &nk->base, next_oid(tr->store), true, name);
    6559         225 :         nk->type = kt;
    6560         225 :         nk->columns = list_create((fdestroy) &kc_destroy);
    6561         225 :         nk->t = t;
    6562         225 :         nk->idx = NULL;
    6563             : 
    6564         225 :         uk = (sql_ukey *) nk;
    6565             : 
    6566         225 :         if (nk->type == pkey)
    6567         225 :                 t->pkey = uk;
    6568             : 
    6569         225 :         if ((res = ol_add(t->keys, &nk->base)))
    6570             :                 return res;
    6571         225 :         if ((res = os_add(t->s->keys, tr, nk->base.name, dup_base(&nk->base))) ||
    6572         225 :                 (isGlobal(t) && (res = os_add(tr->cat->objects, tr, nk->base.name, dup_base(&nk->base)))))
    6573           0 :                 return res;
    6574             : 
    6575         225 :         const char *strnil = (const char*)ATOMnilptr(TYPE_str);
    6576         450 :         if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action, (check) ? &check : &strnil)))
    6577             :                 return res;
    6578         225 :         *kres = nk;
    6579         225 :         return res;
    6580             : }
    6581             : 
    6582             : int
    6583           0 : sql_trans_create_fkey(sql_fkey **kres, sql_trans *tr, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update)
    6584             : {
    6585             : /* can only have keys between persistent tables */
    6586           0 :         sqlstore *store = tr->store;
    6587           0 :         int neg = -1, action = (on_update<<8) + on_delete, res = LOG_OK;
    6588           0 :         sql_key *nk;
    6589           0 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    6590           0 :         sql_table *syskey = find_sql_table(tr, syss, "keys");
    6591           0 :         sql_fkey *fk = NULL;
    6592           0 :         sql_table *dup = NULL;
    6593             : 
    6594           0 :         if (isTempTable(t))
    6595             :                 return -1; /* TODO not sure here */
    6596             : 
    6597           0 :         if ((res = new_table(tr, t, &dup)))
    6598             :                 return res;
    6599           0 :         t = dup;
    6600           0 :         nk = (kt != fkey) ? (sql_key *) ZNEW(sql_ukey)
    6601           0 :         : (sql_key *) ZNEW(sql_fkey);
    6602             : 
    6603           0 :         assert(name);
    6604           0 :         base_init(NULL, &nk->base, next_oid(tr->store), true, name);
    6605           0 :         nk->type = kt;
    6606           0 :         nk->columns = list_create((fdestroy) &kc_destroy);
    6607           0 :         nk->t = t;
    6608           0 :         if ((res = sql_trans_create_idx(&nk->idx, tr, t, name, (nk->type == fkey) ? join_idx : hash_idx)))
    6609             :                 return res;
    6610           0 :         nk->idx->key = nk;
    6611             : 
    6612           0 :         fk = (sql_fkey *) nk;
    6613             : 
    6614           0 :         fk->on_delete = on_delete;
    6615           0 :         fk->on_update = on_update;
    6616             : 
    6617           0 :         fk->rkey = rkey->base.id;
    6618             : 
    6619           0 :         if ((res = ol_add(t->keys, &nk->base)))
    6620             :                 return res;
    6621           0 :         if ((res = os_add(t->s->keys, tr, nk->base.name, dup_base(&nk->base))) ||
    6622           0 :                 (isGlobal(t) && (res = os_add(tr->cat->objects, tr, nk->base.name, dup_base(&nk->base)))))
    6623           0 :                 return res;
    6624             : 
    6625           0 :         if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action)))
    6626             :                 return res;
    6627             : 
    6628           0 :         if ((res = sql_trans_create_dependency(tr, ((sql_fkey *) nk)->rkey, nk->base.id, FKEY_DEPENDENCY)))
    6629             :                 return res;
    6630           0 :         *kres = (sql_fkey*) nk;
    6631           0 :         return res;
    6632             : }
    6633             : 
    6634             : int
    6635         225 : sql_trans_create_kc(sql_trans *tr, sql_key *k, sql_column *c)
    6636             : {
    6637         225 :         sqlstore *store = tr->store;
    6638         225 :         sql_kc *kc = ZNEW(sql_kc);
    6639         225 :         int nr = list_length(k->columns);
    6640         225 :         sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
    6641         225 :         sql_table *syskc = find_sql_table(tr, syss, "objects");
    6642         225 :         int res = LOG_OK;
    6643             : 
    6644         225 :         assert(c);
    6645         225 :         kc->c = c;
    6646         225 :         list_append(k->columns, kc);
    6647         225 :         if (k->idx && (res = sql_trans_create_ic(tr, k->idx, c)))
    6648             :                 return res;
    6649             : 
    6650         225 :         if (k->type == pkey) {
    6651         225 :                 if ((res = sql_trans_create_dependency(tr, c->base.id, k->base.id, KEY_DEPENDENCY)))
    6652             :                         return res;
    6653         225 :                 if ((res = sql_trans_alter_null(tr, c, 0))) /* should never trigger error */
    6654             :                         return res;
    6655             :         }
    6656             : 
    6657         225 :         if ((res = store->table_api.table_insert(tr, syskc, &k->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))))
    6658             :                 return res;
    6659             :         return res;
    6660             : }
    6661             : 
    6662             : int
    6663           0 : sql_trans_create_fkc(sql_trans *tr, sql_fkey *fk, sql_column *c)
    6664             : {
    6665           0 :         sqlstore *store = tr->store;
    6666           0 :         sql_key *k = (sql_key *) fk;
    6667           0 :         sql_kc *kc = ZNEW(sql_kc);
    6668           0 :         int nr = list_length(k->columns);
    6669           0 :         sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
    6670           0 :         sql_table *syskc = find_sql_table(tr, syss, "objects");
    6671           0 :         int res = LOG_OK;
    6672             : 
    6673           0 :         assert(c);
    6674           0 :         kc->c = c;
    6675           0 :         list_append(k->columns, kc);
    6676           0 :         if (k->idx && (res = sql_trans_create_ic(tr, k->idx, c)))
    6677             :                 return res;
    6678             : 
    6679           0 :         if ((res = sql_trans_create_dependency(tr, c->base.id, k->base.id, FKEY_DEPENDENCY)))
    6680             :                 return res;
    6681             : 
    6682           0 :         if ((res = store->table_api.table_insert(tr, syskc, &k->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))))
    6683             :                 return res;
    6684             :         return res;
    6685             : }
    6686             : 
    6687             : static sql_idx *
    6688        6157 : table_has_idx( sql_table *t, list *keycols)
    6689             : {
    6690        6157 :         node *n, *m, *o;
    6691        6157 :         char *found = NULL;
    6692        6157 :         int len = list_length(keycols);
    6693        6157 :         found = NEW_ARRAY(char, len);
    6694        6157 :         if (!found)
    6695             :                 return NULL;
    6696        8024 :         if (t->idxs) for ( n = ol_first_node(t->idxs); n; n = n->next ) {
    6697        1961 :                 sql_idx *i = n->data;
    6698        1961 :                 int nr;
    6699             : 
    6700        1961 :                 memset(found, 0, len);
    6701        4049 :                 for (m = keycols->h, nr = 0; m; m = m->next, nr++ ) {
    6702        2088 :                         sql_kc *kc = m->data;
    6703             : 
    6704        4094 :                         for (o = i->columns->h; o; o = o->next) {
    6705        2164 :                                 sql_kc *ikc = o->data;
    6706             : 
    6707        2164 :                                 if (kc->c == ikc->c) {
    6708         158 :                                         found[nr] = 1;
    6709         158 :                                         break;
    6710             :                                 }
    6711             :                         }
    6712             :                 }
    6713        2085 :                 for (nr = 0; nr<len; nr++)
    6714        1991 :                         if (!found[nr])
    6715             :                                 break;
    6716        1961 :                 if (nr == len) {
    6717          94 :                         _DELETE(found);
    6718          94 :                         return i;
    6719             :                 }
    6720             :         }
    6721        6063 :         if (found)
    6722        6063 :                 _DELETE(found);
    6723        6063 :         return NULL;
    6724             : }
    6725             : 
    6726             : sql_key *
    6727        6892 : key_create_done(sql_trans *tr, allocator *sa, sql_key *k)
    6728             : {
    6729        6892 :         sql_idx *i;
    6730        6892 :         sqlstore *store = tr->store;
    6731             : 
    6732        6892 :         if (k->type != fkey && k->type != ckey) {
    6733        5932 :                 if ((i = table_has_idx(k->t, k->columns)) != NULL) {
    6734             :                         /* use available hash, or use the order */
    6735          94 :                         if (hash_index(i->type)) {
    6736          93 :                                 k->idx = i;
    6737          93 :                                 if (!k->idx->key)
    6738           0 :                                         k->idx->key = k;
    6739             :                         }
    6740             :                 }
    6741             : 
    6742             :                 /* we need to create an index */
    6743        5932 :                 k->idx = create_sql_idx(store, sa, k->t, k->base.name, hash_idx);
    6744        5932 :                 k->idx->key = k;
    6745             : 
    6746       12464 :                 for (node *n=k->columns->h; n; n = n->next) {
    6747        6532 :                         sql_kc *kc = n->data;
    6748             : 
    6749        6532 :                         create_sql_ic(store, sa, k->idx, kc->c);
    6750             :                 }
    6751             :         }
    6752        6892 :         k->idx = create_sql_idx_done(tr, k->idx);
    6753        6892 :         return k;
    6754             : }
    6755             : 
    6756             : int
    6757         225 : sql_trans_key_done(sql_trans *tr, sql_key *k)
    6758             : {
    6759         225 :         sql_idx *i;
    6760         225 :         int res = LOG_OK;
    6761             : 
    6762         225 :         if (k->type != fkey) {
    6763         225 :                 if ((i = table_has_idx(k->t, k->columns)) != NULL) {
    6764             :                         /* use available hash, or use the order */
    6765           0 :                         if (hash_index(i->type)) {
    6766           0 :                                 k->idx = i;
    6767           0 :                                 if (!k->idx->key)
    6768           0 :                                         k->idx->key = k;
    6769             :                         }
    6770           0 :                         return res;
    6771             :                 }
    6772             : 
    6773             :                 /* we need to create an index */
    6774         225 :                 if ((res = sql_trans_create_idx(&k->idx, tr, k->t, k->base.name, hash_idx)))
    6775             :                         return res;
    6776         225 :                 k->idx->key = k;
    6777             : 
    6778         450 :                 for (node *n=k->columns->h; n; n = n->next) {
    6779         225 :                         sql_kc *kc = n->data;
    6780             : 
    6781         225 :                         if ((res = sql_trans_create_ic(tr, k->idx, kc->c)))
    6782           0 :                                 return res;
    6783             :                 }
    6784             :         }
    6785         225 :         k->idx = create_sql_idx_done(tr, k->idx);
    6786         225 :         return res;
    6787             : }
    6788             : 
    6789             : int
    6790         423 : sql_trans_drop_key(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
    6791             : {
    6792         423 :         sqlstore *store = tr->store;
    6793         423 :         sql_base *b = os_find_id(s->keys, tr, id);
    6794         423 :         sql_key *k = (sql_key*)b;
    6795         423 :         sql_table *t = k->t;
    6796         423 :         int res = LOG_OK;
    6797         423 :         sql_table *dup = NULL;
    6798             : 
    6799         423 :         if ((res = new_table(tr, t, &dup)))
    6800             :                 return res;
    6801         423 :         t = dup;
    6802         423 :         k = (sql_key*)os_find_id(s->keys, tr, id); /* fetch updated key */
    6803             : 
    6804         423 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    6805         278 :                 sqlid *local_id = MNEW(sqlid);
    6806         278 :                 if (!local_id)
    6807             :                         return -1;
    6808             : 
    6809         278 :                 if (!tr->dropped) {
    6810           2 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    6811           2 :                         if (!tr->dropped) {
    6812           0 :                                 _DELETE(local_id);
    6813           0 :                                 return -1;
    6814             :                         }
    6815             :                 }
    6816         278 :                 *local_id = k->base.id;
    6817         278 :                 list_append(tr->dropped, local_id);
    6818             :         }
    6819             : 
    6820         423 :         if (k->idx && (res = sql_trans_drop_idx(tr, s, k->idx->base.id, drop_action)))
    6821             :                 return res;
    6822         423 :         if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
    6823             :                 return res;
    6824             : 
    6825         423 :         if ((res = sys_drop_key(tr, k, drop_action)))
    6826             :                 return res;
    6827             : 
    6828             :         /*Clean the key from the keys*/
    6829         423 :         node *n = ol_find_name(k->t->keys, k->base.name);
    6830         423 :         if (n)
    6831         423 :                 ol_del(k->t->keys, store, n);
    6832             : 
    6833         423 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    6834           1 :                 list_destroy(tr->dropped);
    6835           1 :                 tr->dropped = NULL;
    6836             :         }
    6837             :         return res;
    6838             : }
    6839             : 
    6840             : int
    6841         225 : sql_trans_create_idx(sql_idx **i, sql_trans *tr, sql_table *t, const char *name, idx_type it)
    6842             : {
    6843             :         /* can only have idxs between persistent tables */
    6844         225 :         sqlstore *store = tr->store;
    6845         225 :         sql_idx *ni = ZNEW(sql_idx);
    6846         225 :         sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
    6847         225 :         sql_table *sysidx = find_sql_table(tr, syss, "idxs");
    6848         225 :         int res = LOG_OK;
    6849             : 
    6850         225 :         assert(it != oph_idx && it != no_idx && it != new_idx_types);
    6851         225 :         assert(name);
    6852         225 :         base_init(NULL, &ni->base, next_oid(tr->store), true, name);
    6853         225 :         ni->type = it;
    6854         225 :         ni->columns = list_create((fdestroy) &kc_destroy);
    6855         225 :         ni->t = t;
    6856         225 :         ni->key = NULL;
    6857             : 
    6858         225 :         if ((res = ol_add(t->idxs, &ni->base)))
    6859             :                 return res;
    6860         225 :         if (isGlobal(t) && (res = os_add(t->s->idxs, tr, ni->base.name, dup_base(&ni->base))))
    6861             :                 return res;
    6862             : 
    6863         225 :         ATOMIC_PTR_INIT(&ni->data, NULL);
    6864         225 :         if (!isDeclaredTable(t) && isTable(ni->t) && idx_has_column(ni->type))
    6865         225 :                 if ((res = store->storage_api.create_idx(tr, ni))) {
    6866             :                         ATOMIC_PTR_DESTROY(&ni->data);
    6867             :                         return res;
    6868             :                 }
    6869         225 :         if (!isDeclaredTable(t))
    6870         225 :                 if ((res = store->table_api.table_insert(tr, sysidx, &ni->base.id, &t->base.id, &ni->type, &ni->base.name))) {
    6871             :                         ATOMIC_PTR_DESTROY(&ni->data);
    6872             :                         return res;
    6873             :                 }
    6874         225 :         *i = ni;
    6875         225 :         return res;
    6876             : }
    6877             : 
    6878             : int
    6879         225 : sql_trans_create_ic(sql_trans *tr, sql_idx *i, sql_column *c)
    6880             : {
    6881         225 :         sqlstore *store = tr->store;
    6882         225 :         sql_kc *ic = ZNEW(sql_kc);
    6883         225 :         int nr = list_length(i->columns);
    6884         225 :         sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
    6885         225 :         sql_table *sysic = find_sql_table(tr, syss, "objects");
    6886         225 :         int res = LOG_OK;
    6887             : 
    6888         225 :         assert(c);
    6889         225 :         ic->c = c;
    6890         225 :         list_append(i->columns, ic);
    6891             : 
    6892         225 :         if ((res = store->table_api.table_insert(tr, sysic, &i->base.id, &ic->c->base.name, &nr, ATOMnilptr(TYPE_int))))
    6893             :                 return res;
    6894             :         return res;
    6895             : }
    6896             : 
    6897             : int
    6898         586 : sql_trans_drop_idx(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
    6899             : {
    6900         586 :         sqlstore *store = tr->store;
    6901         586 :         sql_idx *i = schema_find_idx_id(tr, s, id);
    6902         586 :         int res = LOG_OK;
    6903             : 
    6904         586 :         if (!i) /* already dropped */
    6905             :                 return res;
    6906             : 
    6907         582 :         sql_table *t = NULL;
    6908         582 :         if ((res = new_table(tr, i->t, &t)))
    6909             :                 return res;
    6910         582 :         i = schema_find_idx_id(tr, s, id); /* fetch updated idx */
    6911             : 
    6912         582 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    6913         282 :                 sqlid *local_id = MNEW(sqlid);
    6914         282 :                 if (!local_id)
    6915             :                         return -1;
    6916             : 
    6917         282 :                 if (!tr->dropped) {
    6918           0 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    6919           0 :                         if (!tr->dropped) {
    6920           0 :                                 _DELETE(local_id);
    6921           0 :                                 return -1;
    6922             :                         }
    6923             :                 }
    6924         282 :                 *local_id = i->base.id;
    6925         282 :                 list_append(tr->dropped, local_id);
    6926             :         }
    6927             : 
    6928         582 :         if (!isNew(i) && (res = sql_trans_add_dependency_change(tr, i->t->base.id, ddl)))
    6929             :                 return res;
    6930         582 :         if (!isNew(i) && isGlobal(i->t) && !isGlobalTemp(i->t) && (res = sql_trans_add_dependency(tr, i->t->base.id, dml)))
    6931             :                 return res;
    6932         582 :         if ((res = sys_drop_idx(tr, i, drop_action)))
    6933             :                 return res;
    6934         582 :         if ((res = store_reset_sql_functions(tr, i->t->base.id))) /* reset sql functions depending on the table */
    6935             :                 return res;
    6936             : 
    6937         582 :         node *n = ol_find_name(i->t->idxs, i->base.name);
    6938         582 :         if (n)
    6939         582 :                 ol_del(i->t->idxs, store, n);
    6940             : 
    6941         582 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    6942           1 :                 list_destroy(tr->dropped);
    6943           1 :                 tr->dropped = NULL;
    6944             :         }
    6945             :         return res;
    6946             : }
    6947             : 
    6948             : 
    6949             : static int
    6950         339 : sql_trans_create_table_trigger(sql_trigger **tres, sql_trans *tr, sql_table *t, const char *name,
    6951             :         sht time, sht orientation, sht event, const char *old_name, const char *new_name,
    6952             :         const char *condition, const char *statement )
    6953             : {
    6954         339 :         sqlstore *store = tr->store;
    6955         339 :         sql_schema *syss = (t != NULL) ? find_sql_schema(tr, isGlobal(t) ? "sys":"tmp") : find_sql_schema(tr, "sys");
    6956         339 :         sql_table *systrigger = find_sql_table(tr, syss, "triggers");
    6957         339 :         char *strnil = (char*)ATOMnilptr(TYPE_str);
    6958         339 :         sql_table *dup = NULL;
    6959         339 :         int res = LOG_OK;
    6960             : 
    6961         339 :         assert(name);
    6962             : 
    6963         339 :         if ( t && (res = new_table(tr, t, &dup)))
    6964             :                 return res;
    6965         339 :         t = dup;
    6966         339 :         sql_trigger *nt = ZNEW(sql_trigger);
    6967         339 :         base_init(NULL, &nt->base, next_oid(tr->store), true, name);
    6968         339 :         nt->columns = list_create((fdestroy) &kc_destroy);
    6969         339 :         nt->t = t;
    6970         339 :         nt->time = time;
    6971         339 :         nt->orientation = orientation;
    6972         339 :         nt->event = event;
    6973         339 :         nt->old_name = nt->new_name = nt->condition = NULL;
    6974         339 :         if (old_name)
    6975          27 :                 nt->old_name =_STRDUP(old_name);
    6976         339 :         if (new_name)
    6977          40 :                 nt->new_name =_STRDUP(new_name);
    6978         339 :         if (condition)
    6979           0 :                 nt->condition =_STRDUP(condition);
    6980         339 :         nt->statement =_STRDUP(statement);
    6981         339 :         if(t) {
    6982         339 :                 assert(isGlobal(t));
    6983         339 :                 if ((res = ol_add(t->triggers, &nt->base)) ||
    6984         339 :                         (res = os_add(t->s->triggers, tr, nt->base.name, dup_base(&nt->base)))) {
    6985           0 :                         return res;
    6986             :                 }
    6987             :         }
    6988         339 :         sqlid tid = t? t->base.id : int_nil;
    6989             : 
    6990         379 :         if ((res = store->table_api.table_insert(tr, systrigger, &nt->base.id, &nt->base.name, &tid, &nt->time, &nt->orientation,
    6991         379 :                                                          &nt->event, (nt->old_name)?&nt->old_name:&strnil, (nt->new_name)?&nt->new_name:&strnil,
    6992         339 :                                                          (nt->condition)?&nt->condition:&strnil, &nt->statement))) {
    6993             :                 return res;
    6994             :         }
    6995         339 :         *tres = nt;
    6996         339 :         return res;
    6997             : }
    6998             : 
    6999             : int
    7000         343 : sql_trans_create_trigger(sql_trigger **tres, sql_trans *tr, sql_table *t, const char *name,
    7001             :         sht time, sht orientation, sht event, const char *old_name, const char *new_name,
    7002             :         const char *condition, const char *statement )
    7003             : {
    7004         343 :         if (t)
    7005         339 :                 return sql_trans_create_table_trigger(
    7006             :                                 tres, tr, t, name, time,
    7007             :                                 orientation, event, old_name,
    7008             :                                 new_name, condition, statement);
    7009             : 
    7010             :         // triggers not bound to objects (e.g. table)
    7011             :         // are added to sys->triggers
    7012             : 
    7013           4 :         sqlstore *store = tr->store;
    7014           4 :         sql_schema *syss = find_sql_schema(tr, "sys");
    7015           4 :         sql_table *systrigger = find_sql_table(tr, syss, "triggers");
    7016           4 :         char *strnil = (char*)ATOMnilptr(TYPE_str);
    7017           4 :         int res = LOG_OK;
    7018             : 
    7019           4 :         assert(name);
    7020             : 
    7021           4 :         sql_trigger *nt = ZNEW(sql_trigger);
    7022           4 :         base_init(NULL, &nt->base, next_oid(tr->store), true, name);
    7023           4 :         nt->time = time;
    7024           4 :         nt->orientation = orientation;
    7025           4 :         nt->event = event;
    7026           4 :         nt->old_name = nt->new_name = nt->condition = NULL;
    7027           4 :         if (old_name)
    7028           0 :                 nt->old_name =_STRDUP(old_name);
    7029           4 :         if (new_name)
    7030           0 :                 nt->new_name =_STRDUP(new_name);
    7031           4 :         if (condition)
    7032           0 :                 nt->condition =_STRDUP(condition);
    7033           4 :         nt->statement =_STRDUP(statement);
    7034           4 :         if ((res = os_add(syss->triggers, tr, nt->base.name, &nt->base))) {
    7035           0 :                 trigger_destroy(store, nt);
    7036           0 :                 return res;
    7037             :         }
    7038           4 :         sqlid tid = int_nil;
    7039             : 
    7040           4 :         if ((res = store->table_api.table_insert(tr, systrigger, &nt->base.id, &nt->base.name, &tid, &nt->time, &nt->orientation,
    7041           4 :                                                          &nt->event, (nt->old_name)?&nt->old_name:&strnil, (nt->new_name)?&nt->new_name:&strnil,
    7042           4 :                                                          (nt->condition)?&nt->condition:&strnil, &nt->statement))) {
    7043           0 :                 trigger_destroy(store, nt);
    7044           0 :                 return res;
    7045             :         }
    7046             : 
    7047           4 :         *tres = nt;
    7048           4 :         return res;
    7049             : }
    7050             : 
    7051             : int
    7052          91 : sql_trans_drop_trigger(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
    7053             : {
    7054          91 :         sqlstore *store = tr->store;
    7055          91 :         sql_base *b = os_find_id(s->triggers, tr, id);
    7056          91 :         int res = LOG_OK;
    7057             : 
    7058          91 :         if (!b) /* already dropped */
    7059             :                 return res;
    7060             : 
    7061          91 :         sql_trigger *i = (sql_trigger*)b;
    7062          91 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    7063           2 :                 sqlid *local_id = MNEW(sqlid);
    7064           2 :                 if (!local_id)
    7065             :                         return -1;
    7066             : 
    7067           2 :                 if (! tr->dropped) {
    7068           0 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    7069           0 :                         if (!tr->dropped) {
    7070           0 :                                 _DELETE(local_id);
    7071           0 :                                 return -1;
    7072             :                         }
    7073             :                 }
    7074           2 :                 *local_id = i->base.id;
    7075           2 :                 list_append(tr->dropped, local_id);
    7076             :         }
    7077             : 
    7078          91 :         if (i->t) {
    7079          88 :                 if ((res = store_reset_sql_functions(tr, i->t->base.id))) /* reset sql functions depending on the table */
    7080             :                         return res;
    7081          88 :                 node *n = ol_find_name(i->t->triggers, i->base.name);
    7082          88 :                 if (n)
    7083          85 :                         ol_del(i->t->triggers, store, n);
    7084             :         }
    7085          91 :         if ((res = sys_drop_trigger(tr, i)))
    7086             :                 return res;
    7087             : 
    7088          88 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    7089           0 :                 list_destroy(tr->dropped);
    7090           0 :                 tr->dropped = NULL;
    7091             :         }
    7092             :         return res;
    7093             : }
    7094             : 
    7095             : static sql_sequence *
    7096         681 : create_sql_sequence_with_id(allocator *sa, sqlid id, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc,
    7097             :                                         lng cacheinc, bit cycle)
    7098             : {
    7099         681 :         sql_sequence *seq = SA_ZNEW(sa, sql_sequence);
    7100             : 
    7101         681 :         assert(name);
    7102         681 :         base_init(sa, &seq->base, id, true, name);
    7103         681 :         seq->start = start;
    7104         681 :         seq->minvalue = min;
    7105         681 :         seq->maxvalue = max;
    7106         681 :         seq->increment = inc;
    7107         681 :         seq->cacheinc = cacheinc;
    7108         681 :         seq->cycle = cycle;
    7109         681 :         seq->s = s;
    7110         681 :         return seq;
    7111             : }
    7112             : 
    7113             : sql_sequence *
    7114         365 : create_sql_sequence(sqlstore *store, allocator *sa, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc,
    7115             :                                         lng cacheinc, bit cycle)
    7116             : {
    7117         365 :         return create_sql_sequence_with_id(sa, next_oid(store), s, name, start, min, max, inc, cacheinc, cycle);
    7118             : }
    7119             : 
    7120             : int
    7121         316 : sql_trans_create_sequence(sql_trans *tr, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc,
    7122             :                                                   lng cacheinc, bit cycle, bit bedropped)
    7123             : {
    7124         316 :         sqlstore *store = tr->store;
    7125         316 :         sql_schema *syss = find_sql_schema(tr, "sys");
    7126         316 :         sql_table *sysseqs = find_sql_table(tr, syss, "sequences");
    7127         316 :         sql_sequence *seq = create_sql_sequence_with_id(NULL, next_oid(tr->store), s, name, start, min, max, inc, cacheinc, cycle);
    7128         316 :         int res = LOG_OK;
    7129             : 
    7130         316 :         if ((res = os_add(s->seqs, tr, seq->base.name, &seq->base)))
    7131             :                 return res;
    7132         316 :         if ((res = store->table_api.table_insert(tr, sysseqs, &seq->base.id, &s->base.id, &seq->base.name, &seq->start, &seq->minvalue,
    7133             :                                                          &seq->maxvalue, &seq->increment, &seq->cacheinc, &seq->cycle)))
    7134             :                 return res;
    7135             : 
    7136             :         /*Create a BEDROPPED dependency for a SERIAL COLUMN*/
    7137         316 :         if (bedropped) {
    7138         197 :                 if ((res = sql_trans_create_dependency(tr, seq->base.id, seq->base.id, BEDROPPED_DEPENDENCY)))
    7139             :                         return res;
    7140         197 :                 if (!isNew(seq) && (res = sql_trans_add_dependency(tr, seq->base.id, ddl)))
    7141             :                         return res;
    7142             :         }
    7143             :         return res;
    7144             : }
    7145             : 
    7146             : int
    7147          30 : sql_trans_drop_sequence(sql_trans *tr, sql_schema *s, sql_sequence *seq, int drop_action)
    7148             : {
    7149          30 :         int res = LOG_OK;
    7150             : 
    7151          30 :         if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
    7152           0 :                 sqlid* local_id = MNEW(sqlid);
    7153           0 :                 if (!local_id)
    7154             :                         return -1;
    7155             : 
    7156           0 :                 if (!tr->dropped) {
    7157           0 :                         tr->dropped = list_create((fdestroy) &id_destroy);
    7158           0 :                         if (!tr->dropped) {
    7159           0 :                                 _DELETE(local_id);
    7160           0 :                                 return -1;
    7161             :                         }
    7162             :                 }
    7163           0 :                 *local_id = seq->base.id;
    7164           0 :                 list_append(tr->dropped, local_id);
    7165             :         }
    7166             : 
    7167          30 :         if ((res = sys_drop_sequence(tr, seq, drop_action)))
    7168             :                 return res;
    7169          30 :         if ((res = os_del(s->seqs, tr, seq->base.name, dup_base(&seq->base))))
    7170             :                 return res;
    7171             : 
    7172          30 :         if (drop_action == DROP_CASCADE_START && tr->dropped) {
    7173           0 :                 list_destroy(tr->dropped);
    7174           0 :                 tr->dropped = NULL;
    7175             :         }
    7176             :         return res;
    7177             : }
    7178             : 
    7179             : int
    7180          45 : sql_trans_alter_sequence(sql_trans *tr, sql_sequence *seq, lng min, lng max, lng inc, lng cache, bit cycle)
    7181             : {
    7182          45 :         sqlstore *store = tr->store;
    7183          45 :         sql_schema *syss = find_sql_schema(tr, "sys");
    7184          45 :         sql_table *seqs = find_sql_table(tr, syss, "sequences");
    7185          45 :         oid rid = store->table_api.column_find_row(tr, find_sql_column(seqs, "id"), &seq->base.id, NULL);
    7186          45 :         sql_column *c;
    7187          45 :         int res = LOG_OK;
    7188             : 
    7189          45 :         if (is_oid_nil(rid))
    7190             :                 return -1;
    7191          45 :         if (!is_lng_nil(min) && seq->minvalue != min) {
    7192          33 :                 seq->minvalue = min;
    7193          33 :                 c = find_sql_column(seqs, "minvalue");
    7194          33 :                 if ((res = store->table_api.column_update_value(tr, c, rid, &seq->minvalue)))
    7195             :                         return res;
    7196             :         }
    7197          45 :         if (!is_lng_nil(max) && seq->maxvalue != max) {
    7198           7 :                 seq->maxvalue = max;
    7199           7 :                 c = find_sql_column(seqs, "maxvalue");
    7200           7 :                 if ((res = store->table_api.column_update_value(tr, c, rid, &seq->maxvalue)))
    7201             :                         return res;
    7202             :         }
    7203          45 :         if (!is_lng_nil(inc) && seq->increment != inc) {
    7204           7 :                 seq->increment = inc;
    7205           7 :                 c = find_sql_column(seqs, "increment");
    7206           7 :                 if ((res = store->table_api.column_update_value(tr, c, rid, &seq->increment)))
    7207             :                         return res;
    7208             :         }
    7209          45 :         if (!is_lng_nil(cache) && seq->cacheinc != cache) {
    7210           0 :                 seq->cacheinc = cache;
    7211           0 :                 c = find_sql_column(seqs, "cacheinc");
    7212           0 :                 if ((res = store->table_api.column_update_value(tr, c, rid, &seq->cacheinc)))
    7213             :                         return res;
    7214             :         }
    7215          45 :         if (!is_bit_nil(cycle) && seq->cycle != cycle) {
    7216           7 :                 seq->cycle = cycle != 0;
    7217           7 :                 c = find_sql_column(seqs, "cycle");
    7218           7 :                 if ((res = store->table_api.column_update_value(tr, c, rid, &seq->cycle)))
    7219             :                         return res;
    7220             :         }
    7221             :         return res;
    7222             : }
    7223             : 
    7224             : int
    7225          47 : sql_trans_sequence_restart(sql_trans *tr, sql_sequence *seq, lng start)
    7226             : {
    7227          47 :         int res = LOG_OK;
    7228          47 :         sqlstore *store = tr->store;
    7229             : 
    7230          47 :         if (!is_lng_nil(start) && seq->start != start) { /* new valid value, change */
    7231          16 :                 sql_schema *syss = find_sql_schema(tr, "sys");
    7232          16 :                 sql_table *seqs = find_sql_table(tr, syss, "sequences");
    7233          16 :                 oid rid = store->table_api.column_find_row(tr, find_sql_column(seqs, "id"), &seq->base.id, NULL);
    7234          16 :                 sql_column *c = find_sql_column(seqs, "start");
    7235             : 
    7236          16 :                 assert(!is_oid_nil(rid));
    7237          16 :                 seq->start = start;
    7238          16 :                 if ((res = store->table_api.column_update_value(tr, c, rid, &start)))
    7239             :                         return res;
    7240             :         }
    7241          47 :         return seq_restart(tr->store, seq, start) ? 0 : -4;
    7242             : }
    7243             : 
    7244             : sql_session *
    7245       37874 : sql_session_create(sqlstore *store, allocator *sa, int ac)
    7246             : {
    7247       37874 :         sql_session *s;
    7248             : 
    7249       37874 :         if (store->singleuser > 1) {
    7250           0 :                 TRC_ERROR(SQL_STORE, "No second connection allowed in singleuser mode\n");
    7251           0 :                 return NULL;
    7252             :         }
    7253             : 
    7254       37874 :         s = ZNEW(sql_session);
    7255       37874 :         if (!s)
    7256             :                 return NULL;
    7257       37874 :         s->sa = sa;
    7258       37874 :         assert(sa);
    7259       37874 :         s->tr = sql_trans_create_(store, NULL, NULL);
    7260       37874 :         if (!s->tr) {
    7261           0 :                 _DELETE(s);
    7262           0 :                 return NULL;
    7263             :         }
    7264       37874 :         s->tr->active = 0;
    7265       37874 :         if (!sql_session_reset(s, ac)) {
    7266           0 :                 sql_trans_destroy(s->tr);
    7267           0 :                 _DELETE(s);
    7268           0 :                 return NULL;
    7269             :         }
    7270       37874 :         if (store->singleuser)
    7271           0 :                 store->singleuser = 2;
    7272             :         return s;
    7273             : }
    7274             : 
    7275             : void
    7276       37874 : sql_session_destroy(sql_session *s)
    7277             : {
    7278       37874 :         if (s->tr) {
    7279       37874 :                 sqlstore *store = s->tr->store;
    7280       37874 :                 if (store->singleuser)
    7281           0 :                         store->singleuser = 1;
    7282             :         }
    7283             :         // TODO check if s->tr is not always there
    7284       37874 :         assert(!s->tr || s->tr->active == 0);
    7285       37874 :         if (s->tr)
    7286       37874 :                 sql_trans_destroy(s->tr);
    7287       37874 :         _DELETE(s);
    7288       37874 : }
    7289             : 
    7290             : int
    7291       37874 : sql_session_reset(sql_session *s, int ac)
    7292             : {
    7293       37874 :         if (!s->tr)
    7294             :                 return 0;
    7295             : 
    7296       37874 :         assert(s->tr && s->tr->active == 0);
    7297       37874 :         s->schema_name = s->def_schema_name;
    7298       37874 :         s->schema = NULL;
    7299       37874 :         s->auto_commit = s->ac_on_commit = ac;
    7300       37874 :         s->level = tr_serializable;
    7301       37874 :         return 1;
    7302             : }
    7303             : 
    7304             : int
    7305      220028 : sql_trans_begin(sql_session *s)
    7306             : {
    7307      220028 :         sql_trans *tr = s->tr;
    7308      220028 :         sqlstore *store = tr->store;
    7309             : 
    7310      220028 :         store_lock(store);
    7311      220029 :         TRC_DEBUG(SQL_STORE, "Enter sql_trans_begin for transaction: " ULLFMT "\n", tr->tid);
    7312      220029 :         tr->ts = store_timestamp(store);
    7313      220029 :         if (s->schema_name && !(s->schema = find_sql_schema(tr, s->schema_name)))
    7314           3 :                 s->schema_name = s->def_schema_name;
    7315      220029 :         if (!s->schema_name)
    7316       37873 :                 s->schema_name = "sys";
    7317      220029 :         if (s->schema_name && !(s->schema = find_sql_schema(tr, s->schema_name))) {
    7318           2 :                 TRC_DEBUG(SQL_STORE, "Exit sql_trans_begin for transaction: " ULLFMT " with error, the schema %s was not found\n", tr->tid, s->schema_name);
    7319           2 :                 store_unlock(store);
    7320           2 :                 return -3;
    7321             :         }
    7322      220027 :         tr->active = 1;
    7323             : 
    7324      440054 :         int res = ATOMIC_GET(&s->schema_version) ?
    7325      220027 :                 ATOMIC_GET(&s->schema_version) != ATOMIC_GET(&tr->cat->schema_version) : 0;
    7326      220027 :         ATOMIC_SET(&s->schema_version, tr->cat->schema_version);
    7327             : 
    7328      220027 :         ATOMIC_INC(&store->nr_active);
    7329      220027 :         list_append(store->active, tr);
    7330             : 
    7331      220027 :         TRC_DEBUG(SQL_STORE, "Exit sql_trans_begin for transaction: " ULLFMT "\n", tr->tid);
    7332      220027 :         store_unlock(store);
    7333      220026 :         s->status = tr->status = 0;
    7334      220026 :         return res;
    7335             : }
    7336             : 
    7337             : int
    7338      220024 : sql_trans_end(sql_session *s, int ok)
    7339             : {
    7340      220024 :         int res = SQL_OK;
    7341      220024 :         TRC_DEBUG(SQL_STORE, "End of transaction: " ULLFMT "\n", s->tr->tid);
    7342      220024 :         if (ok == SQL_OK) {
    7343      158523 :                 res = sql_trans_commit(s->tr);
    7344             :         }
    7345      220024 :         if (ok == SQL_ERR || res != SQL_OK) /* if a conflict happened, it was already rollbacked */
    7346       62415 :                 sql_trans_rollback(s->tr, false);
    7347      220023 :         assert(s->tr->active);
    7348      220023 :         sqlstore *store = s->tr->store;
    7349      220023 :         store_lock(store);
    7350      220027 :         s->tr->active = 0;
    7351      220027 :         s->tr->status = 0;
    7352      220027 :         s->auto_commit = s->ac_on_commit;
    7353      220027 :         s->schema = NULL;
    7354      220027 :         list_remove_data(store->active, NULL, s->tr);
    7355      220027 :         ATOMIC_SET(&store->lastactive, GDKusec());
    7356      220027 :         ATOMIC_DEC(&store->nr_active);
    7357      220027 :         ulng oldest = store_get_timestamp(store);
    7358      220027 :         if (store->active && store->active->h) {
    7359     1346746 :                 for(node *n = store->active->h; n; n = n->next) {
    7360     1208824 :                         sql_trans *tr = n->data;
    7361     1208824 :                         if (tr->ts < oldest)
    7362             :                                 oldest = tr->ts;
    7363             :                 }
    7364             :         }
    7365      220027 :         ATOMIC_SET(&store->oldest, oldest);
    7366      220027 :         assert(list_length(store->active) == (int) ATOMIC_GET(&store->nr_active));
    7367      220027 :         store_unlock(store);
    7368      220027 :         return res;
    7369             : }
    7370             : 
    7371             : void
    7372        1065 : find_partition_type(sql_subtype *tpe, sql_table *mt)
    7373             : {
    7374        1065 :         if (isPartitionedByColumnTable(mt)) {
    7375         913 :                 *tpe = mt->part.pcol->type;
    7376         152 :         } else if (isPartitionedByExpressionTable(mt)) {
    7377         152 :                 *tpe = mt->part.pexp->type;
    7378             :         } else {
    7379           0 :                 assert(0);
    7380             :         }
    7381        1065 : }
    7382             : 
    7383             : static int
    7384          51 : convert_part_values(sql_trans *tr, sql_table *mt )
    7385             : {
    7386          51 :         sql_subtype found = { 0 };
    7387          51 :         int localtype;
    7388          51 :         find_partition_type(&found, mt);
    7389          51 :         localtype = found.type->localtype;
    7390             : 
    7391          51 :         if (localtype != TYPE_str && mt->members && list_length(mt->members)) {
    7392         144 :                 for (node *n = mt->members->h; n; n = n->next) {
    7393          99 :                         sql_part *p = n->data;
    7394             : 
    7395          99 :                         if (isListPartitionTable(mt)) {
    7396         129 :                                 for (node *m = p->part.values->h; m; m = m->next) {
    7397          96 :                                         sql_part_value *v = (sql_part_value*) m->data, ov = *v;
    7398          96 :                                         ValRecord vvalue;
    7399          96 :                                         ptr ok;
    7400             : 
    7401          96 :                                         vvalue = (ValRecord) {.vtype = TYPE_void,};
    7402          96 :                                         ok = VALinit(&vvalue, TYPE_str, v->value);
    7403          96 :                                         if (ok)
    7404          96 :                                                 ok = VALconvert(localtype, &vvalue);
    7405          96 :                                         if (ok) {
    7406          96 :                                                 ok = v->value = NEW_ARRAY(char, vvalue.len);
    7407          96 :                                                 if (ok) {
    7408          96 :                                                         memcpy(v->value, VALget(&vvalue), vvalue.len);
    7409          96 :                                                         v->length = vvalue.len;
    7410             :                                                 }
    7411             :                                         }
    7412          96 :                                         VALclear(&vvalue);
    7413          96 :                                         if (!ok)
    7414           0 :                                                 return -1;
    7415          96 :                                         _DELETE(ov.value);
    7416             :                                 }
    7417          66 :                         } else if (isRangePartitionTable(mt)) {
    7418          66 :                                 ValRecord vmin, vmax;
    7419          66 :                                 ptr ok;
    7420             : 
    7421          66 :                                 vmin = vmax = (ValRecord) {.vtype = TYPE_void,};
    7422          66 :                                 ok = VALinit(&vmin, TYPE_str, p->part.range.minvalue);
    7423          66 :                                 if (ok)
    7424          66 :                                         ok = VALinit(&vmax, TYPE_str, p->part.range.maxvalue);
    7425          66 :                                 _DELETE(p->part.range.minvalue);
    7426          66 :                                 _DELETE(p->part.range.maxvalue);
    7427          66 :                                 if (ok) {
    7428          66 :                                         if (strNil((const char *)VALget(&vmin)) &&
    7429          42 :                                                 strNil((const char *)VALget(&vmax))) {
    7430          32 :                                                 const void *nil_ptr = ATOMnilptr(localtype);
    7431          32 :                                                 size_t nil_len = ATOMlen(localtype, nil_ptr);
    7432             : 
    7433          32 :                                                 p->part.range.minvalue = NEW_ARRAY(char, nil_len);
    7434          32 :                                                 p->part.range.maxvalue = NEW_ARRAY(char, nil_len);
    7435          32 :                                                 if (p->part.range.minvalue == NULL ||
    7436             :                                                         p->part.range.maxvalue == NULL) {
    7437           0 :                                                         ok = NULL;
    7438           0 :                                                         _DELETE(p->part.range.minvalue);
    7439           0 :                                                         _DELETE(p->part.range.maxvalue);
    7440             :                                                 } else {
    7441          32 :                                                         memcpy(p->part.range.minvalue, nil_ptr, nil_len);
    7442          32 :                                                         memcpy(p->part.range.maxvalue, nil_ptr, nil_len);
    7443          32 :                                                         p->part.range.minlength = nil_len;
    7444          32 :                                                         p->part.range.maxlength = nil_len;
    7445             :                                                 }
    7446             :                                         } else {
    7447          34 :                                                 ok = VALconvert(localtype, &vmin);
    7448          34 :                                                 if (ok)
    7449          34 :                                                         ok = VALconvert(localtype, &vmax);
    7450          34 :                                                 if (ok) {
    7451          34 :                                                         p->part.range.minvalue = NEW_ARRAY(char, vmin.len);
    7452          34 :                                                         p->part.range.maxvalue = NEW_ARRAY(char, vmax.len);
    7453          34 :                                                         if (p->part.range.minvalue == NULL ||
    7454             :                                                                 p->part.range.maxvalue == NULL) {
    7455           0 :                                                                 ok = NULL;
    7456           0 :                                                                 _DELETE(p->part.range.minvalue);
    7457           0 :                                                                 _DELETE(p->part.range.maxvalue);
    7458             :                                                         } else {
    7459          34 :                                                                 memcpy(p->part.range.minvalue, VALget(&vmin), vmin.len);
    7460          34 :                                                                 memcpy(p->part.range.maxvalue, VALget(&vmax), vmax.len);
    7461          34 :                                                                 p->part.range.minlength = vmin.len;
    7462          34 :                                                                 p->part.range.maxlength = vmax.len;
    7463             :                                                         }
    7464             :                                                 }
    7465             :                                         }
    7466          66 :                                         if (ok && isPartitionedByColumnTable(p->t))
    7467          64 :                                                 col_set_range(tr, p, true);
    7468             :                                 }
    7469          66 :                                 VALclear(&vmin);
    7470          66 :                                 VALclear(&vmax);
    7471          66 :                                 if (!ok)
    7472           0 :                                         return -1;
    7473             :                         }
    7474             :                 }
    7475             :         }
    7476             :         return 0;
    7477             : }
    7478             : 
    7479             : int
    7480         331 : sql_trans_convert_partitions(sql_trans *tr)
    7481             : {
    7482         331 :         struct os_iter si;
    7483         331 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
    7484        1781 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
    7485        1450 :                 sql_schema *ss = (sql_schema*)b;
    7486        1450 :                 struct os_iter oi;
    7487        1450 :                 os_iterator(&oi, ss->tables, tr, NULL);
    7488       23588 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
    7489       22138 :                         sql_table *tt = (sql_table*)b;
    7490       22138 :                         if (isPartitionedByColumnTable(tt) || isPartitionedByExpressionTable(tt)) {
    7491          51 :                                 if (convert_part_values(tr, tt) < 0)
    7492           0 :                                         return -1;
    7493             :                         }
    7494             :                 }
    7495             :         }
    7496             :         return 0;
    7497             : }
    7498             : 
    7499             : void
    7500         116 : store_printinfo(sqlstore *store)
    7501             : {
    7502         116 :         if (!MT_lock_trytime(&store->commit, 1000)) {
    7503           0 :                 printf("WAL is currently locked, so no WAL information\n");
    7504           0 :                 return;
    7505             :         }
    7506         116 :         printf("WAL:\n");
    7507         116 :         printf("SQL store oldest pending "ULLFMT"\n", store->oldest_pending);
    7508         116 :         log_printinfo(store->logger);
    7509         116 :         MT_lock_unset(&store->commit);
    7510             : }

Generated by: LCOV version 1.14