LCOV - code coverage report
Current view: top level - sql/storage - store.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4217 4871 86.6 %
Date: 2025-03-25 21:27:32 Functions: 208 219 95.0 %

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

Generated by: LCOV version 1.14