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