LCOV - code coverage report
Current view: top level - sql/storage - store.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3346 3917 85.4 %
Date: 2021-10-13 02:24:04 Functions: 195 207 94.2 %

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

Generated by: LCOV version 1.14