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