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

Generated by: LCOV version 1.14