LCOV - code coverage report
Current view: top level - sql/server - sql_mvc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 682 908 75.1 %
Date: 2024-12-20 21:24:02 Functions: 73 80 91.2 %

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

Generated by: LCOV version 1.14