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_psm.h"
11#include "rel_semantic.h"
12#include "rel_schema.h"
13#include "rel_select.h"
14#include "rel_rel.h"
15#include "rel_exp.h"
16#include "rel_updates.h"
17#include "sql_privileges.h"
18
19static list *sequential_block(sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_name, int is_func);
20
21sql_rel *
22rel_psm_block(sql_allocator *sa, list *l)
23{
24 if (l) {
25 sql_rel *r = rel_create(sa);
26 if(!r)
27 return NULL;
28
29 r->op = op_ddl;
30 r->flag = ddl_psm;
31 r->exps = l;
32 return r;
33 }
34 return NULL;
35}
36
37sql_rel *
38rel_psm_stmt(sql_allocator *sa, sql_exp *e)
39{
40 if (e) {
41 list *l = sa_list(sa);
42 if(!l)
43 return NULL;
44
45 list_append(l, e);
46 return rel_psm_block(sa, l);
47 }
48 return NULL;
49}
50
51/* SET variable = value and set (variable1, .., variableN) = (query) */
52static sql_exp *
53psm_set_exp(sql_query *query, dnode *n)
54{
55 mvc *sql = query->sql;
56 symbol *val = n->next->data.sym;
57 sql_exp *e = NULL;
58 int level = 0, is_last = 0;
59 sql_subtype *tpe = NULL;
60 sql_rel *rel = NULL;
61 sql_exp *res = NULL;
62 int single = (n->type == type_string);
63
64 if (single) {
65 exp_kind ek = {type_value, card_value, FALSE};
66 const char *name = n->data.sval;
67 /* name can be
68 'parameter of the function' (ie in the param list)
69 or a local or global variable, declared earlier
70 */
71
72 /* check if variable is known from the stack */
73 if (!stack_find_var(sql, name)) {
74 sql_arg *a = sql_bind_param(sql, name);
75
76 if (!a) /* not parameter, ie local var ? */
77 return sql_error(sql, 01, SQLSTATE(42000) "Variable %s unknown", name);
78 tpe = &a->type;
79 } else {
80 tpe = stack_find_type(sql, name);
81 }
82
83 e = rel_value_exp2(query, &rel, val, sql_sel, ek, &is_last);
84 if (!e || (rel && e->card > CARD_AGGR))
85 return NULL;
86
87 level = stack_find_frame(sql, name);
88 e = rel_check_type(sql, tpe, rel, e, type_cast);
89 if (!e)
90 return NULL;
91
92 res = exp_set(sql->sa, name, e, level);
93 } else { /* multi assignment */
94 exp_kind ek = {type_value, card_relation, FALSE};
95 sql_rel *rel_val = rel_subquery(query, NULL, val, ek);
96 dlist *vars = n->data.lval;
97 dnode *m;
98 node *n;
99 list *b;
100
101 if (!rel_val || !is_project(rel_val->op) || dlist_length(vars) != list_length(rel_val->exps))
102 return sql_error(sql, 02, SQLSTATE(42000) "SET: Number of variables not equal to number of supplied values");
103
104 b = sa_list(sql->sa);
105 append(b, exp_rel(sql, rel_val));
106
107 for(m = vars->h, n = rel_val->exps->h; n && m; n = n->next, m = m->next) {
108 char *vname = m->data.sval;
109 sql_exp *v = n->data;
110
111 if (!stack_find_var(sql, vname)) {
112 sql_arg *a = sql_bind_param(sql, vname);
113
114 if (!a) /* not parameter, ie local var ? */
115 return sql_error(sql, 01, SQLSTATE(42000) "Variable %s unknown", vname);
116 tpe = &a->type;
117 } else {
118 tpe = stack_find_type(sql, vname);
119 }
120
121 if (!exp_name(v))
122 exp_label(sql->sa, v, ++sql->label);
123 v = exp_ref(sql->sa, v);
124
125 level = stack_find_frame(sql, vname);
126 v = rel_check_type(sql, tpe, rel_val, v, type_cast);
127 if (!v)
128 return NULL;
129 if (v->card > CARD_AGGR) {
130 sql_subaggr *zero_or_one = sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(v));
131 assert(zero_or_one);
132 v = exp_aggr1(sql->sa, v, zero_or_one, 0, 0, CARD_ATOM, 0);
133 }
134 append(b, exp_set(sql->sa, vname, v, level));
135 }
136 res = exp_rel(sql, rel_psm_block(sql->sa, b));
137 }
138 return res;
139}
140
141static sql_exp*
142rel_psm_call(sql_query * query, symbol *se)
143{
144 mvc *sql = query->sql;
145 sql_subtype *t;
146 sql_exp *res = NULL;
147 exp_kind ek = {type_value, card_none, FALSE};
148 sql_rel *rel = NULL;
149
150 res = rel_value_exp(query, &rel, se, sql_sel, ek);
151 if (!res || rel || ((t=exp_subtype(res)) && t->type)) /* only procedures */
152 return sql_error(sql, 01, SQLSTATE(42000) "Function calls are ignored");
153 return res;
154}
155
156static list *
157rel_psm_declare(mvc *sql, dnode *n)
158{
159 list *l = sa_list(sql->sa);
160
161 while(n) { /* list of 'identfiers with type' */
162 dnode *ids = n->data.sym->data.lval->h->data.lval->h;
163 sql_subtype *ctype = &n->data.sym->data.lval->h->next->data.typeval;
164 while(ids) {
165 const char *name = ids->data.sval;
166 sql_exp *r = NULL;
167
168 /* check if we overwrite a scope local variable declare x; declare x; */
169 if (frame_find_var(sql, name)) {
170 return sql_error(sql, 01,
171 SQLSTATE(42000) "Variable '%s' already declared", name);
172 }
173 /* variables are put on stack,
174 * TODO make sure on plan/explain etc they only
175 * exist during plan phase */
176 if(!stack_push_var(sql, name, ctype)) {
177 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
178 }
179 r = exp_var(sql->sa, sa_strdup(sql->sa, name), ctype, sql->frame);
180 append(l, r);
181 ids = ids->next;
182 }
183 n = n->next;
184 }
185 return l;
186}
187
188static sql_exp *
189rel_psm_declare_table(sql_query *query, dnode *n)
190{
191 mvc *sql = query->sql;
192 sql_rel *rel = NULL, *baset = NULL;
193 dlist *qname = n->next->data.lval;
194 const char *name = qname_table(qname);
195 const char *sname = qname_schema(qname);
196 sql_table *t;
197
198 if (sname) /* not allowed here */
199 return sql_error(sql, 02, SQLSTATE(42000) "DECLARE TABLE: qualified name not allowed");
200 if (frame_find_var(sql, name))
201 return sql_error(sql, 01, SQLSTATE(42000) "Variable '%s' already declared", name);
202
203 assert(n->next->next->next->type == type_int);
204 rel = rel_create_table(query, cur_schema(sql), SQL_DECLARED_TABLE, NULL, name, n->next->next->data.sym,
205 n->next->next->next->data.i_val, NULL, NULL, NULL, false, NULL, 0);
206
207 if (!rel)
208 return NULL;
209 if(rel->op == op_ddl) {
210 baset = rel;
211 } else if(rel->op == op_insert) {
212 baset = rel->l;
213 } else {
214 return NULL;
215 }
216 if(baset->flag != ddl_create_table)
217 return NULL;
218 t = (sql_table*)((atom*)((sql_exp*)baset->exps->t->data)->l)->data.val.pval;
219 if(!stack_push_table(sql, name, baset, t))
220 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
221 return exp_table(sql->sa, sa_strdup(sql->sa, name), t, sql->frame);
222}
223
224/* [ label: ]
225 while (cond) do
226 statement_list
227 end [ label ]
228 currently we only parse the labels, they cannot be used as there is no
229
230 support for LEAVE and ITERATE (sql multi-level break and continue)
231 */
232static sql_exp *
233rel_psm_while_do( sql_query *query, sql_subtype *res, list *restypelist, dnode *w, int is_func )
234{
235 mvc *sql = query->sql;
236 if (!w)
237 return NULL;
238 if (w->type == type_symbol) {
239 sql_exp *cond;
240 list *whilestmts;
241 dnode *n = w;
242 sql_rel *rel = NULL;
243
244 cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel);
245 n = n->next;
246 whilestmts = sequential_block(query, res, restypelist, n->data.lval, n->next->data.sval, is_func);
247
248 if (sql->session->status || !cond || !whilestmts)
249 return NULL;
250 if (rel) {
251 assert(0);
252 sql_exp *er = exp_rel(sql, rel);
253 list *b = sa_list(sql->sa);
254
255 append(b, er);
256 append(b, exp_while( sql->sa, cond, whilestmts ));
257 return exp_rel(sql, rel_psm_block(sql->sa, b));
258 }
259 return exp_while( sql->sa, cond, whilestmts );
260 }
261 return NULL;
262}
263
264/* if (cond) then statement_list
265 [ elseif (cond) then statement_list ]*
266 [ else statement_list ]
267 end if
268 */
269static list *
270psm_if_then_else( sql_query *query, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
271{
272 mvc *sql = query->sql;
273 if (!elseif)
274 return NULL;
275 assert(elseif->type == type_symbol);
276 if (elseif->data.sym && elseif->data.sym->token == SQL_IF) {
277 sql_exp *cond;
278 list *ifstmts, *elsestmts;
279 dnode *n = elseif->data.sym->data.lval->h;
280 sql_rel *rel = NULL;
281
282 cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel);
283 n = n->next;
284 ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func);
285 n = n->next;
286 elsestmts = psm_if_then_else( query, res, restypelist, n, is_func);
287
288 if (sql->session->status || !cond || !ifstmts)
289 return NULL;
290 if (rel) {
291 assert(0);
292 sql_exp *er = exp_rel(sql, rel);
293 list *b = sa_list(sql->sa);
294
295 append(b, er);
296 append(b, exp_if(sql->sa, cond, ifstmts, elsestmts));
297 return b;
298 }
299 return append(sa_list(sql->sa), exp_if( sql->sa, cond, ifstmts, elsestmts));
300 } else { /* else */
301 symbol *e = elseif->data.sym;
302
303 if (e==NULL || (e->token != SQL_ELSE))
304 return NULL;
305 return sequential_block( query, res, restypelist, e->data.lval, NULL, is_func);
306 }
307}
308
309static sql_exp *
310rel_psm_if_then_else( sql_query *query, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
311{
312 mvc *sql = query->sql;
313 if (!elseif)
314 return NULL;
315 if (elseif->next && elseif->type == type_symbol) { /* if or elseif */
316 sql_exp *cond;
317 list *ifstmts, *elsestmts;
318 dnode *n = elseif;
319 sql_rel *rel = NULL;
320
321 cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel);
322 n = n->next;
323 ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func);
324 n = n->next;
325 elsestmts = psm_if_then_else( query, res, restypelist, n, is_func);
326 if (sql->session->status || !cond || !ifstmts)
327 return NULL;
328 if (rel) {
329 assert(0);
330 sql_exp *er = exp_rel(sql, rel);
331 list *b = sa_list(sql->sa);
332
333 append(b, er);
334 append(b, exp_if(sql->sa, cond, ifstmts, elsestmts));
335 return exp_rel(sql, rel_psm_block(sql->sa, b));
336 }
337 return exp_if( sql->sa, cond, ifstmts, elsestmts);
338 }
339 return NULL;
340}
341
342/* 1
343 CASE
344 WHEN search_condition THEN statements
345 [ WHEN search_condition THEN statements ]
346 [ ELSE statements ]
347 END CASE
348
349 2
350 CASE case_value
351 WHEN when_value THEN statements
352 [ WHEN when_value THEN statements ]
353 [ ELSE statements ]
354 END CASE
355 */
356static list *
357rel_psm_case( sql_query *query, sql_subtype *res, list *restypelist, dnode *case_when, int is_func )
358{
359 mvc *sql = query->sql;
360 list *case_stmts = sa_list(sql->sa);
361
362 if (!case_when)
363 return NULL;
364
365 /* case 1 */
366 if (case_when->type == type_symbol) {
367 dnode *n = case_when;
368 symbol *case_value = n->data.sym;
369 dlist *when_statements = n->next->data.lval;
370 dlist *else_statements = n->next->next->data.lval;
371 list *else_stmt = NULL;
372 sql_rel *rel = NULL;
373 exp_kind ek = {type_value, card_value, FALSE};
374 sql_exp *v = rel_value_exp(query, &rel, case_value, sql_sel, ek);
375
376 if (!v)
377 return NULL;
378 if (rel)
379 return sql_error(sql, 02, SQLSTATE(42000) "CASE: No SELECT statements allowed within the CASE condition");
380 if (else_statements) {
381 else_stmt = sequential_block( query, res, restypelist, else_statements, NULL, is_func);
382 if (!else_stmt)
383 return NULL;
384 }
385 n = when_statements->h;
386 while(n) {
387 dnode *m = n->data.sym->data.lval->h;
388 sql_exp *cond=0, *when_value = rel_value_exp(query, &rel, m->data.sym, sql_sel, ek);
389 list *if_stmts = NULL;
390 sql_exp *case_stmt = NULL;
391
392 if (!when_value || rel ||
393 (cond = rel_binop_(sql, rel, v, when_value, NULL, "=", card_value)) == NULL ||
394 (if_stmts = sequential_block( query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) {
395 if (rel)
396 return sql_error(sql, 02, SQLSTATE(42000) "CASE: No SELECT statements allowed within the CASE condition");
397 return NULL;
398 }
399 case_stmt = exp_if(sql->sa, cond, if_stmts, NULL);
400 list_append(case_stmts, case_stmt);
401 n = n->next;
402 }
403 if (else_stmt)
404 list_merge(case_stmts, else_stmt, NULL);
405 return case_stmts;
406 } else {
407 /* case 2 */
408 dnode *n = case_when;
409 dlist *whenlist = n->data.lval;
410 dlist *else_statements = n->next->data.lval;
411 list *else_stmt = NULL;
412
413 if (else_statements) {
414 else_stmt = sequential_block( query, res, restypelist, else_statements, NULL, is_func);
415 if (!else_stmt)
416 return NULL;
417 }
418 n = whenlist->h;
419 while(n) {
420 dnode *m = n->data.sym->data.lval->h;
421 sql_rel *rel = NULL;
422 sql_exp *cond = rel_logical_value_exp(query, &rel, m->data.sym, sql_sel);
423 list *if_stmts = NULL;
424 sql_exp *case_stmt = NULL;
425
426 if (!cond || rel ||
427 (if_stmts = sequential_block( query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) {
428 if (rel)
429 return sql_error(sql, 02, SQLSTATE(42000) "CASE: No SELECT statements allowed within the CASE condition");
430 return NULL;
431 }
432 case_stmt = exp_if(sql->sa, cond, if_stmts, NULL);
433 list_append(case_stmts, case_stmt);
434 n = n->next;
435 }
436 if (else_stmt)
437 list_merge(case_stmts, else_stmt, NULL);
438 return case_stmts;
439 }
440}
441
442/* return val;
443 */
444static list *
445rel_psm_return( sql_query *query, sql_subtype *restype, list *restypelist, symbol *return_sym )
446{
447 mvc *sql = query->sql;
448 exp_kind ek = {type_value, card_value, FALSE};
449 sql_exp *res;
450 sql_rel *rel = NULL;
451 int is_last = 0;
452 list *l = sa_list(sql->sa);
453
454 if (restypelist)
455 ek.card = card_relation;
456 res = rel_value_exp2(query, &rel, return_sym, sql_sel, ek, &is_last);
457 if (!res)
458 return NULL;
459 if (!rel && exp_is_rel(res))
460 rel = exp_rel_get_rel(sql->sa, res);
461 if (ek.card != card_relation && (!restype || (res = rel_check_type(sql, restype, rel, res, type_equal)) == NULL))
462 return (!restype)?sql_error(sql, 02, SQLSTATE(42000) "RETURN: return type does not match"):NULL;
463 else if (ek.card == card_relation && !rel)
464 return NULL;
465
466 if (rel && !is_ddl(rel->op) && ek.card == card_relation) {
467 list *exps = sa_list(sql->sa), *oexps = rel->exps;
468 node *n, *m;
469 int isproject = (rel->op == op_project);
470 sql_rel *l = rel->l, *oexps_rel = rel;
471
472 if (is_topn(rel->op) || is_sample(rel->op)) {
473 oexps_rel = l;
474 oexps = l->exps;
475 }
476 for (n = oexps->h, m = restypelist->h; n && m; n = n->next, m = m->next) {
477 sql_exp *e = n->data;
478 sql_arg *ce = m->data;
479 const char *cname = exp_name(e);
480 char name[16];
481
482 if (!cname)
483 cname = sa_strdup(sql->sa, number2name(name, sizeof(name), ++sql->label));
484 if (!isproject)
485 e = exp_ref(sql->sa, e);
486 e = rel_check_type(sql, &ce->type, oexps_rel, e, type_equal);
487 if (!e)
488 return NULL;
489 append(exps, e);
490 }
491 if (isproject)
492 rel -> exps = exps;
493 else
494 rel = rel_project(sql->sa, rel, exps);
495 res = exp_rel(sql, rel);
496 } else if (rel && restypelist){ /* handle return table-var */
497 list *exps = sa_list(sql->sa);
498 sql_table *t = rel_ddl_table_get(rel);
499 node *n, *m;
500 const char *tname = t->base.name;
501
502 if (cs_size(&t->columns) != list_length(restypelist))
503 return sql_error(sql, 02, SQLSTATE(42000) "RETURN: number of columns do not match");
504 for (n = t->columns.set->h, m = restypelist->h; n && m; n = n->next, m = m->next) {
505 sql_column *c = n->data;
506 sql_arg *ce = m->data;
507 sql_exp *e = exp_column(sql->sa, tname, c->base.name, &c->type, CARD_MULTI, c->null, 0);
508
509 e = rel_check_type(sql, &ce->type, rel, e, type_equal);
510 if (!e)
511 return NULL;
512 append(exps, e);
513 }
514 rel = rel_project(sql->sa, rel, exps);
515 res = exp_rel(sql, rel);
516 }
517 append(l, res = exp_return(sql->sa, res, stack_nr_of_declared_tables(sql)));
518 if (ek.card != card_relation)
519 res->card = CARD_ATOM;
520 else
521 res->card = CARD_MULTI;
522 return l;
523}
524
525static list *
526rel_select_into( sql_query *query, symbol *sq, exp_kind ek)
527{
528 mvc *sql = query->sql;
529 SelectNode *sn = (SelectNode*)sq;
530 dlist *into = sn->into;
531 node *m;
532 dnode *n;
533 sql_rel *r;
534 list *nl = NULL;
535
536 /* SELECT ... INTO var_list */
537 sn->into = NULL;
538 r = rel_subquery(query, NULL, sq, ek);
539 if (!r)
540 return NULL;
541 nl = sa_list(sql->sa);
542 append(nl, exp_rel(sql, r));
543 for (m = r->exps->h, n = into->h; m && n; m = m->next, n = n->next) {
544 sql_subtype *tpe = NULL;
545 char *nme = n->data.sval;
546 sql_exp *v = m->data;
547 int level;
548
549 if (!stack_find_var(sql, nme))
550 return sql_error(sql, 02, SQLSTATE(42000) "SELECT INTO: variable '%s' unknown", nme);
551 /* dynamic check for single values */
552 if (v->card > CARD_AGGR) {
553 sql_subaggr *zero_or_one = sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(v));
554 assert(zero_or_one);
555 v = exp_aggr1(sql->sa, v, zero_or_one, 0, 0, CARD_ATOM, 0);
556 }
557 tpe = stack_find_type(sql, nme);
558 level = stack_find_frame(sql, nme);
559 if (!v || !(v = rel_check_type(sql, tpe, r, v, type_equal)))
560 return NULL;
561 v = exp_set(sql->sa, nme, v, level);
562 list_append(nl, v);
563 }
564 return nl;
565}
566
567extern sql_rel *
568rel_select_with_into(sql_query *query, symbol *sq)
569{
570 exp_kind ek = {type_value, card_row, TRUE};
571 list *reslist = rel_select_into(query, sq, ek);
572 if (!reslist)
573 return NULL;
574 return rel_psm_block(query->sql->sa, reslist);
575}
576
577static int has_return( list *l );
578
579static int
580exp_has_return(sql_exp *e)
581{
582 if (e->type == e_psm) {
583 if (e->flag & PSM_RETURN)
584 return 1;
585 if (e->flag & PSM_IF)
586 return has_return(e->r) && (!e->f || has_return(e->f));
587 }
588 return 0;
589}
590
591static int
592has_return( list *l )
593{
594 node *n = l->t;
595 sql_exp *e = n->data;
596
597 /* last statment of sequential block */
598 if (exp_has_return(e))
599 return 1;
600 return 0;
601}
602
603static list *
604sequential_block (sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_label, int is_func)
605{
606 mvc *sql = query->sql;
607 list *l=0;
608 dnode *n;
609
610 assert(!restype || !restypelist);
611
612 if (THRhighwater())
613 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
614
615 if (blk->h)
616 l = sa_list(sql->sa);
617 if(!stack_push_frame(sql, opt_label))
618 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
619 for (n = blk->h; n; n = n->next ) {
620 sql_exp *res = NULL;
621 list *reslist = NULL;
622 symbol *s = n->data.sym;
623
624 switch (s->token) {
625 case SQL_SET:
626 res = psm_set_exp(query, s->data.lval->h);
627 break;
628 case SQL_DECLARE:
629 reslist = rel_psm_declare(sql, s->data.lval->h);
630 break;
631 case SQL_DECLARE_TABLE:
632 case SQL_CREATE_TABLE:
633 res = rel_psm_declare_table(query, s->data.lval->h);
634 break;
635 case SQL_WHILE:
636 res = rel_psm_while_do(query, restype, restypelist, s->data.lval->h, is_func);
637 break;
638 case SQL_IF:
639 res = rel_psm_if_then_else(query, restype, restypelist, s->data.lval->h, is_func);
640 break;
641 case SQL_CASE:
642 reslist = rel_psm_case(query, restype, restypelist, s->data.lval->h, is_func);
643 break;
644 case SQL_CALL:
645 res = rel_psm_call(query, s->data.sym);
646 break;
647 case SQL_RETURN:
648 /*If it is not a function it cannot have a return statement*/
649 if (!is_func)
650 res = sql_error(sql, 01, SQLSTATE(42000) "Return statement in the procedure body");
651 else {
652 /* should be last statement of a sequential_block */
653 if (n->next) {
654 res = sql_error(sql, 01, SQLSTATE(42000) "Statement after return");
655 } else {
656 res = NULL;
657 reslist = rel_psm_return(query, restype, restypelist, s->data.sym);
658 }
659 }
660 break;
661 case SQL_SELECT: { /* row selections (into variables) */
662 exp_kind ek = {type_value, card_row, TRUE};
663 reslist = rel_select_into(query, s, ek);
664 } break;
665 case SQL_COPYFROM:
666 case SQL_BINCOPYFROM:
667 case SQL_INSERT:
668 case SQL_UPDATE:
669 case SQL_DELETE:
670 case SQL_TRUNCATE:
671 case SQL_MERGE: {
672 sql_rel *r = rel_updates(query, s);
673 if (!r)
674 return NULL;
675 res = exp_rel(sql, r);
676 } break;
677 default:
678 res = sql_error(sql, 01, SQLSTATE(42000) "Statement '%s' is not a valid flow control statement",
679 token2string(s->token));
680 }
681 if (!res && !reslist) {
682 l = NULL;
683 break;
684 }
685 if (res)
686 list_append(l, res);
687 else
688 list_merge(l, reslist, NULL);
689 }
690 stack_pop_frame(sql);
691 return l;
692}
693
694static int
695arg_cmp(void *A, void *N)
696{
697 sql_arg *a = A;
698 char *name = N;
699 return strcmp(a->name, name);
700}
701
702static list *
703result_type(mvc *sql, symbol *res)
704{
705 if (res->token == SQL_TYPE) {
706 sql_subtype *st = &res->data.lval->h->data.typeval;
707 sql_arg *a = sql_create_arg(sql->sa, "result", st, ARG_OUT);
708
709 return list_append(sa_list(sql->sa), a);
710 } else if (res->token == SQL_TABLE) {
711 sql_arg *a;
712 dnode *n = res->data.lval->h;
713 list *types = sa_list(sql->sa);
714
715 for(;n; n = n->next->next) {
716 sql_subtype *ct = &n->next->data.typeval;
717
718 if (list_find(types, n->data.sval, &arg_cmp) != NULL)
719 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "CREATE FUNC: identifier '%s' ambiguous", n->data.sval);
720
721 a = sql_create_arg(sql->sa, n->data.sval, ct, ARG_OUT);
722 list_append(types, a);
723 }
724 return types;
725 }
726 return NULL;
727}
728
729static list *
730create_type_list(mvc *sql, dlist *params, int param)
731{
732 sql_subtype *par_subtype;
733 list * type_list = sa_list(sql->sa);
734 dnode * n = NULL;
735
736 if (params) {
737 for (n = params->h; n; n = n->next) {
738 dnode *an = n;
739
740 if (param) {
741 an = n->data.lval->h;
742 par_subtype = &an->next->data.typeval;
743 if (par_subtype && !par_subtype->type) /* var arg */
744 return type_list;
745 list_append(type_list, par_subtype);
746 } else {
747 par_subtype = &an->data.typeval;
748 list_prepend(type_list, par_subtype);
749 }
750 }
751 }
752 return type_list;
753}
754
755static sql_rel*
756rel_create_function(sql_allocator *sa, const char *sname, sql_func *f)
757{
758 sql_rel *rel = rel_create(sa);
759 list *exps = new_exp_list(sa);
760 if(!rel || !exps)
761 return NULL;
762
763 append(exps, exp_atom_clob(sa, sname));
764 if (f)
765 append(exps, exp_atom_clob(sa, f->base.name));
766 append(exps, exp_atom_ptr(sa, f));
767 rel->l = NULL;
768 rel->r = NULL;
769 rel->op = op_ddl;
770 rel->flag = ddl_create_function;
771 rel->exps = exps;
772 rel->card = 0;
773 rel->nrcols = 0;
774 return rel;
775}
776
777static sql_rel *
778rel_create_func(sql_query *query, dlist *qname, dlist *params, symbol *res, dlist *ext_name, dlist *body, sql_ftype type, sql_flang lang, int replace)
779{
780 mvc *sql = query->sql;
781 const char *fname = qname_table(qname);
782 const char *sname = qname_schema(qname);
783 sql_schema *s = NULL;
784 sql_func *f = NULL;
785 sql_subfunc *sf;
786 dnode *n;
787 list *type_list = NULL, *restype = NULL;
788 int instantiate = (sql->emode == m_instantiate);
789 int deps = (sql->emode == m_deps);
790 int create = (!instantiate && !deps);
791 bit vararg = FALSE;
792
793 char is_table = (res && res->token == SQL_TABLE);
794 char is_aggr = (type == F_AGGR);
795 char is_func = (type != F_PROC);
796 char is_loader = (type == F_LOADER);
797
798 char *F = is_loader?"LOADER":(is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE"));
799 char *fn = is_loader?"loader":(is_aggr ? "aggregate" : (is_func ? "function" : "procedure"));
800 char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
801 char *kf = type == F_FILT ? "filter " : type == F_UNION ? "union " : "";
802
803 assert(res || type == F_PROC || type == F_FILT || type == F_LOADER);
804
805 if (is_table)
806 type = F_UNION;
807
808 if (STORE_READONLY && create)
809 return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
810
811 if (sname && !(s = mvc_bind_schema(sql, sname)))
812 return sql_error(sql, 02, SQLSTATE(3F000) "CREATE %s%s: no such schema '%s'", KF, F, sname);
813 if (s == NULL)
814 s = cur_schema(sql);
815
816 type_list = create_type_list(sql, params, 1);
817 if ((sf = sql_bind_func_(sql->sa, s, fname, type_list, type)) != NULL && create) {
818 if (replace) {
819 sql_func *func = sf->func;
820 if (!mvc_schema_privs(sql, s))
821 return sql_error(sql, 02, SQLSTATE(42000) "CREATE OR REPLACE %s%s: access denied for %s to schema '%s'", KF, F, stack_get_string(sql, "current_user"), s->base.name);
822 if (mvc_check_dependency(sql, func->base.id, !IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY, NULL))
823 return sql_error(sql, 02, SQLSTATE(42000) "CREATE OR REPLACE %s%s: there are database objects dependent on %s%s %s;", KF, F, kf, fn, func->base.name);
824 if (!func->s)
825 return sql_error(sql, 02, SQLSTATE(42000) "CREATE OR REPLACE %s%s: not allowed to replace system %s%s %s;", KF, F, kf, fn, func->base.name);
826 if (mvc_drop_func(sql, s, func, 0))
827 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
828 sf = NULL;
829 } else {
830 if (params) {
831 char *arg_list = NULL;
832 node *n;
833
834 for (n = type_list->h; n; n = n->next) {
835 char *tpe = subtype2string((sql_subtype *) n->data);
836
837 if (arg_list) {
838 char *t = arg_list;
839 arg_list = sql_message("%s, %s", arg_list, tpe);
840 _DELETE(t);
841 _DELETE(tpe);
842 } else {
843 arg_list = tpe;
844 }
845 }
846 (void)sql_error(sql, 02, SQLSTATE(42000) "CREATE %s%s: name '%s' (%s) already in use", KF, F, fname, arg_list ? arg_list : "");
847 _DELETE(arg_list);
848 list_destroy(type_list);
849 return NULL;
850 } else {
851 list_destroy(type_list);
852 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s%s: name '%s' already in use", KF, F, fname);
853 }
854 }
855 }
856 list_destroy(type_list);
857 if (create && !mvc_schema_privs(sql, s)) {
858 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s%s: insufficient privileges for user '%s' in schema '%s'", KF, F,
859 stack_get_string(sql, "current_user"), s->base.name);
860 } else {
861 char *q = QUERY(sql->scanner);
862 list *l = NULL;
863
864 if (params) {
865 for (n = params->h; n; n = n->next) {
866 dnode *an = n->data.lval->h;
867 sql_add_param(sql, an->data.sval, &an->next->data.typeval);
868 }
869 l = sql->params;
870 if (l && list_length(l) == 1) {
871 sql_arg *a = l->h->data;
872
873 if (strcmp(a->name, "*") == 0) {
874 l = NULL;
875 vararg = TRUE;
876 }
877 }
878 }
879 if (!l)
880 l = sa_list(sql->sa);
881 if (res) {
882 restype = result_type(sql, res);
883 if (!restype)
884 return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: failed to get restype", KF, F);
885 }
886 if (body && LANG_EXT(lang)) {
887 char *lang_body = body->h->data.sval, *mod = NULL, *slang = NULL;
888 switch (lang) {
889 case FUNC_LANG_R:
890 mod = "rapi";
891 slang = "R";
892 break;
893 case FUNC_LANG_C:
894 mod = "capi";
895 slang = "C";
896 break;
897 case FUNC_LANG_CPP:
898 mod = "capi";
899 slang = "CPP";
900 break;
901 case FUNC_LANG_J:
902 mod = "japi";
903 slang = "Javascript";
904 break;
905 case FUNC_LANG_PY:
906 mod = "pyapi";
907 slang = "Python";
908 break;
909 case FUNC_LANG_MAP_PY:
910 mod = "pyapimap";
911 slang = "Python";
912 break;
913 default:
914 assert(0);
915 }
916 sql->params = NULL;
917 if (create) {
918 f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, mod, fname, lang_body, (type == F_LOADER)?TRUE:FALSE, vararg, FALSE);
919 } else if (!sf) {
920 return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: %s function %s.%s not bound", KF, F, slang, s->base.name, fname);
921 }
922 } else if (body) { /* SQL implementation */
923 sql_arg *ra = (restype && !is_table)?restype->h->data:NULL;
924 list *b = NULL;
925 sql_schema *old_schema = cur_schema(sql);
926
927 if (create) { /* needed for recursive functions */
928 q = query_cleaned(q);
929 sql->forward = f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, "user", q, q, FALSE, vararg, FALSE);
930 GDKfree(q);
931 }
932 sql->session->schema = s;
933 b = sequential_block(query, (ra)?&ra->type:NULL, ra?NULL:restype, body, NULL, is_func);
934 sql->forward = NULL;
935 sql->session->schema = old_schema;
936 sql->params = NULL;
937 if (!b)
938 return NULL;
939
940 /* check if we have a return statement */
941 if (is_func && restype && !has_return(b))
942 return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: missing return statement", KF, F);
943 if (!is_func && !restype && has_return(b))
944 return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: procedures cannot have return statements", KF, F);
945 /* in execute mode we instantiate the function */
946 if (instantiate || deps)
947 return rel_psm_block(sql->sa, b);
948 } else { /* MAL implementation */
949 char *fmod = qname_module(ext_name);
950 char *fnme = qname_fname(ext_name);
951
952 if (!fmod || !fnme)
953 return NULL;
954 sql->params = NULL;
955 if (create) {
956 q = query_cleaned(q);
957 f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, fmod, fnme, q, FALSE, vararg, FALSE);
958 GDKfree(q);
959 } else if (!sf) {
960 return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: external name %s.%s not bound (%s.%s)", KF, F, fmod, fnme, s->base.name, fname );
961 } else {
962 sql_func *f = sf->func;
963 if (!f->mod || strcmp(f->mod, fmod))
964 f->mod = _STRDUP(fmod);
965 if (!f->imp || strcmp(f->imp, fnme))
966 f->imp = (f->sa)?sa_strdup(f->sa, fnme):_STRDUP(fnme);
967 if (!f->mod || !f->imp) {
968 _DELETE(f->mod);
969 _DELETE(f->imp);
970 return sql_error(sql, 02, SQLSTATE(HY001) "CREATE %s%s: could not allocate space", KF, F);
971 }
972 f->sql = 0; /* native */
973 f->lang = FUNC_LANG_INT;
974 }
975 if (!f)
976 f = sf->func;
977 assert(f);
978 if (!backend_resolve_function(sql, f))
979 return sql_error(sql, 01, SQLSTATE(3F000) "CREATE %s%s: external name %s.%s not bound (%s.%s)", KF, F, fmod, fnme, s->base.name, fname );
980 }
981 }
982 return rel_create_function(sql->sa, s->base.name, f);
983}
984
985static sql_rel*
986rel_drop_function(sql_allocator *sa, const char *sname, const char *name, int nr, sql_ftype type, int action)
987{
988 sql_rel *rel = rel_create(sa);
989 list *exps = new_exp_list(sa);
990 if(!rel || !exps)
991 return NULL;
992
993 append(exps, exp_atom_clob(sa, sname));
994 append(exps, exp_atom_clob(sa, name));
995 append(exps, exp_atom_int(sa, nr));
996 append(exps, exp_atom_int(sa, (int) type));
997 append(exps, exp_atom_int(sa, action));
998 rel->l = NULL;
999 rel->r = NULL;
1000 rel->op = op_ddl;
1001 rel->flag = ddl_drop_function;
1002 rel->exps = exps;
1003 rel->card = 0;
1004 rel->nrcols = 0;
1005 return rel;
1006}
1007
1008sql_func *
1009resolve_func( mvc *sql, sql_schema *s, const char *name, dlist *typelist, sql_ftype type, char *op, int if_exists)
1010{
1011 sql_func *func = NULL;
1012 list *list_func = NULL, *type_list = NULL;
1013 char is_aggr = (type == F_AGGR);
1014 char is_func = (type != F_PROC && type != F_LOADER);
1015 char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
1016 char *f = is_aggr?"aggregate":(is_func?"function":"procedure");
1017 char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
1018 char *kf = type==F_FILT?"filter ": type==F_UNION?"union ": "";
1019
1020 if (typelist) {
1021 sql_subfunc *sub_func;
1022
1023 type_list = create_type_list(sql, typelist, 0);
1024 sub_func = sql_bind_func_(sql->sa, s, name, type_list, type);
1025 if (!sub_func && type == F_FUNC) {
1026 sub_func = sql_bind_func_(sql->sa, s, name, type_list, F_UNION);
1027 type = sub_func?F_UNION:F_FUNC;
1028 }
1029 if ( sub_func && sub_func->func->type == type)
1030 func = sub_func->func;
1031 } else {
1032 list_func = schema_bind_func(sql, s, name, type);
1033 if (!list_func && type == F_FUNC)
1034 list_func = schema_bind_func(sql,s,name, F_UNION);
1035 if (list_func && list_func->cnt > 1) {
1036 list_destroy(list_func);
1037 return sql_error(sql, 02, SQLSTATE(42000) "%s %s%s: there are more than one %s%s called '%s', please use the full signature", op, KF, F, kf, f,name);
1038 }
1039 if (list_func && list_func->cnt == 1)
1040 func = (sql_func*) list_func->h->data;
1041 }
1042
1043 if (!func) {
1044 void *e = NULL;
1045 if (typelist) {
1046 char *arg_list = NULL;
1047 node *n;
1048
1049 if (type_list->cnt > 0) {
1050 for (n = type_list->h; n; n = n->next) {
1051 char *tpe = subtype2string((sql_subtype *) n->data);
1052
1053 if (arg_list) {
1054 char *t = arg_list;
1055 arg_list = sql_message("%s, %s", arg_list, tpe);
1056 _DELETE(tpe);
1057 _DELETE(t);
1058 } else {
1059 arg_list = tpe;
1060 }
1061 }
1062 list_destroy(list_func);
1063 list_destroy(type_list);
1064 if(!if_exists)
1065 e = sql_error(sql, 02, SQLSTATE(42000) "%s %s%s: no such %s%s '%s' (%s)", op, KF, F, kf, f, name, arg_list);
1066 _DELETE(arg_list);
1067 return e;
1068 }
1069 list_destroy(list_func);
1070 list_destroy(type_list);
1071 if(!if_exists)
1072 e = sql_error(sql, 02, SQLSTATE(42000) "%s %s%s: no such %s%s '%s' ()", op, KF, F, kf, f, name);
1073 return e;
1074
1075 } else {
1076 if(!if_exists)
1077 e = sql_error(sql, 02, SQLSTATE(42000) "%s %s%s: no such %s%s '%s'", op, KF, F, kf, f, name);
1078 return e;
1079 }
1080 } else if (((is_func && type != F_FILT) && !func->res) ||
1081 (!is_func && func->res)) {
1082 list_destroy(list_func);
1083 list_destroy(type_list);
1084 return sql_error(sql, 02, SQLSTATE(42000) "%s %s%s: cannot drop %s '%s'", KF, F, is_func?"procedure":"function", op, name);
1085 }
1086
1087 list_destroy(list_func);
1088 list_destroy(type_list);
1089 return func;
1090}
1091
1092static sql_rel*
1093rel_drop_func(mvc *sql, dlist *qname, dlist *typelist, int drop_action, sql_ftype type, int if_exists)
1094{
1095 const char *name = qname_table(qname);
1096 const char *sname = qname_schema(qname);
1097 sql_schema *s = NULL;
1098 sql_func *func = NULL;
1099
1100 char is_aggr = (type == F_AGGR);
1101 char is_func = (type != F_PROC);
1102 char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
1103 char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
1104
1105 if (sname && !(s = mvc_bind_schema(sql, sname)))
1106 return sql_error(sql, 02, SQLSTATE(3F000) "DROP %s%s: no such schema '%s'", KF, F, sname);
1107
1108 if (s == NULL)
1109 s = cur_schema(sql);
1110
1111 func = resolve_func(sql, s, name, typelist, type, "DROP", if_exists);
1112 if (!func && !sname) {
1113 s = tmp_schema(sql);
1114 func = resolve_func(sql, s, name, typelist, type, "DROP", if_exists);
1115 }
1116 if (func)
1117 return rel_drop_function(sql->sa, s->base.name, name, func->base.id, type, drop_action);
1118 else if(if_exists && !sql->session->status)
1119 return rel_drop_function(sql->sa, s->base.name, name, -2, type, drop_action);
1120 return NULL;
1121}
1122
1123static sql_rel*
1124rel_drop_all_func(mvc *sql, dlist *qname, int drop_action, sql_ftype type)
1125{
1126 const char *name = qname_table(qname);
1127 const char *sname = qname_schema(qname);
1128 sql_schema *s = NULL;
1129 list * list_func = NULL;
1130
1131 char is_aggr = (type == F_AGGR);
1132 char is_func = (type != F_PROC);
1133 char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
1134 char *f = is_aggr?"aggregate":(is_func?"function":"procedure");
1135 char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
1136 char *kf = type==F_FILT?"filter ": type==F_UNION?"union ": "";
1137
1138 if (sname && !(s = mvc_bind_schema(sql, sname)))
1139 return sql_error(sql, 02, SQLSTATE(3F000) "DROP %s%s: no such schema '%s'", KF, F, sname);
1140
1141 if (s == NULL)
1142 s = cur_schema(sql);
1143
1144 list_func = schema_bind_func(sql, s, name, type);
1145 if (!list_func)
1146 return sql_error(sql, 02, SQLSTATE(3F000) "DROP ALL %s%s: no such %s%s '%s'", KF, F, kf, f, name);
1147 list_destroy(list_func);
1148 return rel_drop_function(sql->sa, s->base.name, name, -1, type, drop_action);
1149}
1150
1151static sql_rel *
1152rel_create_trigger(mvc *sql, const char *sname, const char *tname, const char *triggername, int time, int orientation, int event, const char *old_name, const char *new_name, symbol *condition, const char *query)
1153{
1154 sql_rel *rel = rel_create(sql->sa);
1155 list *exps = new_exp_list(sql->sa);
1156 if(!rel || !exps)
1157 return NULL;
1158
1159 append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
1160 append(exps, exp_atom_str(sql->sa, tname, sql_bind_localtype("str") ));
1161 append(exps, exp_atom_str(sql->sa, triggername, sql_bind_localtype("str") ));
1162 append(exps, exp_atom_int(sql->sa, time));
1163 append(exps, exp_atom_int(sql->sa, orientation));
1164 append(exps, exp_atom_int(sql->sa, event));
1165 append(exps, exp_atom_str(sql->sa, old_name, sql_bind_localtype("str") ));
1166 append(exps, exp_atom_str(sql->sa, new_name, sql_bind_localtype("str") ));
1167 (void)condition;
1168 append(exps, exp_atom_str(sql->sa, NULL, sql_bind_localtype("str") ));
1169 append(exps, exp_atom_str(sql->sa, query, sql_bind_localtype("str") ));
1170 rel->l = NULL;
1171 rel->r = NULL;
1172 rel->op = op_ddl;
1173 rel->flag = ddl_create_trigger;
1174 rel->exps = exps;
1175 rel->card = CARD_MULTI;
1176 rel->nrcols = 0;
1177 return rel;
1178}
1179
1180static sql_var*
1181_stack_push_table(mvc *sql, const char *tname, sql_table *t)
1182{
1183 sql_rel *r = rel_basetable(sql, t, tname );
1184 return stack_push_rel_view(sql, tname, r);
1185}
1186
1187static sql_rel *
1188create_trigger(sql_query *query, dlist *qname, int time, symbol *trigger_event, dlist *tqname, dlist *opt_ref, dlist *triggered_action, int replace)
1189{
1190 mvc *sql = query->sql;
1191 const char *triggerschema = qname_schema(qname);
1192 const char *triggername = qname_table(qname);
1193 const char *sname = qname_schema(tqname);
1194 const char *tname = qname_table(tqname);
1195 sql_schema *ss = cur_schema(sql);
1196 sql_table *t = NULL;
1197 sql_trigger *st = NULL;
1198 int instantiate = (sql->emode == m_instantiate);
1199 int create = (!instantiate && sql->emode != m_deps), event, orientation;
1200 list *sq = NULL;
1201 sql_rel *r = NULL;
1202 char *q, *base = replace ? "CREATE OR REPLACE" : "CREATE";
1203
1204 dlist *columns = trigger_event->data.lval;
1205 const char *old_name = NULL, *new_name = NULL;
1206 dlist *stmts = triggered_action->h->next->next->data.lval;
1207 symbol *condition = triggered_action->h->next->data.sym;
1208
1209 if (!sname)
1210 sname = ss->base.name;
1211
1212 if (sname && !(ss = mvc_bind_schema(sql, sname)))
1213 return sql_error(sql, 02, SQLSTATE(3F000) "%s TRIGGER: no such schema '%s'", base, sname);
1214
1215 if (opt_ref) {
1216 dnode *dl = opt_ref->h;
1217 for ( ; dl; dl = dl->next) {
1218 /* list (new(1)/old(0)), char */
1219 char *n = dl->data.lval->h->next->data.sval;
1220
1221 assert(dl->data.lval->h->type == type_int);
1222 if (!dl->data.lval->h->data.i_val) /*?l_val?*/
1223 old_name = n;
1224 else
1225 new_name = n;
1226 }
1227 }
1228
1229 if (create && !mvc_schema_privs(sql, ss))
1230 return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: access denied for %s to schema '%s'", base, stack_get_string(sql, "current_user"), ss->base.name);
1231 if (create && !(t = mvc_bind_table(sql, ss, tname)))
1232 return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: unknown table '%s'", base, tname);
1233 if (create && isView(t))
1234 return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: cannot create trigger on view '%s'", base, tname);
1235 if (triggerschema && strcmp(triggerschema, sname) != 0)
1236 return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: trigger and respective table must belong to the same schema", base);
1237 if (create && (st = mvc_bind_trigger(sql, ss, triggername)) != NULL) {
1238 if (replace) {
1239 if(mvc_drop_trigger(sql, ss, st))
1240 return sql_error(sql, 02, SQLSTATE(HY001) "%s TRIGGER: %s", base, MAL_MALLOC_FAIL);
1241 } else {
1242 return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: name '%s' already in use", base, triggername);
1243 }
1244 }
1245
1246 if (create) {
1247 switch (trigger_event->token) {
1248 case SQL_INSERT:
1249 event = 0;
1250 break;
1251 case SQL_DELETE:
1252 event = 1;
1253 break;
1254 case SQL_TRUNCATE:
1255 event = 3;
1256 break;
1257 default:
1258 event = 2;
1259 break;
1260 }
1261 orientation = triggered_action->h->data.i_val;
1262 q = query_cleaned(QUERY(sql->scanner));
1263
1264 assert(triggered_action->h->type == type_int);
1265 r = rel_create_trigger(sql, t->s->base.name, t->base.name, triggername, time, orientation, event, old_name, new_name, condition, q);
1266 GDKfree(q);
1267 return r;
1268 }
1269
1270 if (!instantiate) {
1271 t = mvc_bind_table(sql, ss, tname);
1272 if (!stack_push_frame(sql, "OLD-NEW"))
1273 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
1274 /* we need to add the old and new tables */
1275 if (new_name && !_stack_push_table(sql, new_name, t)) {
1276 stack_pop_frame(sql);
1277 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
1278 }
1279 if (old_name && !_stack_push_table(sql, old_name, t)) {
1280 stack_pop_frame(sql);
1281 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
1282 }
1283 }
1284 if (condition) {
1285 sql_rel *rel = NULL;
1286
1287 if (new_name) /* in case of updates same relations is available via both names */
1288 rel = stack_find_rel_view(sql, new_name);
1289 if (!rel && old_name)
1290 rel = stack_find_rel_view(sql, old_name);
1291 if (rel)
1292 rel = rel_logical_exp(query, rel, condition, sql_where);
1293 if (!rel) {
1294 if (!instantiate)
1295 stack_pop_frame(sql);
1296 return NULL;
1297 }
1298 /* transition tables */
1299 /* insert: rel_select(table [new], searchcondition) */
1300 /* delete: rel_select(table [old], searchcondition) */
1301 /* update: rel_select(table [old,new]), searchcondition) */
1302 if (new_name)
1303 stack_update_rel_view(sql, new_name, rel);
1304 if (old_name)
1305 stack_update_rel_view(sql, old_name, new_name?rel_dup(rel):rel);
1306 }
1307 sq = sequential_block(query, NULL, NULL, stmts, NULL, 1);
1308 r = rel_psm_block(sql->sa, sq);
1309
1310 if (!instantiate)
1311 stack_pop_frame(sql);
1312 /* todo trigger_columns */
1313 (void)columns;
1314 return r;
1315}
1316
1317static sql_rel *
1318rel_drop_trigger(mvc *sql, const char *sname, const char *tname, int if_exists)
1319{
1320 sql_rel *rel = rel_create(sql->sa);
1321 list *exps = new_exp_list(sql->sa);
1322 if(!rel || !exps)
1323 return NULL;
1324
1325 append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
1326 append(exps, exp_atom_str(sql->sa, tname, sql_bind_localtype("str") ));
1327 append(exps, exp_atom_int(sql->sa, if_exists));
1328 rel->l = NULL;
1329 rel->r = NULL;
1330 rel->op = op_ddl;
1331 rel->flag = ddl_drop_trigger;
1332 rel->exps = exps;
1333 rel->card = CARD_MULTI;
1334 rel->nrcols = 0;
1335 return rel;
1336}
1337
1338static sql_rel *
1339drop_trigger(mvc *sql, dlist *qname, int if_exists)
1340{
1341 const char *sname = qname_schema(qname);
1342 const char *tname = qname_table(qname);
1343 sql_schema *ss = cur_schema(sql);
1344
1345 if (!sname)
1346 sname = ss->base.name;
1347
1348 if (sname && !(ss = mvc_bind_schema(sql, sname)))
1349 return sql_error(sql, 02, SQLSTATE(3F000) "DROP TRIGGER: no such schema '%s'", sname);
1350
1351 if (!mvc_schema_privs(sql, ss))
1352 return sql_error(sql, 02, SQLSTATE(3F000) "DROP TRIGGER: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), ss->base.name);
1353 return rel_drop_trigger(sql, ss->base.name, tname, if_exists);
1354}
1355
1356static sql_rel *
1357psm_analyze(sql_query *query, char *analyzeType, dlist *qname, dlist *columns, symbol *sample, int minmax )
1358{
1359 mvc *sql = query->sql;
1360 exp_kind ek = {type_value, card_value, FALSE};
1361 sql_exp *sample_exp = NULL, *call, *mm_exp = NULL;
1362 const char *sname = NULL, *tname = NULL;
1363 list *tl = sa_list(sql->sa);
1364 list *exps = sa_list(sql->sa), *analyze_calls = sa_list(sql->sa);
1365 sql_subfunc *f = NULL;
1366
1367 append(exps, mm_exp = exp_atom_int(sql->sa, minmax));
1368 append(tl, exp_subtype(mm_exp));
1369 if (sample) {
1370 sql_subtype *tpe = sql_bind_localtype("lng");
1371 dlist* sample_parameters = sample->data.lval;
1372
1373 if (sample_parameters->cnt == 1 && (sample_exp = rel_value_exp(query, NULL, sample_parameters->h->data.sym, 0, ek)))
1374 sample_exp = rel_check_type(sql, tpe, NULL, sample_exp, type_cast);
1375 else
1376 return sql_error(sql, 01, SQLSTATE(42000) "Analyze sample size incorrect");
1377 } else {
1378 sample_exp = exp_atom_lng(sql->sa, 0);
1379 }
1380 append(exps, sample_exp);
1381 append(tl, exp_subtype(sample_exp));
1382
1383 assert(qname);
1384 if (qname) {
1385 if (qname->h->next)
1386 sname = qname_schema(qname);
1387 else
1388 sname = qname_table(qname);
1389 if (!sname)
1390 sname = cur_schema(sql)->base.name;
1391 if (qname->h->next)
1392 tname = qname_table(qname);
1393 }
1394 /* call analyze( [schema, [ table ]], opt_sample_size, opt_minmax ) */
1395 if (sname) {
1396 sql_exp *sname_exp = exp_atom_clob(sql->sa, sname);
1397
1398 append(exps, sname_exp);
1399 append(tl, exp_subtype(sname_exp));
1400 }
1401 if (tname) {
1402 sql_exp *tname_exp = exp_atom_clob(sql->sa, tname);
1403
1404 append(exps, tname_exp);
1405 append(tl, exp_subtype(tname_exp));
1406
1407 if (columns)
1408 append(tl, exp_subtype(tname_exp));
1409 }
1410 if (!columns) {
1411 f = sql_bind_func_(sql->sa, mvc_bind_schema(sql, "sys"), analyzeType, tl, F_PROC);
1412 if (!f)
1413 return sql_error(sql, 01, SQLSTATE(42000) "Analyze procedure missing");
1414 call = exp_op(sql->sa, exps, f);
1415 append(analyze_calls, call);
1416 } else {
1417 dnode *n;
1418
1419 if (!sname || !tname)
1420 return sql_error(sql, 01, SQLSTATE(42000) "Analyze schema or table name missing");
1421 f = sql_bind_func_(sql->sa, mvc_bind_schema(sql, "sys"), analyzeType, tl, F_PROC);
1422 if (!f)
1423 return sql_error(sql, 01, SQLSTATE(42000) "Analyze procedure missing");
1424 for( n = columns->h; n; n = n->next) {
1425 const char *cname = n->data.sval;
1426 list *nexps = list_dup(exps, NULL);
1427 sql_exp *cname_exp = exp_atom_clob(sql->sa, cname);
1428
1429 append(nexps, cname_exp);
1430 /* call analyze( opt_minmax, opt_sample_size, sname, tname, cname) */
1431 call = exp_op(sql->sa, nexps, f);
1432 append(analyze_calls, call);
1433 }
1434 }
1435 return rel_psm_block(sql->sa, analyze_calls);
1436}
1437
1438static sql_rel*
1439create_table_from_loader(sql_query *query, dlist *qname, symbol *fcall)
1440{
1441 mvc *sql = query->sql;
1442 sql_schema *s = NULL;
1443 char *sname = qname_schema(qname);
1444 char *tname = qname_table(qname);
1445 sql_subfunc *loader = NULL;
1446 sql_rel* rel = NULL;
1447
1448 if (sname && !(s = mvc_bind_schema(sql, sname)))
1449 return sql_error(sql, 02, SQLSTATE(3F000) "CREATE TABLE: no such schema '%s'", sname);
1450
1451 if (mvc_bind_table(sql, s, tname)) {
1452 return sql_error(sql, 02, SQLSTATE(42S01) "CREATE TABLE: name '%s' already in use", tname);
1453 } else if (!mvc_schema_privs(sql, s)){
1454 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);
1455 }
1456
1457 rel = rel_loader_function(query, fcall, new_exp_list(sql->sa), &loader);
1458 if (!rel || !loader) {
1459 return NULL;
1460 }
1461 loader->sname = sname ? sa_zalloc(sql->sa, strlen(sname) + 1) : NULL;
1462 loader->tname = tname ? sa_zalloc(sql->sa, strlen(tname) + 1) : NULL;
1463
1464 if (sname) strcpy(loader->sname, sname);
1465 if (tname) strcpy(loader->tname, tname);
1466
1467 return rel;
1468}
1469
1470sql_rel *
1471rel_psm(sql_query *query, symbol *s)
1472{
1473 mvc *sql = query->sql;
1474 sql_rel *ret = NULL;
1475
1476 switch (s->token) {
1477 case SQL_CREATE_FUNC:
1478 {
1479 dlist *l = s->data.lval;
1480 sql_ftype type = (sql_ftype) l->h->next->next->next->next->next->data.i_val;
1481 sql_flang lang = (sql_flang) l->h->next->next->next->next->next->next->data.i_val;
1482 int repl = l->h->next->next->next->next->next->next->next->data.i_val;
1483
1484 ret = rel_create_func(query, l->h->data.lval, l->h->next->data.lval, l->h->next->next->data.sym, l->h->next->next->next->data.lval, l->h->next->next->next->next->data.lval, type, lang, repl);
1485 sql->type = Q_SCHEMA;
1486 } break;
1487 case SQL_DROP_FUNC:
1488 {
1489 dlist *l = s->data.lval;
1490 dlist *qname = l->h->data.lval;
1491 dlist *typelist = l->h->next->data.lval;
1492 sql_ftype type = (sql_ftype) l->h->next->next->data.i_val;
1493 int if_exists = l->h->next->next->next->data.i_val;
1494 int all = l->h->next->next->next->next->data.i_val;
1495 int drop_action = l->h->next->next->next->next->next->data.i_val;
1496
1497 if (STORE_READONLY)
1498 return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
1499
1500 if (all)
1501 ret = rel_drop_all_func(sql, qname, drop_action, type);
1502 else {
1503 ret = rel_drop_func(sql, qname, typelist, drop_action, type, if_exists);
1504 }
1505
1506 sql->type = Q_SCHEMA;
1507 } break;
1508 case SQL_SET:
1509 ret = rel_psm_stmt(sql->sa, psm_set_exp(query, s->data.lval->h));
1510 sql->type = Q_SCHEMA;
1511 break;
1512 case SQL_DECLARE:
1513 ret = rel_psm_block(sql->sa, rel_psm_declare(sql, s->data.lval->h));
1514 sql->type = Q_SCHEMA;
1515 break;
1516 case SQL_CALL:
1517 ret = rel_psm_stmt(sql->sa, rel_psm_call(query, s->data.sym));
1518 sql->type = Q_UPDATE;
1519 break;
1520 case SQL_CREATE_TABLE_LOADER:
1521 {
1522 dlist *l = s->data.lval;
1523 dlist *qname = l->h->data.lval;
1524 symbol *sym = l->h->next->data.sym;
1525
1526 ret = create_table_from_loader(query, qname, sym);
1527 if (ret == NULL)
1528 return NULL;
1529 ret = rel_psm_stmt(sql->sa, exp_rel(sql, ret));
1530 sql->type = Q_SCHEMA;
1531 } break;
1532 case SQL_CREATE_TRIGGER:
1533 {
1534 dlist *l = s->data.lval;
1535
1536 assert(l->h->next->type == type_int);
1537 ret = create_trigger(query, l->h->data.lval, l->h->next->data.i_val, l->h->next->next->data.sym, l->h->next->next->next->data.lval, l->h->next->next->next->next->data.lval, l->h->next->next->next->next->next->data.lval, l->h->next->next->next->next->next->next->data.i_val);
1538 sql->type = Q_SCHEMA;
1539 }
1540 break;
1541
1542 case SQL_DROP_TRIGGER:
1543 {
1544 dlist *l = s->data.lval;
1545 dlist *qname = l->h->data.lval;
1546 int if_exists = l->h->next->data.i_val;
1547
1548 ret = drop_trigger(sql, qname, if_exists);
1549 sql->type = Q_SCHEMA;
1550 }
1551 break;
1552
1553 case SQL_ANALYZE: {
1554 dlist *l = s->data.lval;
1555
1556 ret = psm_analyze(query, "analyze", l->h->data.lval /* qualified table name */, l->h->next->data.lval /* opt list of column */, l->h->next->next->data.sym /* opt_sample_size */, l->h->next->next->next->data.i_val);
1557 sql->type = Q_UPDATE;
1558 } break;
1559 default:
1560 return sql_error(sql, 01, SQLSTATE(42000) "Schema statement unknown symbol(%p)->token = %s", s, token2string(s->token));
1561 }
1562 return ret;
1563}
1564