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