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