LCOV - code coverage report
Current view: top level - sql/storage - store.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4068 4688 86.8 %
Date: 2024-12-19 23:10:26 Functions: 207 218 95.0 %

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

Generated by: LCOV version 1.14