LCOV - code coverage report
Current view: top level - sql/server - rel_schema.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1631 2065 79.0 %
Date: 2024-04-25 20:03:45 Functions: 58 58 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "rel_trans.h"
      15             : #include "rel_rel.h"
      16             : #include "rel_basetable.h"
      17             : #include "rel_select.h"
      18             : #include "rel_updates.h"
      19             : #include "rel_exp.h"
      20             : #include "rel_schema.h"
      21             : #include "rel_remote.h"
      22             : #include "rel_psm.h"
      23             : #include "rel_propagate.h"
      24             : #include "sql_parser.h"
      25             : #include "sql_privileges.h"
      26             : #include "sql_partition.h"
      27             : 
      28             : #include "mal_authorize.h"
      29             : #include "mal_exception.h"
      30             : 
      31             : sql_rel *
      32       33190 : rel_table(mvc *sql, int cat_type, const char *sname, sql_table *t, int nr)
      33             : {
      34       33190 :         sql_rel *rel = rel_create(sql->sa);
      35       33190 :         list *exps = new_exp_list(sql->sa);
      36       33190 :         if (!rel || !exps)
      37             :                 return NULL;
      38             : 
      39       33190 :         append(exps, exp_atom_int(sql->sa, nr));
      40       33190 :         append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
      41       33190 :         append(exps, exp_atom_str(sql->sa, t->base.name, sql_bind_localtype("str") ));
      42       33190 :         append(exps, exp_atom_ptr(sql->sa, t));
      43       33190 :         rel->l = rel_basetable(sql, t, t->base.name);
      44       33190 :         rel->r = NULL;
      45       33190 :         rel->op = op_ddl;
      46       33190 :         rel->flag = cat_type;
      47       33190 :         rel->exps = exps;
      48       33190 :         rel->card = CARD_MULTI;
      49       33190 :         rel->nrcols = 0;
      50       33190 :         return rel;
      51             : }
      52             : 
      53             : static sql_rel *
      54          94 : rel_create_remote(mvc *sql, int cat_type, const char *sname, sql_table *t, int pw_encrypted, const char *username, const char *passwd)
      55             : {
      56          94 :         sql_rel *rel = rel_create(sql->sa);
      57          94 :         list *exps = new_exp_list(sql->sa);
      58          94 :         if (!rel || !exps)
      59             :                 return NULL;
      60             : 
      61          94 :         append(exps, exp_atom_int(sql->sa, pw_encrypted));
      62          94 :         append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
      63          94 :         append(exps, exp_atom_str(sql->sa, t->base.name, sql_bind_localtype("str") ));
      64          94 :         append(exps, exp_atom_ptr(sql->sa, t));
      65          94 :         append(exps, exp_atom_str(sql->sa, username, sql_bind_localtype("str") ));
      66          94 :         append(exps, exp_atom_str(sql->sa, passwd, sql_bind_localtype("str") ));
      67          94 :         rel->l = rel_basetable(sql, t, t->base.name);
      68          94 :         rel->r = NULL;
      69          94 :         rel->op = op_ddl;
      70          94 :         rel->flag = cat_type;
      71          94 :         rel->exps = exps;
      72          94 :         rel->card = CARD_MULTI;
      73          94 :         rel->nrcols = 0;
      74          94 :         return rel;
      75             : }
      76             : 
      77             : static sql_rel *
      78       22182 : rel_create_view_ddl(mvc *sql, int cat_type, const char *sname, sql_table *t, int nr, int replace)
      79             : {
      80       22182 :         sql_rel *rel = rel_table(sql, cat_type, sname, t, nr);
      81       22182 :         if (!rel)
      82             :                 return NULL;
      83       22182 :         append(rel->exps, exp_atom_int(sql->sa, replace));
      84       22182 :         return rel;
      85             : }
      86             : 
      87             : static sql_rel *
      88        2537 : rel_alter_table(sql_allocator *sa, int cattype, char *sname, char *tname, char *sname2, char *tname2, int action)
      89             : {
      90        2537 :         sql_rel *rel = rel_create(sa);
      91        2537 :         list *exps = new_exp_list(sa);
      92        2537 :         if (!rel || !exps)
      93             :                 return NULL;
      94             : 
      95        2537 :         append(exps, exp_atom_clob(sa, sname));
      96        2537 :         append(exps, exp_atom_clob(sa, tname));
      97        2537 :         assert((sname2 && tname2) || (!sname2 && !tname2));
      98        2537 :         if (sname2) {
      99         470 :                 append(exps, exp_atom_clob(sa, sname2));
     100         470 :                 append(exps, exp_atom_clob(sa, tname2));
     101             :         }
     102        2537 :         append(exps, exp_atom_int(sa, action));
     103        2537 :         rel->l = NULL;
     104        2537 :         rel->r = NULL;
     105        2537 :         rel->op = op_ddl;
     106        2537 :         rel->flag = cattype;
     107        2537 :         rel->exps = exps;
     108        2537 :         rel->card = CARD_MULTI;
     109        2537 :         rel->nrcols = 0;
     110        2537 :         return rel;
     111             : }
     112             : 
     113             : static sql_rel *
     114       11864 : view_rename_columns(mvc *sql, const char *name, sql_rel *sq, dlist *column_spec)
     115             : {
     116       11864 :         dnode *n = column_spec->h;
     117       11864 :         node *m = sq->exps->h, *p = m;
     118             : 
     119       11864 :         assert(is_project(sq->op));
     120       52638 :         for (; n && m; n = n->next, p = m, m = m->next) {
     121       40774 :                 char *cname = n->data.sval;
     122       40774 :                 sql_exp *e = m->data;
     123       40774 :                 sql_exp *n = e;
     124             : 
     125       40774 :                 exp_setname(sql->sa, n, name, cname);
     126       40774 :                 set_basecol(n);
     127             :         }
     128             :         /* skip any intern columns */
     129       11864 :         for (; m; m = m->next) {
     130           0 :                 sql_exp *e = m->data;
     131           0 :                 if (!is_intern(e))
     132             :                         break;
     133             :         }
     134       11864 :         if (p)
     135       11864 :                 p->next = 0;
     136       11864 :         if (n || m)
     137           0 :                 return sql_error(sql, 02, SQLSTATE(M0M03) "Column lists do not match");
     138       11864 :         list_hash_clear(sq->exps);
     139       11864 :         set_processed(sq);
     140       11864 :         return sq;
     141             : }
     142             : 
     143             : static int
     144       22283 : as_subquery(mvc *sql, sql_table *t, table_types tt, sql_rel *sq, dlist *column_spec, const char *msg)
     145             : {
     146       22283 :         sql_rel *r = sq;
     147             : 
     148       22283 :         if (!r)
     149             :                 return 0;
     150       22283 :         if (column_spec) {
     151         677 :                 dnode *n = column_spec->h;
     152         677 :                 node *m = r->exps->h;
     153             : 
     154        3349 :                 for (; n && m; n = n->next, m = m->next) {
     155        2672 :                         char *cname = n->data.sval;
     156        2672 :                         sql_exp *e = m->data;
     157        2672 :                         sql_subtype *tp = exp_subtype(e);
     158        2672 :                         sql_column *col = NULL;
     159             : 
     160        2672 :                         if (tt != tt_view && cname && cname[0] == '%') {
     161           0 :                                 sql_error(sql, 01, SQLSTATE(42000) "%s: generated labels not allowed in column names, use an alias instead", msg);
     162           0 :                                 return -1;
     163        2672 :                         } else if (!tp) {
     164           0 :                                 sql_error(sql, 01, SQLSTATE(42000) "%s: columns must have a type defined", msg);
     165           0 :                                 return -1;
     166        2672 :                         } else if (tp->type->eclass == EC_ANY) {
     167           0 :                                 sql_error(sql, 01, SQLSTATE(42000) "%s: any type (plain null value) not allowed as a column type, use an explicit cast", msg);
     168           0 :                                 return -1;
     169        2672 :                         } else if (mvc_bind_column(sql, t, cname)) {
     170           0 :                                 sql_error(sql, 01, SQLSTATE(42S21) "%s: duplicate column name %s", msg, cname);
     171           0 :                                 return -1;
     172             :                         }
     173        2672 :                         switch (mvc_create_column(&col, sql, t, cname, tp)) {
     174           0 :                                 case -1:
     175           0 :                                         sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     176           0 :                                         return -1;
     177           0 :                                 case -2:
     178             :                                 case -3:
     179           0 :                                         sql_error(sql, 01, SQLSTATE(42000) "%s: transaction conflict detected", msg);
     180           0 :                                         return -1;
     181             :                                 default:
     182        2672 :                                         break;
     183             :                         }
     184             :                 }
     185         677 :                 if (n || m) {
     186           0 :                         sql_error(sql, 01, SQLSTATE(21S02) "%s: number of columns does not match", msg);
     187           0 :                         return -1;
     188             :                 }
     189             :         } else {
     190      220067 :                 for (node *m = r->exps->h; m; m = m->next) {
     191      198465 :                         sql_exp *e = m->data;
     192      198465 :                         const char *cname = exp_name(e);
     193      198465 :                         sql_subtype *tp = exp_subtype(e);
     194      198465 :                         sql_column *col = NULL;
     195             : 
     196      198465 :                         if (!cname)
     197           4 :                                 cname = "v";
     198      198465 :                         if (tt != tt_view && cname[0] == '%') {
     199           1 :                                 sql_error(sql, 01, SQLSTATE(42000) "%s: generated labels not allowed in column names, use an alias instead", msg);
     200           4 :                                 return -1;
     201      198464 :                         } else if (!tp) {
     202           0 :                                 sql_error(sql, 01, SQLSTATE(42000) "%s: columns must have a type defined", msg);
     203           0 :                                 return -1;
     204      198464 :                         } else if (tp->type->eclass == EC_ANY) {
     205           1 :                                 sql_error(sql, 01, SQLSTATE(42000) "%s: any type (plain null value) not allowed as a column type, use an explicit cast", msg);
     206           1 :                                 return -1;
     207      198463 :                         } else if (mvc_bind_column(sql, t, cname)) {
     208           2 :                                 sql_error(sql, 01, SQLSTATE(42S21) "%s: duplicate column name %s", msg, cname);
     209           2 :                                 return -1;
     210             :                         }
     211      198461 :                         switch (mvc_create_column(&col, sql, t, cname, tp)) {
     212           0 :                                 case -1:
     213           0 :                                         sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     214           0 :                                         return -1;
     215           0 :                                 case -2:
     216             :                                 case -3:
     217           0 :                                         sql_error(sql, 01, SQLSTATE(42000) "%s: transaction conflict detected", msg);
     218           0 :                                         return -1;
     219             :                                 default:
     220      198461 :                                         break;
     221             :                         }
     222             :                 }
     223             :         }
     224             :         return 0;
     225             : }
     226             : 
     227             : sql_table *
     228         100 : mvc_create_table_as_subquery(mvc *sql, sql_rel *sq, sql_schema *s, const char *tname, dlist *column_spec, int temp, int commit_action, const char *action)
     229             : {
     230         100 :         sql_table *t = NULL;
     231         100 :         table_types tt =(temp == SQL_REMOTE)?tt_remote:
     232             :                 (temp == SQL_MERGE_TABLE)?tt_merge_table:
     233             :                 (temp == SQL_REPLICA_TABLE)?tt_replica_table:
     234             :                 (temp == SQL_UNLOGGED_TABLE)?tt_unlogged_table:tt_table;
     235             : 
     236         100 :         switch (mvc_create_table(&t, sql, s, tname, tt, 0, SQL_DECLARED_TABLE, commit_action, -1, 0)) {
     237           0 :                 case -1:
     238           0 :                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     239           0 :                 case -2:
     240             :                 case -3:
     241           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s TABLE: transaction conflict detected", action);
     242           0 :                 case -4:
     243           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s TABLE: the partition's expression is too long", action);
     244             :                 case -5:
     245             :                         return NULL;
     246             :                 default:
     247         100 :                         break;
     248             :         }
     249         100 :         if (as_subquery(sql, t, tt, sq, column_spec, action) != 0)
     250             :                 return NULL;
     251          97 :         return t;
     252             : }
     253             : 
     254             : static char *
     255         885 : table_constraint_name(mvc *sql, symbol *s, sql_table *t)
     256             : {
     257             :         /* create a descriptive name like table_col_pkey */
     258         885 :         char *suffix;           /* stores the type of this constraint */
     259         885 :         dnode *nms = NULL;
     260         885 :         char *buf;
     261         885 :         size_t buflen, len, slen;
     262             : 
     263         885 :         switch (s->token) {
     264          48 :                 case SQL_UNIQUE:
     265          48 :                         suffix = "_unique";
     266          48 :                         nms = s->data.lval->h;    /* list of columns */
     267          48 :                         break;
     268         460 :                 case SQL_PRIMARY_KEY:
     269         460 :                         suffix = "_pkey";
     270         460 :                         nms = s->data.lval->h;    /* list of columns */
     271         460 :                         break;
     272         377 :                 case SQL_FOREIGN_KEY:
     273         377 :                         suffix = "_fkey";
     274         377 :                         nms = s->data.lval->h->next->data.lval->h;       /* list of colums */
     275         377 :                         break;
     276           0 :                 case SQL_CHECK:
     277           0 :                         suffix = "_check";
     278           0 :                         nms = s->data.lval->h;    /* list of check constraint conditions */
     279           0 :                         break;
     280             :                 default:
     281             :                         suffix = "_?";
     282             :                         nms = NULL;
     283             :         }
     284             : 
     285             :         /* copy table name */
     286         885 :         len = strlen(t->base.name);
     287         885 :         buflen = BUFSIZ;
     288         885 :         slen = strlen(suffix);
     289         885 :         while (len + slen >= buflen)
     290           0 :                 buflen += BUFSIZ;
     291         885 :         buf = SA_NEW_ARRAY(sql->ta, char, buflen);
     292         885 :         strcpy(buf, t->base.name);
     293             : 
     294             :         /* add column name(s) */
     295        2140 :         for (; nms; nms = nms->next) {
     296        1255 :                 slen = strlen(nms->data.sval);
     297        1255 :                 while (len + slen + 1 >= buflen) {
     298           0 :                         size_t nbuflen = buflen + BUFSIZ;
     299           0 :                         char *nbuf = SA_RENEW_ARRAY(sql->ta, char, buf, nbuflen, buflen);
     300             :                         buf = nbuf;
     301             :                         buflen = nbuflen;
     302             :                 }
     303        1255 :                 snprintf(buf + len, buflen - len, "_%s", nms->data.sval);
     304        1255 :                 len += slen + 1;
     305             :         }
     306             : 
     307             :         /* add suffix */
     308         885 :         slen = strlen(suffix);
     309         885 :         while (len + slen >= buflen) {
     310           0 :                 size_t nbuflen = buflen + BUFSIZ;
     311           0 :                 char *nbuf = SA_RENEW_ARRAY(sql->ta, char, buf, nbuflen, buflen);
     312             :                 buf = nbuf;
     313             :                 buflen = nbuflen;
     314             :         }
     315         885 :         snprintf(buf + len, buflen - len, "%s", suffix);
     316         885 :         return buf;
     317             : }
     318             : 
     319             : static char *
     320       21022 : column_constraint_name(mvc *sql, symbol *s, sql_column *sc, sql_table *t)
     321             : {
     322             :         /* create a descriptive name like table_col_pkey */
     323       21022 :         char *suffix /* stores the type of this constraint */, *buf;
     324       21022 :         size_t buflen;
     325             : 
     326       21022 :         switch (s->token) {
     327             :                 case SQL_UNIQUE:
     328             :                         suffix = "unique";
     329             :                         break;
     330        2754 :                 case SQL_PRIMARY_KEY:
     331        2754 :                         suffix = "pkey";
     332        2754 :                         break;
     333          57 :                 case SQL_FOREIGN_KEY:
     334          57 :                         suffix = "fkey";
     335          57 :                         break;
     336           5 :                 case SQL_CHECK:
     337           5 :                         suffix = "check";
     338           5 :                         break;
     339       16500 :                 default:
     340       16500 :                         suffix = "?";
     341             :         }
     342             : 
     343       21022 :         buflen = strlen(t->base.name) + strlen(sc->base.name) + strlen(suffix) + 3;
     344       21022 :         buf = SA_NEW_ARRAY(sql->ta, char, buflen);
     345       21022 :         snprintf(buf, buflen, "%s_%s_%s", t->base.name, sc->base.name, suffix);
     346       21022 :         return buf;
     347             : }
     348             : 
     349             : #define COL_NULL        0
     350             : #define COL_DEFAULT 1
     351             : 
     352             : static bool
     353         966 : foreign_key_check_types(sql_subtype *lt, sql_subtype *rt)
     354             : {
     355         966 :         if (lt->type->eclass == EC_EXTERNAL && rt->type->eclass == EC_EXTERNAL)
     356           1 :                 return lt->type->localtype == rt->type->localtype;
     357        1921 :         return lt->type->eclass == rt->type->eclass || (EC_VARCHAR(lt->type->eclass) && EC_VARCHAR(rt->type->eclass));
     358             : }
     359             : 
     360             : static int
     361       21027 : column_constraint_type(mvc *sql, const char *name, symbol *s, sql_schema *ss, sql_table *t, sql_column *cs, bool isDeclared, int *used)
     362             : {
     363       21027 :         int res = SQL_ERR;
     364             : 
     365       21027 :         if (isDeclared && (s->token != SQL_NULL && s->token != SQL_NOT_NULL)) {
     366           1 :                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT: constraints on declared tables are not supported");
     367           1 :                 return res;
     368             :         }
     369       21026 :         switch (s->token) {
     370        4463 :         case SQL_UNIQUE:
     371             :         case SQL_PRIMARY_KEY: {
     372        4463 :                 key_type kt = (s->token == SQL_UNIQUE) ? ukey : pkey;
     373        4463 :                 sql_key *k;
     374        4463 :                 const char *ns = name;
     375             : 
     376        4463 :                 if (kt == pkey && t->pkey) {
     377           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT PRIMARY KEY: a table can have only one PRIMARY KEY");
     378           0 :                         return res;
     379             :                 }
     380        4463 :                 if (!ns || !*ns) { /* add this to be safe */
     381           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: key name name cannot be empty", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     382           0 :                         return res;
     383             :                 }
     384        4463 :                 while (isdigit((unsigned char) *ns))
     385           0 :                         ns++;
     386        4463 :                 if (!*ns) { /* if a key name just contains digit characters, the generated index name can be mistaken with a label */
     387           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: key name cannot contain just digit characters (0 through 9)", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     388           0 :                         return res;
     389             :                 }
     390        4463 :                 if (ol_find_name(t->keys, name) || mvc_bind_key(sql, ss, name)) {
     391           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: key %s already exists", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE", name);
     392           0 :                         return res;
     393             :                 }
     394        4463 :                 if (ol_find_name(t->idxs, name) || mvc_bind_idx(sql, ss, name)) {
     395           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: an index named '%s' already exists, and it would conflict with the key", kt == pkey ? "PRIMARY KEY" : "UNIQUE", name);
     396           0 :                         return res;
     397             :                 }
     398        4463 :                 switch (mvc_create_ukey(&k, sql, t, name, kt)) {
     399           0 :                         case -1:
     400           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     401           0 :                                 return res;
     402           0 :                         case -2:
     403             :                         case -3:
     404           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: transaction conflict detected", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     405           0 :                                 return res;
     406             :                         default:
     407        4463 :                                 break;
     408             :                 }
     409        4463 :                 switch (mvc_create_kc(sql, k, cs)) {
     410           0 :                         case -1:
     411           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     412           0 :                                 return res;
     413           0 :                         case -2:
     414             :                         case -3:
     415           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: transaction conflict detected", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     416           0 :                                 return res;
     417             :                         default:
     418        4463 :                                 break;
     419             :                 }
     420        4463 :                 switch (mvc_create_key_done(sql, k)) {
     421           0 :                         case -1:
     422           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     423           0 :                                 return res;
     424           0 :                         case -2:
     425             :                         case -3:
     426           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: transaction conflict detected", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     427           0 :                                 return res;
     428             :                         default:
     429        4463 :                                 break;
     430             :                 }
     431        4463 :                 res = SQL_OK;
     432        4463 :         }       break;
     433          58 :         case SQL_FOREIGN_KEY: {
     434          58 :                 dnode *n = s->data.lval->h;
     435          58 :                 char *rsname = qname_schema(n->data.lval);
     436          58 :                 char *rtname = qname_schema_object(n->data.lval);
     437          58 :                 int ref_actions = n->next->next->next->data.i_val;
     438          58 :                 sql_table *rt;
     439          58 :                 sql_fkey *fk;
     440          58 :                 list *cols;
     441          58 :                 sql_key *rk = NULL;
     442          58 :                 sql_kc *kc;
     443          58 :                 const char *ns = name;
     444             : 
     445          58 :                 assert(n->next->next->next->type == type_int);
     446          58 :                 rt = find_table_or_view_on_scope(sql, ss, rsname, rtname, "CONSTRAINT FOREIGN KEY", false);
     447             :                 /* self referenced table */
     448          58 :                 if (!rt && t->s == ss && strcmp(t->base.name, rtname) == 0) {
     449           1 :                         sql->errstr[0] = '\0'; /* reset table not found error */
     450           1 :                         sql->session->status = 0;
     451           1 :                         rt = t;
     452             :                 }
     453           1 :                 if (!rt)
     454           1 :                         return SQL_ERR;
     455          58 :                 if (!rt->s) { /* disable foreign key on declared table */
     456           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key with declared tables");
     457           0 :                         return res;
     458             :                 }
     459          58 :                 if (isTempSchema(t->s) != isTempSchema(rt->s)) { /* disable foreign key between temp and non temp */
     460           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key between temporary and non temporary tables");
     461           0 :                         return res;
     462             :                 }
     463          58 :                 if (isUnloggedTable(t) != isUnloggedTable(rt)) { /* disable foreign key between logged and unlogged */
     464           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key between logged and unlogged tables");
     465           0 :                         return res;
     466             :                 }
     467          58 :                 if (!ns || !*ns) { /* add this to be safe */
     468           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: key name name cannot be empty");
     469           0 :                         return res;
     470             :                 }
     471          58 :                 while (isdigit((unsigned char) *ns))
     472           0 :                         ns++;
     473          58 :                 if (!*ns) { /* if a key name just contains digit characters, the generated index name can be mistaken with a label */
     474           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: key name cannot contain just digit characters (0 through 9)");
     475           0 :                         return res;
     476             :                 }
     477          58 :                 if (ol_find_name(t->keys, name) || mvc_bind_key(sql, ss, name)) {
     478           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: key '%s' already exists", name);
     479           0 :                         return res;
     480             :                 }
     481          58 :                 if (ol_find_name(t->idxs, name) || mvc_bind_idx(sql, ss, name)) {
     482           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: an index named '%s' already exists, and it would conflict with the key", name);
     483           0 :                         return res;
     484             :                 }
     485             : 
     486             :                 /* find unique referenced key */
     487          58 :                 if (n->next->data.lval) {
     488          53 :                         char *rcname = n->next->data.lval->h->data.sval;
     489             : 
     490          53 :                         cols = list_append(sa_list(sql->sa), rcname);
     491          53 :                         rk = mvc_bind_ukey(rt, cols);
     492           5 :                 } else if (rt->pkey) {
     493             :                         /* no columns specified use rt.pkey */
     494           5 :                         rk = &rt->pkey->k;
     495             :                 }
     496          58 :                 if (!rk) {
     497           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: could not find referenced PRIMARY KEY in table %s.%s", rsname, rtname);
     498           0 :                         return res;
     499             :                 }
     500          58 :                 if (list_length(rk->columns) != 1) {
     501           1 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: not all columns are handled");
     502           1 :                         return res;
     503             :                 }
     504          57 :                 kc = rk->columns->h->data;
     505          57 :                 if (!foreign_key_check_types(&cs->type, &kc->c->type)) {
     506           0 :                         str tp1 = sql_subtype_string(sql->ta, &cs->type), tp2 = sql_subtype_string(sql->ta, &kc->c->type);
     507           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column '%s' %s is not compatible with the referenced %s KEY column type %s",
     508           0 :                                                          cs->base.name, tp1, rk->type == pkey ? "PRIMARY" : "UNIQUE", tp2);
     509           0 :                         return res;
     510             :                 }
     511          57 :                 switch (mvc_create_fkey(&fk, sql, t, name, fkey, rk, ref_actions & 255, (ref_actions>>8) & 255)) {
     512           0 :                         case -1:
     513           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     514           0 :                                 return res;
     515           0 :                         case -2:
     516             :                         case -3:
     517           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: transaction conflict detected");
     518           0 :                                 return res;
     519             :                         default:
     520          57 :                                 break;
     521             :                 }
     522          57 :                 switch (mvc_create_fkc(sql, fk, cs)) {
     523           0 :                         case -1:
     524           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     525           0 :                                 return res;
     526           0 :                         case -2:
     527             :                         case -3:
     528           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: transaction conflict detected");
     529           0 :                                 return res;
     530             :                         default:
     531          57 :                                 break;
     532             :                 }
     533          57 :                 switch (mvc_create_key_done(sql, (sql_key*)fk)) {
     534           0 :                         case -1:
     535           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     536           0 :                                 return res;
     537           0 :                         case -2:
     538             :                         case -3:
     539           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: transaction conflict detected");
     540           0 :                                 return res;
     541             :                         default:
     542          57 :                                 break;
     543             :                 }
     544          57 :                 res = SQL_OK;
     545          57 :         }       break;
     546       16500 :         case SQL_NOT_NULL:
     547             :         case SQL_NULL: {
     548       16500 :                 int null = (s->token != SQL_NOT_NULL);
     549             : 
     550       16500 :                 if (((*used)&(1<<COL_NULL))) {
     551           1 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "NULL constraint for a column may be specified at most once");
     552           1 :                         return SQL_ERR;
     553             :                 }
     554       16499 :                 *used |= (1<<COL_NULL);
     555             : 
     556       16499 :                 switch (mvc_null(sql, cs, null)) {
     557           0 :                         case -1:
     558           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     559           0 :                                 return SQL_ERR;
     560           0 :                         case -2:
     561             :                         case -3:
     562           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "NULL CONSTRAINT: transaction conflict detected");
     563           0 :                                 return SQL_ERR;
     564             :                         default:
     565             :                                 break;
     566             :                 }
     567             :                 res = SQL_OK;
     568             :         }       break;
     569           5 :         case SQL_CHECK: {
     570           5 :                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT CHECK: check constraints not supported");
     571           5 :                 return SQL_ERR;
     572             :         }       break;
     573             :         default:{
     574             :                 res = SQL_ERR;
     575             :         }
     576             :         }
     577        4520 :         if (res == SQL_ERR) {
     578           0 :                 (void) sql_error(sql, 02, SQLSTATE(M0M03) "Unknown constraint (%p)->token = %s", s, token2string(s->token));
     579             :         }
     580             :         return res;
     581             : }
     582             : 
     583             : static int
     584       51909 : column_options(sql_query *query, dlist *opt_list, sql_schema *ss, sql_table *t, sql_column *cs, bool isDeclared)
     585             : {
     586       51909 :         mvc *sql = query->sql;
     587       51909 :         int res = SQL_OK, used = 0;
     588       51909 :         assert(cs);
     589             : 
     590       51909 :         if (opt_list) {
     591       39810 :                 for (dnode *n = opt_list->h; n && res == SQL_OK; n = n->next) {
     592       22415 :                         symbol *s = n->data.sym;
     593             : 
     594       22415 :                         switch (s->token) {
     595       21027 :                                 case SQL_CONSTRAINT: {
     596       21027 :                                         dlist *l = s->data.lval;
     597       21027 :                                         char *opt_name = l->h->data.sval, *default_name = NULL;
     598       21027 :                                         symbol *sym = l->h->next->data.sym;
     599             : 
     600       21027 :                                         if (!opt_name && !(default_name = column_constraint_name(sql, sym, cs, t)))
     601             :                                                 return SQL_ERR;
     602             : 
     603       21027 :                                         res = column_constraint_type(sql, opt_name ? opt_name : default_name, sym, ss, t, cs, isDeclared, &used);
     604       21027 :                                 }       break;
     605        1388 :                                 case SQL_DEFAULT: {
     606        1388 :                                         symbol *sym = s->data.sym;
     607        1388 :                                         char *err = NULL, *r;
     608             : 
     609        1388 :                                         if ((used&(1<<COL_DEFAULT))) {
     610           1 :                                                 (void) sql_error(sql, 02, SQLSTATE(42000) "A default value for a column may be specified at most once");
     611           4 :                                                 return SQL_ERR;
     612             :                                         }
     613        1387 :                                         used |= (1<<COL_DEFAULT);
     614             : 
     615        1387 :                                         if (sym->token == SQL_COLUMN || sym->token == SQL_IDENT || sym->token == SQL_NEXT) {
     616         263 :                                                 exp_kind ek = {type_value, card_value, FALSE};
     617         263 :                                                 sql_exp *e = rel_logical_value_exp(query, NULL, sym, sql_sel, ek);
     618             : 
     619         263 :                                                 if (!e)
     620           2 :                                                         return SQL_ERR;
     621         261 :                                                 if (e && is_atom(e->type)) {
     622           0 :                                                         atom *a = exp_value(sql, e);
     623             : 
     624           0 :                                                         if (a && atom_null(a)) {
     625           0 :                                                                 switch (mvc_default(sql, cs, NULL)) {
     626           0 :                                                                         case -1:
     627           0 :                                                                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     628           0 :                                                                                 return SQL_ERR;
     629           0 :                                                                         case -2:
     630             :                                                                         case -3:
     631           0 :                                                                                 (void) sql_error(sql, 02, SQLSTATE(42000) "DEFAULT: transaction conflict detected while setting default value");
     632           0 :                                                                                 return SQL_ERR;
     633             :                                                                         default:
     634           0 :                                                                                 break;
     635             :                                                                 }
     636           0 :                                                                 break;
     637             :                                                         }
     638             :                                                 }
     639             :                                                 /* reset error */
     640         261 :                                                 sql->session->status = 0;
     641         261 :                                                 sql->errstr[0] = '\0';
     642             :                                         }
     643        1385 :                                         r = symbol2string(sql, s->data.sym, 0, &err);
     644        1385 :                                         if (!r) {
     645           1 :                                                 (void) sql_error(sql, 02, SQLSTATE(42000) "Incorrect default value '%s'", err?err:"");
     646           1 :                                                 return SQL_ERR;
     647             :                                         } else {
     648        1384 :                                                 switch (mvc_default(sql, cs, r)) {
     649           0 :                                                         case -1:
     650           0 :                                                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     651           0 :                                                                 return SQL_ERR;
     652           0 :                                                         case -2:
     653             :                                                         case -3:
     654           0 :                                                                 (void) sql_error(sql, 02, SQLSTATE(42000) "DEFAULT: transaction conflict detected while setting default value");
     655           0 :                                                                 return SQL_ERR;
     656             :                                                         default:
     657        1384 :                                                                 break;
     658             :                                                 }
     659             :                                         }
     660        1384 :                                 }       break;
     661           0 :                                 case SQL_NOT_NULL:
     662             :                                 case SQL_NULL: {
     663           0 :                                         int null = (s->token != SQL_NOT_NULL);
     664             : 
     665           0 :                                         if ((used&(1<<COL_NULL))) {
     666           0 :                                                 (void) sql_error(sql, 02, SQLSTATE(42000) "NULL constraint for a column may be specified at most once");
     667           0 :                                                 return SQL_ERR;
     668             :                                         }
     669           0 :                                         used |= (1<<COL_NULL);
     670             : 
     671           0 :                                         switch (mvc_null(sql, cs, null)) {
     672           0 :                                                 case -1:
     673           0 :                                                         (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     674           0 :                                                         return SQL_ERR;
     675           0 :                                                 case -2:
     676             :                                                 case -3:
     677           0 :                                                         (void) sql_error(sql, 02, SQLSTATE(42000) "NULL CONSTRAINT: transaction conflict detected");
     678           0 :                                                         return SQL_ERR;
     679             :                                                 default:
     680             :                                                         break;
     681             :                                         }
     682             :                                 }       break;
     683           0 :                                 default: {
     684           0 :                                         (void) sql_error(sql, 02, SQLSTATE(M0M03) "Unknown column option (%p)->token = %s", s, token2string(s->token));
     685           0 :                                         return SQL_ERR;
     686             :                                 }
     687             :                         }
     688             :                 }
     689             :         }
     690             :         return res;
     691             : }
     692             : 
     693             : static int
     694         894 : table_foreign_key(mvc *sql, const char *name, symbol *s, sql_schema *ss, sql_table *t)
     695             : {
     696         894 :         dnode *n = s->data.lval->h;
     697         894 :         char *rsname = qname_schema(n->data.lval);
     698         894 :         char *rtname = qname_schema_object(n->data.lval);
     699         894 :         const char *ns = name;
     700         894 :         sql_table *ft = NULL;
     701             : 
     702         894 :         ft = find_table_or_view_on_scope(sql, ss, rsname, rtname, "CONSTRAINT FOREIGN KEY", false);
     703             :         /* self referenced table */
     704         894 :         if (!ft && t->s == ss && strcmp(t->base.name, rtname) == 0) {
     705           9 :                 sql->errstr[0] = '\0'; /* reset table not found error */
     706           9 :                 sql->session->status = 0;
     707           9 :                 ft = t;
     708             :         }
     709           9 :         if (!ft) {
     710             :                 return SQL_ERR;
     711             :         } else {
     712         894 :                 sql_key *rk = NULL;
     713         894 :                 sql_fkey *fk;
     714         894 :                 dnode *nms = n->next->data.lval->h;
     715         894 :                 node *fnms;
     716         894 :                 int ref_actions = n->next->next->next->next->data.i_val;
     717             : 
     718         894 :                 assert(n->next->next->next->next->type == type_int);
     719         894 :                 if (!ft->s) { /* disable foreign key on declared table */
     720           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key with declared tables");
     721          26 :                         return SQL_ERR;
     722             :                 }
     723         894 :                 if (isTempSchema(t->s) != isTempSchema(ft->s)) { /* disable foreign key between temp and non temp */
     724           2 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key between temporary and non temporary tables");
     725           2 :                         return SQL_ERR;
     726             :                 }
     727         892 :                 if (isTempTable(ft) && !isGlobal(ft) && ft != t) { /* disable foreign key on local temporary table */
     728           1 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key with local temporary tables");
     729           1 :                         return SQL_ERR;
     730             :                 }
     731         891 :                 if (isUnloggedTable(t) != isUnloggedTable(ft)) { /* disable foreign key between logged and unlogged */
     732           2 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: cannot create foreign key between logged and unlogged tables");
     733           2 :                         return SQL_ERR;
     734             :                 }
     735         889 :                 if (!ns || !*ns) { /* add this to be safe */
     736           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: key name name cannot be empty");
     737           0 :                         return SQL_ERR;
     738             :                 }
     739         889 :                 while (isdigit((unsigned char) *ns))
     740           0 :                         ns++;
     741         889 :                 if (!*ns) { /* if a key name just contains digit characters, the generated index name can be mistaken with a label */
     742           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: key name cannot contain just digit characters (0 through 9)");
     743           0 :                         return SQL_ERR;
     744             :                 }
     745         889 :                 if (ol_find_name(t->keys, name) || mvc_bind_key(sql, ss, name)) {
     746           2 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: key '%s' already exists", name);
     747           2 :                         return SQL_ERR;
     748             :                 }
     749         887 :                 if (ol_find_name(t->idxs, name) || mvc_bind_idx(sql, ss, name)) {
     750           1 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: an index named '%s' already exists, and it would conflict with the key", name);
     751           1 :                         return SQL_ERR;
     752             :                 }
     753         886 :                 if (n->next->next->data.lval) {        /* find unique referenced key */
     754         849 :                         dnode *rnms = n->next->next->data.lval->h;
     755         849 :                         list *cols = sa_list(sql->sa);
     756             : 
     757        2576 :                         for (; rnms; rnms = rnms->next)
     758         878 :                                 list_append(cols, rnms->data.sval);
     759             : 
     760             :                         /* find key in ft->keys */
     761         849 :                         rk = mvc_bind_ukey(ft, cols);
     762          37 :                 } else if (ft->pkey) {
     763             :                         /* no columns specified use ft.pkey */
     764          37 :                         rk = &ft->pkey->k;
     765             :                 }
     766         886 :                 if (!rk) {
     767           5 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: could not find referenced PRIMARY KEY in table '%s'", ft->base.name);
     768           5 :                         return SQL_ERR;
     769             :                 }
     770         881 :                 switch (mvc_create_fkey(&fk, sql, t, name, fkey, rk, ref_actions & 255, (ref_actions>>8) & 255)) {
     771           0 :                         case -1:
     772           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     773           0 :                                 return SQL_ERR;
     774           0 :                         case -2:
     775             :                         case -3:
     776           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: transaction conflict detected");
     777           0 :                                 return SQL_ERR;
     778             :                         default:
     779         881 :                                 break;
     780             :                 }
     781             : 
     782        1781 :                 for (fnms = rk->columns->h; nms && fnms; nms = nms->next, fnms = fnms->next) {
     783         912 :                         char *nm = nms->data.sval;
     784         912 :                         sql_column *cs = mvc_bind_column(sql, t, nm);
     785         912 :                         sql_kc *kc = fnms->data;
     786             : 
     787         912 :                         if (!cs) {
     788           3 :                                 (void) sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "CONSTRAINT FOREIGN KEY: no such column '%s' in table '%s'", nm, t->base.name);
     789           3 :                                 return SQL_ERR;
     790             :                         }
     791         909 :                         if (!foreign_key_check_types(&cs->type, &kc->c->type)) {
     792           9 :                                 str tp1 = sql_subtype_string(sql->ta, &cs->type), tp2 = sql_subtype_string(sql->ta, &kc->c->type);
     793          18 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column '%s' %s is not compatible with the referenced %s KEY column type %s",
     794           9 :                                                                  cs->base.name, tp1, rk->type == pkey ? "PRIMARY" : "UNIQUE", tp2);
     795           9 :                                 return SQL_ERR;
     796             :                         }
     797         900 :                         switch (mvc_create_fkc(sql, fk, cs)) {
     798           0 :                                 case -1:
     799           0 :                                         (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     800           0 :                                         return SQL_ERR;
     801           0 :                                 case -2:
     802             :                                 case -3:
     803           0 :                                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: transaction conflict detected");
     804           0 :                                         return SQL_ERR;
     805             :                                 default:
     806         900 :                                         break;
     807             :                         }
     808             :                 }
     809         869 :                 if (nms || fnms) {
     810           1 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: not all columns are handled");
     811           1 :                         return SQL_ERR;
     812             :                 }
     813         868 :                 switch (mvc_create_key_done(sql, (sql_key*)fk)) {
     814           0 :                         case -1:
     815           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     816           0 :                                 return SQL_ERR;
     817           0 :                         case -2:
     818             :                         case -3:
     819           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: transaction conflict detected");
     820           0 :                                 return SQL_ERR;
     821             :                         default:
     822         868 :                                 break;
     823             :                 }
     824             :         }
     825         868 :         return SQL_OK;
     826             : }
     827             : 
     828             : static int
     829        2212 : table_constraint_type(mvc *sql, const char *name, symbol *s, sql_schema *ss, sql_table *t)
     830             : {
     831        2212 :         int res = SQL_OK;
     832             : 
     833        2212 :         switch (s->token) {
     834        1318 :         case SQL_UNIQUE:
     835             :         case SQL_PRIMARY_KEY: {
     836        1318 :                 key_type kt = (s->token == SQL_PRIMARY_KEY ? pkey : ukey);
     837        1318 :                 dnode *nms = s->data.lval->h;
     838        1318 :                 sql_key *k;
     839        1318 :                 const char *ns = name;
     840             : 
     841        1318 :                 if (kt == pkey && t->pkey) {
     842           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT PRIMARY KEY: a table can have only one PRIMARY KEY");
     843           9 :                         return SQL_ERR;
     844             :                 }
     845        1318 :                 if (!ns || !*ns) { /* add this to be safe */
     846           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: key name name cannot be empty", kt == pkey ? "PRIMARY KEY" : "UNIQUE");
     847           0 :                         return SQL_ERR;
     848             :                 }
     849        1318 :                 while (isdigit((unsigned char) *ns))
     850           0 :                         ns++;
     851        1318 :                 if (!*ns) { /* if a key name just contains digit characters, the generated index name can be mistaken with a label */
     852           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: key name cannot contain just digit characters (0 through 9)", kt == pkey ? "PRIMARY KEY" : "UNIQUE");
     853           0 :                         return SQL_ERR;
     854             :                 }
     855        1318 :                 if (ol_find_name(t->keys, name) || mvc_bind_key(sql, ss, name)) {
     856           3 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: key '%s' already exists", kt == pkey ? "PRIMARY KEY" : "UNIQUE", name);
     857           3 :                         return SQL_ERR;
     858             :                 }
     859        1315 :                 if (ol_find_name(t->idxs, name) || mvc_bind_idx(sql, ss, name)) {
     860           0 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: an index named '%s' already exists, and it would conflict with the key", kt == pkey ? "PRIMARY KEY" : "UNIQUE", name);
     861           0 :                         return SQL_ERR;
     862             :                 }
     863             : 
     864        1315 :                 switch (mvc_create_ukey(&k, sql, t, name, kt)) {
     865           0 :                         case -1:
     866           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     867           0 :                                 return SQL_ERR;
     868           0 :                         case -2:
     869             :                         case -3:
     870           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: transaction conflict detected", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     871           0 :                                 return SQL_ERR;
     872             :                         default:
     873             :                                 break;
     874             :                 }
     875        3218 :                 for (; nms; nms = nms->next) {
     876        1909 :                         char *nm = nms->data.sval;
     877        1909 :                         sql_column *c = mvc_bind_column(sql, t, nm);
     878             : 
     879        1909 :                         if (!c) {
     880           6 :                                 (void) sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "CONSTRAINT %s: no such column '%s' for table '%s'",
     881             :                                                 kt == pkey ? "PRIMARY KEY" : "UNIQUE",
     882             :                                                 nm, t->base.name);
     883           6 :                                 return SQL_ERR;
     884             :                         }
     885        1903 :                         switch (mvc_create_kc(sql, k, c)) {
     886           0 :                                 case -1:
     887           0 :                                         (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     888           0 :                                         return SQL_ERR;
     889           0 :                                 case -2:
     890             :                                 case -3:
     891           0 :                                         (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: transaction conflict detected", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     892           0 :                                         return SQL_ERR;
     893             :                                 default:
     894        1903 :                                         break;
     895             :                         }
     896             :                 }
     897        1309 :                 switch (mvc_create_key_done(sql, k)) {
     898           0 :                         case -1:
     899           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     900           0 :                                 return SQL_ERR;
     901           0 :                         case -2:
     902             :                         case -3:
     903           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT %s: transaction conflict detected", (kt == pkey) ? "PRIMARY KEY" : "UNIQUE");
     904           0 :                                 return SQL_ERR;
     905             :                         default:
     906        1309 :                                 break;
     907             :                 }
     908        1309 :         }       break;
     909         894 :         case SQL_FOREIGN_KEY:
     910         894 :                 res = table_foreign_key(sql, name, s, ss, t);
     911         894 :                 break;
     912           0 :         case SQL_CHECK: {
     913           0 :                 (void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT CHECK: check constraints not supported");
     914           0 :                 return SQL_ERR;
     915             :         }       break;
     916             :         default:
     917             :                 res = SQL_ERR;
     918             :         }
     919        2203 :         if (res != SQL_OK) {
     920          26 :                 (void) sql_error(sql, 02, SQLSTATE(M0M03) "Table constraint type: wrong token (%p) = %s", s, token2string(s->token));
     921          26 :                 return SQL_ERR;
     922             :         }
     923             :         return res;
     924             : }
     925             : 
     926             : static int
     927        2212 : table_constraint(mvc *sql, symbol *s, sql_schema *ss, sql_table *t)
     928             : {
     929        2212 :         int res = SQL_OK;
     930             : 
     931        2212 :         if (s->token == SQL_CONSTRAINT) {
     932        2212 :                 dlist *l = s->data.lval;
     933        2212 :                 char *opt_name = l->h->data.sval;
     934        2212 :                 symbol *sym = l->h->next->data.sym;
     935             : 
     936        2212 :                 if (!opt_name)
     937         885 :                         opt_name = table_constraint_name(sql, sym, t);
     938         885 :                 if (opt_name == NULL)
     939             :                         return SQL_ERR;
     940        2212 :                 res = table_constraint_type(sql, opt_name, sym, ss, t);
     941             :         }
     942             : 
     943        2212 :         if (res != SQL_OK) {
     944          35 :                 (void) sql_error(sql, 02, SQLSTATE(M0M03) "Table constraint: wrong token (%p) = %s", s, token2string(s->token));
     945          35 :                 return SQL_ERR;
     946             :         }
     947             :         return res;
     948             : }
     949             : 
     950             : static int
     951       51911 : create_column(sql_query *query, symbol *s, sql_schema *ss, sql_table *t, int alter, bool isDeclared)
     952             : {
     953       51911 :         mvc *sql = query->sql;
     954       51911 :         dlist *l = s->data.lval;
     955       51911 :         char *cname = l->h->data.sval;
     956       51911 :         sql_subtype *ctype = &l->h->next->data.typeval;
     957       51911 :         dlist *opt_list = NULL;
     958       51911 :         int res = SQL_OK;
     959             : 
     960       51911 :         (void) ss;
     961       51911 :         if (alter && !(isTable(t) || ((isMergeTable(t) || isReplicaTable(t)) && list_length(t->members)==0))) {
     962           0 :                 (void) sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot add column to %s '%s'%s",
     963           0 :                                   TABLE_TYPE_DESCRIPTION(t->type, t->properties),
     964           0 :                                   t->base.name, ((isMergeTable(t) || isReplicaTable(t)) && list_length(t->members)) ? " while it has partitions" : "");
     965           0 :                 return SQL_ERR;
     966             :         }
     967       51911 :         if (l->h->next->next)
     968       51911 :                 opt_list = l->h->next->next->data.lval;
     969             : 
     970       51911 :         if (cname && ctype) {
     971       51911 :                 sql_column *cs = NULL;
     972             : 
     973       51911 :                 if (!isView(t) && cname && cname[0] == '%') {
     974           0 :                         (void) sql_error(sql, 01, SQLSTATE(42000) "%s TABLE: generated labels not allowed in column names, use an alias instead", (alter)?"ALTER":"CREATE");
     975          14 :                         return SQL_ERR;
     976       51911 :                 } else if (ctype->type->eclass == EC_ANY) {
     977           0 :                         (void) sql_error(sql, 01, SQLSTATE(42000) "%s TABLE: any type (plain null value) not allowed as a column type, use an explicit cast", (alter)?"ALTER":"CREATE");
     978           0 :                         return SQL_ERR;
     979       51911 :                 } else if ((cs = find_sql_column(t, cname))) {
     980           2 :                         (void) sql_error(sql, 02, SQLSTATE(42S21) "%s TABLE: a column named '%s' already exists", (alter)?"ALTER":"CREATE", cname);
     981           2 :                         return SQL_ERR;
     982             :                 }
     983       51909 :                 switch (mvc_create_column(&cs, sql, t, cname, ctype)) {
     984           0 :                         case -1:
     985           0 :                                 (void) sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     986           0 :                                 return SQL_ERR;
     987           0 :                         case -2:
     988             :                         case -3:
     989           0 :                                 (void) sql_error(sql, 01, SQLSTATE(42000) "%s TABLE: transaction conflict detected", (alter)?"ALTER":"CREATE");
     990           0 :                                 return SQL_ERR;
     991             :                         default:
     992       51909 :                                 break;
     993             :                 }
     994       51909 :                 if (column_options(query, opt_list, ss, t, cs, isDeclared) == SQL_ERR)
     995             :                         return SQL_ERR;
     996             :         }
     997             :         return res;
     998             : }
     999             : 
    1000             : static int
    1001       54513 : table_element(sql_query *query, symbol *s, sql_schema *ss, sql_table *t, int alter, bool isDeclared, const char *action)
    1002             : {
    1003       54513 :         mvc *sql = query->sql;
    1004       54513 :         int res = SQL_OK;
    1005             : 
    1006       54513 :         if (alter &&
    1007        1233 :                 (isView(t) ||
    1008        1225 :                 ((isMergeTable(t) || isReplicaTable(t)) && (s->token != SQL_TABLE && s->token != SQL_DROP_TABLE && list_length(t->members))) ||
    1009        2440 :                 (isTable(t) && (s->token == SQL_TABLE || s->token == SQL_DROP_TABLE)) ||
    1010        1220 :                 (partition_find_part(sql->session->tr, t, NULL) &&
    1011           5 :                          (s->token == SQL_DROP_COLUMN || s->token == SQL_COLUMN || s->token == SQL_CONSTRAINT ||
    1012             :                           s->token == SQL_DEFAULT || s->token == SQL_DROP_DEFAULT || s->token == SQL_NOT_NULL || s->token == SQL_NULL || s->token == SQL_DROP_CONSTRAINT)))){
    1013          18 :                 char *msg = "";
    1014             : 
    1015          18 :                 switch (s->token) {
    1016             :                 case SQL_TABLE:
    1017             :                         msg = "add table to";
    1018             :                         break;
    1019           3 :                 case SQL_COLUMN:
    1020           3 :                         msg = "add column to";
    1021           3 :                         break;
    1022           4 :                 case SQL_CONSTRAINT:
    1023           4 :                         msg = "add constraint to";
    1024           4 :                         break;
    1025           4 :                 case SQL_COLUMN_OPTIONS:
    1026             :                 case SQL_DEFAULT:
    1027             :                 case SQL_NOT_NULL:
    1028             :                 case SQL_NULL:
    1029           4 :                         msg = "set column options for";
    1030           4 :                         break;
    1031           0 :                 case SQL_STORAGE:
    1032           0 :                         msg = "set column storage for";
    1033           0 :                         break;
    1034           0 :                 case SQL_DROP_DEFAULT:
    1035           0 :                         msg = "drop default column option from";
    1036           0 :                         break;
    1037           0 :                 case SQL_DROP_TABLE:
    1038           0 :                         msg = "drop table from";
    1039           0 :                         break;
    1040           5 :                 case SQL_DROP_COLUMN:
    1041           5 :                         msg = "drop column from";
    1042           5 :                         break;
    1043           2 :                 case SQL_DROP_CONSTRAINT:
    1044           2 :                         msg = "drop constraint from";
    1045           2 :                         break;
    1046           0 :                 default:
    1047           0 :                         sql_error(sql, 02, SQLSTATE(M0M03) "%s: Unknown table element (%p)->token = %s\n", action, s, token2string(s->token));
    1048           0 :                         return SQL_ERR;
    1049             :                 }
    1050          18 :                 sql_error(sql, 02, SQLSTATE(42000) "%s: cannot %s %s '%s'%s\n",
    1051             :                                 action,
    1052             :                                 msg,
    1053          18 :                                 partition_find_part(sql->session->tr, t, NULL)?"a PARTITION of a MERGE or REPLICA TABLE":
    1054          13 :                                 TABLE_TYPE_DESCRIPTION(t->type, t->properties),
    1055          18 :                                 t->base.name, ((isMergeTable(t) || isReplicaTable(t)) && list_length(t->members)) ? " while it has partitions" : "");
    1056          18 :                 return SQL_ERR;
    1057             :         }
    1058             : 
    1059       54495 :         switch (s->token) {
    1060       51911 :         case SQL_COLUMN:
    1061       51911 :                 res = create_column(query, s, ss, t, alter, isDeclared);
    1062       51911 :                 break;
    1063        2212 :         case SQL_CONSTRAINT:
    1064        2212 :                 res = table_constraint(sql, s, ss, t);
    1065        2212 :                 break;
    1066           0 :         case SQL_COLUMN_OPTIONS:
    1067             :         {
    1068           0 :                 dnode *n = s->data.lval->h;
    1069           0 :                 char *cname = n->data.sval;
    1070           0 :                 sql_column *c = mvc_bind_column(sql, t, cname);
    1071           0 :                 dlist *olist = n->next->data.lval;
    1072             : 
    1073           0 :                 if (!c) {
    1074           0 :                         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "%s: no such column '%s'\n", action, cname);
    1075           0 :                         return SQL_ERR;
    1076             :                 } else {
    1077           0 :                         return column_options(query, olist, ss, t, c, isDeclared);
    1078             :                 }
    1079          19 :         }       break;
    1080          19 :         case SQL_DEFAULT:
    1081             :         {
    1082          19 :                 char *r, *err = NULL;
    1083          19 :                 dlist *l = s->data.lval;
    1084          19 :                 char *cname = l->h->data.sval;
    1085          19 :                 symbol *sym = l->h->next->data.sym;
    1086          19 :                 sql_column *c = mvc_bind_column(sql, t, cname);
    1087             : 
    1088          19 :                 if (!c) {
    1089           3 :                         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "%s: no such column '%s'\n", action, cname);
    1090           5 :                         return SQL_ERR;
    1091             :                 }
    1092          16 :                 if (sym->token == SQL_COLUMN || sym->token == SQL_IDENT || sym->token == SQL_NEXT) {
    1093           5 :                                 exp_kind ek = {type_value, card_value, FALSE};
    1094           5 :                                 sql_exp *e = rel_logical_value_exp(query, NULL, sym, sql_sel, ek);
    1095             : 
    1096           5 :                                 if (!e)
    1097           1 :                                         return SQL_ERR;
    1098           4 :                                 if (e && is_atom(e->type)) {
    1099           0 :                                         atom *a = exp_value(sql, e);
    1100             : 
    1101           0 :                                         if (a && atom_null(a)) {
    1102           0 :                                                 switch (mvc_default(sql, c, NULL)) {
    1103           0 :                                                 case -1:
    1104           0 :                                                         (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1105           0 :                                                         return SQL_ERR;
    1106           0 :                                                 case -2:
    1107             :                                                 case -3:
    1108           0 :                                                         (void) sql_error(sql, 02, SQLSTATE(42000) "DEFAULT: transaction conflict detected while setting default value");
    1109           0 :                                                         return SQL_ERR;
    1110             :                                                 default:
    1111           0 :                                                         break;
    1112             :                                         }
    1113           0 :                                         break;
    1114             :                                 }
    1115             :                         }
    1116             :                         /* reset error */
    1117           4 :                         sql->session->status = 0;
    1118           4 :                         sql->errstr[0] = '\0';
    1119             :                 }
    1120          15 :                 r = symbol2string(sql, sym, 0, &err);
    1121          15 :                 if (!r) {
    1122           1 :                         (void) sql_error(sql, 02, SQLSTATE(42000) "%s: incorrect default value '%s'\n", action, err?err:"");
    1123           1 :                         return SQL_ERR;
    1124             :                 }
    1125          14 :                 switch (mvc_default(sql, c, r)) {
    1126           0 :                         case -1:
    1127           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1128           0 :                                 return SQL_ERR;
    1129           0 :                         case -2:
    1130             :                         case -3:
    1131           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "DEFAULT: transaction conflict detected while setting default value");
    1132           0 :                                 return SQL_ERR;
    1133             :                         default:
    1134          14 :                                 break;
    1135             :                 }
    1136             :         }
    1137          14 :         break;
    1138           0 :         case SQL_STORAGE:
    1139             :         {
    1140           0 :                 dlist *l = s->data.lval;
    1141           0 :                 char *cname = l->h->data.sval;
    1142           0 :                 char *storage_type = l->h->next->data.sval;
    1143           0 :                 sql_column *c = mvc_bind_column(sql, t, cname);
    1144             : 
    1145           0 :                 if (!c) {
    1146           0 :                         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "%s: no such column '%s'\n", action, cname);
    1147           0 :                         return SQL_ERR;
    1148             :                 }
    1149           0 :                 switch (mvc_storage(sql, c, storage_type)) {
    1150           0 :                         case -1:
    1151           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1152           0 :                                 return SQL_ERR;
    1153           0 :                         case -2:
    1154             :                         case -3:
    1155           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "STORAGE: transaction conflict detected");
    1156           0 :                                 return SQL_ERR;
    1157             :                         default:
    1158             :                                 break;
    1159             :                 }
    1160             :         }
    1161             :         break;
    1162          45 :         case SQL_NOT_NULL:
    1163             :         case SQL_NULL:
    1164             :         {
    1165          45 :                 dnode *n = s->data.lval->h;
    1166          45 :                 char *cname = n->data.sval;
    1167          45 :                 sql_column *c = mvc_bind_column(sql, t, cname);
    1168          45 :                 int null = (s->token != SQL_NOT_NULL);
    1169             : 
    1170          45 :                 if (!c) {
    1171           4 :                         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "%s: no such column '%s'\n", action, cname);
    1172           4 :                         return SQL_ERR;
    1173             :                 }
    1174          41 :                 switch (mvc_null(sql, c, null)) {
    1175           0 :                         case -1:
    1176           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1177           0 :                                 return SQL_ERR;
    1178           0 :                         case -2:
    1179             :                         case -3:
    1180           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "NULL CONSTRAINT: transaction conflict detected");
    1181           0 :                                 return SQL_ERR;
    1182             :                         default:
    1183             :                                 break;
    1184             :                 }
    1185             :         }       break;
    1186           7 :         case SQL_DROP_DEFAULT:
    1187             :         {
    1188           7 :                 char *cname = s->data.sval;
    1189           7 :                 sql_column *c = mvc_bind_column(sql, t, cname);
    1190           7 :                 if (!c) {
    1191           2 :                         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "%s: no such column '%s'\n", action, cname);
    1192           2 :                         return SQL_ERR;
    1193             :                 }
    1194           5 :                 switch (mvc_drop_default(sql, c)) {
    1195           0 :                         case -1:
    1196           0 :                                 (void) sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1197           0 :                                 return SQL_ERR;
    1198           0 :                         case -2:
    1199             :                         case -3:
    1200           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "DEFAULT: transaction conflict detected while setting default value");
    1201           0 :                                 return SQL_ERR;
    1202             :                         default:
    1203             :                                 break;
    1204             :                 }
    1205             :         }       break;
    1206          69 :         case SQL_LIKE:
    1207             :         {
    1208          69 :                 char *sname = qname_schema(s->data.lval);
    1209          69 :                 char *name = qname_schema_object(s->data.lval);
    1210          69 :                 sql_table *ot = NULL;
    1211             : 
    1212          69 :                 if (!(ot = find_table_or_view_on_scope(sql, ss, sname, name, action, false)))
    1213             :                         return SQL_ERR;
    1214         143 :                 for (node *n = ol_first_node(ot->columns); n; n = n->next) {
    1215          76 :                         sql_column *oc = n->data, *nc = NULL;
    1216             : 
    1217          76 :                         if (!isView(t) && oc->base.name && oc->base.name[0] == '%') {
    1218           0 :                                 sql_error(sql, 02, SQLSTATE(42000) "%s: generated labels not allowed in column names, use an alias instead", action);
    1219           2 :                                 return SQL_ERR;
    1220          76 :                         } else if (mvc_bind_column(sql, t, oc->base.name)) {
    1221           2 :                                 sql_error(sql, 02, SQLSTATE(42S21) "%s: a column named '%s' already exists\n", action, oc->base.name);
    1222           2 :                                 return SQL_ERR;
    1223             :                         }
    1224          74 :                         assert(oc->type.type->eclass != EC_ANY);
    1225          74 :                         switch (mvc_create_column(&nc, sql, t, oc->base.name, &oc->type)) {
    1226           0 :                                 case -1:
    1227           0 :                                         sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1228           0 :                                         return SQL_ERR;
    1229           0 :                                 case -2:
    1230             :                                 case -3:
    1231           0 :                                         sql_error(sql, 01, SQLSTATE(42000) "%s: transaction conflict detected", action);
    1232           0 :                                         return SQL_ERR;
    1233             :                                 default:
    1234          74 :                                         break;
    1235             :                         }
    1236             :                 }
    1237             :         }       break;
    1238          86 :         case SQL_DROP_COLUMN:
    1239             :         {
    1240          86 :                 dlist *l = s->data.lval;
    1241          86 :                 char *cname = l->h->data.sval;
    1242          86 :                 int drop_action = l->h->next->data.i_val;
    1243          86 :                 sql_column *col = mvc_bind_column(sql, t, cname);
    1244             : 
    1245          86 :                 assert(l->h->next->type == type_int);
    1246          86 :                 if (col == NULL) {
    1247           9 :                         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "%s: no such column '%s'\n", action, cname);
    1248           9 :                         return SQL_ERR;
    1249             :                 }
    1250          77 :                 if (ol_length(t->columns) <= 1) {
    1251           2 :                         sql_error(sql, 02, SQLSTATE(42000) "%s: cannot drop column '%s': table needs at least one column\n", action, cname);
    1252           2 :                         return SQL_ERR;
    1253             :                 }
    1254          75 :                 if (t->system) {
    1255           0 :                         sql_error(sql, 02, SQLSTATE(42000) "%s: cannot drop column '%s': table is a system table\n", action, cname);
    1256           0 :                         return SQL_ERR;
    1257             :                 }
    1258          75 :                 if (isView(t)) {
    1259           0 :                         sql_error(sql, 02, SQLSTATE(42000) "%s: cannot drop column '%s': '%s' is a view\n", action, cname, t->base.name);
    1260           0 :                         return SQL_ERR;
    1261             :                 }
    1262          75 :                 if (!drop_action && mvc_check_dependency(sql, col->base.id, COLUMN_DEPENDENCY, NULL)) {
    1263           3 :                         sql_error(sql, 02, SQLSTATE(2BM37) "%s: cannot drop column '%s': there are database objects which depend on it\n", action, cname);
    1264           3 :                         return SQL_ERR;
    1265             :                 }
    1266          64 :                 if (!drop_action  && t->keys) {
    1267          64 :                         node *n, *m;
    1268             : 
    1269          64 :                         for (n = ol_first_node(t->keys); n; n = n->next) {
    1270           0 :                                 sql_key *k = n->data;
    1271           0 :                                 for (m = k->columns->h; m; m = m->next) {
    1272           0 :                                         sql_kc *kc = m->data;
    1273           0 :                                         if (strcmp(kc->c->base.name, cname) == 0) {
    1274           0 :                                                 sql_error(sql, 02, SQLSTATE(2BM37) "%s: cannot drop column '%s': there are constraints which depend on it\n", action, cname);
    1275           0 :                                                 return SQL_ERR;
    1276             :                                         }
    1277             :                                 }
    1278             :                         }
    1279             :                 }
    1280          72 :                 if (isPartitionedByColumnTable(t) && t->part.pcol->base.id == col->base.id) {
    1281           2 :                         sql_error(sql, 02, SQLSTATE(42000) "%s: cannot drop column '%s': is the partitioned column on the table '%s'\n", action, cname, t->base.name);
    1282           2 :                         return SQL_ERR;
    1283             :                 }
    1284          70 :                 if (isPartitionedByExpressionTable(t)) {
    1285           8 :                         for (node *n = t->part.pexp->cols->h; n; n = n->next) {
    1286           6 :                                 int next = *(int*) n->data;
    1287           6 :                                 if (next == col->colnr) {
    1288           2 :                                         sql_error(sql, 02, SQLSTATE(42000) "%s: cannot drop column '%s': the expression used in '%s' depends on it\n", action, cname, t->base.name);
    1289           2 :                                         return SQL_ERR;
    1290             :                                 }
    1291             :                         }
    1292             :                 }
    1293          68 :                 switch (mvc_drop_column(sql, t, col, drop_action)) {
    1294           0 :                         case -1:
    1295           0 :                                 sql_error(sql, 02, SQLSTATE(42000) "%s: %s\n", action, MAL_MALLOC_FAIL);
    1296           0 :                                 return SQL_ERR;
    1297           0 :                         case -2:
    1298             :                         case -3:
    1299           0 :                                 sql_error(sql, 02, SQLSTATE(42000) "%s: transaction conflict detected\n", action);
    1300           0 :                                 return SQL_ERR;
    1301             :                         default:
    1302             :                                 break;
    1303             :                 }
    1304             :         }       break;
    1305             :         case SQL_DROP_CONSTRAINT:
    1306             :                 res = SQL_OK;
    1307             :                 break;
    1308             :         default:
    1309             :                 res = SQL_ERR;
    1310             :         }
    1311       54204 :         if (res == SQL_ERR) {
    1312          49 :                 sql_error(sql, 02, SQLSTATE(M0M03) "%s: Unknown table element (%p)->token = %s\n", action, s, token2string(s->token));
    1313          49 :                 return SQL_ERR;
    1314             :         }
    1315             :         return res;
    1316             : }
    1317             : 
    1318             : static int
    1319        9619 : create_partition_definition(mvc *sql, sql_table *t, symbol *partition_def)
    1320             : {
    1321        9619 :         char *err = NULL;
    1322             : 
    1323        9619 :         if (partition_def) {
    1324          99 :                 dlist *list = partition_def->data.lval;
    1325          99 :                 symbol *type = list->h->next->data.sym;
    1326          99 :                 dlist *list2 = type->data.lval;
    1327          99 :                 if (isPartitionedByColumnTable(t)) {
    1328          76 :                         str colname = list2->h->data.sval;
    1329          76 :                         node *n;
    1330          76 :                         sql_class sql_ec;
    1331          92 :                         for (n = ol_first_node(t->columns); n ; n = n->next) {
    1332          90 :                                 sql_column *col = n->data;
    1333          90 :                                 if (!strcmp(col->base.name, colname)) {
    1334          74 :                                         t->part.pcol = col;
    1335          74 :                                         break;
    1336             :                                 }
    1337             :                         }
    1338          76 :                         if (!t->part.pcol) {
    1339           2 :                                 sql_error(sql, 02, SQLSTATE(42000) "CREATE MERGE TABLE: the partition column '%s' is not part of the table", colname);
    1340           2 :                                 return SQL_ERR;
    1341             :                         }
    1342          74 :                         sql_ec = t->part.pcol->type.type->eclass;
    1343          74 :                         if (!(sql_ec == EC_BIT || EC_VARCHAR(sql_ec) || EC_TEMP(sql_ec) || sql_ec == EC_POS || sql_ec == EC_NUM ||
    1344           2 :                                  EC_INTERVAL(sql_ec)|| sql_ec == EC_DEC || sql_ec == EC_BLOB)) {
    1345           2 :                                 err = sql_subtype_string(sql->ta, &(t->part.pcol->type));
    1346           2 :                                 sql_error(sql, 02, SQLSTATE(42000) "CREATE MERGE TABLE: column type %s not yet supported for the partition column", err);
    1347           2 :                                 return SQL_ERR;
    1348             :                         }
    1349          23 :                 } else if (isPartitionedByExpressionTable(t)) {
    1350          23 :                         char *query = symbol2string(sql, list2->h->data.sym, 1, &err);
    1351          23 :                         if (!query) {
    1352           1 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "CREATE MERGE TABLE: error compiling expression '%s'", err?err:"");
    1353           1 :                                 return SQL_ERR;
    1354             :                         }
    1355          22 :                         t->part.pexp = SA_ZNEW(sql->sa, sql_expression);
    1356          22 :                         t->part.pexp->exp = query;
    1357          22 :                         t->part.pexp->type = *sql_bind_localtype("void");
    1358             :                 }
    1359             :         }
    1360             :         return SQL_OK;
    1361             : }
    1362             : 
    1363             : sql_rel *
    1364        9772 : rel_create_table(sql_query *query, int temp, const char *sname, const char *name, bool global, symbol *table_elements_or_subquery,
    1365             :                                  int commit_action, const char *loc, const char *username, const char *password, bool pw_encrypted,
    1366             :                                  symbol* partition_def, int if_not_exists)
    1367             : {
    1368        9772 :         mvc *sql = query->sql;
    1369        9772 :         int tt = (temp == SQL_REMOTE)?tt_remote:
    1370             :                  (temp == SQL_MERGE_TABLE)?tt_merge_table:
    1371             :                  (temp == SQL_REPLICA_TABLE)?tt_replica_table:
    1372             :                  (temp == SQL_UNLOGGED_TABLE)?tt_unlogged_table:tt_table;
    1373        9772 :         bit properties = partition_def ? (bit) partition_def->data.lval->h->next->next->data.i_val : 0;
    1374        9772 :         sql_table *t = NULL;
    1375        9772 :         const char *action = (temp == SQL_DECLARED_TABLE)?"DECLARE":"CREATE";
    1376        9772 :         sql_schema *s = cur_schema(sql);
    1377             : 
    1378        9772 :         if (sname && !(s = mvc_bind_schema(sql, sname)))
    1379           1 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s TABLE: no such schema '%s'", action, sname);
    1380             : 
    1381        9771 :         if ((temp != SQL_PERSIST && tt == tt_table && commit_action == CA_COMMIT) || temp == SQL_DECLARE)
    1382         180 :                 commit_action = CA_DELETE;
    1383             : 
    1384        9771 :         if (temp == SQL_LOCAL_TEMP || temp == SQL_GLOBAL_TEMP) {
    1385         111 :                 if (sname && strcmp(sname, "tmp") != 0)
    1386           7 :                         return sql_error(sql, 02, SQLSTATE(3F000) "%s TABLE: %s temporary tables should be stored in the 'tmp' schema",
    1387             :                                                          action, (temp == SQL_LOCAL_TEMP) ? "local" : "global");
    1388         106 :                 s = tmp_schema(sql);
    1389             :         }
    1390             : 
    1391        9766 :         if (global && mvc_bind_table(sql, s, name)) {
    1392           8 :                 if (if_not_exists)
    1393           2 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1394           6 :                 return sql_error(sql, 02, SQLSTATE(42S01) "%s TABLE: name '%s' already in use", action, name);
    1395         107 :         } else if (!global && frame_find_table(sql, name)) {
    1396           1 :                 assert(temp == SQL_DECLARED_TABLE);
    1397           1 :                 if (if_not_exists)
    1398           0 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1399           1 :                 return sql_error(sql, 02, SQLSTATE(42S01) "%s TABLE: name '%s' already declared", action, name);
    1400        9757 :         } else if (temp != SQL_DECLARED_TABLE && (!mvc_schema_privs(sql, s) && !(isTempSchema(s) && temp == SQL_LOCAL_TEMP))){
    1401           4 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE TABLE: insufficient privileges for user '%s' in schema '%s'", get_string_global_var(sql, "current_user"), s->base.name);
    1402        9753 :         } else if ((temp == SQL_PERSIST || temp == SQL_MERGE_TABLE || temp == SQL_REMOTE || temp == SQL_REPLICA_TABLE || temp == SQL_UNLOGGED_TABLE) && isTempSchema(s)) {
    1403           7 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: cannot create persistent table '%s' in the schema '%s'", TABLE_TYPE_DESCRIPTION(tt, properties), name, s->base.name);
    1404        9747 :         } else if (table_elements_or_subquery->token == SQL_CREATE_TABLE) {
    1405             :                 /* table element list */
    1406        9643 :                 dnode *n;
    1407        9643 :                 dlist *columns = table_elements_or_subquery->data.lval;
    1408        9643 :                 int res = LOG_OK;
    1409             : 
    1410        9643 :                 if (tt == tt_remote) {
    1411          94 :                         if (!mapiuri_valid(loc))
    1412           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s TABLE: incorrect uri '%s' for remote table '%s'", action, loc, name);
    1413          94 :                         res = mvc_create_remote(&t, sql, s, name, SQL_DECLARED_TABLE, loc);
    1414             :                 } else {
    1415        9549 :                         res = mvc_create_table(&t, sql, s, name, tt, 0, SQL_DECLARED_TABLE, commit_action, -1, properties);
    1416             :                 }
    1417        9643 :                 switch (res) {
    1418           0 :                         case -1:
    1419           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1420           0 :                         case -2:
    1421             :                         case -3:
    1422           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s TABLE: transaction conflict detected", action);
    1423           0 :                         case -4:
    1424           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s TABLE: the partition's expression is too long", action);
    1425             :                         case -5:
    1426             :                                 return NULL;
    1427             :                         default:
    1428        9643 :                                 break;
    1429             :                 }
    1430             : 
    1431       62899 :                 for (n = columns->h; n; n = n->next) {
    1432       53280 :                         symbol *sym = n->data.sym;
    1433      106364 :                         int res = table_element(query, sym, s, t, 0, (temp == SQL_DECLARED_TABLE), (temp == SQL_DECLARED_TABLE)?"DECLARE TABLE":"CREATE TABLE");
    1434             : 
    1435       53280 :                         if (res == SQL_ERR)
    1436             :                                 return NULL;
    1437             :                 }
    1438             : 
    1439        9619 :                 if (create_partition_definition(sql, t, partition_def) != SQL_OK)
    1440             :                         return NULL;
    1441             : 
    1442        9614 :                 temp = (tt == tt_table)?temp:SQL_PERSIST;
    1443             : 
    1444         374 :                 if (tt == tt_remote)
    1445          94 :                         return rel_create_remote(sql, ddl_create_table, s->base.name, t, pw_encrypted, username, password);
    1446        9520 :                 return rel_table(sql, ddl_create_table, s->base.name, t, temp);
    1447             :         } else { /* [col name list] as subquery with or without data */
    1448         104 :                 sql_rel *sq = NULL, *res = NULL;
    1449         104 :                 dlist *as_sq = table_elements_or_subquery->data.lval;
    1450         104 :                 dlist *column_spec = as_sq->h->data.lval;
    1451         104 :                 symbol *subquery = as_sq->h->next->data.sym;
    1452         104 :                 int with_data = as_sq->h->next->next->data.i_val;
    1453             : 
    1454         104 :                 assert(as_sq->h->next->next->type == type_int);
    1455         104 :                 sq = rel_selects(query, subquery);
    1456         104 :                 if (!sq)
    1457             :                         return NULL;
    1458         101 :                 if (!is_project(sq->op)) /* make sure sq is a projection */
    1459           6 :                         sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 1));
    1460             : 
    1461         101 :                 if ((tt != tt_table && tt != tt_unlogged_table) && with_data)
    1462           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s TABLE: cannot create %s 'with data'", action,
    1463           1 :                                                          TABLE_TYPE_DESCRIPTION(tt, properties));
    1464             : 
    1465             :                 /* create table */
    1466         197 :                 if ((t = mvc_create_table_as_subquery(sql, sq, s, name, column_spec, temp, commit_action, (temp == SQL_DECLARED_TABLE)?"DECLARE TABLE":"CREATE TABLE")) == NULL) {
    1467           3 :                         rel_destroy(sq);
    1468           3 :                         return NULL;
    1469             :                 }
    1470             : 
    1471             :                 /* insert query result into this table */
    1472          97 :                 temp = (tt == tt_table)?temp:SQL_PERSIST;
    1473          97 :                 res = rel_table(sql, ddl_create_table, s->base.name, t, temp);
    1474          97 :                 if (with_data) {
    1475          90 :                         res = rel_insert(query->sql, res, sq);
    1476             :                 } else {
    1477           7 :                         rel_destroy(sq);
    1478             :                 }
    1479          97 :                 return res;
    1480             :         }
    1481             :         /*return NULL;*/ /* never reached as all branches of the above if () end with return ... */
    1482             : }
    1483             : 
    1484             : static sql_rel *
    1485       77553 : rel_create_view(sql_query *query, dlist *qname, dlist *column_spec, symbol *ast, int check, int persistent, int replace)
    1486             : {
    1487       77553 :         mvc *sql = query->sql;
    1488       77553 :         const char *name = qname_schema_object(qname);
    1489       77553 :         const char *sname = qname_schema(qname);
    1490       77553 :         sql_schema *s = cur_schema(sql);
    1491       77553 :         sql_table *t = NULL;
    1492       77553 :         int instantiate = (sql->emode == m_instantiate || !persistent);
    1493       77553 :         int deps = (sql->emode == m_deps);
    1494       77553 :         int create = (!instantiate && !deps);
    1495       77553 :         sqlid pfoundid = 0, foundid = 0;
    1496       77553 :         const char *base = replace ? "CREATE OR REPLACE VIEW" : "CREATE VIEW";
    1497             : 
    1498       77553 :         (void) check;           /* Stefan: unused!? */
    1499             : 
    1500       77553 :         if (sname && !(s = mvc_bind_schema(sql, sname)))
    1501           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s: no such schema '%s'", base, sname);
    1502       77553 :         if (create && (!mvc_schema_privs(sql, s) && !(isTempSchema(s) && persistent == SQL_LOCAL_TEMP)))
    1503           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: access denied for %s to schema '%s'", base, get_string_global_var(sql, "current_user"), s->base.name);
    1504       22195 :         if (create && (t = mvc_bind_table(sql, s, name))) {
    1505          21 :                 if (!replace)
    1506           1 :                         return sql_error(sql, 02, SQLSTATE(42S01) "%s: name '%s' already in use", base, name);
    1507          20 :                 if (!isView(t))
    1508           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: '%s' is not a view", base, name);
    1509          20 :                 if (t->system)
    1510           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot replace system view '%s'", base, name);
    1511          20 :                 foundid = t->base.id; /* when recreating a view, the view itself can't be found */
    1512             :         }
    1513             : 
    1514       77552 :         if (ast) {
    1515       77552 :                 sql_rel *sq = NULL;
    1516       77552 :                 char *q = QUERY(sql->scanner);
    1517       77552 :                 symbol *sym = ast;
    1518             : 
    1519       77552 :                 if (sym->token == SQL_WITH)
    1520        5539 :                         sym = sym->data.lval->h->next->data.sym;
    1521       77552 :                 if (sym->token == SQL_SELECT) {
    1522       74739 :                         SelectNode *sn = (SelectNode *) sym;
    1523             : 
    1524       74739 :                         if (sn->limit || sn->sample)
    1525           4 :                                 return sql_error(sql, 01, SQLSTATE(42000) "%s: %s not supported", base, sn->limit ? "LIMIT" : "SAMPLE");
    1526             :                 }
    1527             : 
    1528       77549 :                 pfoundid = sql->objid;
    1529       77549 :                 sql->objid = foundid; /* when recreating a view, the view itself can't be found */
    1530       77549 :                 sq = schema_selects(query, s, ast);
    1531       77549 :                 sql->objid = pfoundid;
    1532       77549 :                 if (!sq)
    1533             :                         return NULL;
    1534       77536 :                 if (!is_project(sq->op)) /* make sure sq is a projection */
    1535           0 :                         sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 1));
    1536             : 
    1537       77536 :                 if (!create) {
    1538       55353 :                         if (column_spec) {
    1539       13467 :                                 dnode *n = column_spec->h;
    1540       13467 :                                 node *m = sq->exps->h;
    1541             : 
    1542       62016 :                                 for (; n && m; n = n->next, m = m->next)
    1543             :                                         ;
    1544       13467 :                                 if (n || m) {
    1545           2 :                                         sql_error(sql, 01, SQLSTATE(21S02) "WITH CLAUSE: number of columns does not match");
    1546           2 :                                         rel_destroy(sq);
    1547           2 :                                         return NULL;
    1548             :                                 }
    1549             :                         }
    1550             :                 }
    1551             : 
    1552       55351 :                 if (create) {
    1553       22183 :                         q = query_cleaned(sql->ta, q);
    1554       22183 :                         switch (mvc_create_view(&t, sql, s, name, SQL_DECLARED_TABLE, q, 0)) {
    1555           0 :                                 case -1:
    1556           0 :                                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1557           0 :                                 case -2:
    1558             :                                 case -3:
    1559           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: transaction conflict detected", base);
    1560             :                                 default:
    1561       22183 :                                         break;
    1562             :                         }
    1563       22183 :                         if (as_subquery(sql, t, tt_view, sq, column_spec, base) != 0) {
    1564           1 :                                 rel_destroy(sq);
    1565           1 :                                 return NULL;
    1566             :                         }
    1567       22182 :                         return rel_create_view_ddl(sql, ddl_create_view, s->base.name, t, SQL_PERSIST, replace);
    1568             :                 }
    1569       55351 :                 if (!persistent && column_spec)
    1570       11864 :                         sq = view_rename_columns(sql, name, sq, column_spec);
    1571       55351 :                 if (sq && is_simple_project(sq->op) && sq->l && sq->exps && sq->card == CARD_AGGR) {
    1572        3976 :                         exps_setcard(sq->exps, CARD_MULTI);
    1573        3976 :                         sq->card = CARD_MULTI;
    1574             :                 }
    1575       55351 :                 return sq;
    1576             :         }
    1577             :         return NULL;
    1578             : }
    1579             : 
    1580             : static sql_rel *
    1581         318 : rel_schema2(sql_allocator *sa, int cat_type, char *sname, char *auth, int nr)
    1582             : {
    1583         318 :         sql_rel *rel = rel_create(sa);
    1584         318 :         list *exps = new_exp_list(sa);
    1585         318 :         if (!rel || !exps)
    1586             :                 return NULL;
    1587             : 
    1588         318 :         append(exps, exp_atom_clob(sa, sname));
    1589         318 :         append(exps, exp_atom_clob(sa, auth));
    1590         318 :         append(exps, exp_atom_int(sa, nr));
    1591         318 :         rel->l = NULL;
    1592         318 :         rel->r = NULL;
    1593         318 :         rel->op = op_ddl;
    1594         318 :         rel->flag = cat_type;
    1595         318 :         rel->exps = exps;
    1596         318 :         rel->card = 0;
    1597         318 :         rel->nrcols = 0;
    1598         318 :         return rel;
    1599             : }
    1600             : 
    1601             : static sql_rel *
    1602         898 : rel_schema3(sql_allocator *sa, int cat_type, char *sname, char *tname, char *name)
    1603             : {
    1604         898 :         sql_rel *rel = rel_create(sa);
    1605         898 :         list *exps = new_exp_list(sa);
    1606         898 :         if (!rel || !exps)
    1607             :                 return NULL;
    1608             : 
    1609         898 :         append(exps, exp_atom_clob(sa, sname));
    1610         898 :         append(exps, exp_atom_clob(sa, tname));
    1611         898 :         append(exps, exp_atom_clob(sa, name));
    1612         898 :         rel->l = NULL;
    1613         898 :         rel->r = NULL;
    1614         898 :         rel->op = op_ddl;
    1615         898 :         rel->flag = cat_type;
    1616         898 :         rel->exps = exps;
    1617         898 :         rel->card = 0;
    1618         898 :         rel->nrcols = 0;
    1619         898 :         return rel;
    1620             : }
    1621             : 
    1622             : static sql_rel *
    1623           5 : rel_drop_type(mvc *sql, dlist *qname, int drop_action)
    1624             : {
    1625           5 :         char *name = qname_schema_object(qname);
    1626           5 :         char *sname = qname_schema(qname);
    1627           5 :         sql_type *t = NULL;
    1628             : 
    1629           5 :         if (!(t = find_type_on_scope(sql, sname, name, "DROP TYPE")))
    1630             :                 return NULL;
    1631           4 :         if (!mvc_schema_privs(sql, t->s))
    1632           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DROP TYPE: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), t->s->base.name);
    1633           4 :         return rel_schema2(sql->sa, ddl_drop_type, t->s->base.name, name, drop_action);
    1634             : }
    1635             : 
    1636             : static sql_rel *
    1637         898 : rel_create_type(mvc *sql, dlist *qname, char *impl)
    1638             : {
    1639         898 :         char *name = qname_schema_object(qname);
    1640         898 :         char *sname = qname_schema(qname);
    1641         898 :         sql_schema *s = cur_schema(sql);
    1642             : 
    1643         898 :         if (sname && !(s = mvc_bind_schema(sql, sname)))
    1644           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "CREATE TYPE: no such schema '%s'", sname);
    1645         898 :         if (schema_bind_type(sql, s, name) != NULL)
    1646           0 :                 return sql_error(sql, 02, SQLSTATE(42S01) "CREATE TYPE: name '%s' already in use", name);
    1647         898 :         if (!mvc_schema_privs(sql, s))
    1648           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE TYPE: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), s->base.name);
    1649         898 :         return rel_schema3(sql->sa, ddl_create_type, s->base.name, name, impl);
    1650             : }
    1651             : 
    1652             : static char *
    1653        1262 : dlist_get_schema_name(dlist *name_auth)
    1654             : {
    1655        1262 :         assert(name_auth && name_auth->h);
    1656        1262 :         return name_auth->h->data.sval;
    1657             : }
    1658             : 
    1659             : static char *
    1660        1078 : schema_auth(dlist *name_auth)
    1661             : {
    1662        1078 :         assert(name_auth && name_auth->h && dlist_length(name_auth) == 2);
    1663        1078 :         return name_auth->h->next->data.sval;
    1664             : }
    1665             : 
    1666             : static sql_rel *
    1667        4109 : rel_drop(sql_allocator *sa, int cat_type, char *sname, char *first_val, char *second_val, int nr, int exists_check)
    1668             : {
    1669        4109 :         sql_rel *rel = rel_create(sa);
    1670        4109 :         list *exps = new_exp_list(sa);
    1671             : 
    1672        4109 :         append(exps, exp_atom_int(sa, nr));
    1673        4109 :         append(exps, exp_atom_clob(sa, sname));
    1674        4109 :         if (first_val)
    1675        3925 :                 append(exps, exp_atom_clob(sa, first_val));
    1676        4109 :         if (second_val)
    1677         146 :                 append(exps, exp_atom_clob(sa, second_val));
    1678        4109 :         append(exps, exp_atom_int(sa, exists_check));
    1679        4109 :         rel->l = NULL;
    1680        4109 :         rel->r = NULL;
    1681        4109 :         rel->op = op_ddl;
    1682        4109 :         rel->flag = cat_type;
    1683        4109 :         rel->exps = exps;
    1684        4109 :         rel->card = 0;
    1685        4109 :         rel->nrcols = 0;
    1686        4109 :         return rel;
    1687             : }
    1688             : 
    1689             : static sql_rel *
    1690        1075 : rel_create_schema_dll(sql_allocator *sa, char *sname, char *auth, int nr)
    1691             : {
    1692        1075 :         sql_rel *rel = rel_create(sa);
    1693        1075 :         list *exps = new_exp_list(sa);
    1694        1075 :         if (!rel || !exps)
    1695             :                 return NULL;
    1696             : 
    1697        1075 :         append(exps, exp_atom_int(sa, nr));
    1698        1075 :         append(exps, exp_atom_clob(sa, sname));
    1699        1075 :         if (auth)
    1700          35 :                 append(exps, exp_atom_clob(sa, auth));
    1701        1075 :         rel->l = NULL;
    1702        1075 :         rel->r = NULL;
    1703        1075 :         rel->op = op_ddl;
    1704        1075 :         rel->flag = ddl_create_schema;
    1705        1075 :         rel->exps = exps;
    1706        1075 :         rel->card = 0;
    1707        1075 :         rel->nrcols = 0;
    1708        1075 :         return rel;
    1709             : }
    1710             : 
    1711             : static sql_rel *
    1712        1078 : rel_create_schema(sql_query *query, dlist *auth_name, dlist *schema_elements, int if_not_exists)
    1713             : {
    1714        1078 :         mvc *sql = query->sql;
    1715        1078 :         char *name = dlist_get_schema_name(auth_name);
    1716        1078 :         char *auth = schema_auth(auth_name);
    1717        1078 :         sqlid auth_id = sql->role_id;
    1718             : 
    1719        1078 :         if (auth && (auth_id = sql_find_auth(sql, auth)) < 0)
    1720           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(28000) "CREATE SCHEMA: no such authorization '%s'", auth);
    1721        1078 :         if (sql->user_id != USER_MONETDB && sql->role_id != ROLE_SYSADMIN)
    1722           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE SCHEMA: insufficient privileges for user '%s'", get_string_global_var(sql, "current_user"));
    1723        1077 :         if (!name)
    1724           0 :                 name = auth;
    1725           0 :         assert(name);
    1726        1077 :         if (mvc_bind_schema(sql, name)) {
    1727           2 :                 if (!if_not_exists)
    1728           1 :                         return sql_error(sql, 02, SQLSTATE(3F000) "CREATE SCHEMA: name '%s' already in use", name);
    1729           1 :                 return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1730             :         } else {
    1731        1075 :                 sql_schema *os = cur_schema(sql);
    1732        1075 :                 dnode *n = schema_elements->h;
    1733        1075 :                 sql_schema *ss = SA_ZNEW(sql->sa, sql_schema);
    1734        1075 :                 sql_rel *ret = rel_create_schema_dll(sql->sa, name, auth, 0);
    1735             : 
    1736        1075 :                 ss->base.name = name;
    1737        1075 :                 ss->auth_id = auth_id;
    1738        1075 :                 ss->owner = sql->user_id;
    1739             : 
    1740        1075 :                 sql->session->schema = ss;
    1741        1077 :                 while (n) {
    1742           2 :                         sql_rel *res = rel_semantic(query, n->data.sym);
    1743           2 :                         if (!res) {
    1744           0 :                                 rel_destroy(ret);
    1745           0 :                                 sql->session->schema = os;
    1746           0 :                                 return NULL;
    1747             :                         }
    1748           2 :                         ret = rel_list(sql->sa, ret, res);
    1749           2 :                         n = n->next;
    1750             :                 }
    1751        1075 :                 sql->session->schema = os;
    1752        1075 :                 return ret;
    1753             :         }
    1754             : }
    1755             : 
    1756             : static sql_rel *
    1757        3627 : sql_drop_table(sql_query *query, dlist *qname, int nr, int if_exists)
    1758             : {
    1759        3627 :         mvc *sql = query->sql;
    1760        3627 :         char *sname = qname_schema(qname);
    1761        3627 :         char *tname = qname_schema_object(qname);
    1762        3627 :         sql_table *t = NULL;
    1763             : 
    1764        3627 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "DROP TABLE", false))) {
    1765          85 :                 if (if_exists) {
    1766          45 :                         sql->errstr[0] = '\0'; /* reset table not found error */
    1767          45 :                         sql->session->status = 0;
    1768          45 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1769             :                 }
    1770             :                 return NULL;
    1771             :         }
    1772        3542 :         if (isDeclaredTable(t))
    1773           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DROP TABLE: cannot drop a declared table");
    1774             : 
    1775        3542 :         return rel_drop(sql->sa, ddl_drop_table, t->s->base.name, tname, NULL, nr, if_exists);
    1776             : }
    1777             : 
    1778             : static sql_rel *
    1779         258 : sql_drop_view(sql_query *query, dlist *qname, int nr, int if_exists)
    1780             : {
    1781         258 :         mvc *sql = query->sql;
    1782         258 :         char *sname = qname_schema(qname);
    1783         258 :         char *tname = qname_schema_object(qname);
    1784         258 :         sql_table *t = NULL;
    1785             : 
    1786         258 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "DROP VIEW", true))) {
    1787          20 :                 if (if_exists) {
    1788           1 :                         sql->errstr[0] = '\0'; /* reset table not found error */
    1789           1 :                         sql->session->status = 0;
    1790           1 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1791             :                 }
    1792             :                 return NULL;
    1793             :         }
    1794         238 :         if (!isView(t))
    1795           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "DROP VIEW: unable to drop view '%s': is a table", tname);
    1796             : 
    1797         237 :         return rel_drop(sql->sa, ddl_drop_view, t->s->base.name, tname, NULL, nr, if_exists);
    1798             : }
    1799             : 
    1800             : static sql_rel *
    1801        4075 : sql_alter_table(sql_query *query, dlist *dl, dlist *qname, symbol *te, int if_exists)
    1802             : {
    1803        4075 :         mvc *sql = query->sql;
    1804        4075 :         char *sname = qname_schema(qname);
    1805        4075 :         char *tname = qname_schema_object(qname);
    1806        4075 :         sql_table *t = NULL, *nt = NULL;
    1807        4075 :         sql_rel *res = NULL, *r;
    1808        4075 :         sql_exp **updates, *e;
    1809             : 
    1810        4075 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "ALTER TABLE", false))) {
    1811          17 :                 if (if_exists) {
    1812           1 :                         sql->errstr[0] = '\0'; /* reset table not found error */
    1813           1 :                         sql->session->status = 0;
    1814           1 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1815             :                 }
    1816             :                 return NULL;
    1817             :         }
    1818        4058 :         if (isDeclaredTable(t))
    1819           0 :                 return sql_error(sql, 02, SQLSTATE(42S02) "ALTER TABLE: can't alter declared table '%s'", tname);
    1820        4058 :         if (isTempSchema(t->s))
    1821           3 :                 return sql_error(sql, 02, SQLSTATE(42S02) "ALTER TABLE: can't alter temporary table '%s'", tname);
    1822        4055 :         if (!mvc_schema_privs(sql, t->s))
    1823           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), t->s->base.name);
    1824             : 
    1825        4055 :         assert(te);
    1826        4055 :         if (t->persistence != SQL_DECLARED_TABLE)
    1827        4055 :                 sname = t->s->base.name;
    1828             : 
    1829        4055 :         if ((te->token == SQL_TABLE || te->token == SQL_DROP_TABLE)) {
    1830         755 :                 dlist *nqname = te->data.lval->h->data.lval;
    1831         755 :                 sql_table *pt = NULL;
    1832         755 :                 char *nsname = qname_schema(nqname);
    1833         755 :                 char *ntname = qname_schema_object(nqname);
    1834             : 
    1835         755 :                 if (!(pt = find_table_or_view_on_scope(sql, t->s, nsname, ntname, "ALTER TABLE", false)))
    1836             :                         return NULL;
    1837         745 :                 if (isView(pt))
    1838           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: can't add/drop a view into a %s",
    1839           1 :                                                         TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1840         744 :                 if (isDeclaredTable(pt))
    1841           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: can't add/drop a declared table into a %s",
    1842           0 :                                                         TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1843         744 :                 if (isTempSchema(pt->s))
    1844           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: can't add/drop a temporary table into a %s",
    1845           2 :                                                         TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1846         742 :                 if (isReplicaTable(t) && isMergeTable(pt))
    1847           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: can't add/drop a %s table into a %s",
    1848           0 :                                                         TABLE_TYPE_DESCRIPTION(pt->type, pt->properties), TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1849         742 :                 nsname = pt->s->base.name;
    1850         742 :                 if (strcmp(sname, nsname) != 0)
    1851           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: all children tables of '%s.%s' must be part of schema '%s'",
    1852             :                                                 sname, tname, sname);
    1853             : 
    1854         741 :                 if (te->token == SQL_TABLE) {
    1855         561 :                         symbol *extra = dl->h->next->next->next->data.sym;
    1856             : 
    1857         561 :                         if (!extra) {
    1858         292 :                                 if (isRangePartitionTable(t)) {
    1859           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: a range partition is required while adding under a %s",
    1860           1 :                                                                 TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1861         291 :                                 } else if (isListPartitionTable(t)) {
    1862           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: a value partition is required while adding under a %s",
    1863           1 :                                                                 TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1864             :                                 }
    1865         290 :                                 return rel_alter_table(sql->sa, ddl_alter_table_add_table, sname, tname, nsname, ntname, 0);
    1866             :                         }
    1867         269 :                         if ((isMergeTable(pt) || isReplicaTable(pt)) && list_length(pt->members)==0)
    1868           2 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s '%s'.'%s' should have at least one table associated",
    1869           2 :                                                                 TABLE_TYPE_DESCRIPTION(pt->type, pt->properties), pt->s->base.name, pt->base.name);
    1870             : 
    1871         267 :                         if (extra->token == SQL_MERGE_PARTITION) { /* partition to hold null values only */
    1872          15 :                                 dlist* ll = extra->data.lval;
    1873          15 :                                 int update = ll->h->next->next->next->data.i_val;
    1874             : 
    1875          15 :                                 if (isRangePartitionTable(t)) {
    1876          12 :                                         return rel_alter_table_add_partition_range(query, t, pt, sname, tname, nsname, ntname, NULL, NULL, true, update);
    1877           3 :                                 } else if (isListPartitionTable(t)) {
    1878           3 :                                         return rel_alter_table_add_partition_list(query, t, pt, sname, tname, nsname, ntname, NULL, true, update);
    1879             :                                 } else {
    1880           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot add a partition into a %s",
    1881           0 :                                                                 TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1882             :                                 }
    1883         252 :                         } else if (extra->token == SQL_PARTITION_RANGE) {
    1884         198 :                                 dlist* ll = extra->data.lval;
    1885         198 :                                 symbol* min = ll->h->data.sym, *max = ll->h->next->data.sym;
    1886         198 :                                 int nills = ll->h->next->next->data.i_val, update = ll->h->next->next->next->data.i_val;
    1887             : 
    1888         198 :                                 if (!isRangePartitionTable(t)) {
    1889           2 :                                         return sql_error(sql, 02,SQLSTATE(42000) "ALTER TABLE: cannot add a range partition into a %s",
    1890           1 :                                                                 TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1891             :                                 }
    1892             : 
    1893         197 :                                 assert(nills == 0 || nills == 1);
    1894         197 :                                 return rel_alter_table_add_partition_range(query, t, pt, sname, tname, nsname, ntname, min, max, (bit) nills, update);
    1895          54 :                         } else if (extra->token == SQL_PARTITION_LIST) {
    1896          54 :                                 dlist* ll = extra->data.lval, *values = ll->h->data.lval;
    1897          54 :                                 int nills = ll->h->next->data.i_val, update = ll->h->next->next->data.i_val;
    1898             : 
    1899          54 :                                 if (!isListPartitionTable(t)) {
    1900           2 :                                         return sql_error(sql, 02,SQLSTATE(42000) "ALTER TABLE: cannot add a value partition into a %s",
    1901           1 :                                                                 TABLE_TYPE_DESCRIPTION(t->type, t->properties));
    1902             :                                 }
    1903             : 
    1904          53 :                                 assert(nills == 0 || nills == 1);
    1905          53 :                                 return rel_alter_table_add_partition_list(query, t, pt, sname, tname, nsname, ntname, values, (bit) nills, update);
    1906             :                         }
    1907           0 :                         assert(0);
    1908             :                 } else {
    1909         180 :                         int drop_action = te->data.lval->h->next->data.i_val;
    1910             : 
    1911         180 :                         return rel_alter_table(sql->sa, ddl_alter_table_del_table, sname, tname, nsname, ntname, drop_action);
    1912             :                 }
    1913             :         }
    1914             : 
    1915             :         /* read only or read write */
    1916        3300 :         if (te->token == SQL_ALTER_TABLE) {
    1917        2067 :                 int state = te->data.i_val;
    1918             : 
    1919        2067 :                 if (state == tr_readonly) {
    1920             :                         state = TABLE_READONLY;
    1921             :                 } else if (state == tr_append) {
    1922             :                         state = TABLE_APPENDONLY;
    1923             :                 } else {
    1924           0 :                         assert(state == tr_writable);
    1925             :                         state = TABLE_WRITABLE;
    1926             :                 }
    1927        2067 :                 return rel_alter_table(sql->sa, ddl_alter_table_set_access, sname, tname, NULL, NULL, state);
    1928             :         }
    1929             : 
    1930        1233 :         nt = dup_sql_table(sql->sa, t);
    1931        1233 :         if (!nt || (table_element(query, te, t->s, nt, 1, t->persistence == SQL_DECLARED_TABLE, "ALTER TABLE") == SQL_ERR))
    1932          74 :                 return NULL;
    1933             : 
    1934        1159 :         if (te->token == SQL_DROP_CONSTRAINT) {
    1935         146 :                 dlist *l = te->data.lval;
    1936         146 :                 char *kname = l->h->data.sval;
    1937         146 :                 int drop_action = l->h->next->data.i_val;
    1938             : 
    1939         146 :                 return rel_drop(sql->sa, ddl_drop_constraint, sname, tname, kname, drop_action, 0);
    1940             :         }
    1941             : 
    1942        1013 :         res = rel_table(sql, ddl_alter_table, sname, nt, 0);
    1943        1013 :         sql_rel *bt = rel_ddl_basetable_get(res);
    1944             : 
    1945        1013 :         if (!isTable(nt))
    1946             :                 return res;
    1947             : 
    1948             :         /* New columns need update with default values. Add one more element for new column */
    1949         988 :         updates = SA_ZNEW_ARRAY(sql->sa, sql_exp*, (ol_length(nt->columns) + 1));
    1950         988 :         rel_base_use_tid(sql, bt);
    1951         988 :         e = exp_column(sql->sa, nt->base.name, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
    1952         988 :         r = rel_project(sql->sa, res, append(new_exp_list(sql->sa),e));
    1953             : 
    1954         988 :         list *cols = new_exp_list(sql->sa);
    1955       14510 :         for (node *n = ol_first_node(nt->columns); n; n = n->next) {
    1956       13522 :                 sql_column *c = n->data;
    1957             : 
    1958       13522 :                 rel_base_use(sql, bt, c->colnr);
    1959             :                 /* handle new columns */
    1960       13522 :                 if (!c->base.new || c->base.deleted)
    1961       13418 :                         continue;
    1962         104 :                 if (c->def) {
    1963           5 :                         e = rel_parse_val(sql, nt->s, c->def, &c->type, sql->emode, NULL);
    1964             :                 } else {
    1965          99 :                         e = exp_atom(sql->sa, atom_general(sql->sa, &c->type, NULL));
    1966             :                 }
    1967         104 :                 if (!e || (e = exp_check_type(sql, &c->type, r, e, type_equal)) == NULL) {
    1968           0 :                         rel_destroy(r);
    1969           0 :                         return NULL;
    1970             :                 }
    1971         104 :                 list_append(cols, exp_column(sql->sa, nt->base.name, c->base.name, &c->type, CARD_MULTI, 0, 0, 0));
    1972             : 
    1973         104 :                 assert(!updates[c->colnr]);
    1974         104 :                 exp_setname(sql->sa, e, c->t->base.name, c->base.name);
    1975         104 :                 updates[c->colnr] = e;
    1976             :         }
    1977         988 :         res = rel_update(sql, res, r, updates, list_length(cols)?cols:NULL);
    1978         988 :         return res;
    1979             : }
    1980             : 
    1981             : static sql_rel *
    1982          48 : rel_role(sql_allocator *sa, char *grantee, char *auth, int grantor, int admin, int type)
    1983             : {
    1984          48 :         sql_rel *rel = rel_create(sa);
    1985          48 :         list *exps = new_exp_list(sa);
    1986          48 :         if (!rel || !exps)
    1987             :                 return NULL;
    1988             : 
    1989          48 :         assert(type == ddl_grant_roles || type == ddl_revoke_roles);
    1990          48 :         append(exps, exp_atom_clob(sa, grantee));
    1991          48 :         append(exps, exp_atom_clob(sa, auth));
    1992          48 :         append(exps, exp_atom_int(sa, grantor));
    1993          48 :         append(exps, exp_atom_int(sa, admin));
    1994          48 :         rel->l = NULL;
    1995          48 :         rel->r = NULL;
    1996          48 :         rel->op = op_ddl;
    1997          48 :         rel->flag = type;
    1998          48 :         rel->exps = exps;
    1999          48 :         rel->card = 0;
    2000          48 :         rel->nrcols = 0;
    2001          48 :         return rel;
    2002             : }
    2003             : 
    2004             : static sql_rel *
    2005          48 : rel_grant_or_revoke_roles(mvc *sql, dlist *roles, dlist *grantees, int grant, int grantor, ddl_statement action)
    2006             : {
    2007          48 :         sql_rel *res = NULL;
    2008             :         /* grant/revoke roles to the grantees */
    2009             : 
    2010          96 :         for (dnode *r = roles->h; r; r = r->next) {
    2011          48 :                 char *role = r->data.sval;
    2012             : 
    2013          96 :                 for (dnode *g = grantees->h; g; g = g->next) {
    2014          48 :                         char *grantee = g->data.sval;
    2015             : 
    2016          48 :                         if ((res = rel_list(sql->sa, res, rel_role(sql->sa, grantee, role, grantor, grant, action))) == NULL) {
    2017           0 :                                 rel_destroy(res);
    2018           0 :                                 return NULL;
    2019             :                         }
    2020             :                 }
    2021             :         }
    2022             :         return res;
    2023             : }
    2024             : 
    2025             : static sql_rel *
    2026       17888 : rel_priv(sql_allocator *sa, char *sname, char *name, char *grantee, int privs, char *cname, int grant, int grantor, int type)
    2027             : {
    2028       17888 :         sql_rel *rel = rel_create(sa);
    2029       17888 :         list *exps = new_exp_list(sa);
    2030       17888 :         if (!rel || !exps)
    2031             :                 return NULL;
    2032             : 
    2033       17888 :         assert(type == ddl_grant || type == ddl_revoke);
    2034       17888 :         append(exps, exp_atom_clob(sa, sname));
    2035       17888 :         append(exps, exp_atom_clob(sa, name));
    2036       17888 :         append(exps, exp_atom_clob(sa, grantee));
    2037       17888 :         append(exps, exp_atom_int(sa, privs));
    2038       17888 :         append(exps, cname?(void*)exp_atom_clob(sa, cname):(void*)cname);
    2039       17888 :         append(exps, exp_atom_int(sa, grant));
    2040       17888 :         append(exps, exp_atom_int(sa, grantor));
    2041       17888 :         rel->l = NULL;
    2042       17888 :         rel->r = NULL;
    2043       17888 :         rel->op = op_ddl;
    2044       17888 :         rel->flag = type;
    2045       17888 :         rel->exps = exps;
    2046       17888 :         rel->card = 0;
    2047       17888 :         rel->nrcols = 0;
    2048       17888 :         return rel;
    2049             : }
    2050             : 
    2051             : static sql_rel *
    2052       89897 : rel_func_priv(sql_allocator *sa, char *sname, int func, char *grantee, int privs, int grant, int grantor, int type)
    2053             : {
    2054       89897 :         sql_rel *rel = rel_create(sa);
    2055       89897 :         list *exps = new_exp_list(sa);
    2056       89897 :         if (!rel || !exps)
    2057             :                 return NULL;
    2058             : 
    2059       89897 :         assert(type == ddl_grant_func || type == ddl_revoke_func);
    2060       89897 :         append(exps, exp_atom_clob(sa, sname));
    2061       89897 :         append(exps, exp_atom_int(sa, func));
    2062       89897 :         append(exps, exp_atom_clob(sa, grantee));
    2063       89897 :         append(exps, exp_atom_int(sa, privs));
    2064       89897 :         append(exps, exp_atom_int(sa, grant));
    2065       89897 :         append(exps, exp_atom_int(sa, grantor));
    2066       89897 :         rel->l = NULL;
    2067       89897 :         rel->r = NULL;
    2068       89897 :         rel->op = op_ddl;
    2069       89897 :         rel->flag = type;
    2070       89897 :         rel->exps = exps;
    2071       89897 :         rel->card = 0;
    2072       89897 :         rel->nrcols = 0;
    2073       89897 :         return rel;
    2074             : }
    2075             : 
    2076             : static sql_rel *
    2077          10 : rel_grant_or_revoke_global(mvc *sql, dlist *privs, dlist *grantees, int grant, int grantor, ddl_statement action)
    2078             : {
    2079          10 :         sql_rel *res = NULL;
    2080          10 :         char *sname = cur_schema(sql)->base.name;
    2081             : 
    2082          10 :         if (!privs)
    2083             :                 return NULL;
    2084          20 :         for (dnode *gn = grantees->h; gn; gn = gn->next) {
    2085          10 :                 char *grantee = gn->data.sval;
    2086             : 
    2087          10 :                 if (!grantee)
    2088           0 :                         grantee = "public";
    2089             : 
    2090          20 :                 for (dnode *opn = privs->h; opn; opn = opn->next) {
    2091          10 :                         int priv = opn->data.i_val;
    2092             : 
    2093          10 :                         if ((res = rel_list(sql->sa, res, rel_priv(sql->sa, sname, NULL, grantee, priv, NULL, grant, grantor, action))) == NULL) {
    2094           0 :                                 rel_destroy(res);
    2095           0 :                                 return NULL;
    2096             :                         }
    2097             :                 }
    2098             :         }
    2099             :         return res;
    2100             : }
    2101             : 
    2102             : static sql_rel *
    2103       17841 : rel_grant_or_revoke_table(mvc *sql, dlist *privs, dlist *qname, dlist *grantees, int grant, int grantor, ddl_statement action, const char *err)
    2104             : {
    2105       17841 :         sql_rel *res = NULL;
    2106       17841 :         int all = PRIV_SELECT | PRIV_UPDATE | PRIV_INSERT | PRIV_DELETE | PRIV_TRUNCATE;
    2107       17841 :         char *sname = qname_schema(qname);
    2108       17841 :         char *tname = qname_schema_object(qname);
    2109       17841 :         sql_table *t = NULL;
    2110             : 
    2111       17841 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, err, false)))
    2112             :                 return NULL;
    2113       17840 :         if (isDeclaredTable(t))
    2114           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "Cannot %s on a declared table", err);
    2115       35680 :         for (dnode *gn = grantees->h; gn; gn = gn->next) {
    2116       17840 :                 char *grantee = gn->data.sval;
    2117             : 
    2118       17840 :                 if (!grantee)
    2119       17728 :                         grantee = "public";
    2120             : 
    2121       17840 :                 if (!privs) {
    2122           7 :                         if ((res = rel_list(sql->sa, res, rel_priv(sql->sa, t->s->base.name, tname, grantee, all, NULL, grant, grantor, action))) == NULL) {
    2123           0 :                                 rel_destroy(res);
    2124           0 :                                 return NULL;
    2125             :                         }
    2126           7 :                         continue;
    2127             :                 }
    2128       35692 :                 for (dnode *opn = privs->h; opn; opn = opn->next) {
    2129       17859 :                         symbol *op = opn->data.sym;
    2130       17859 :                         int priv = PRIV_SELECT;
    2131             : 
    2132       17859 :                         switch (op->token) {
    2133             :                         case SQL_SELECT:
    2134             :                                 priv = PRIV_SELECT;
    2135             :                                 break;
    2136          28 :                         case SQL_UPDATE:
    2137          28 :                                 priv = PRIV_UPDATE;
    2138          28 :                                 break;
    2139          28 :                         case SQL_INSERT:
    2140          28 :                                 priv = PRIV_INSERT;
    2141          28 :                                 break;
    2142          21 :                         case SQL_DELETE:
    2143          21 :                                 priv = PRIV_DELETE;
    2144          21 :                                 break;
    2145           1 :                         case SQL_TRUNCATE:
    2146           1 :                                 priv = PRIV_TRUNCATE;
    2147           1 :                                 break;
    2148           0 :                         case SQL_EXECUTE:
    2149             :                         default:
    2150           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Cannot %s EXECUTE on table name %s", err, tname);
    2151             :                         }
    2152             : 
    2153       17859 :                         if ((op->token == SQL_SELECT || op->token == SQL_UPDATE) && op->data.lval) {
    2154          96 :                                 for (dnode *cn = op->data.lval->h; cn; cn = cn->next) {
    2155          54 :                                         char *cname = cn->data.sval;
    2156          54 :                                         if ((res = rel_list(sql->sa, res, rel_priv(sql->sa, t->s->base.name, tname, grantee, priv, cname, grant, grantor, action))) == NULL) {
    2157           0 :                                                 rel_destroy(res);
    2158           0 :                                                 return NULL;
    2159             :                                         }
    2160             :                                 }
    2161       17817 :                         } else if ((res = rel_list(sql->sa, res, rel_priv(sql->sa, t->s->base.name, tname, grantee, priv, NULL, grant, grantor, action))) == NULL) {
    2162           0 :                                 rel_destroy(res);
    2163           0 :                                 return NULL;
    2164             :                         }
    2165             :                 }
    2166             :         }
    2167             :         return res;
    2168             : }
    2169             : 
    2170             : static sql_rel *
    2171       89898 : rel_grant_or_revoke_func(mvc *sql, dlist *privs, dlist *qname, dlist *typelist, sql_ftype type, dlist *grantees, int grant, int grantor, ddl_statement action, const char *err)
    2172             : {
    2173       89898 :         sql_rel *res = NULL;
    2174       89898 :         char *sname = qname_schema(qname);
    2175       89898 :         char *fname = qname_schema_object(qname);
    2176       89898 :         sql_func *func = resolve_func(sql, sname, fname, typelist, type, err, 0);
    2177             : 
    2178       89898 :         if (!func)
    2179             :                 return NULL;
    2180       89897 :         if (!func->s)
    2181           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "Cannot %s EXECUTE on system function '%s'", err, fname);
    2182      179794 :         for (dnode *gn = grantees->h; gn; gn = gn->next) {
    2183       89897 :                 char *grantee = gn->data.sval;
    2184             : 
    2185       89897 :                 if (!grantee)
    2186       89426 :                         grantee = "public";
    2187             : 
    2188       89897 :                 if (!privs) {
    2189           4 :                         if ((res = rel_list(sql->sa, res, rel_func_priv(sql->sa, func->s->base.name, func->base.id, grantee, PRIV_EXECUTE, grant, grantor, action))) == NULL) {
    2190           0 :                                 rel_destroy(res);
    2191           0 :                                 return NULL;
    2192             :                         }
    2193           4 :                         continue;
    2194             :                 }
    2195      179786 :                 for (dnode *opn = privs->h; opn; opn = opn->next) {
    2196       89893 :                         symbol *op = opn->data.sym;
    2197             : 
    2198       89893 :                         if (op->token != SQL_EXECUTE)
    2199           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Can only %s 'EXECUTE' on function '%s'", err, fname);
    2200       89893 :                         if ((res = rel_list(sql->sa, res, rel_func_priv(sql->sa, func->s->base.name, func->base.id, grantee, PRIV_EXECUTE, grant, grantor, action))) == NULL) {
    2201           0 :                                 rel_destroy(res);
    2202           0 :                                 return NULL;
    2203             :                         }
    2204             :                 }
    2205             :         }
    2206             :         return res;
    2207             : }
    2208             : 
    2209             : static sql_rel *
    2210      107749 : rel_grant_or_revoke_privs(mvc *sql, dlist *privs, dlist *grantees, int grant, int grantor, ddl_statement action)
    2211             : {
    2212      107749 :         dlist *obj_privs = privs->h->data.lval;
    2213      107749 :         symbol *obj = privs->h->next->data.sym;
    2214      107749 :         tokens token = obj->token;
    2215      107749 :         const char *err = (action == ddl_grant) ? "GRANT" : "REVOKE";
    2216             : 
    2217      107749 :         switch (token) {
    2218          10 :         case SQL_GRANT:
    2219          10 :                 return rel_grant_or_revoke_global(sql, obj_privs, grantees, grant, grantor, action);
    2220       17841 :         case SQL_TABLE:
    2221             :         case SQL_NAME:
    2222       17841 :                 return rel_grant_or_revoke_table(sql, obj_privs, obj->data.lval, grantees, grant, grantor, action, err);
    2223       89898 :         case SQL_FUNC: {
    2224       89898 :                 dlist *r = obj->data.lval;
    2225       89898 :                 dlist *qname = r->h->data.lval;
    2226       89898 :                 dlist *typelist = r->h->next->data.lval;
    2227       89898 :                 sql_ftype type = (sql_ftype) r->h->next->next->data.i_val;
    2228             : 
    2229       89899 :                 return rel_grant_or_revoke_func(sql, obj_privs, qname, typelist, type, grantees, grant, grantor, (action == ddl_grant) ? ddl_grant_func : ddl_revoke_func, err);
    2230             :         }
    2231           0 :         default:
    2232           0 :                 return sql_error(sql, 02, SQLSTATE(M0M03) "%s: unknown token %d", err, (int) token);
    2233             :         }
    2234             : }
    2235             : 
    2236             : /* iname, itype, sname.tname (col1 .. coln) */
    2237             : static sql_rel *
    2238         337 : rel_create_index(mvc *sql, char *iname, idx_type itype, dlist *qname, dlist *column_list)
    2239             : {
    2240         337 :         sql_table *t = NULL, *nt;
    2241         337 :         sql_rel *r, *res;
    2242         337 :         sql_exp **updates, *e;
    2243         337 :         sql_idx *i;
    2244         337 :         dnode *n;
    2245         337 :         char *sname = qname_schema(qname), *tname = qname_schema_object(qname), *s = iname;
    2246             : 
    2247         337 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "CREATE INDEX", false)))
    2248             :                 return NULL;
    2249         336 :         if (isDeclaredTable(t))
    2250           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: cannot create index on a declared table");
    2251         336 :         if (!mvc_schema_privs(sql, t->s))
    2252           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), t->s->base.name);
    2253         336 :         if (!s || !*s) /* add this to be safe */
    2254           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: index name cannot be empty");
    2255         336 :         while (isdigit((unsigned char) *s))
    2256           0 :                 s++;
    2257         336 :         if (!*s) /* if an index name just contains digit characters, it can be mistaken with a label */
    2258           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: index name cannot contain just digit characters (0 through 9)");
    2259         336 :         if ((i = mvc_bind_idx(sql, t->s, iname)))
    2260           3 :                 return sql_error(sql, 02, SQLSTATE(42S11) "CREATE INDEX: name '%s' already in use", iname);
    2261         333 :         if (ol_find_name(t->keys, iname) || mvc_bind_key(sql, t->s, iname))
    2262           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: a key named '%s' already exists, and it would conflict with the index", iname);
    2263         333 :         if (!isTable(t))
    2264           2 :                 return sql_error(sql, 02, SQLSTATE(42S02) "CREATE INDEX: cannot create index on %s '%s'", TABLE_TYPE_DESCRIPTION(t->type, t->properties), tname);
    2265         331 :         nt = dup_sql_table(sql->sa, t);
    2266             : 
    2267         331 :         if (t->persistence != SQL_DECLARED_TABLE)
    2268         331 :                 sname = t->s->base.name;
    2269             : 
    2270             :         /* add index here */
    2271         331 :         switch (mvc_create_idx(&i, sql, nt, iname, itype)) {
    2272           0 :                 case -1:
    2273           0 :                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2274           0 :                 case -2:
    2275             :                 case -3:
    2276           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: transaction conflict detected");
    2277             :                 default:
    2278         331 :                         break;
    2279             :         }
    2280         754 :         for (n = column_list->h; n; n = n->next) {
    2281         425 :                 sql_column *c = mvc_bind_column(sql, nt, n->data.sval);
    2282             : 
    2283         425 :                 if (!c)
    2284           2 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "CREATE INDEX: no such column '%s'", n->data.sval);
    2285         423 :                 switch (mvc_create_ic(sql, i, c)) {
    2286           0 :                         case -1:
    2287           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2288           0 :                         case -2:
    2289             :                         case -3:
    2290           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE INDEX: transaction conflict detected");
    2291             :                         default:
    2292         423 :                                 break;
    2293             :                 }
    2294             :         }
    2295         329 :         mvc_create_idx_done(sql, i);
    2296             : 
    2297             :         /* new columns need update with default values */
    2298         329 :         updates = SA_ZNEW_ARRAY(sql->sa, sql_exp*, ol_length(nt->columns));
    2299         329 :         e = exp_column(sql->sa, nt->base.name, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
    2300         329 :         res = rel_table(sql, ddl_alter_table, sname, nt, 0);
    2301         329 :         r = rel_project(sql->sa, res, append(new_exp_list(sql->sa),e));
    2302         329 :         res = rel_update(sql, res, r, updates, NULL);
    2303         329 :         return res;
    2304             : }
    2305             : 
    2306             : static sql_rel *
    2307         331 : rel_create_user(sql_allocator *sa, char *user, char *passwd, int enc, char *fullname, char *schema, char *schema_path, lng max_memory, int max_workers, char *optimizer, char *default_role)
    2308             : {
    2309         331 :         sql_rel *rel = rel_create(sa);
    2310         331 :         list *exps = new_exp_list(sa);
    2311         331 :         if (!rel || !exps)
    2312             :                 return NULL;
    2313             : 
    2314         331 :         append(exps, exp_atom_clob(sa, user));
    2315         331 :         append(exps, exp_atom_clob(sa, passwd));
    2316         331 :         append(exps, exp_atom_int(sa, enc));
    2317         331 :         append(exps, exp_atom_clob(sa, schema));
    2318         331 :         append(exps, exp_atom_clob(sa, schema_path));
    2319         331 :         append(exps, exp_atom_clob(sa, fullname));
    2320         331 :         append(exps, exp_atom_lng(sa, max_memory >= 0 ? max_memory : 0));
    2321         331 :         append(exps, exp_atom_int(sa, max_workers >= 0 ? max_workers: 0));
    2322         331 :         append(exps, exp_atom_clob(sa, optimizer));
    2323         331 :         append(exps, exp_atom_clob(sa, default_role));
    2324         331 :         rel->l = NULL;
    2325         331 :         rel->r = NULL;
    2326         331 :         rel->op = op_ddl;
    2327         331 :         rel->flag = ddl_create_user;
    2328         331 :         rel->exps = exps;
    2329         331 :         rel->card = 0;
    2330         331 :         rel->nrcols = 0;
    2331         331 :         return rel;
    2332             : }
    2333             : 
    2334             : static sql_rel *
    2335          76 : rel_alter_user(sql_allocator *sa, char *user, char *passwd, int enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers)
    2336             : {
    2337          76 :         sql_rel *rel = rel_create(sa);
    2338          76 :         list *exps = new_exp_list(sa);
    2339          76 :         if (!rel || !exps)
    2340             :                 return NULL;
    2341             : 
    2342          76 :         append(exps, exp_atom_clob(sa, user));
    2343          76 :         append(exps, exp_atom_clob(sa, passwd));
    2344          76 :         append(exps, exp_atom_int(sa, enc));
    2345          76 :         append(exps, exp_atom_clob(sa, schema));
    2346          76 :         append(exps, exp_atom_clob(sa, schema_path));
    2347          76 :         append(exps, exp_atom_clob(sa, oldpasswd));
    2348          76 :         append(exps, exp_atom_clob(sa, role));
    2349          76 :         append(exps, exp_atom_lng(sa, max_memory));
    2350          76 :         append(exps, exp_atom_int(sa, max_workers));
    2351             : 
    2352          76 :         rel->l = NULL;
    2353          76 :         rel->r = NULL;
    2354          76 :         rel->op = op_ddl;
    2355          76 :         rel->flag = ddl_alter_user;
    2356          76 :         rel->exps = exps;
    2357          76 :         rel->card = 0;
    2358          76 :         rel->nrcols = 0;
    2359          76 :         return rel;
    2360             : }
    2361             : 
    2362             : static sqlid
    2363         249 : rel_find_designated_schema(mvc *sql, symbol *sym, sql_schema **schema_out) {
    2364         249 :         char *sname;
    2365         249 :         sql_schema *s;
    2366             : 
    2367         249 :         assert(sym->type == type_string);
    2368         249 :         sname = sym->data.sval;
    2369         249 :         if (!(s = mvc_bind_schema(sql, sname))) {
    2370           0 :                 sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "COMMENT ON: no such schema: '%s'", sname);
    2371           0 :                 return 0;
    2372             :         }
    2373             : 
    2374         249 :         *schema_out = s;
    2375         249 :         return s->base.id;
    2376             : }
    2377             : 
    2378             : static sqlid
    2379          25 : rel_find_designated_table(mvc *sql, symbol *sym, sql_schema **schema_out) {
    2380          25 :         dlist *qname;
    2381          25 :         char *sname, *tname;
    2382          25 :         sql_table *t;
    2383          25 :         int want_table = sym->token == SQL_TABLE;
    2384             : 
    2385          25 :         assert(sym->type == type_list);
    2386          25 :         qname = sym->data.lval;
    2387          25 :         sname = qname_schema(qname);
    2388          25 :         tname = qname_schema_object(qname);
    2389          25 :         t = find_table_or_view_on_scope(sql, NULL, sname, tname, "COMMENT ON", !want_table);
    2390          25 :         if (t && isDeclaredTable(t)) {
    2391           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON declared table not allowed");
    2392           0 :                 return 0;
    2393             :         }
    2394          25 :         if (t && t->s && isTempSchema(t->s)) {
    2395           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON tmp object not allowed");
    2396           0 :                 return 0;
    2397             :         }
    2398          45 :         if (t && !want_table == !isKindOfTable(t)) {    /* comparing booleans can be tricky */
    2399          25 :                 *schema_out = t->s;
    2400          25 :                 return t->base.id;
    2401             :         }
    2402             : 
    2403           0 :         sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "COMMENT ON: no such %s: %s%s%s'%s'",
    2404             :                           want_table ? "table" : "view", sname ? "'":"", sname ? sname : "", sname ? "'.":"", tname);
    2405           0 :         return 0;
    2406             : }
    2407             : 
    2408             : static sqlid
    2409          18 : rel_find_designated_column(mvc *sql, symbol *sym, sql_schema **schema_out) {
    2410          18 :         char *sname, *tname, *cname;
    2411          18 :         dlist *colname;
    2412          18 :         sql_table *t;
    2413          18 :         sql_column *c;
    2414             : 
    2415          18 :         assert(sym->type == type_list);
    2416          18 :         colname = sym->data.lval;
    2417          18 :         assert(colname->cnt == 2 || colname->cnt == 3);
    2418          18 :         assert(colname->h->type == type_string);
    2419          18 :         assert(colname->h->next->type == type_string);
    2420          18 :         if (colname->cnt == 2) {
    2421           7 :                 sname = NULL;
    2422           7 :                 tname = colname->h->data.sval;
    2423           7 :                 cname = colname->h->next->data.sval;
    2424             :         } else {
    2425             :                 // cnt == 3
    2426          11 :                 sname = colname->h->data.sval;
    2427          11 :                 tname = colname->h->next->data.sval;
    2428          11 :                 assert(colname->h->next->next->type == type_string);
    2429          11 :                 cname = colname->h->next->next->data.sval;
    2430             :         }
    2431          18 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "COMMENT ON", false)))
    2432             :                 return 0;
    2433          18 :         if (t && isDeclaredTable(t)) {
    2434           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON declared table not allowed");
    2435           0 :                 return 0;
    2436             :         }
    2437          18 :         if (t && t->s && isTempSchema(t->s)) {
    2438           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON tmp object not allowed");
    2439           0 :                 return 0;
    2440             :         }
    2441          18 :         if (!(c = mvc_bind_column(sql, t, cname))) {
    2442           0 :                 sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S12) "COMMENT ON: no such column: %s%s%s'%s'.'%s'",
    2443             :                                   sname ? "'":"", sname ? sname : "", sname ? "'.":"", tname, cname);
    2444           0 :                 return 0;
    2445             :         }
    2446          18 :         *schema_out = t->s;
    2447          18 :         return c->base.id;
    2448             : }
    2449             : 
    2450             : static sqlid
    2451          15 : rel_find_designated_index(mvc *sql, symbol *sym, sql_schema **schema_out) {
    2452          15 :         dlist *qname;
    2453          15 :         char *iname, *sname;
    2454          15 :         sql_idx *idx;
    2455             : 
    2456          15 :         assert(sym->type == type_list);
    2457          15 :         qname = sym->data.lval;
    2458          15 :         sname = qname_schema(qname);
    2459          15 :         iname = qname_schema_object(qname);
    2460          15 :         if (!(idx = find_idx_on_scope(sql, sname, iname, "COMMENT ON")))
    2461             :                 return 0;
    2462          15 :         if (idx && idx->t->s && isTempSchema(idx->t->s)) {
    2463           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON tmp object not allowed");
    2464           0 :                 return 0;
    2465             :         }
    2466             :         if (idx) {
    2467          15 :                 *schema_out = idx->t->s;
    2468          15 :                 return idx->base.id;
    2469             :         }
    2470             : 
    2471             :         return 0;
    2472             : }
    2473             : 
    2474             : static sqlid
    2475           8 : rel_find_designated_sequence(mvc *sql, symbol *sym, sql_schema **schema_out) {
    2476           8 :         (void)sql;
    2477           8 :         (void)sym;
    2478           8 :         dlist *qname;
    2479           8 :         char *seqname, *sname;
    2480           8 :         sql_sequence *seq;
    2481             : 
    2482           8 :         assert(sym->type == type_list);
    2483           8 :         qname = sym->data.lval;
    2484           8 :         sname = qname_schema(qname);
    2485           8 :         seqname = qname_schema_object(qname);
    2486             : 
    2487           8 :         seq = find_sequence_on_scope(sql, sname, seqname, "COMMENT ON");
    2488           8 :         if (seq && seq->s && isTempSchema(seq->s)) {
    2489           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON tmp object not allowed");
    2490           0 :                 return 0;
    2491             :         }
    2492             :         if (seq) {
    2493           8 :                 *schema_out = seq->s;
    2494           8 :                 return seq->base.id;
    2495             :         }
    2496             : 
    2497             :         return 0;
    2498             : }
    2499             : 
    2500             : static sqlid
    2501          22 : rel_find_designated_routine(mvc *sql, symbol *sym, sql_schema **schema_out) {
    2502          22 :         (void)sql;
    2503          22 :         (void)sym;
    2504          22 :         dlist *designator;
    2505          22 :         dlist *qname;
    2506          22 :         dlist *typelist;
    2507          22 :         sql_ftype func_type;
    2508          22 :         char *fname, *sname;
    2509          22 :         sql_func *func;
    2510             : 
    2511          22 :         assert(sym->type == type_list);
    2512          22 :         designator = sym->data.lval;
    2513          22 :         assert(designator->cnt == 3);
    2514          22 :         qname = designator->h->data.lval;
    2515          22 :         sname = qname_schema(qname);
    2516          22 :         typelist = designator->h->next->data.lval;
    2517          22 :         func_type = (sql_ftype) designator->h->next->next->data.i_val;
    2518             : 
    2519          22 :         fname = qname_schema_object(qname);
    2520          22 :         func = resolve_func(sql, sname, fname, typelist, func_type, "COMMENT", 0);
    2521          22 :         if (func && func->s && isTempSchema(func->s)) {
    2522           0 :                 sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON tmp object not allowed");
    2523           0 :                 return 0;
    2524             :         }
    2525             :         if (func) {
    2526          22 :                 *schema_out = func->s ? func->s : mvc_bind_schema(sql, "sys");
    2527          22 :                 return func->base.id;
    2528             :         }
    2529             : 
    2530             :         return 0;
    2531             : }
    2532             : 
    2533             : static sqlid
    2534         337 : rel_find_designated_object(mvc *sql, symbol *sym, sql_schema **schema_out)
    2535             : {
    2536         337 :         sql_schema *dummy = NULL;
    2537             : 
    2538         337 :         if (schema_out == NULL)
    2539           0 :                 schema_out = &dummy;
    2540         337 :         switch (sym->token) {
    2541         249 :         case SQL_SCHEMA:
    2542         249 :                 return rel_find_designated_schema(sql, sym, schema_out);
    2543          20 :         case SQL_TABLE:
    2544          20 :                 return rel_find_designated_table(sql, sym, schema_out);
    2545           5 :         case SQL_VIEW:
    2546           5 :                 return rel_find_designated_table(sql, sym, schema_out);
    2547          18 :         case SQL_COLUMN:
    2548          18 :                 return rel_find_designated_column(sql, sym, schema_out);
    2549          15 :         case SQL_INDEX:
    2550          15 :                 return rel_find_designated_index(sql, sym, schema_out);
    2551           8 :         case SQL_SEQUENCE:
    2552           8 :                 return rel_find_designated_sequence(sql, sym, schema_out);
    2553          22 :         case SQL_ROUTINE:
    2554          22 :                 return rel_find_designated_routine(sql, sym, schema_out);
    2555           0 :         default:
    2556           0 :                 sql_error(sql, 2, SQLSTATE(42000) "COMMENT ON %s is not supported", token2string(sym->token));
    2557           0 :                 return 0;
    2558             :         }
    2559             : }
    2560             : 
    2561             : static sql_rel *
    2562         336 : rel_comment_on(sql_allocator *sa, sqlid obj_id, const char *remark)
    2563             : {
    2564         336 :         sql_rel *rel = rel_create(sa);
    2565         336 :         list *exps = new_exp_list(sa);
    2566             : 
    2567         336 :         if (rel == NULL || exps == NULL)
    2568             :                 return NULL;
    2569             : 
    2570         336 :         append(exps, exp_atom_int(sa, obj_id));
    2571         336 :         append(exps, exp_atom_clob(sa, remark));
    2572         336 :         rel->l = NULL;
    2573         336 :         rel->r = NULL;
    2574         336 :         rel->op = op_ddl;
    2575         336 :         rel->flag = ddl_comment_on;
    2576         336 :         rel->exps = exps;
    2577         336 :         rel->card = 0;
    2578         336 :         rel->nrcols = 0;
    2579         336 :         return rel;
    2580             : }
    2581             : 
    2582             : static char *
    2583        9665 : credentials_username(dlist *credentials)
    2584             : {
    2585        9665 :         if (credentials == NULL) {
    2586             :                 return NULL;
    2587             :         }
    2588          95 :         assert(credentials->h);
    2589             : 
    2590          95 :         if (credentials->h->data.sval != NULL) {
    2591             :                 return credentials->h->data.sval;
    2592             :         }
    2593             : 
    2594             :         // No username specified.
    2595             :         return NULL;
    2596             : }
    2597             : 
    2598             : static char *
    2599        9665 : credentials_password(dlist *credentials)
    2600             : {
    2601        9665 :         if (credentials == NULL) {
    2602             :                 return NULL;
    2603             :         }
    2604          95 :         assert(credentials->h);
    2605             : 
    2606          95 :         char *password = credentials->h->next->next->data.sval;
    2607             : 
    2608          95 :         return password;
    2609             : }
    2610             : 
    2611             : static sql_rel *
    2612          11 : rel_rename_schema(mvc *sql, char *old_name, char *new_name, int if_exists)
    2613             : {
    2614          11 :         sql_schema *s;
    2615          11 :         sql_rel *rel;
    2616          11 :         list *exps;
    2617          11 :         sql_trans *tr = sql->session->tr;
    2618             : 
    2619          11 :         assert(old_name && new_name);
    2620          11 :         if (!(s = mvc_bind_schema(sql, old_name))) {
    2621           2 :                 if (if_exists)
    2622           1 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    2623           1 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "ALTER SCHEMA: no such schema '%s'", old_name);
    2624             :         }
    2625           9 :         if (!mvc_schema_privs(sql, s))
    2626           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER SCHEMA: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), old_name);
    2627           9 :         if (s->system)
    2628           1 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER SCHEMA: cannot rename a system schema");
    2629           8 :         if (os_size(s->tables, tr) || os_size(s->types, tr) || os_size(s->funcs, tr) || os_size(s->seqs, tr))
    2630           1 :                 return sql_error(sql, 02, SQLSTATE(2BM37) "ALTER SCHEMA: unable to rename schema '%s' (there are database objects which depend on it)", old_name);
    2631           7 :         if (strNil(new_name) || *new_name == '\0')
    2632           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER SCHEMA: invalid new schema name");
    2633           7 :         if (mvc_bind_schema(sql, new_name))
    2634           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER SCHEMA: there is a schema named '%s' in the database", new_name);
    2635             : 
    2636           7 :         rel = rel_create(sql->sa);
    2637           7 :         exps = new_exp_list(sql->sa);
    2638           7 :         append(exps, exp_atom_clob(sql->sa, old_name));
    2639           7 :         append(exps, exp_atom_clob(sql->sa, new_name));
    2640           7 :         rel->op = op_ddl;
    2641           7 :         rel->flag = ddl_rename_schema;
    2642           7 :         rel->exps = exps;
    2643           7 :         return rel;
    2644             : }
    2645             : 
    2646             : static sql_rel *
    2647          23 : rel_rename_table(mvc *sql, char *schema_name, char *old_name, char *new_name, int if_exists)
    2648             : {
    2649          23 :         sql_table *t = NULL;
    2650          23 :         sql_rel *rel;
    2651          23 :         list *exps;
    2652             : 
    2653          23 :         assert(old_name && new_name);
    2654             : 
    2655          23 :         if (!(t = find_table_or_view_on_scope(sql, NULL, schema_name, old_name, "ALTER TABLE", false))) {
    2656           1 :                 if (if_exists) {
    2657           1 :                         sql->errstr[0] = '\0'; /* reset table not found error */
    2658           1 :                         sql->session->status = 0;
    2659           1 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    2660             :                 }
    2661             :                 return NULL;
    2662             :         }
    2663          22 :         if (isDeclaredTable(t))
    2664           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot rename a declared table");
    2665          22 :         if (!mvc_schema_privs(sql, t->s))
    2666           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), t->s->base.name);
    2667          22 :         if (t->system)
    2668           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot rename a system table");
    2669          22 :         if (isView(t))
    2670           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot rename a view");
    2671          21 :         if (mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY, NULL))
    2672           2 :                 return sql_error(sql, 02, SQLSTATE(2BM37) "ALTER TABLE: unable to rename table '%s' (there are database objects which depend on it)", old_name);
    2673          19 :         if (strNil(new_name) || *new_name == '\0')
    2674           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER TABLE: invalid new table name");
    2675          19 :         if (mvc_bind_table(sql, t->s, new_name))
    2676           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER TABLE: there is a table named '%s' in schema '%s'", new_name, t->s->base.name);
    2677             : 
    2678          19 :         rel = rel_create(sql->sa);
    2679          19 :         exps = new_exp_list(sql->sa);
    2680          19 :         append(exps, exp_atom_clob(sql->sa, t->s->base.name));
    2681          19 :         append(exps, exp_atom_clob(sql->sa, t->s->base.name));
    2682          19 :         append(exps, exp_atom_clob(sql->sa, old_name));
    2683          19 :         append(exps, exp_atom_clob(sql->sa, new_name));
    2684          19 :         rel->op = op_ddl;
    2685          19 :         rel->flag = ddl_rename_table;
    2686          19 :         rel->exps = exps;
    2687          19 :         return rel;
    2688             : }
    2689             : 
    2690             : static sql_rel *
    2691          20 : rel_rename_column(mvc *sql, char *schema_name, char *table_name, char *old_name, char *new_name, int if_exists)
    2692             : {
    2693          20 :         sql_table *t = NULL;
    2694          20 :         sql_column *col;
    2695          20 :         sql_rel *rel;
    2696          20 :         list *exps;
    2697             : 
    2698          20 :         assert(table_name && old_name && new_name);
    2699             : 
    2700          20 :         if (!(t = find_table_or_view_on_scope(sql, NULL, schema_name, table_name, "ALTER TABLE", false))) {
    2701           2 :                 if (if_exists) {
    2702           1 :                         sql->errstr[0] = '\0'; /* reset table not found error */
    2703           1 :                         sql->session->status = 0;
    2704           1 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    2705             :                 }
    2706             :                 return NULL;
    2707             :         }
    2708          18 :         if (isDeclaredTable(t))
    2709           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot rename a column in a declared table");
    2710          18 :         if (!mvc_schema_privs(sql, t->s))
    2711           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), t->s->base.name);
    2712          18 :         if (t->system)
    2713           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot rename a column in a system table");
    2714          18 :         if (isView(t))
    2715           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot rename column '%s': '%s' is a view", old_name, table_name);
    2716          18 :         if (!(col = mvc_bind_column(sql, t, old_name)))
    2717           5 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "ALTER TABLE: no such column '%s' in table '%s'", old_name, table_name);
    2718          13 :         if (mvc_check_dependency(sql, col->base.id, COLUMN_DEPENDENCY, NULL))
    2719           0 :                 return sql_error(sql, 02, SQLSTATE(2BM37) "ALTER TABLE: cannot rename column '%s' (there are database objects which depend on it)", old_name);
    2720          13 :         if (strNil(new_name) || *new_name == '\0')
    2721           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER TABLE: invalid new column name");
    2722          13 :         if (mvc_bind_column(sql, t, new_name))
    2723           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER TABLE: there is a column named '%s' in table '%s'", new_name, table_name);
    2724             : 
    2725          13 :         rel = rel_create(sql->sa);
    2726          13 :         exps = new_exp_list(sql->sa);
    2727          13 :         append(exps, exp_atom_clob(sql->sa, t->s->base.name));
    2728          13 :         append(exps, exp_atom_clob(sql->sa, table_name));
    2729          13 :         append(exps, exp_atom_clob(sql->sa, old_name));
    2730          13 :         append(exps, exp_atom_clob(sql->sa, new_name));
    2731          13 :         rel->op = op_ddl;
    2732          13 :         rel->flag = ddl_rename_column;
    2733          13 :         rel->exps = exps;
    2734          13 :         return rel;
    2735             : }
    2736             : 
    2737             : static sql_rel *
    2738          29 : rel_set_table_schema(sql_query *query, char *old_schema, char *tname, char *new_schema, int if_exists)
    2739             : {
    2740          29 :         mvc *sql = query->sql;
    2741          29 :         sql_schema *ns = NULL;
    2742          29 :         sql_table *ot = NULL;
    2743          29 :         sql_rel *rel;
    2744          29 :         list *exps;
    2745             : 
    2746          29 :         assert(tname && new_schema);
    2747             : 
    2748          29 :         if (!(ot = find_table_or_view_on_scope(sql, NULL, old_schema, tname, "ALTER TABLE", false))) {
    2749           0 :                 if (if_exists) {
    2750           0 :                         sql->errstr[0] = '\0'; /* reset table not found error */
    2751           0 :                         sql->session->status = 0;
    2752           0 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    2753             :                 }
    2754             :                 return NULL;
    2755             :         }
    2756          29 :         if (isDeclaredTable(ot))
    2757           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: not possible to change schema of a declared table");
    2758          29 :         if (!mvc_schema_privs(sql, ot->s))
    2759           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), ot->s->base.name);
    2760          29 :         if (ot->system)
    2761           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot set schema of a system table");
    2762          29 :         if (isTempSchema(ot->s))
    2763           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: not possible to change a temporary table schema");
    2764          29 :         if (isView(ot))
    2765           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: not possible to change schema of a view");
    2766          29 :         if (mvc_check_dependency(sql, ot->base.id, TABLE_DEPENDENCY, NULL) || list_length(ot->members) || ol_length(ot->triggers))
    2767           3 :                 return sql_error(sql, 02, SQLSTATE(2BM37) "ALTER TABLE: unable to set schema of table '%s' (there are database objects which depend on it)", tname);
    2768          26 :         if (!(ns = mvc_bind_schema(sql, new_schema)))
    2769           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "ALTER TABLE: no such schema '%s'", new_schema);
    2770          26 :         if (!mvc_schema_privs(sql, ns))
    2771           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: access denied for '%s' to schema '%s'", get_string_global_var(sql, "current_user"), new_schema);
    2772          26 :         if (isTempSchema(ns))
    2773           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "ALTER TABLE: not possible to change table's schema to temporary");
    2774          26 :         if (mvc_bind_table(sql, ns, tname))
    2775           0 :                 return sql_error(sql, 02, SQLSTATE(42S02) "ALTER TABLE: table '%s' on schema '%s' already exists", tname, new_schema);
    2776             : 
    2777          26 :         rel = rel_create(sql->sa);
    2778          26 :         exps = new_exp_list(sql->sa);
    2779          26 :         append(exps, exp_atom_clob(sql->sa, ot->s->base.name));
    2780          26 :         append(exps, exp_atom_clob(sql->sa, new_schema));
    2781          26 :         append(exps, exp_atom_clob(sql->sa, tname));
    2782          26 :         append(exps, exp_atom_clob(sql->sa, tname));
    2783          26 :         rel->op = op_ddl;
    2784          26 :         rel->flag = ddl_rename_table;
    2785          26 :         rel->exps = exps;
    2786          26 :         return rel;
    2787             : }
    2788             : 
    2789             : sql_rel *
    2790      206658 : rel_schemas(sql_query *query, symbol *s)
    2791             : {
    2792      206658 :         mvc *sql = query->sql;
    2793      206658 :         sql_rel *ret = NULL;
    2794             : 
    2795      206658 :         if (s->token != SQL_CREATE_TABLE && s->token != SQL_CREATE_VIEW && store_readonly(sql->session->tr->store))
    2796           2 :                 return sql_error(sql, 06, SQLSTATE(25006) "Schema statements cannot be executed on a readonly database.");
    2797             : 
    2798      206656 :         switch (s->token) {
    2799        1078 :         case SQL_CREATE_SCHEMA:
    2800             :         {
    2801        1078 :                 dlist *l = s->data.lval;
    2802             : 
    2803        1078 :                 ret = rel_create_schema(query, l->h->data.lval,
    2804        1078 :                                 l->h->next->next->next->data.lval,
    2805        1078 :                                 l->h->next->next->next->next->data.i_val); /* if not exists */
    2806        1078 :         }       break;
    2807         184 :         case SQL_DROP_SCHEMA:
    2808             :         {
    2809         184 :                 dlist *l = s->data.lval;
    2810         184 :                 dlist *auth_name = l->h->data.lval;
    2811             : 
    2812         184 :                 assert(l->h->next->type == type_int);
    2813         368 :                 ret = rel_drop(sql->sa, ddl_drop_schema,
    2814             :                            dlist_get_schema_name(auth_name),
    2815             :                            NULL,
    2816             :                            NULL,
    2817             :                            l->h->next->data.i_val,     /* drop_action */
    2818         184 :                            l->h->next->next->data.i_val); /* if exists */
    2819         184 :         }       break;
    2820           1 :         case SQL_DECLARE_TABLE:
    2821           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "Tables cannot be declared on the global scope");
    2822        9665 :         case SQL_CREATE_TABLE:
    2823             :         {
    2824        9665 :                 dlist *l = s->data.lval;
    2825        9665 :                 dlist *qname = l->h->next->data.lval;
    2826        9665 :                 char *sname = qname_schema(qname);
    2827        9665 :                 char *name = qname_schema_object(qname);
    2828        9665 :                 int temp = l->h->data.i_val;
    2829        9665 :                 dlist *credentials = l->h->next->next->next->next->next->data.lval;
    2830        9665 :                 char *username = credentials_username(credentials);
    2831        9665 :                 char *password = credentials_password(credentials);
    2832        9665 :                 bool pw_encrypted = credentials == NULL || credentials->h->next->data.i_val == SQL_PW_ENCRYPTED;
    2833        9665 :                 if (username == NULL) {
    2834             :                         // No username specified, get the current username
    2835        9651 :                         username = get_string_global_var(sql, "current_user");
    2836             :                 }
    2837             : 
    2838        9665 :                 assert(l->h->type == type_int);
    2839        9665 :                 assert(l->h->next->next->next->type == type_int);
    2840        9665 :                 ret = rel_create_table(query, temp, sname, name, true,
    2841        9665 :                                        l->h->next->next->data.sym,                   /* elements or subquery */
    2842             :                                        l->h->next->next->next->data.i_val,           /* commit action */
    2843        9665 :                                        l->h->next->next->next->next->data.sval,      /* location */
    2844             :                                        username, password, pw_encrypted,
    2845        9665 :                                        l->h->next->next->next->next->next->next->next->data.sym,
    2846        9665 :                                        l->h->next->next->next->next->next->next->data.i_val); /* if not exists */
    2847        9665 :         }       break;
    2848       77553 :         case SQL_CREATE_VIEW:
    2849             :         {
    2850       77553 :                 dlist *l = s->data.lval;
    2851             : 
    2852       77553 :                 assert(l->h->next->next->next->type == type_int);
    2853       77553 :                 assert(l->h->next->next->next->next->type == type_int);
    2854       77553 :                 ret = rel_create_view(query, l->h->data.lval,
    2855       77553 :                                                           l->h->next->data.lval,
    2856       77553 :                                                           l->h->next->next->data.sym,
    2857             :                                                           l->h->next->next->next->data.i_val,
    2858             :                                                           l->h->next->next->next->next->data.i_val,
    2859       77553 :                                                           l->h->next->next->next->next->next->data.i_val); /* or replace */
    2860       77553 :         }       break;
    2861        3627 :         case SQL_DROP_TABLE:
    2862             :         {
    2863        3627 :                 dlist *l = s->data.lval;
    2864             : 
    2865        3627 :                 assert(l->h->next->type == type_int);
    2866        3627 :                 ret = sql_drop_table(query, l->h->data.lval,
    2867             :                                                          l->h->next->data.i_val,
    2868        3627 :                                                          l->h->next->next->data.i_val); /* if exists */
    2869        3627 :         }       break;
    2870         258 :         case SQL_DROP_VIEW:
    2871             :         {
    2872         258 :                 dlist *l = s->data.lval;
    2873             : 
    2874         258 :                 assert(l->h->next->type == type_int);
    2875         258 :                 ret = sql_drop_view(query, l->h->data.lval,
    2876             :                                                         l->h->next->data.i_val,
    2877         258 :                                                         l->h->next->next->data.i_val); /* if exists */
    2878         258 :         }       break;
    2879        4075 :         case SQL_ALTER_TABLE:
    2880             :         {
    2881        4075 :                 dlist *l = s->data.lval;
    2882             : 
    2883        4075 :                 ret = sql_alter_table(query, l,
    2884        4075 :                         l->h->data.lval,      /* table name */
    2885        4075 :                         l->h->next->data.sym, /* table element */
    2886        4075 :                         l->h->next->next->data.i_val); /* if exists */
    2887        4075 :         }       break;
    2888          38 :         case SQL_GRANT_ROLES:
    2889             :         {
    2890          38 :                 dlist *l = s->data.lval;
    2891             : 
    2892          38 :                 assert(l->h->next->next->type == type_int);
    2893          38 :                 assert(l->h->next->next->next->type == type_int);
    2894          38 :                 ret = rel_grant_or_revoke_roles(sql, l->h->data.lval,     /* authids */
    2895          38 :                                   l->h->next->data.lval,       /* grantees */
    2896             :                                   l->h->next->next->data.i_val,     /* admin? */
    2897          38 :                                   l->h->next->next->next->data.i_val == cur_user ? sql->user_id : sql->role_id, ddl_grant_roles);
    2898             :                 /* grantor ? */
    2899          38 :         }       break;
    2900          10 :         case SQL_REVOKE_ROLES:
    2901             :         {
    2902          10 :                 dlist *l = s->data.lval;
    2903             : 
    2904          10 :                 assert(l->h->next->next->type == type_int);
    2905          10 :                 assert(l->h->next->next->next->type == type_int);
    2906          10 :                 ret = rel_grant_or_revoke_roles(sql, l->h->data.lval,     /* authids */
    2907          10 :                                   l->h->next->data.lval,       /* grantees */
    2908             :                                   l->h->next->next->data.i_val,     /* admin? */
    2909          10 :                                   l->h->next->next->next->data.i_val  == cur_user? sql->user_id : sql->role_id, ddl_revoke_roles);
    2910             :                 /* grantor ? */
    2911          10 :         }       break;
    2912      107733 :         case SQL_GRANT:
    2913             :         {
    2914      107733 :                 dlist *l = s->data.lval;
    2915             : 
    2916      107733 :                 assert(l->h->next->next->type == type_int);
    2917      107733 :                 assert(l->h->next->next->next->type == type_int);
    2918      107733 :                 ret = rel_grant_or_revoke_privs(sql, l->h->data.lval,     /* privileges */
    2919      107733 :                                   l->h->next->data.lval,       /* grantees */
    2920             :                                   l->h->next->next->data.i_val,     /* grant ? */
    2921      107733 :                                   l->h->next->next->next->data.i_val  == cur_user? sql->user_id : sql->role_id, ddl_grant);
    2922             :                 /* grantor ? */
    2923      107733 :         }       break;
    2924          16 :         case SQL_REVOKE:
    2925             :         {
    2926          16 :                 dlist *l = s->data.lval;
    2927             : 
    2928          16 :                 assert(l->h->next->next->type == type_int);
    2929          16 :                 assert(l->h->next->next->next->type == type_int);
    2930          16 :                 ret = rel_grant_or_revoke_privs(sql, l->h->data.lval,     /* privileges */
    2931          16 :                                    l->h->next->data.lval,      /* grantees */
    2932             :                                    l->h->next->next->data.i_val,    /* grant ? */
    2933          16 :                                    l->h->next->next->next->data.i_val  == cur_user? sql->user_id : sql->role_id, ddl_revoke);
    2934             :                 /* grantor ? */
    2935          16 :         }       break;
    2936          25 :         case SQL_CREATE_ROLE:
    2937             :         {
    2938          25 :                 dlist *l = s->data.lval;
    2939          25 :                 char *rname = l->h->data.sval;
    2940          25 :                 ret = rel_schema2(sql->sa, ddl_create_role, rname, NULL,
    2941          25 :                                  l->h->next->data.i_val  == cur_user? sql->user_id : sql->role_id);
    2942          25 :         }       break;
    2943          19 :         case SQL_DROP_ROLE:
    2944             :         {
    2945          19 :                 char *rname = s->data.sval;
    2946          19 :                 ret = rel_schema2(sql->sa, ddl_drop_role, rname, NULL, 0);
    2947          19 :         }       break;
    2948         337 :         case SQL_CREATE_INDEX: {
    2949         337 :                 dlist *l = s->data.lval;
    2950             : 
    2951         337 :                 assert(l->h->next->type == type_int);
    2952         337 :                 ret = rel_create_index(sql, l->h->data.sval, (idx_type) l->h->next->data.i_val, l->h->next->next->data.lval, l->h->next->next->next->data.lval);
    2953         337 :         }       break;
    2954         198 :         case SQL_DROP_INDEX: {
    2955         198 :                 dlist *l = s->data.lval;
    2956         198 :                 char *sname = qname_schema(l);
    2957         198 :                 char *iname = qname_schema_object(l);
    2958         198 :                 sql_idx *idx = NULL;
    2959             : 
    2960         198 :                 if (!(idx = find_idx_on_scope(sql, sname, iname, "DROP INDEX")))
    2961             :                         return NULL;
    2962         161 :                 ret = rel_schema2(sql->sa, ddl_drop_index, idx->t->s->base.name, iname, 0);
    2963         161 :         }       break;
    2964         331 :         case SQL_CREATE_USER: {
    2965         331 :                 dlist *l = s->data.lval;
    2966         331 :                 dlist *schema_details = l->h->next->next->next->data.lval;
    2967             : 
    2968         331 :                 ret = rel_create_user(sql->sa, l->h->data.sval,        /* user name */
    2969             :                                   l->h->next->data.sval,       /* password */
    2970         331 :                                   l->h->next->next->next->next->data.i_val == SQL_PW_ENCRYPTED, /* encrypted */
    2971             :                                   l->h->next->next->data.sval,      /* fullname */
    2972             :                                   schema_details->h->data.sval,   /* schema ident*/
    2973         331 :                                   schema_details->h->next->data.sval,  /* schema path */
    2974             :                                   l->h->next->next->next->next->next->data.l_val,  /* max memory */
    2975             :                                   l->h->next->next->next->next->next->next->data.i_val, /* max workers */
    2976             :                                   l->h->next->next->next->next->next->next->next->data.sval, /* optimizer */
    2977         331 :                                   l->h->next->next->next->next->next->next->next->next->data.sval); /* default role */
    2978         331 :         }       break;
    2979         104 :         case SQL_DROP_USER:
    2980         104 :                 ret = rel_schema2(sql->sa, ddl_drop_user, s->data.sval, NULL, 0);
    2981         104 :                 break;
    2982          76 :         case SQL_ALTER_USER: {
    2983          76 :                 dlist *l = s->data.lval;
    2984          76 :                 dnode *a = l->h->next->data.lval->h;
    2985             : 
    2986          76 :                 ret = rel_alter_user(sql->sa, l->h->data.sval, /* user */
    2987             :                              a->data.sval,   /* passwd */
    2988          76 :                              a->next->next->next->data.i_val == SQL_PW_ENCRYPTED, /* encrypted */
    2989             :                              a->next->data.sval,  /* schema */
    2990             :                                  a->next->next->data.sval, /* schema path */
    2991          76 :                              a->next->next->next->next->data.sval, /* old passwd */
    2992             :                              l->h->next->next->data.sval, /* default role */
    2993             :                              l->h->next->next->next->data.l_val, /* max_memory */
    2994          76 :                              l->h->next->next->next->next->data.i_val /* max_workers */
    2995             :                     );
    2996          76 :         }       break;
    2997           5 :         case SQL_RENAME_USER: {
    2998           5 :                 dlist *l = s->data.lval;
    2999             : 
    3000           5 :                 ret = rel_schema2(sql->sa, ddl_rename_user, l->h->data.sval, l->h->next->data.sval, 0);
    3001           5 :         }       break;
    3002          11 :         case SQL_RENAME_SCHEMA: {
    3003          11 :                 dlist *l = s->data.lval;
    3004          11 :                 ret = rel_rename_schema(sql, l->h->data.sval, l->h->next->data.sval, l->h->next->next->data.i_val);
    3005          11 :         }       break;
    3006          23 :         case SQL_RENAME_TABLE: {
    3007          23 :                 dlist *l = s->data.lval;
    3008          23 :                 char *sname = qname_schema(l->h->data.lval);
    3009          23 :                 char *tname = qname_schema_object(l->h->data.lval);
    3010          23 :                 ret = rel_rename_table(sql, sname, tname, l->h->next->data.sval, l->h->next->next->data.i_val);
    3011          23 :         }       break;
    3012          20 :         case SQL_RENAME_COLUMN: {
    3013          20 :                 dlist *l = s->data.lval;
    3014          20 :                 char *sname = qname_schema(l->h->data.lval);
    3015          20 :                 char *tname = qname_schema_object(l->h->data.lval);
    3016          20 :                 ret = rel_rename_column(sql, sname, tname, l->h->next->data.sval, l->h->next->next->data.sval, l->h->next->next->next->data.i_val);
    3017          20 :         }       break;
    3018          29 :         case SQL_SET_TABLE_SCHEMA: {
    3019          29 :                 dlist *l = s->data.lval;
    3020          29 :                 char *sname = qname_schema(l->h->data.lval);
    3021          29 :                 char *tname = qname_schema_object(l->h->data.lval);
    3022          29 :                 ret = rel_set_table_schema(query, sname, tname, l->h->next->data.sval, l->h->next->next->data.i_val);
    3023          29 :         }       break;
    3024         898 :         case SQL_CREATE_TYPE: {
    3025         898 :                 dlist *l = s->data.lval;
    3026             : 
    3027         898 :                 ret = rel_create_type(sql, l->h->data.lval, l->h->next->data.sval);
    3028         898 :         }       break;
    3029           5 :         case SQL_DROP_TYPE: {
    3030           5 :                 dlist *l = s->data.lval;
    3031           5 :                 ret = rel_drop_type(sql, l->h->data.lval, l->h->next->data.i_val);
    3032           5 :         }       break;
    3033         337 :         case SQL_COMMENT:
    3034             :         {
    3035         337 :                 dlist *l = s->data.lval;
    3036         337 :                 symbol *catalog_object = l->h->data.sym;
    3037         337 :                 char *remark;
    3038         337 :                 sql_schema *s;
    3039         337 :                 sqlid id;
    3040             : 
    3041         337 :                 assert(l->cnt == 2);
    3042         337 :                 remark = l->h->next->data.sval;
    3043             : 
    3044         337 :                 id = rel_find_designated_object(sql, catalog_object, &s);
    3045         337 :                 if (!id) {
    3046             :                         /* rel_find_designated_object has already set the error message so we don't have to */
    3047             :                         return NULL;
    3048             :                 }
    3049             : 
    3050             :                 // Check authorization
    3051         337 :                 if (!mvc_schema_privs(sql, s)) {
    3052           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON: insufficient privileges for user '%s' in schema '%s'", get_string_global_var(sql, "current_user"), s->base.name);
    3053             :                 }
    3054             : 
    3055         336 :                 return rel_comment_on(sql->sa, id, remark);
    3056             :         }
    3057           0 :         default:
    3058           0 :                 return sql_error(sql, 01, SQLSTATE(M0M03) "Schema statement unknown symbol(%p)->token = %s", s, token2string(s->token));
    3059             :         }
    3060             : 
    3061      206281 :         sql->type = Q_SCHEMA;
    3062      206281 :         return ret;
    3063             : }

Generated by: LCOV version 1.14