LCOV - code coverage report
Current view: top level - sql/storage - store.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4016 4611 87.1 %
Date: 2024-04-25 20:03:45 Functions: 206 217 94.9 %

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

Generated by: LCOV version 1.14