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