LCOV - code coverage report
Current view: top level - sql/server - sql_mvc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 679 904 75.1 %
Date: 2024-10-03 20:03:20 Functions: 72 79 91.1 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /* multi version catalog */
      14             : 
      15             : #include "monetdb_config.h"
      16             : #include "gdk.h"
      17             : 
      18             : #include "sql_mvc.h"
      19             : #include "sql_qc.h"
      20             : #include "sql_types.h"
      21             : #include "sql_env.h"
      22             : #include "sql_semantic.h"
      23             : #include "sql_partition.h"
      24             : #include "sql_privileges.h"
      25             : #include "mapi_querytype.h"
      26             : #include "rel_rel.h"
      27             : #include "rel_exp.h"
      28             : #include "rel_semantic.h"
      29             : #include "rel_unnest.h"
      30             : #include "rel_optimizer.h"
      31             : #include "rel_statistics.h"
      32             : 
      33             : #include "mal_authorize.h"
      34             : #include "mal_profiler.h"
      35             : #include "mal_exception.h"
      36             : #include "mal_interpreter.h"
      37             : 
      38             : static void
      39         225 : sql_create_comments(mvc *m, sql_schema *s)
      40             : {
      41         225 :         sql_table *t = NULL;
      42         225 :         sql_column *c = NULL;
      43         225 :         sql_key *k = NULL;
      44             : 
      45         225 :         mvc_create_table(&t, m, s, "comments", tt_table, 1, SQL_PERSIST, 0, -1, 0);
      46         225 :         mvc_create_column_(&c, m, t, "id", "int", 32);
      47         225 :         sql_trans_create_ukey(&k, m->session->tr, t, "comments_id_pkey", pkey, NULL);
      48         225 :         sql_trans_create_kc(m->session->tr, k, c);
      49         225 :         sql_trans_key_done(m->session->tr, k);
      50         225 :         sql_trans_create_dependency(m->session->tr, c->base.id, k->idx->base.id, INDEX_DEPENDENCY);
      51         225 :         mvc_create_column_(&c, m, t, "remark", "varchar", 65000);
      52         225 :         sql_trans_alter_null(m->session->tr, c, 0);
      53         225 : }
      54             : 
      55             : static sql_table *
      56         466 : mvc_init_create_view(mvc *m, sql_schema *s, const char *name, const char *query)
      57             : {
      58         466 :         sql_table *t = NULL;
      59             : 
      60         466 :         mvc_create_view(&t, m, s, name, SQL_PERSIST, query, 1);
      61         466 :         if (t) {
      62         466 :                 char *buf;
      63         466 :                 sql_rel *r = NULL;
      64             : 
      65         466 :                 if (!(buf = sa_strdup(m->ta, t->query))) {
      66           0 :                         (void) sql_error(m, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      67           0 :                         return NULL;
      68             :                 }
      69             : 
      70         466 :                 r = rel_parse(m, s, buf, m_deps);
      71         466 :                 if (r)
      72         466 :                         r = sql_processrelation(m, r, 0, 0, 0, 0);
      73         466 :                 if (r) {
      74         466 :                         list *blist = rel_dependencies(m, r);
      75         466 :                         if (mvc_create_dependencies(m, blist, t->base.id, VIEW_DEPENDENCY)) {
      76           0 :                                 sa_reset(m->ta);
      77           0 :                                 (void) sql_error(m, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      78           0 :                                 return NULL;
      79             :                         }
      80             :                 }
      81         466 :                 sa_reset(m->ta);
      82         466 :                 assert(r);
      83             :         }
      84         466 :         return t;
      85             : }
      86             : 
      87             : #define MVC_INIT_DROP_TABLE(SQLID, TNAME, VIEW, NCOL)                   \
      88             :         do {                                                            \
      89             :                 str output;                                             \
      90             :                 t = mvc_bind_table(m, s, TNAME);                        \
      91             :                 SQLID = t->base.id;                                  \
      92             :                 for (int i = 0; i < NCOL; i++) {                     \
      93             :                         sql_column *col = mvc_bind_column(m, t, VIEW[i].name); \
      94             :                         VIEW[i].oldid = col->base.id;                        \
      95             :                 }                                                       \
      96             :                 if ((output = mvc_drop_table(m, s, t, 0)) != MAL_SUCCEED) { \
      97             :                         mvc_destroy(m);                                 \
      98             :                         mvc_exit(store);        \
      99             :                         TRC_CRITICAL(SQL_TRANS,                         \
     100             :                                      "Initialization error: %s\n", output);   \
     101             :                         freeException(output);                          \
     102             :                         return NULL;                                    \
     103             :                 }                                                       \
     104             :         } while (0)
     105             : 
     106             : struct view_t {
     107             :         const char *name;
     108             :         const char *type;
     109             :         unsigned int digits;
     110             :         sqlid oldid;
     111             :         sqlid newid;
     112             : };
     113             : 
     114             : static void
     115          32 : mvc_fix_depend(mvc *m, sql_column *depids, struct view_t *v, int n)
     116             : {
     117          32 :         sqlstore *store = m->store;
     118          32 :         oid rid;
     119          32 :         rids *rs;
     120             : 
     121         368 :         for (int i = 0; i < n; i++) {
     122         672 :                 rs = store->table_api.rids_select(m->session->tr, depids,
     123         336 :                                              &v[i].oldid, &v[i].oldid, NULL);
     124         336 :                 if (rs) {
     125        2144 :                         while ((rid = store->table_api.rids_next(rs)), !is_oid_nil(rid)) {
     126        1808 :                                 store->table_api.column_update_value(m->session->tr, depids, rid, &v[i].newid);
     127             :                         }
     128         336 :                         store->table_api.rids_destroy(rs);
     129             :                 }
     130             :         }
     131          32 : }
     132             : 
     133             : sql_store
     134         327 : mvc_init(int debug, store_type store_tpe, int ro, int su, const char *initpasswd)
     135             : {
     136         327 :         sqlstore *store = NULL;
     137         327 :         sql_schema *s;
     138         327 :         sql_table *t;
     139         327 :         mvc *m;
     140         327 :         str msg;
     141             : 
     142         327 :         TRC_DEBUG(SQL_TRANS, "Initialization\n");
     143         327 :         keyword_init();
     144         327 :         if (scanner_init_keywords() != 0) {
     145           0 :                 TRC_CRITICAL(SQL_TRANS, "Malloc failure\n");
     146           0 :                 return NULL;
     147             :         }
     148             : 
     149         327 :         if ((store = store_init(debug, store_tpe, ro, su)) == NULL) {
     150           1 :                 keyword_exit();
     151           1 :                 TRC_CRITICAL(SQL_TRANS, "Unable to create system tables\n");
     152           1 :                 return NULL;
     153             :         }
     154             : 
     155         326 :         initialize_sql_functions_lookup(store->sa);
     156             : 
     157         326 :         m = mvc_create((sql_store)store, store->sa, 0, 0, NULL, NULL);
     158         326 :         if (!m) {
     159           0 :                 mvc_exit(store);
     160           0 :                 TRC_CRITICAL(SQL_TRANS, "Malloc failure\n");
     161           0 :                 return NULL;
     162             :         }
     163             : 
     164         326 :         assert(m->sa == NULL);
     165         326 :         m->sa = sa_create(m->pa);
     166         326 :         if (!m->sa) {
     167           0 :                 mvc_destroy(m);
     168           0 :                 mvc_exit(store);
     169           0 :                 TRC_CRITICAL(SQL_TRANS, "Malloc failure\n");
     170           0 :                 return NULL;
     171             :         }
     172             : 
     173         326 :         if (store->first || store->catalog_version) {
     174         233 :                 sqlid tid = 0, cid = 0;
     175         233 :                 struct view_t tview[10] = {
     176             :                         {
     177             :                                 .name = "id",
     178             :                                 .type = "int",
     179             :                                 .digits = 32,
     180             :                         },
     181             :                         {
     182             :                                 .name = "name",
     183             :                                 .type = "varchar",
     184             :                                 .digits = 1024,
     185             :                         },
     186             :                         {
     187             :                                 .name = "schema_id",
     188             :                                 .type = "int",
     189             :                                 .digits = 32,
     190             :                         },
     191             :                         {
     192             :                                 .name = "query",
     193             :                                 .type = "varchar",
     194             :                                 .digits = 1 << 20,
     195             :                         },
     196             :                         {
     197             :                                 .name = "type",
     198             :                                 .type = "smallint",
     199             :                                 .digits = 16,
     200             :                         },
     201             :                         {
     202             :                                 .name = "system",
     203             :                                 .type = "boolean",
     204             :                                 .digits = 1,
     205             :                         },
     206             :                         {
     207             :                                 .name = "commit_action",
     208             :                                 .type = "smallint",
     209             :                                 .digits = 16,
     210             :                         },
     211             :                         {
     212             :                                 .name = "access",
     213             :                                 .type = "smallint",
     214             :                                 .digits = 16,
     215             :                         },
     216             :                         {
     217             :                                 .name = "temporary",
     218             :                                 .type = "smallint",
     219             :                                 .digits = 16,
     220             :                         },
     221             :                         {
     222             :                                 0
     223             :                         },
     224         233 :                 }, cview[11] = {
     225             :                         {
     226             :                                 .name = "id",
     227             :                                 .type = "int",
     228             :                                 .digits = 32,
     229             :                         },
     230             :                         {
     231             :                                 .name = "name",
     232             :                                 .type = "varchar",
     233             :                                 .digits = 1024,
     234             :                         },
     235             :                         {
     236             :                                 .name = "type",
     237             :                                 .type = "varchar",
     238             :                                 .digits = 1024,
     239             :                         },
     240             :                         {
     241             :                                 .name = "type_digits",
     242             :                                 .type = "int",
     243             :                                 .digits = 32,
     244             :                         },
     245             :                         {
     246             :                                 .name = "type_scale",
     247             :                                 .type = "int",
     248             :                                 .digits = 32,
     249             :                         },
     250             :                         {
     251             :                                 .name = "table_id",
     252             :                                 .type = "int",
     253             :                                 .digits = 32,
     254             :                         },
     255             :                         {
     256             :                                 .name = "default",
     257             :                                 .type = "varchar",
     258             :                                 .digits = STORAGE_MAX_VALUE_LENGTH,
     259             :                         },
     260             :                         {
     261             :                                 .name = "null",
     262             :                                 .type = "boolean",
     263             :                                 .digits = 1,
     264             :                         },
     265             :                         {
     266             :                                 .name = "number",
     267             :                                 .type = "int",
     268             :                                 .digits = 32,
     269             :                         },
     270             :                         {
     271             :                                 .name = "storage",
     272             :                                 .type = "varchar",
     273             :                                 .digits = 2048,
     274             :                         },
     275             :                         {
     276             :                                 0
     277             :                         },
     278             :                 };
     279         233 :                 if (mvc_trans(m) < 0) {
     280           0 :                         mvc_destroy(m);
     281           0 :                         mvc_exit(store);
     282           0 :                         TRC_CRITICAL(SQL_TRANS, "Failed to start transaction\n");
     283           0 :                         return NULL;
     284             :                 }
     285         233 :                 s = m->session->schema = mvc_bind_schema(m, "sys");
     286         233 :                 assert(m->session->schema != NULL);
     287             : 
     288         233 :                 if (!store->first) {
     289          80 :                         MVC_INIT_DROP_TABLE(tid, "tables", tview, 9);
     290          88 :                         MVC_INIT_DROP_TABLE(cid, "columns", cview, 10);
     291             :                 }
     292             : 
     293         233 :                 t = mvc_init_create_view(m, s, "tables", "SELECT \"id\", \"name\", \"schema_id\", \"query\", CAST(CASE WHEN \"system\" THEN \"type\" + 10 /* system table/view */ ELSE (CASE WHEN \"commit_action\" = 0 THEN \"type\" /* table/view */ ELSE \"type\" + 20 /* global temp table */ END) END AS SMALLINT) AS \"type\", \"system\", \"commit_action\", \"access\", CASE WHEN (NOT \"system\" AND \"commit_action\" > 0) THEN 1 ELSE 0 END AS \"temporary\" FROM \"sys\".\"_tables\" WHERE \"type\" <> 2 UNION ALL SELECT \"id\", \"name\", \"schema_id\", \"query\", CAST(\"type\" + 30 /* local temp table */ AS SMALLINT) AS \"type\", \"system\", \"commit_action\", \"access\", 1 AS \"temporary\" FROM \"tmp\".\"_tables\";");
     294         233 :                 if (!t) {
     295           0 :                         mvc_destroy(m);
     296           0 :                         mvc_exit(store);
     297           0 :                         TRC_CRITICAL(SQL_TRANS, "Failed to create 'tables' view\n");
     298           0 :                         return NULL;
     299             :                 }
     300             : 
     301        2330 :                 for (int i = 0; i < 9; i++) {
     302        2097 :                         sql_column *col = NULL;
     303             : 
     304        2097 :                         mvc_create_column_(&col, m, t, tview[i].name, tview[i].type, tview[i].digits);
     305        2097 :                         if (col == NULL) {
     306           0 :                                 mvc_destroy(m);
     307           0 :                                 mvc_exit(store);
     308           0 :                                 TRC_CRITICAL(SQL_TRANS,
     309             :                                              "Initialization: creation of sys.tables column %s failed\n", tview[i].name);
     310           0 :                                 return NULL;
     311             :                         }
     312        2097 :                         tview[i].newid = col->base.id;
     313             :                 }
     314             : 
     315         233 :                 if (!store->first) {
     316           8 :                         int pub = ROLE_PUBLIC;
     317           8 :                         int p = PRIV_SELECT;
     318           8 :                         int zero = 0;
     319           8 :                         sql_table *privs = find_sql_table(m->session->tr, s, "privileges");
     320           8 :                         sql_table *deps = find_sql_table(m->session->tr, s, "dependencies");
     321           8 :                         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
     322           8 :                         assert(tview[9].name == NULL);
     323           8 :                         tview[9].oldid = tid;
     324           8 :                         tview[9].newid = t->base.id;
     325           8 :                         mvc_fix_depend(m, find_sql_column(deps, "id"), tview, 10);
     326           8 :                         mvc_fix_depend(m, find_sql_column(deps, "depend_id"), tview, 10);
     327             :                 }
     328             : 
     329         233 :                 t = mvc_init_create_view(m, s, "columns", "SELECT * FROM (SELECT p.* FROM \"sys\".\"_columns\" AS p UNION ALL SELECT t.* FROM \"tmp\".\"_columns\" AS t) AS columns;");
     330         233 :                 if (!t) {
     331           0 :                         mvc_destroy(m);
     332           0 :                         mvc_exit(store);
     333           0 :                         TRC_CRITICAL(SQL_TRANS, "Failed to create 'columns' view\n");
     334           0 :                         return NULL;
     335             :                 }
     336        2563 :                 for (int i = 0; i < 10; i++) {
     337        2330 :                         sql_column *col = NULL;
     338             : 
     339        2330 :                         mvc_create_column_(&col, m, t, cview[i].name, cview[i].type, cview[i].digits);
     340        2330 :                         if (col == NULL) {
     341           0 :                                 mvc_destroy(m);
     342           0 :                                 mvc_exit(store);
     343           0 :                                 TRC_CRITICAL(SQL_TRANS,
     344             :                                              "Initialization: creation of sys.tables column %s failed\n", cview[i].name);
     345           0 :                                 return NULL;
     346             :                         }
     347        2330 :                         cview[i].newid = col->base.id;
     348             :                 }
     349             : 
     350         233 :                 if (!store->first) {
     351           8 :                         int pub = ROLE_PUBLIC;
     352           8 :                         int p = PRIV_SELECT;
     353           8 :                         int zero = 0;
     354           8 :                         sql_table *privs = find_sql_table(m->session->tr, s, "privileges");
     355           8 :                         sql_table *deps = find_sql_table(m->session->tr, s, "dependencies");
     356           8 :                         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
     357           8 :                         assert(cview[10].name == NULL);
     358           8 :                         cview[10].oldid = cid;
     359           8 :                         cview[10].newid = t->base.id;
     360           8 :                         mvc_fix_depend(m, find_sql_column(deps, "id"), cview, 11);
     361           8 :                         mvc_fix_depend(m, find_sql_column(deps, "depend_id"), cview, 11);
     362             :                 } else {
     363         225 :                         sql_create_env(m, s);
     364         225 :                         sql_create_comments(m, s);
     365         225 :                         sql_create_privileges(m, s, initpasswd);
     366             :                 }
     367             : 
     368         233 :                 if ((msg = mvc_commit(m, 0, NULL, false)) != MAL_SUCCEED) {
     369           0 :                         TRC_CRITICAL(SQL_TRANS, "Unable to commit system tables: %s\n", (msg + 6));
     370           0 :                         freeException(msg);
     371           0 :                         mvc_destroy(m);
     372           0 :                         mvc_exit(store);
     373           0 :                         return NULL;
     374             :                 }
     375             :         }
     376             : 
     377         326 :         if (mvc_trans(m) < 0) {
     378           0 :                 mvc_destroy(m);
     379           0 :                 mvc_exit(store);
     380           0 :                 TRC_CRITICAL(SQL_TRANS, "Failed to start transaction\n");
     381           0 :                 return NULL;
     382             :         }
     383             : 
     384             :         //as the sql_parser is not yet initialized in the storage, we determine the sql type of the sql_parts here
     385             : 
     386         326 :         struct os_iter si;
     387         326 :         os_iterator(&si, m->session->tr->cat->schemas, m->session->tr, NULL);
     388        1741 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     389        1415 :                 sql_schema *ss = (sql_schema*)b;
     390        1415 :                 struct os_iter oi;
     391        1415 :                 os_iterator(&oi, ss->tables, m->session->tr, NULL);
     392       22815 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     393       21400 :                         sql_table *tt = (sql_table*)b;
     394       21400 :                         if (isPartitionedByColumnTable(tt) || isPartitionedByExpressionTable(tt)) {
     395          45 :                                 char *err;
     396          45 :                                 if ((err = parse_sql_parts(m, tt)) != NULL) {
     397           0 :                                         TRC_CRITICAL(SQL_TRANS, "Unable to start partitioned table: %s.%s: %s\n", ss->base.name, tt->base.name, err);
     398           0 :                                         freeException(err);
     399           0 :                                         mvc_destroy(m);
     400           0 :                                         mvc_exit(store);
     401           0 :                                         return NULL;
     402             :                                 }
     403             :                         }
     404             :                 }
     405             :         }
     406         326 :         if (sql_trans_convert_partitions(m->session->tr) < 0) {
     407           0 :                 TRC_CRITICAL(SQL_TRANS, "Unable to start partitioned tables\n");
     408           0 :                 mvc_destroy(m);
     409           0 :                 mvc_exit(store);
     410           0 :                 return NULL;
     411             :         }
     412             : 
     413         326 :         if ((msg = mvc_commit(m, 0, NULL, false)) != MAL_SUCCEED) {
     414           0 :                 TRC_CRITICAL(SQL_TRANS, "Unable to commit system tables: %s\n", (msg + 6));
     415           0 :                 freeException(msg);
     416           0 :                 mvc_destroy(m);
     417           0 :                 mvc_exit(store);
     418           0 :                 return NULL;
     419             :         }
     420         326 :         mvc_destroy(m);
     421         326 :         return store;
     422             : }
     423             : 
     424             : void
     425         325 : mvc_exit(sql_store store)
     426             : {
     427         325 :         TRC_DEBUG(SQL_TRANS, "MVC exit\n");
     428         325 :         store_exit(store);
     429         325 :         keyword_exit();
     430         325 : }
     431             : 
     432             : void
     433         325 : mvc_logmanager(sql_store store)
     434             : {
     435         325 :         store_manager(store);
     436         324 : }
     437             : 
     438             : int
     439     1465932 : mvc_status(mvc *m)
     440             : {
     441     1465932 :         int res = m->session->status;
     442             : 
     443     1465932 :         return res;
     444             : }
     445             : 
     446             : int
     447           0 : mvc_error_retry(mvc *m)
     448             : {
     449           0 :         int res = m->session->status;
     450             : 
     451           0 :         if (!res || res == -ERR_AMBIGUOUS || res == -ERR_GROUPBY)
     452           0 :                 return 0;
     453             :         return res;
     454             : }
     455             : 
     456             : int
     457           0 : mvc_type(mvc *m)
     458             : {
     459           0 :         int res = m->type;
     460             : 
     461           0 :         m->type = Q_PARSE;
     462           0 :         return res;
     463             : }
     464             : 
     465             : int
     466       64523 : mvc_debug_on(mvc *m, int flg)
     467             : {
     468             : 
     469       64523 :         if (m->debug & flg)
     470           0 :                 return 1;
     471             : 
     472             :         return 0;
     473             : }
     474             : 
     475             : void
     476           0 : mvc_cancel_session(mvc *m)
     477             : {
     478           0 :         (void)sql_trans_end(m->session, SQL_ERR);
     479           0 : }
     480             : 
     481             : int
     482      220546 : mvc_trans(mvc *m)
     483             : {
     484      220546 :         int res = 0, err = m->session->status;
     485      220546 :         assert(!m->session->tr->active);       /* can only start a new transaction */
     486             : 
     487      220546 :         TRC_INFO(SQL_TRANS, "Starting transaction\n");
     488      220546 :         res = sql_trans_begin(m->session);
     489      220550 :         if (m->qc && (res || err))
     490       28959 :                 qc_restart(m->qc);
     491      220550 :         return res;
     492             : }
     493             : 
     494             : str
     495      157979 : mvc_commit(mvc *m, int chain, const char *name, bool enabling_auto_commit)
     496             : {
     497      157979 :         sql_trans *tr = m->session->tr;
     498      157979 :         int ok = SQL_OK;
     499      157979 :         str msg = MAL_SUCCEED, other;
     500      157979 :         char operation[BUFSIZ];
     501             : 
     502      157979 :         assert(tr);
     503      157979 :         assert(m->session->tr->active);        /* only commit an active transaction */
     504      157979 :         TRC_DEBUG(SQL_TRANS,"Commit: %s\n", (name) ? name : "");
     505      157979 :         if(enabling_auto_commit)
     506           1 :                 snprintf(operation, BUFSIZ, "Commit failed while enabling auto_commit: ");
     507      157978 :         else if(name)
     508          46 :                 snprintf(operation, BUFSIZ, "SAVEPOINT: (%s)", name);
     509             :         else
     510      157932 :                 snprintf(operation, BUFSIZ, "COMMIT:");
     511             : 
     512      157979 :         if (m->session->status < 0) {
     513          12 :                 msg = createException(SQL, "sql.commit", SQLSTATE(40000) "%s transaction is aborted, will ROLLBACK instead", operation);
     514          12 :                 if ((other = mvc_rollback(m, chain, name, false)) != MAL_SUCCEED)
     515           0 :                         freeException(other);
     516          12 :                 return msg;
     517             :         }
     518             : 
     519             :         /* savepoint, simply make a new sub transaction */
     520      157967 :         if (name && name[0] != '\0') {
     521          46 :                 sql_trans *tr = m->session->tr;
     522          46 :                 TRC_DEBUG(SQL_TRANS, "Savepoint\n");
     523          46 :                 if (!(m->session->tr = sql_trans_create(m->store, tr, name)))
     524           0 :                         return createException(SQL, "sql.commit", SQLSTATE(HY013) "%s allocation failure while creating savepoint", operation);
     525             : 
     526          46 :                 if (!(m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name))) {
     527           0 :                         m->session->tr = sql_trans_destroy(m->session->tr);
     528           0 :                         return createException(SQL, "sql.commit", SQLSTATE(40000) "%s finished successfully, but the session's schema could not be found on the current transaction", operation);
     529             :                 }
     530          46 :                 m->type = Q_TRANS;
     531          46 :                 TRC_INFO(SQL_TRANS, "Savepoint commit '%s' done\n", name);
     532          46 :                 return msg;
     533             :         }
     534             : 
     535      157921 :         if (!tr->parent && !name) {
     536      157916 :                 lng Tbegin = 0;
     537      157916 :                 ulng ts_start = 0;
     538      157916 :                 bool log_usec = profilerMode == 0 || m->session->auto_commit;
     539      157916 :                 if(profilerStatus > 0) {
     540           0 :                         if (log_usec) Tbegin = GDKusec();
     541           0 :                         ts_start = m->session->tr->ts;
     542             :                 }
     543             : 
     544      157916 :                 const int state = sql_trans_end(m->session, ok);
     545             : 
     546      157916 :                 if(profilerStatus > 0) {
     547           0 :                         lng Tend = GDKusec();
     548           0 :                         Client  c = mal_clients+m->clientid;
     549           0 :                         profilerEvent(NULL,
     550             :                                                   &(struct NonMalEvent)
     551           0 :                                                   { state == SQL_CONFLICT ? CONFLICT : COMMIT , c, Tend, &ts_start, &m->session->tr->ts, state == SQL_ERR, log_usec?Tend-Tbegin:0});
     552             :                 }
     553      157916 :                 switch (state) {
     554           0 :                         case SQL_ERR:
     555           0 :                                 GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
     556         897 :                                 break;
     557         897 :                         case SQL_CONFLICT:
     558             : 
     559             :                                 /* transaction conflict */
     560         897 :                                 return createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
     561             :                         default:
     562      157019 :                                 break;
     563             :                 }
     564      157019 :                 if (chain) {
     565           2 :                         if (sql_trans_begin(m->session) < 0)
     566           0 :                                 return createException(SQL, "sql.commit", SQLSTATE(40000) "%s finished successfully, but the session's schema could not be found while starting the next transaction", operation);
     567           2 :                         m->session->auto_commit = 0; /* disable auto-commit while chaining */
     568             :                 }
     569      157019 :                 m->type = Q_TRANS;
     570      157019 :                 TRC_INFO(SQL_TRANS,
     571             :                         "Commit done\n");
     572      157019 :                 return msg;
     573             :         }
     574             : 
     575             :         /* save points only */
     576             :         assert(name || tr->parent);
     577             : 
     578             :         /* commit and cleanup nested transactions */
     579           5 :         if (tr->parent) {
     580          12 :                 while (tr->parent != NULL && ok == SQL_OK) {
     581           7 :                         if ((ok = sql_trans_commit(tr)) == SQL_ERR)
     582           0 :                                 GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
     583           7 :                         m->session->tr = tr = sql_trans_destroy(tr);
     584             :                 }
     585           5 :                 while (tr->parent != NULL)
     586           0 :                         m->session->tr = tr = sql_trans_destroy(tr);
     587           5 :                 if (ok != SQL_OK)
     588           0 :                         msg = createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
     589             :         }
     590             : 
     591             :         /* if there is nothing to commit reuse the current transaction */
     592           5 :         if (list_empty(tr->changes)) {
     593           0 :                 if (!chain) {
     594           0 :                         switch (sql_trans_end(m->session, ok)) {
     595           0 :                                 case SQL_ERR:
     596           0 :                                         GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
     597           0 :                                         break;
     598           0 :                                 case SQL_CONFLICT:
     599           0 :                                         if (!msg)
     600           0 :                                                 msg = createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
     601             :                                         break;
     602             :                                 default:
     603             :                                         break;
     604             :                         }
     605             :                 }
     606           0 :                 m->type = Q_TRANS;
     607           0 :                 TRC_INFO(SQL_TRANS,
     608             :                         "Commit done (no changes)\n");
     609           0 :                 return msg;
     610             :         }
     611             : 
     612           5 :         switch (sql_trans_end(m->session, ok)) {
     613           0 :                 case SQL_ERR:
     614           0 :                         GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
     615           0 :                         break;
     616           0 :                 case SQL_CONFLICT:
     617           0 :                         if (!msg)
     618           0 :                                 msg = createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
     619             :                         return msg;
     620             :                 default:
     621           5 :                         break;
     622             :         }
     623           5 :         if (chain) {
     624           0 :                 if (sql_trans_begin(m->session) < 0) {
     625           0 :                         if (!msg)
     626           0 :                                 msg = createException(SQL, "sql.commit", SQLSTATE(40000) "%s finished successfully, but the session's schema could not be found while starting the next transaction", operation);
     627           0 :                         return msg;
     628             :                 }
     629           0 :                 m->session->auto_commit = 0; /* disable auto-commit while chaining */
     630             :         }
     631           5 :         m->type = Q_TRANS;
     632           5 :         TRC_INFO(SQL_TRANS,
     633             :                 "Commit done\n");
     634             :         return msg;
     635             : }
     636             : 
     637             : str
     638       62470 : mvc_rollback(mvc *m, int chain, const char *name, bool disabling_auto_commit)
     639             : {
     640       62470 :         str msg = MAL_SUCCEED;
     641             : 
     642       62470 :         TRC_DEBUG(SQL_TRANS, "Rollback: %s\n", (name) ? name : "");
     643       62470 :         (void) disabling_auto_commit;
     644             : 
     645       62470 :         sql_trans *tr = m->session->tr;
     646       62470 :         assert(m->session->tr && m->session->tr->active);        /* only abort an active transaction */
     647       62470 :         if (name && name[0] != '\0') {
     648          38 :                 while (tr && (!tr->name || strcmp(tr->name, name) != 0))
     649          20 :                         tr = tr->parent;
     650          18 :                 if (!tr || !tr->name || strcmp(tr->name, name) != 0) {
     651           2 :                         msg = createException(SQL, "sql.rollback", SQLSTATE(42000) "ROLLBACK TO SAVEPOINT: no such savepoint: '%s'", name);
     652           2 :                         m->session->status = -1;
     653           2 :                         return msg;
     654             :                 }
     655             :                 tr = m->session->tr;
     656          34 :                 while (!tr->name || strcmp(tr->name, name) != 0) {
     657             :                         /* make sure we do not reuse changed data */
     658          18 :                         if (!list_empty(tr->changes))
     659           9 :                                 tr->status = 1;
     660          18 :                         m->session->tr = tr = sql_trans_destroy(tr);
     661             :                 }
     662             :                 /* start a new transaction after rolling back */
     663          16 :                 if (!(m->session->tr = tr = sql_trans_create(m->store, tr, name))) {
     664           0 :                         msg = createException(SQL, "sql.rollback", SQLSTATE(HY013) "ROLLBACK TO SAVEPOINT: allocation failure while restarting savepoint");
     665           0 :                         m->session->status = -1;
     666           0 :                         return msg;
     667             :                 }
     668          16 :                 m->session->status = tr->parent->status;
     669          16 :                 if (!(m->session->schema = find_sql_schema(tr, m->session->schema_name))) {
     670           1 :                         msg = createException(SQL, "sql.rollback", SQLSTATE(40000) "ROLLBACK TO SAVEPOINT: finished successfully, but the session's schema could not be found on the current transaction");
     671           1 :                         m->session->status = -1;
     672           1 :                         return msg;
     673             :                 }
     674             :         } else {
     675             :                 /* first release all intermediate savepoints */
     676       62468 :                 while (tr->parent != NULL)
     677          16 :                         m->session-> tr = tr = sql_trans_destroy(tr);
     678             :                 /* make sure we do not reuse changed data */
     679       62452 :                 if (!list_empty(tr->changes))
     680        1119 :                         tr->status = 1;
     681             : 
     682             : 
     683       62452 :                 lng Tbegin = 0;
     684       62452 :                 ulng ts_start = 0;
     685       62452 :                 bool log_usec = profilerMode == 0 || m->session->auto_commit;
     686       62452 :                 if(profilerStatus > 0) {
     687           0 :                         if (log_usec) Tbegin = GDKusec();
     688           0 :                         ts_start = m->session->tr->ts;
     689             :                 }
     690       62452 :                 (void) sql_trans_end(m->session, SQL_ERR);
     691             : 
     692       62452 :                 if(profilerStatus > 0) {
     693           0 :                         lng Tend = GDKusec();
     694           0 :                         Client  c = mal_clients+m->clientid;
     695           0 :                         profilerEvent(NULL,
     696             :                                                   &(struct NonMalEvent)
     697           0 :                                                   { ROLLBACK , c, Tend, &ts_start, &m->session->tr->ts, 0, log_usec?Tend-Tbegin:0});
     698             :                 }
     699       62452 :                 if (chain) {
     700           2 :                         if (sql_trans_begin(m->session) < 0) {
     701           1 :                                 msg = createException(SQL, "sql.rollback", SQLSTATE(40000) "ROLLBACK: finished successfully, but the session's schema could not be found while starting the next transaction");
     702           1 :                                 m->session->status = -1;
     703           1 :                                 return msg;
     704             :                         }
     705           1 :                         m->session->auto_commit = 0; /* disable auto-commit while chaining */
     706             :                 }
     707             :         }
     708       62466 :         if (msg != MAL_SUCCEED) {
     709             :                 m->session->status = -1;
     710             :                 return msg;
     711             :         }
     712       62466 :         m->type = Q_TRANS;
     713       62466 :         TRC_INFO(SQL_TRANS,
     714             :                 "Commit%s%s rolled back%s\n",
     715             :                 name ? " " : "", name ? name : "",
     716             :                 list_empty(tr->changes) ? " (no changes)" : "");
     717             :         return msg;
     718             : }
     719             : 
     720             : /* release all savepoints up including the given named savepoint
     721             :  * but keep the current changes.
     722             :  * */
     723             : str
     724          12 : mvc_release(mvc *m, const char *name)
     725             : {
     726          12 :         sql_trans *tr = m->session->tr;
     727          12 :         str msg = MAL_SUCCEED;
     728             : 
     729          12 :         assert(tr && tr->active);    /* only release active transactions */
     730             : 
     731          12 :         TRC_DEBUG(SQL_TRANS, "Release: %s\n", (name) ? name : "");
     732             : 
     733          12 :         if (!name && (msg = mvc_rollback(m, 0, name, false)) != MAL_SUCCEED) {
     734           0 :                 m->session->status = -1;
     735           0 :                 return msg;
     736             :         }
     737             : 
     738          33 :         while (tr && (!tr->name || strcmp(tr->name, name) != 0))
     739          21 :                 tr = tr->parent;
     740          12 :         if (!tr || !tr->name || strcmp(tr->name, name) != 0) {
     741           0 :                 msg = createException(SQL, "sql.release", SQLSTATE(42000) "RELEASE: no such savepoint: '%s'", name);
     742           0 :                 m->session->status = -1;
     743           0 :                 return msg;
     744             :         }
     745          12 :         tr = m->session->tr;
     746          33 :         while (!tr->name || strcmp(tr->name, name) != 0) {
     747             :                 /* commit all intermediate savepoints */
     748          21 :                 if (sql_trans_commit(tr) != SQL_OK)
     749           0 :                         GDKfatal("release savepoints should not fail");
     750          21 :                 m->session->tr = tr = sql_trans_destroy(tr);
     751             :         }
     752          12 :         _DELETE(m->session->tr->name); /* name will no longer be used */
     753          12 :         m->session->status = tr->status;
     754          12 :         if (!(m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name))) {
     755           0 :                 msg = createException(SQL, "sql.release", SQLSTATE(40000) "RELEASE: finished successfully, but the session's schema could not be found on the current transaction");
     756           0 :                 m->session->status = -1;
     757           0 :                 return msg;
     758             :         }
     759             : 
     760          12 :         m->type = Q_TRANS;
     761          12 :         return msg;
     762             : }
     763             : 
     764             : static void
     765       76942 : _free(void *dummy, void *data)
     766             : {
     767       76942 :         (void)dummy;
     768       76942 :         GDKfree(data);
     769       76941 : }
     770             : 
     771             : mvc *
     772       38815 : mvc_create(sql_store *store, allocator *pa, int clientid, int debug, bstream *rs, stream *ws)
     773             : {
     774       38815 :         mvc *m;
     775       38815 :         str sys_str = NULL;
     776             : 
     777       38815 :         assert(pa);
     778       38815 :         m = SA_ZNEW(pa, mvc);
     779       38815 :         if (!m)
     780             :                 return NULL;
     781             : 
     782       38815 :         TRC_DEBUG(SQL_TRANS, "MVC create\n");
     783             : 
     784       38815 :         m->errstr[0] = '\0';
     785             :         /* if an error exceeds the buffer we don't want garbage at the end */
     786       38815 :         m->errstr[ERRSIZE-1] = '\0';
     787             : 
     788       38815 :         m->qc = qc_create(pa, clientid, 0);
     789       38815 :         if (!m->qc) {
     790             :                 return NULL;
     791             :         }
     792       38815 :         m->pa = pa;
     793       38815 :         m->sa = NULL;
     794       38815 :         m->ta = sa_create(m->pa);
     795             : #ifdef __has_builtin
     796             : #if __has_builtin(__builtin_frame_address)
     797       38815 :         m->sp = (uintptr_t) __builtin_frame_address(0);
     798             : #define BUILTIN_USED
     799             : #endif
     800             : #endif
     801             : #ifndef BUILTIN_USED
     802             :         m->sp = (uintptr_t)(&m);
     803             : #endif
     804             : #undef BUILTIN_USED
     805             : 
     806       38815 :         m->params = NULL;
     807       38815 :         m->sizeframes = MAXPARAMS;
     808       38815 :         m->frames = SA_NEW_ARRAY(pa, sql_frame*, m->sizeframes);
     809       38815 :         m->topframes = 0;
     810       38815 :         m->frame = 0;
     811             : 
     812       38815 :         m->use_views = false;
     813       38815 :         if (!m->frames) {
     814           0 :                 qc_destroy(m->qc);
     815           0 :                 return NULL;
     816             :         }
     817       38815 :         if (init_global_variables(m) < 0) {
     818           0 :                 qc_destroy(m->qc);
     819           0 :                 list_destroy(m->global_vars);
     820           0 :                 return NULL;
     821             :         }
     822       38815 :         m->sym = NULL;
     823             : 
     824       38815 :         m->role_id = m->user_id = -1;
     825       38815 :         m->timezone = 0;
     826       38815 :         m->sql_optimizer = INT_MAX;
     827       38815 :         m->clientid = clientid;
     828             : 
     829       38815 :         m->emode = m_normal;
     830       38815 :         m->emod = mod_none;
     831       38815 :         m->reply_size = 100;
     832       38815 :         m->debug = debug;
     833             : 
     834       38815 :         m->label = 0;
     835       38815 :         m->nid = 1;
     836       38815 :         m->cascade_action = NULL;
     837       38815 :         m->runs = NULL;
     838             : 
     839       38815 :         if (!(m->schema_path = list_create((fdestroy)_free))) {
     840           0 :                 qc_destroy(m->qc);
     841           0 :                 list_destroy(m->global_vars);
     842           0 :                 return NULL;
     843             :         }
     844       38815 :         if (!(sys_str = _STRDUP("sys")) || !list_append(m->schema_path, sys_str)) {
     845           0 :                 _DELETE(sys_str);
     846           0 :                 qc_destroy(m->qc);
     847           0 :                 list_destroy(m->global_vars);
     848           0 :                 list_destroy(m->schema_path);
     849           0 :                 return NULL;
     850             :         }
     851       38815 :         m->schema_path_has_sys = true;
     852       38815 :         m->schema_path_has_tmp = false;
     853       38815 :         m->no_int128 = false;
     854       38815 :         m->store = store;
     855             : 
     856       38815 :         m->session = sql_session_create(m->store, m->pa, 1 /*autocommit on*/);
     857       38815 :         if (!m->session) {
     858           0 :                 qc_destroy(m->qc);
     859           0 :                 list_destroy(m->global_vars);
     860           0 :                 list_destroy(m->schema_path);
     861           0 :                 return NULL;
     862             :         }
     863             : 
     864       38815 :         m->type = Q_PARSE;
     865             : 
     866       38815 :         scanner_init(&m->scanner, rs, ws);
     867       38815 :         return m;
     868             : }
     869             : 
     870             : void
     871       38815 : mvc_destroy(mvc *m)
     872             : {
     873       38815 :         sql_trans *tr;
     874             : 
     875       38815 :         TRC_DEBUG(SQL_TRANS, "MVC destroy\n");
     876       38815 :         tr = m->session->tr;
     877       38815 :         if (tr) {
     878       38815 :                 if (m->session->tr->active)
     879           0 :                         (void)sql_trans_end(m->session, SQL_ERR);
     880       38815 :                 while (tr->parent)
     881           0 :                         m->session->tr = tr = sql_trans_destroy(tr);
     882             :         }
     883       38815 :         sql_session_destroy(m->session);
     884             : 
     885       38815 :         list_destroy(m->global_vars);
     886       38815 :         list_destroy(m->schema_path);
     887       38815 :         stack_pop_until(m, 0);
     888             : 
     889       38815 :         if (m->scanner.log) /* close and destroy stream */
     890           0 :                 close_stream(m->scanner.log);
     891             : 
     892       38815 :         m->sa = NULL;
     893       38815 :         m->ta = NULL;
     894       38815 :         if (m->qc)
     895       38815 :                 qc_destroy(m->qc);
     896       38815 :         m->qc = NULL;
     897       38815 : }
     898             : 
     899             : sql_type *
     900       37677 : mvc_bind_type(mvc *sql, const char *name)
     901             : {
     902       37677 :         sql_type *t = sql_trans_bind_type(sql->session->tr, NULL, name);
     903       37677 :         TRC_DEBUG(SQL_TRANS, "Bind type: %s\n", name);
     904       37677 :         return t;
     905             : }
     906             : 
     907             : sql_type *
     908        1826 : schema_bind_type(mvc *sql, sql_schema *s, const char *name)
     909             : {
     910        1826 :         sql_type *t = find_sql_type(sql->session->tr, s, name);
     911             : 
     912        1826 :         (void) sql;
     913        1826 :         if (!t)
     914             :                 return NULL;
     915           8 :         TRC_DEBUG(SQL_TRANS, "Schema bind type: %s\n", name);
     916             :         return t;
     917             : }
     918             : 
     919             : sql_schema *
     920     7626536 : mvc_bind_schema(mvc *m, const char *sname)
     921             : {
     922     7626536 :         sql_trans *tr = m->session->tr;
     923     7626536 :         sql_schema *s;
     924             : 
     925     7626536 :         if (!tr)
     926             :                 return NULL;
     927             : 
     928     7626536 :         s = find_sql_schema(tr, sname);
     929     7625553 :         if (!s)
     930             :                 return NULL;
     931     7556930 :         TRC_DEBUG(SQL_TRANS, "Bind schema: %s\n", sname);
     932             :         return s;
     933             : }
     934             : 
     935             : sql_table *
     936     4297299 : mvc_bind_table(mvc *m, sql_schema *s, const char *tname)
     937             : {
     938     4297299 :         sql_table *t = find_sql_table(m->session->tr, s, tname);
     939             : 
     940     4297377 :         (void) m;
     941     4297377 :         if (!t)
     942             :                 return NULL;
     943             : 
     944     4020483 :         TRC_DEBUG(SQL_TRANS, "Bind table: %s.%s\n", s->base.name, tname);
     945             :         return t;
     946             : }
     947             : 
     948             : sql_column *
     949     3107630 : mvc_bind_column(mvc *m, sql_table *t, const char *cname)
     950             : {
     951     3107630 :         sql_column *c;
     952             : 
     953     3107630 :         (void)m;
     954     3107630 :         c = find_sql_column(t, cname);
     955     3107069 :         if (!c)
     956             :                 return NULL;
     957     2903596 :         TRC_DEBUG(SQL_TRANS, "Bind column: %s.%s\n", t->base.name, cname);
     958             :         return c;
     959             : }
     960             : 
     961             : static sql_column *
     962           0 : first_column(sql_table *t)
     963             : {
     964           0 :         node *n = ol_first_node(t->columns);
     965             : 
     966           0 :         if (n)
     967           0 :                 return n->data;
     968             :         return NULL;
     969             : }
     970             : 
     971             : sql_column *
     972           0 : mvc_first_column(mvc *m, sql_table *t)
     973             : {
     974           0 :         sql_column *c = first_column(t);
     975             : 
     976           0 :         (void) m;
     977           0 :         if (!c)
     978             :                 return NULL;
     979           0 :         TRC_DEBUG(SQL_TRANS, "First column: %s.%s\n", t->base.name, c->base.name);
     980             :         return c;
     981             : }
     982             : 
     983             : sql_key *
     984        7308 : mvc_bind_key(mvc *m, sql_schema *s, const char *kname)
     985             : {
     986        7308 :         sql_key *k = schema_find_key(m->session->tr, s, kname);
     987             : 
     988        7308 :         if (!k)
     989             :                 return NULL;
     990          43 :         TRC_DEBUG(SQL_TRANS, "Bind key: %s.%s\n", s->base.name, kname);
     991             :         return k;
     992             : }
     993             : 
     994             : sql_idx *
     995       19779 : mvc_bind_idx(mvc *m, sql_schema *s, const char *iname)
     996             : {
     997       19779 :         sql_idx *i = schema_find_idx(m->session->tr, s, iname);
     998             : 
     999       19777 :         if (!i)
    1000             :                 return NULL;
    1001       12300 :         TRC_DEBUG(SQL_TRANS, "Bind index: %s.%s\n", s->base.name, iname);
    1002             :         return i;
    1003             : }
    1004             : 
    1005             : static int
    1006         915 : uniqueKey(sql_key *k)
    1007             : {
    1008         915 :         return (k->type == pkey || k->type == ukey);
    1009             : }
    1010             : 
    1011             : sql_key *
    1012         905 : mvc_bind_ukey(sql_table *t, list *colnames)
    1013             : {
    1014         905 :         node *cn;
    1015         905 :         node *cur;
    1016         905 :         sql_key *res = NULL;
    1017         905 :         int len = list_length(colnames);
    1018             : 
    1019         905 :         if (ol_length(t->keys))
    1020         917 :                 for (cur = ol_first_node(t->keys); cur; cur = cur->next) {
    1021         915 :                         node *cc;
    1022         915 :                         sql_key *k = cur->data;
    1023             : 
    1024         915 :                         if (uniqueKey(k) && list_length(k->columns) == len) {
    1025         905 :                                 res = k;
    1026        1835 :                                 for (cc = k->columns->h, cn = colnames->h; cc && cn; cc = cc->next, cn = cn->next) {
    1027         935 :                                         sql_kc *c = cc->data;
    1028         935 :                                         char *n = cn->data;
    1029             : 
    1030         935 :                                         if (strcmp(c->c->base.name, n) != 0) {
    1031             :                                                 res = NULL;
    1032             :                                                 break;
    1033             :                                         }
    1034             :                                 }
    1035         905 :                                 if (res)
    1036             :                                         break;
    1037             :                         }
    1038             :                 }
    1039         905 :         return res;
    1040             : }
    1041             : 
    1042             : sql_trigger *
    1043         950 : mvc_bind_trigger(mvc *m, sql_schema *s, const char *tname)
    1044             : {
    1045         950 :         sql_trigger *t = schema_find_trigger(m->session->tr, s, tname);
    1046             : 
    1047         950 :         if (!t)
    1048             :                 return NULL;
    1049         173 :         TRC_DEBUG(SQL_TRANS, "Bind trigger: %s.%s\n", s->base.name, tname);
    1050             :         return t;
    1051             : }
    1052             : 
    1053             : int
    1054         906 : mvc_create_type(mvc *sql, sql_schema *s, const char *name, unsigned int digits, unsigned int scale, int radix, const char *impl)
    1055             : {
    1056         906 :         TRC_DEBUG(SQL_TRANS, "Create type: %s\n", name);
    1057         906 :         return sql_trans_create_type(sql->session->tr, s, name, digits, scale, radix, impl);
    1058             : }
    1059             : 
    1060             : int
    1061           3 : mvc_drop_type(mvc *m, sql_schema *s, sql_type *t, int drop_action)
    1062             : {
    1063           3 :         TRC_DEBUG(SQL_TRANS, "Drop type: %s %s\n", s->base.name, t->base.name);
    1064           3 :         if (t)
    1065           5 :                 return sql_trans_drop_type(m->session->tr, s, t->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
    1066             :         return 0;
    1067             : }
    1068             : 
    1069             : int
    1070      241080 : mvc_create_func(sql_func **f, mvc *m, allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang,
    1071             :                                 const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect)
    1072             : {
    1073      241080 :         int lres = LOG_OK;
    1074             : 
    1075      241080 :         TRC_DEBUG(SQL_TRANS, "Create function: %s\n", name);
    1076      241080 :         if (sa) {
    1077      120339 :                 *f = create_sql_func(m->store, sa, name, args, res, type, lang, mod, impl, query, varres, vararg, system, side_effect);
    1078      120339 :                 (*f)->s = s;
    1079             :         } else
    1080      120741 :                 lres = sql_trans_create_func(f, m->session->tr, s, name, args, res, type, lang, mod, impl, query, varres, vararg, system, side_effect);
    1081      241080 :         return lres;
    1082             : }
    1083             : 
    1084             : int
    1085         646 : mvc_drop_func(mvc *m, sql_schema *s, sql_func *f, int drop_action)
    1086             : {
    1087         646 :         TRC_DEBUG(SQL_TRANS, "Drop function: %s %s\n", s->base.name, f->base.name);
    1088        1250 :         return sql_trans_drop_func(m->session->tr, s, f->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
    1089             : }
    1090             : 
    1091             : int
    1092          30 : mvc_drop_all_func(mvc *m, sql_schema *s, list *list_func, int drop_action)
    1093             : {
    1094          30 :         TRC_DEBUG(SQL_TRANS, "Drop all functions: %s %s\n", s->base.name, ((sql_func *) list_func->h->data)->base.name);
    1095          60 :         return sql_trans_drop_all_func(m->session->tr, s, list_func, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
    1096             : }
    1097             : 
    1098             : int
    1099        1082 : mvc_create_schema(mvc *m, const char *name, sqlid auth_id, sqlid owner)
    1100             : {
    1101        1082 :         TRC_DEBUG(SQL_TRANS, "Create schema: %s %d %d\n", name, auth_id, owner);
    1102        1082 :         return sql_trans_create_schema(m->session->tr, name, auth_id, owner, NULL);
    1103             : }
    1104             : 
    1105             : int
    1106         159 : mvc_drop_schema(mvc *m, sql_schema * s, int drop_action)
    1107             : {
    1108         159 :         TRC_DEBUG(SQL_TRANS, "Drop schema: %s\n", s->base.name);
    1109         237 :         return sql_trans_drop_schema(m->session->tr, s->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
    1110             : }
    1111             : 
    1112             : int
    1113        5969 : mvc_create_ukey(sql_key **kres, mvc *m, sql_table *t, const char *name, key_type kt, const char* check)
    1114             : {
    1115        5969 :         int res = LOG_OK;
    1116             : 
    1117        5969 :         TRC_DEBUG(SQL_TRANS, "Create ukey: %s %u\n", t->base.name, (unsigned) kt);
    1118        5969 :         if (t->persistence == SQL_DECLARED_TABLE)
    1119        5969 :                 *kres = create_sql_ukey(m->store, m->sa, t, name, kt, check);
    1120             :         else
    1121           0 :                 res = sql_trans_create_ukey(kres, m->session->tr, t, name, kt, check);
    1122        5969 :         return res;
    1123             : }
    1124             : 
    1125             : int
    1126        6891 : mvc_create_key_done(mvc *m, sql_key *k)
    1127             : {
    1128        6891 :         int res = LOG_OK;
    1129             : 
    1130        6891 :         if (k->t->persistence == SQL_DECLARED_TABLE)
    1131        6891 :                 key_create_done(m->session->tr, m->sa, k);
    1132             :         else
    1133           0 :                 res = sql_trans_key_done(m->session->tr, k);
    1134        6891 :         return res;
    1135             : }
    1136             : 
    1137             : int
    1138         941 : mvc_create_fkey(sql_fkey **kres, mvc *m, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update)
    1139             : {
    1140         941 :         int res = LOG_OK;
    1141             : 
    1142         941 :         TRC_DEBUG(SQL_TRANS, "Create fkey: %s %u %p\n", t->base.name, (unsigned) kt, rkey);
    1143         941 :         if (t->persistence == SQL_DECLARED_TABLE)
    1144         941 :                 *kres = create_sql_fkey(m->store, m->sa, t, name, kt, rkey, on_delete, on_update);
    1145             :         else
    1146           0 :                 res = sql_trans_create_fkey(kres, m->session->tr, t, name, kt, rkey, on_delete, on_update);
    1147         941 :         return res;
    1148             : }
    1149             : 
    1150             : int
    1151        6567 : mvc_create_kc(mvc *m, sql_key *k, sql_column *c)
    1152             : {
    1153        6567 :         int res = LOG_OK;
    1154             : 
    1155        6567 :         if (k->t->persistence == SQL_DECLARED_TABLE)
    1156        6567 :                 create_sql_kc(m->store, m->sa, k, c);
    1157             :         else
    1158           0 :                 res = sql_trans_create_kc(m->session->tr, k, c);
    1159        6567 :         return res;
    1160             : }
    1161             : 
    1162             : int
    1163         962 : mvc_create_fkc(mvc *m, sql_fkey *fk, sql_column *c)
    1164             : {
    1165         962 :         int res = LOG_OK;
    1166         962 :         sql_key *k = (sql_key*)fk;
    1167             : 
    1168         962 :         if (k->t->persistence == SQL_DECLARED_TABLE)
    1169         962 :                 create_sql_kc(m->store, m->sa, k, c);
    1170             :         else
    1171           0 :                 res = sql_trans_create_fkc(m->session->tr, fk, c);
    1172         962 :         return res;
    1173             : }
    1174             : 
    1175             : int
    1176         146 : mvc_drop_key(mvc *m, sql_schema *s, sql_key *k, int drop_action)
    1177             : {
    1178         146 :         TRC_DEBUG(SQL_TRANS, "Drop key: %s %s\n", s->base.name, k->base.name);
    1179         146 :         if (k->t->persistence == SQL_DECLARED_TABLE) {
    1180           0 :                 drop_sql_key(k->t, k->base.id, drop_action);
    1181           0 :                 return 0;
    1182             :         } else
    1183         291 :                 return sql_trans_drop_key(m->session->tr, s, k->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
    1184             : }
    1185             : 
    1186             : int
    1187         337 : mvc_create_idx(sql_idx **i, mvc *m, sql_table *t, const char *name, idx_type it)
    1188             : {
    1189         337 :         int res = LOG_OK;
    1190             : 
    1191         337 :         TRC_DEBUG(SQL_TRANS, "Create index: %s %u\n", t->base.name, (unsigned) it);
    1192         337 :         if (t->persistence == SQL_DECLARED_TABLE)
    1193             :                 /* declared tables should not end up in the catalog */
    1194         337 :                 *i = create_sql_idx(m->store, m->sa, t, name, it);
    1195             :         else
    1196           0 :                 res = sql_trans_create_idx(i, m->session->tr, t, name, it);
    1197         337 :         return res;
    1198             : }
    1199             : 
    1200             : int
    1201         431 : mvc_create_ic(mvc *m, sql_idx *i, sql_column *c)
    1202             : {
    1203         431 :         int res = LOG_OK;
    1204             : 
    1205         431 :         if (i->t->persistence == SQL_DECLARED_TABLE)
    1206             :                 /* declared tables should not end up in the catalog */
    1207         431 :                 create_sql_ic(m->store, m->sa, i, c);
    1208             :         else
    1209           0 :                 res = sql_trans_create_ic(m->session->tr, i, c);
    1210         431 :         return res;
    1211             : }
    1212             : 
    1213             : int
    1214         335 : mvc_create_idx_done(mvc *m, sql_idx *i)
    1215             : {
    1216         335 :         int res = LOG_OK;
    1217             : 
    1218         335 :         (void) m;
    1219         335 :         (void) create_sql_idx_done(m->session->tr, i);
    1220         335 :         return res;
    1221             : }
    1222             : 
    1223             : int
    1224         159 : mvc_drop_idx(mvc *m, sql_schema *s, sql_idx *i)
    1225             : {
    1226         159 :         TRC_DEBUG(SQL_TRANS, "Drop index: %s %s\n", s->base.name, i->base.name);
    1227         159 :         if (i->t->persistence == SQL_DECLARED_TABLE) {
    1228             :                 /* declared tables should not end up in the catalog */
    1229           0 :                 drop_sql_idx(i->t, i->base.id);
    1230           0 :                 return 0;
    1231             :         } else
    1232         159 :                 return sql_trans_drop_idx(m->session->tr, s, i->base.id, DROP_RESTRICT);
    1233             : }
    1234             : 
    1235             : int
    1236         343 : mvc_create_trigger(sql_trigger **tri, mvc *m, sql_table *t, const char *name, sht time, sht orientation, sht event, const char *old_name,
    1237             :                                    const char *new_name, const char *condition, const char *statement)
    1238             : {
    1239         343 :         TRC_DEBUG(SQL_TRANS, "Create trigger: %s %d %d %d\n", t->base.name, time, orientation, event);
    1240         343 :         return sql_trans_create_trigger(tri, m->session->tr, t, name, time, orientation, event, old_name, new_name, condition, statement);
    1241             : }
    1242             : 
    1243             : int
    1244          89 : mvc_drop_trigger(mvc *m, sql_schema *s, sql_trigger *tri)
    1245             : {
    1246          89 :         TRC_DEBUG(SQL_TRANS, "Drop trigger: %s %s\n", s->base.name, tri->base.name);
    1247          89 :         return sql_trans_drop_trigger(m->session->tr, s, tri->base.id, DROP_RESTRICT);
    1248             : }
    1249             : 
    1250             : int
    1251       11533 : mvc_create_table(sql_table **t, mvc *m, sql_schema *s, const char *name, int tt, bit system, int persistence, int commit_action, int sz, bit properties)
    1252             : {
    1253       11533 :         char *err = NULL;
    1254       11533 :         int res = LOG_OK;
    1255             : 
    1256       11533 :         assert(s);
    1257       11533 :         TRC_DEBUG(SQL_TRANS, "Create table: %s %s %d %d %d %d %d\n", s->base.name, name, tt, system, persistence, commit_action, (int)properties);
    1258       11533 :         if (persistence == SQL_DECLARED_TABLE) {
    1259       10183 :                 *t = create_sql_table(m->store, m->sa, name, tt, system, persistence, commit_action, properties);
    1260       10183 :                 (*t)->s = s;
    1261             :         } else {
    1262        1350 :                 res = sql_trans_create_table(t, m->session->tr, s, name, NULL, tt, system, persistence, commit_action, sz, properties);
    1263        1350 :                 if (res == LOG_OK && isPartitionedByExpressionTable(*t) && (err = bootstrap_partition_expression(m, *t, 1))) {
    1264           0 :                         (void) sql_error(m, 02, "%s", err);
    1265           0 :                         return -5;
    1266             :                 }
    1267        1350 :                 if (res == LOG_OK)
    1268        1350 :                         res = sql_trans_set_partition_table(m->session->tr, *t);
    1269             :         }
    1270             :         return res;
    1271             : }
    1272             : 
    1273             : int
    1274       22825 : mvc_create_view(sql_table **t, mvc *m, sql_schema *s, const char *name, int persistence, const char *sql, bit system)
    1275             : {
    1276       22825 :         int res = LOG_OK;
    1277             : 
    1278       22825 :         TRC_DEBUG(SQL_TRANS, "Create view: %s %s %s\n", s->base.name, name, sql);
    1279       22825 :         if (persistence == SQL_DECLARED_TABLE) {
    1280       22359 :                 *t = create_sql_table(m->store, m->sa, name, tt_view, system, persistence, 0, 0);
    1281       22359 :                 (*t)->s = s;
    1282       22359 :                 (*t)->query = sa_strdup(m->sa, sql);
    1283             :         } else {
    1284         466 :                 res = sql_trans_create_table(t, m->session->tr, s, name, sql, tt_view, system, SQL_PERSIST, 0, 0, 0);
    1285             :         }
    1286       22825 :         return res;
    1287             : }
    1288             : 
    1289             : int
    1290         101 : mvc_create_remote(sql_table **t, mvc *m, sql_schema *s, const char *name, int persistence, const char *loc)
    1291             : {
    1292         101 :         int res = LOG_OK;
    1293             : 
    1294         101 :         TRC_DEBUG(SQL_TRANS, "Create remote: %s %s %s\n", s->base.name, name, loc);
    1295         101 :         if (persistence == SQL_DECLARED_TABLE) {
    1296         101 :                 *t = create_sql_table(m->store, m->sa, name, tt_remote, 0, persistence, 0, 0);
    1297         101 :                 (*t)->s = s;
    1298         101 :                 (*t)->query = sa_strdup(m->sa, loc);
    1299             :         } else {
    1300           0 :                 res = sql_trans_create_table(t, m->session->tr, s, name, loc, tt_remote, 0, SQL_REMOTE, 0, 0, 0);
    1301             :         }
    1302         101 :         return res;
    1303             : }
    1304             : 
    1305             : static str
    1306          35 : remote_drop(mvc *m, sql_table *t)
    1307             : {
    1308          35 :         sqlid id = t->base.id;
    1309          35 :         int log_res = 0;
    1310          35 :         sql_trans *tr = m->session->tr;
    1311          35 :         sqlstore *store = tr->store;
    1312          35 :         sql_schema *sys = find_sql_schema(tr, "sys");
    1313          35 :         sql_table *remote_user_info = find_sql_table(tr, sys, REMOTE_USER_INFO);
    1314          35 :         sql_column *remote_user_info_id = find_sql_column(remote_user_info, "table_id");
    1315          35 :         oid rid = store->table_api.column_find_row(tr, remote_user_info_id, &id, NULL);
    1316          35 :         if (is_oid_nil(rid)) {
    1317           1 :                 TRC_WARNING(SQL_TRANS, "Drop table: %s %s no remote info\n", t->s->base.name, t->base.name);
    1318          34 :         } else if ((log_res = store->table_api.table_delete(tr, remote_user_info, rid)) != 0)
    1319           0 :                 throw(SQL, "sql.drop_table", SQLSTATE(42000) "Drop table failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
    1320             :         return MAL_SUCCEED;
    1321             : }
    1322             : 
    1323             : str
    1324        3993 : mvc_drop_table(mvc *m, sql_schema *s, sql_table *t, int drop_action)
    1325             : {
    1326        3993 :         char *msg = NULL;
    1327        3993 :         TRC_DEBUG(SQL_TRANS, "Drop table: %s %s\n", s->base.name, t->base.name);
    1328             : 
    1329        3993 :         if (isRemote(t) && (msg = remote_drop(m, t)) != NULL)
    1330             :                 return msg;
    1331             : 
    1332        7512 :         switch (sql_trans_drop_table(m->session->tr, s, t->base.name, drop_action ? DROP_CASCADE_START : DROP_RESTRICT)) {
    1333           0 :                 case -1:
    1334           0 :                         throw(SQL,"sql.mvc_drop_table",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1335           0 :                 case -2:
    1336             :                 case -3:
    1337           0 :                         throw(SQL, "sql.mvc_drop_table", SQLSTATE(42000) "Transaction conflict while dropping table %s.%s", s->base.name, t->base.name);
    1338             :                 default:
    1339             :                         break;
    1340             :         }
    1341             :         return MAL_SUCCEED;
    1342             : }
    1343             : 
    1344             : BUN
    1345       41826 : mvc_clear_table(mvc *m, sql_table *t)
    1346             : {
    1347       41826 :         return sql_trans_clear_table(m->session->tr, t);
    1348             : }
    1349             : 
    1350             : int
    1351        9827 : mvc_create_column_(sql_column **col, mvc *m, sql_table *t, const char *name, const char *type, unsigned int digits)
    1352             : {
    1353        9827 :         sql_subtype tpe;
    1354             : 
    1355        9827 :         if (!sql_find_subtype(&tpe, type, digits, 0))
    1356             :                 return -1;
    1357             : 
    1358        9827 :         return sql_trans_create_column(col, m->session->tr, t, name, &tpe);
    1359             : }
    1360             : 
    1361             : int
    1362      256628 : mvc_create_column(sql_column **col, mvc *m, sql_table *t, const char *name, sql_subtype *tpe)
    1363             : {
    1364      256628 :         int res = LOG_OK;
    1365             : 
    1366      256628 :         TRC_DEBUG(SQL_TRANS, "Create column: %s %s %s\n", t->base.name, name, tpe->type->base.name);
    1367      256628 :         if (t->persistence == SQL_DECLARED_TABLE)
    1368             :                 /* declared tables should not end up in the catalog */
    1369      256628 :                 *col = create_sql_column(m->store, m->sa, t, name, tpe);
    1370             :         else
    1371           0 :                 res = sql_trans_create_column(col, m->session->tr, t, name, tpe);
    1372      256628 :         return res;
    1373             : }
    1374             : 
    1375             : int
    1376         136 : mvc_drop_column(mvc *m, sql_table *t, sql_column *col, int drop_action)
    1377             : {
    1378         136 :         TRC_DEBUG(SQL_TRANS, "Drop column: %s %s\n", t->base.name, col->base.name);
    1379         136 :         if (col->t->persistence == SQL_DECLARED_TABLE) {
    1380          68 :                 drop_sql_column(t, col->base.id, drop_action);
    1381          68 :                 return 0;
    1382             :         } else
    1383         128 :                 return sql_trans_drop_column(m->session->tr, t, col->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
    1384             : }
    1385             : 
    1386             : int
    1387      370199 : mvc_create_dependency(mvc *m, sql_base *b, sqlid depend_id, sql_dependency depend_type)
    1388             : {
    1389      370199 :         int res = LOG_OK;
    1390             : 
    1391      370199 :         TRC_DEBUG(SQL_TRANS, "Create dependency: %d %d %d\n", b->id, depend_id, (int) depend_type);
    1392      370199 :         if ( (b->id != depend_id) || (depend_type == BEDROPPED_DEPENDENCY) ) {
    1393      370198 :                 if (!b->new)
    1394      222629 :                         res = sql_trans_add_dependency(m->session->tr, b->id, ddl);
    1395      222629 :                 if (res == LOG_OK)
    1396      370198 :                         res = sql_trans_create_dependency(m->session->tr, b->id, depend_id, depend_type);
    1397             :         }
    1398      370199 :         return res;
    1399             : }
    1400             : 
    1401             : int
    1402      144421 : mvc_create_dependencies(mvc *m, list *blist, sqlid depend_id, sql_dependency dep_type)
    1403             : {
    1404      144421 :         int res = LOG_OK;
    1405             : 
    1406      144421 :         TRC_DEBUG(SQL_TRANS, "Create dependencies on '%d' of type: %d\n", depend_id, (int) dep_type);
    1407      144421 :         if (!list_empty(blist)) {
    1408      383736 :                 for (node *n = blist->h ; n && res == LOG_OK ; n = n->next) {
    1409      356655 :                         sql_base *b = n->data;
    1410      356655 :                         if (!b->new) /* only add old objects to the transaction dependency list */
    1411      222585 :                                 res = sql_trans_add_dependency(m->session->tr, b->id, ddl);
    1412      356655 :                         if (res == LOG_OK)
    1413      356655 :                                 res = mvc_create_dependency(m, b, depend_id, dep_type);
    1414             :                 }
    1415             :         }
    1416      144421 :         return res;
    1417             : }
    1418             : 
    1419             : int
    1420        4668 : mvc_check_dependency(mvc *m, sqlid id, sql_dependency type, list *ignore_ids)
    1421             : {
    1422        4668 :         list *dep_list = NULL;
    1423             : 
    1424        4668 :         TRC_DEBUG(SQL_TRANS, "Check dependency on: %d\n", id);
    1425        4668 :         switch (type) {
    1426         107 :                 case OWNER_DEPENDENCY:
    1427         107 :                         dep_list = sql_trans_owner_schema_dependencies(m->session->tr, id);
    1428         107 :                         break;
    1429          17 :                 case SCHEMA_DEPENDENCY:
    1430          17 :                         dep_list = sql_trans_schema_user_dependencies(m->session->tr, id);
    1431          17 :                         if (!dep_list)
    1432          17 :                                 dep_list = sql_trans_get_dependents(m->session->tr, id, SCHEMA_DEPENDENCY, NULL);
    1433             :                         break;
    1434        3309 :                 case TABLE_DEPENDENCY:
    1435        3309 :                         dep_list = sql_trans_get_dependents(m->session->tr, id, TABLE_DEPENDENCY, NULL);
    1436        3309 :                         break;
    1437         311 :                 case VIEW_DEPENDENCY:
    1438         311 :                         dep_list = sql_trans_get_dependents(m->session->tr, id, TABLE_DEPENDENCY, NULL);
    1439         311 :                         break;
    1440         650 :                 case FUNC_DEPENDENCY:
    1441             :                 case PROC_DEPENDENCY:
    1442         650 :                         dep_list = sql_trans_get_dependents(m->session->tr, id, FUNC_DEPENDENCY, ignore_ids);
    1443         650 :                         break;
    1444         274 :                 default:
    1445         274 :                         dep_list =  sql_trans_get_dependents(m->session->tr, id, COLUMN_DEPENDENCY, NULL);
    1446             :         }
    1447             : 
    1448        4668 :         if (!dep_list)
    1449             :                 return DEPENDENCY_CHECK_ERROR;
    1450             : 
    1451        4668 :         if (list_length(dep_list) >= 2) {
    1452          49 :                 list_destroy(dep_list);
    1453          49 :                 return HAS_DEPENDENCY;
    1454             :         }
    1455             : 
    1456        4619 :         list_destroy(dep_list);
    1457        4619 :         return NO_DEPENDENCY;
    1458             : }
    1459             : 
    1460             : int
    1461       17190 : mvc_null(mvc *m, sql_column *col, int isnull)
    1462             : {
    1463       17190 :         TRC_DEBUG(SQL_TRANS, "Null: %s %d\n", col->base.name, isnull);
    1464       17190 :         if (col->t->persistence == SQL_DECLARED_TABLE) {
    1465       17093 :                 col->null = isnull;
    1466       17093 :                 return 0;
    1467             :         }
    1468          97 :         return sql_trans_alter_null(m->session->tr, col, isnull);
    1469             : }
    1470             : 
    1471             : int
    1472        1431 : mvc_default(mvc *m, sql_column *col, char *val)
    1473             : {
    1474        1431 :         TRC_DEBUG(SQL_TRANS, "Default: %s %s\n", col->base.name, val);
    1475        1431 :         if (col->t->persistence == SQL_DECLARED_TABLE) {
    1476        1408 :                 col->def = val?sa_strdup(m->sa, val):NULL;
    1477        1408 :                 return 0;
    1478             :         } else {
    1479          23 :                 return sql_trans_alter_default(m->session->tr, col, val);
    1480             :         }
    1481             : }
    1482             : 
    1483             : int
    1484           6 : mvc_drop_default(mvc *m, sql_column *col)
    1485             : {
    1486           6 :         TRC_DEBUG(SQL_TRANS, "Drop default: %s\n", col->base.name);
    1487           6 :         if (col->t->persistence == SQL_DECLARED_TABLE) {
    1488           6 :                 col->def = NULL;
    1489           6 :                 return 0;
    1490             :         } else {
    1491           0 :                 return sql_trans_alter_default(m->session->tr, col, NULL);
    1492             :         }
    1493             : }
    1494             : 
    1495             : int
    1496           0 : mvc_storage(mvc *m, sql_column *col, char *storage)
    1497             : {
    1498           0 :         TRC_DEBUG(SQL_TRANS, "Storage: %s %s\n", col->base.name, storage);
    1499           0 :         if (col->t->persistence == SQL_DECLARED_TABLE) {
    1500           0 :                 col->storage_type = storage?sa_strdup(m->sa, storage):NULL;
    1501           0 :                 return 0;
    1502             :         } else {
    1503           0 :                 return sql_trans_alter_storage(m->session->tr, col, storage);
    1504             :         }
    1505             : }
    1506             : 
    1507             : int
    1508        2309 : mvc_access(mvc *m, sql_table *t, sht access)
    1509             : {
    1510        2309 :         TRC_DEBUG(SQL_TRANS, "Access: %s %d\n", t->base.name, access);
    1511        2309 :         if (t->persistence == SQL_DECLARED_TABLE) {
    1512           0 :                 t->access = access;
    1513           0 :                 return 0;
    1514             :         }
    1515        2309 :         return sql_trans_alter_access(m->session->tr, t, access);
    1516             : }
    1517             : 
    1518             : int
    1519       21598 : mvc_is_sorted(mvc *m, sql_column *col)
    1520             : {
    1521       21598 :         TRC_DEBUG(SQL_TRANS, "Is sorted: %s\n", col->base.name);
    1522       21598 :         return sql_trans_is_sorted(m->session->tr, col);
    1523             : }
    1524             : 
    1525             : int
    1526        7814 : mvc_is_unique(mvc *m, sql_column *col)
    1527             : {
    1528        7814 :         TRC_DEBUG(SQL_TRANS, "Is unique: %s\n", col->base.name);
    1529        7814 :         return sql_trans_is_unique(m->session->tr, col);
    1530             : }
    1531             : 
    1532             : int
    1533        2048 : mvc_is_duplicate_eliminated(mvc *m, sql_column *col)
    1534             : {
    1535        2048 :         TRC_DEBUG(SQL_TRANS, "Is duplicate eliminated: %s\n", col->base.name);
    1536        2048 :         return sql_trans_is_duplicate_eliminated(m->session->tr, col);
    1537             : }
    1538             : 
    1539             : int
    1540     4053813 : mvc_col_stats(mvc *m, sql_column *col, bool *nonil, bool *unique, double *unique_est, ValPtr min, ValPtr max)
    1541             : {
    1542     4053813 :         TRC_DEBUG(SQL_TRANS, "Retrieving column stats for: %s\n", col->base.name);
    1543     4053813 :         return sql_trans_col_stats(m->session->tr, col, nonil, unique, unique_est, min, max);
    1544             : }
    1545             : 
    1546             : int
    1547      256208 : mvc_copy_column(mvc *m, sql_table *t, sql_column *c, sql_column **cres)
    1548             : {
    1549      256208 :         return sql_trans_copy_column(m->session->tr, t, c, cres);
    1550             : }
    1551             : 
    1552             : int
    1553        6868 : mvc_copy_key(mvc *m, sql_table *t, sql_key *k, sql_key **kres)
    1554             : {
    1555        6868 :         return sql_trans_copy_key(m->session->tr, t, k, kres);
    1556             : }
    1557             : 
    1558             : int
    1559        7165 : mvc_copy_idx(mvc *m, sql_table *t, sql_idx *i, sql_idx **ires)
    1560             : {
    1561        7165 :         return sql_trans_copy_idx(m->session->tr, t, i, ires);
    1562             : }
    1563             : 
    1564             : int
    1565           0 : mvc_copy_trigger(mvc *m, sql_table *t, sql_trigger *tr, sql_trigger **tres)
    1566             : {
    1567           0 :         return sql_trans_copy_trigger(m->session->tr, t, tr, tres);
    1568             : }
    1569             : 
    1570             : sql_rel *
    1571      708625 : sql_processrelation(mvc *sql, sql_rel *rel, int profile, int instantiate, int value_based_opt, int storage_based_opt)
    1572             : {
    1573      708625 :         int emode = sql->emode;
    1574      708625 :         if (!instantiate)
    1575      143407 :                 sql->emode = m_deps;
    1576      708625 :         if (rel)
    1577      708625 :                 rel = rel_unnest(sql, rel);
    1578      708600 :         sql->emode = emode;
    1579      708600 :         if (rel)
    1580      708584 :                 rel = rel_optimizer(sql, rel, profile, instantiate, value_based_opt, storage_based_opt);
    1581      708616 :         return rel;
    1582             : }
    1583             : 
    1584             : static inline int dlist_cmp(mvc *sql, dlist *l1, dlist *l2);
    1585             : 
    1586             : static inline int
    1587         385 : dnode_cmp(mvc *sql, dnode *d1, dnode *d2)
    1588             : {
    1589         385 :         if (d1 == d2)
    1590             :                 return 0;
    1591             : 
    1592         385 :         if (!d1 || !d2)
    1593             :                 return -1;
    1594             : 
    1595         385 :         if (d1->type == d2->type) {
    1596         385 :                 switch (d1->type) {
    1597          35 :                         case type_int:
    1598          35 :                                 return (d1->data.i_val - d2->data.i_val);
    1599           0 :                         case type_lng: {
    1600           0 :                                 lng c = d1->data.l_val - d2->data.l_val;
    1601           0 :                                 assert((lng) GDK_int_min <= c && c <= (lng) GDK_int_max);
    1602           0 :                                 return (int) c;
    1603             :                         }
    1604         202 :                         case type_string:
    1605         202 :                                 if (d1->data.sval == d2->data.sval)
    1606             :                                         return 0;
    1607         202 :                                 if (!d1->data.sval || !d2->data.sval)
    1608             :                                         return -1;
    1609         202 :                                 return strcmp(d1->data.sval, d2->data.sval);
    1610          63 :                         case type_list:
    1611          63 :                                 return dlist_cmp(sql, d1->data.lval, d2->data.lval);
    1612          85 :                         case type_symbol:
    1613          85 :                                 return symbol_cmp(sql, d1->data.sym, d2->data.sym);
    1614           0 :                         case type_type:
    1615           0 :                                 return subtype_cmp(&d1->data.typeval, &d2->data.typeval);
    1616             :                         default:
    1617           0 :                                 assert(0);
    1618             :                 }
    1619             :         }
    1620             :         return -1;
    1621             : }
    1622             : 
    1623             : static inline int
    1624         268 : dlist_cmp(mvc *sql, dlist *l1, dlist *l2)
    1625             : {
    1626         268 :         int res = 0;
    1627         268 :         dnode *d1, *d2;
    1628             : 
    1629         268 :         if (l1 == l2)
    1630             :                 return 0;
    1631             : 
    1632         268 :         if (!l1 || !l2 || dlist_length(l1) != dlist_length(l2))
    1633          20 :                 return -1;
    1634             : 
    1635         633 :         for (d1 = l1->h, d2 = l2->h; !res && d1; d1 = d1->next, d2 = d2->next) {
    1636         385 :                 res = dnode_cmp(sql, d1, d2);
    1637             :         }
    1638             :         return res;
    1639             : }
    1640             : 
    1641             : static inline int
    1642          30 : AtomNodeCmp(AtomNode *a1, AtomNode *a2)
    1643             : {
    1644          30 :         if (a1 == a2)
    1645             :                 return 0;
    1646          30 :         if (!a1 || !a2)
    1647             :                 return -1;
    1648          30 :         if (a1->a && a2->a)
    1649          30 :                 return atom_cmp(a1->a, a2->a);
    1650             :         return -1;
    1651             : }
    1652             : 
    1653             : static inline int
    1654           0 : SelectNodeCmp(mvc *sql, SelectNode *s1, SelectNode *s2)
    1655             : {
    1656           0 :         if (s1 == s2)
    1657             :                 return 0;
    1658           0 :         if (!s1 || !s2)
    1659             :                 return -1;
    1660             : 
    1661           0 :         if (symbol_cmp(sql, s1->limit, s2->limit) == 0 &&
    1662           0 :                 symbol_cmp(sql, s1->offset, s2->offset) == 0 &&
    1663           0 :                 symbol_cmp(sql, s1->sample, s2->sample) == 0 &&
    1664           0 :                 symbol_cmp(sql, s1->seed, s2->seed) == 0 &&
    1665           0 :                 s1->distinct == s2->distinct &&
    1666           0 :                 s1->lateral == s2->lateral &&
    1667           0 :                 symbol_cmp(sql, s1->name, s2->name) == 0 &&
    1668           0 :                 symbol_cmp(sql, s1->orderby, s2->orderby) == 0 &&
    1669           0 :                 symbol_cmp(sql, s1->having, s2->having) == 0 &&
    1670           0 :                 symbol_cmp(sql, s1->groupby, s2->groupby) == 0 &&
    1671           0 :                 symbol_cmp(sql, s1->where, s2->where) == 0 &&
    1672           0 :                 symbol_cmp(sql, s1->from, s2->from) == 0 &&
    1673           0 :                 symbol_cmp(sql, s1->window, s2->window) == 0 &&
    1674           0 :                 dlist_cmp(sql, s1->selection, s2->selection) == 0)
    1675             :                 return 0;
    1676             :         return -1;
    1677             : }
    1678             : 
    1679             : static inline int
    1680         239 : _symbol_cmp(mvc *sql, symbol *s1, symbol *s2)
    1681             : {
    1682         239 :         if (s1 == s2)
    1683             :                 return 0;
    1684         239 :         if (!s1 || !s2)
    1685             :                 return -1;
    1686         239 :         if (s1->token != s2->token || s1->type != s2->type)
    1687             :                 return -1;
    1688         235 :         switch (s1->type) {
    1689           0 :                 case type_int:
    1690           0 :                         return (s1->data.i_val - s2->data.i_val);
    1691           0 :                 case type_lng: {
    1692           0 :                         lng c = s1->data.l_val - s2->data.l_val;
    1693           0 :                         assert((lng) GDK_int_min <= c && c <= (lng) GDK_int_max);
    1694           0 :                         return (int) c;
    1695             :                 }
    1696           0 :                 case type_string:
    1697           0 :                         if (s1->data.sval == s2->data.sval)
    1698             :                                 return 0;
    1699           0 :                         if (!s1->data.sval || !s2->data.sval)
    1700             :                                 return -1;
    1701           0 :                         return strcmp(s1->data.sval, s2->data.sval);
    1702         205 :                 case type_list: {
    1703         205 :                                 return dlist_cmp(sql, s1->data.lval, s2->data.lval);
    1704             :                 }
    1705           0 :                 case type_type:
    1706           0 :                         return subtype_cmp(&s1->data.typeval, &s2->data.typeval);
    1707          30 :                 case type_symbol:
    1708          30 :                         if (s1->token == SQL_SELECT) {
    1709           0 :                                 if (s2->token != SQL_SELECT)
    1710             :                                         return -1;
    1711           0 :                                 return SelectNodeCmp(sql, (SelectNode *) s1, (SelectNode *) s2);
    1712          30 :                         } else if (s1->token == SQL_ATOM) {
    1713          30 :                                 if (s2->token != SQL_ATOM)
    1714             :                                         return -1;
    1715          30 :                                 return AtomNodeCmp((AtomNode *) s1, (AtomNode *) s2);
    1716             :                         } else {
    1717           0 :                                 return symbol_cmp(sql, s1->data.sym, s2->data.sym);
    1718             :                         }
    1719             :                 default:
    1720           0 :                         assert(0);
    1721             :         }
    1722             :         return 0;               /* never reached, just to pacify compilers */
    1723             : }
    1724             : 
    1725             : int
    1726         239 : symbol_cmp(mvc *sql, symbol *s1, symbol *s2)
    1727             : {
    1728         239 :         return _symbol_cmp(sql, s1, s2);
    1729             : }

Generated by: LCOV version 1.14