LCOV - code coverage report
Current view: top level - sql/server - sql_mvc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 592 814 72.7 %
Date: 2021-10-13 02:24:04 Functions: 71 78 91.0 %

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

Generated by: LCOV version 1.14