LCOV - code coverage report
Current view: top level - sql/storage - store.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4063 4680 86.8 %
Date: 2025-03-25 20:06:35 Functions: 207 218 95.0 %

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

Generated by: LCOV version 1.14