LCOV - code coverage report
Current view: top level - sql/server - rel_schema.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1402 1764 79.5 %
Date: 2021-10-13 02:24:04 Functions: 58 58 100.0 %

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

Generated by: LCOV version 1.14