LCOV - code coverage report
Current view: top level - sql/server - rel_schema.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1749 2203 79.4 %
Date: 2025-03-24 21:28:01 Functions: 62 62 100.0 %

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

Generated by: LCOV version 1.14