Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024, 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "rel_psm.h"
15 : #include "rel_semantic.h"
16 : #include "rel_schema.h"
17 : #include "rel_select.h"
18 : #include "rel_rel.h"
19 : #include "rel_basetable.h"
20 : #include "rel_exp.h"
21 : #include "rel_updates.h"
22 : #include "sql_privileges.h"
23 : #include "sql_storage.h"
24 :
25 : #define psm_zero_or_one(exp) \
26 : do { \
27 : if (exp && exp->card > CARD_AGGR) { \
28 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", exp_subtype(exp), NULL, F_AGGR, true, true); \
29 : assert(zero_or_one); \
30 : exp = exp_aggr1(sql->sa, exp, zero_or_one, 0, 0, CARD_ATOM, has_nil(exp)); \
31 : } \
32 : } while(0)
33 :
34 : static list *sequential_block(sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_name, int is_func);
35 :
36 : sql_rel *
37 56323 : rel_psm_block(allocator *sa, list *l)
38 : {
39 56323 : if (l) {
40 56321 : sql_rel *r = rel_create(sa);
41 56321 : if(!r)
42 : return NULL;
43 :
44 56321 : r->op = op_ddl;
45 56321 : r->flag = ddl_psm;
46 56321 : r->exps = l;
47 56321 : return r;
48 : }
49 : return NULL;
50 : }
51 :
52 : sql_rel *
53 42163 : rel_psm_stmt(allocator *sa, sql_exp *e)
54 : {
55 42163 : if (e) {
56 42125 : list *l = sa_list(sa);
57 42125 : if(!l)
58 : return NULL;
59 :
60 42125 : list_append(l, e);
61 42124 : return rel_psm_block(sa, l);
62 : }
63 : return NULL;
64 : }
65 :
66 : /* SET [ schema '.' ] variable = value and set ( [ schema1 '.' ] variable1, .., [ schemaN '.' ] variableN) = (query) */
67 : static sql_exp *
68 14950 : psm_set_exp(sql_query *query, dnode *n)
69 : {
70 14950 : mvc *sql = query->sql;
71 14950 : dlist *qname = n->data.lval;
72 14950 : symbol *val = n->next->data.sym;
73 14950 : sql_exp *res = NULL, *e = NULL;
74 14950 : int level = 0, single = (qname->h->type == type_string);
75 14950 : sql_rel *rel = NULL;
76 14950 : sql_subtype *tpe;
77 :
78 14950 : if (single) {
79 14944 : exp_kind ek = {type_value, card_value, FALSE};
80 14944 : const char *sname = qname_schema(qname);
81 14944 : const char *vname = qname_schema_object(qname);
82 14944 : sql_var *var = NULL;
83 14944 : sql_arg *a = NULL;
84 :
85 14944 : if (!find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SET"))
86 29 : return NULL;
87 14924 : if (!(e = rel_value_exp2(query, &rel, val, sql_sel | sql_psm, ek)))
88 : return NULL;
89 14916 : psm_zero_or_one(e);
90 :
91 14916 : if (!(e = exp_check_type(sql, tpe, rel, e, type_cast)))
92 : return NULL;
93 15819 : res = exp_set(sql->sa, var && var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, vname), e, level);
94 : } else { /* multi assignment */
95 6 : exp_kind ek = {type_relation, card_value, FALSE};
96 6 : sql_rel *rel_val = rel_subquery(query, val, ek);
97 6 : dlist *vars = n->data.lval;
98 6 : dnode *m;
99 6 : node *n;
100 6 : list *b;
101 :
102 6 : if (!rel_val)
103 0 : return NULL;
104 6 : if (!is_project(rel_val->op))
105 0 : return sql_error(sql, 02, SQLSTATE(42000) "SET: The subquery is not a projection");
106 6 : if (dlist_length(vars) != list_length(rel_val->exps))
107 0 : return sql_error(sql, 02, SQLSTATE(42000) "SET: Number of variables not equal to number of supplied values");
108 6 : rel_val = rel_return_zero_or_one(sql, rel_val, ek);
109 :
110 6 : b = sa_list(sql->sa);
111 6 : append(b, exp_rel(sql, rel_val));
112 :
113 18 : for (m = vars->h, n = rel_val->exps->h; n && m; n = n->next, m = m->next) {
114 12 : dlist *nqname = m->data.lval;
115 12 : const char *sname = qname_schema(nqname);
116 12 : const char *vname = qname_schema_object(nqname);
117 12 : sql_exp *v = n->data;
118 12 : sql_var *var = NULL;
119 12 : sql_arg *a = NULL;
120 :
121 12 : if (!find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SET"))
122 0 : return NULL;
123 :
124 12 : v = exp_ref(sql, v);
125 12 : if (!(v = exp_check_type(sql, tpe, rel_val, v, type_cast)))
126 : return NULL;
127 12 : append(b, exp_set(sql->sa, var && var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, vname), v, level));
128 : }
129 6 : res = exp_rel(sql, rel_psm_block(sql->sa, b));
130 : }
131 : return res;
132 : }
133 :
134 : static sql_exp*
135 43462 : rel_psm_call(sql_query * query, symbol *se)
136 : {
137 43462 : mvc *sql = query->sql;
138 43462 : sql_subtype *t;
139 43462 : sql_exp *res = NULL;
140 43462 : exp_kind ek = {type_value, card_none, FALSE};
141 43462 : sql_rel *rel = NULL;
142 :
143 43462 : res = rel_value_exp(query, &rel, se, sql_sel | psm_call, ek);
144 43462 : if (!res || rel || ((t=exp_subtype(res)) && t->type)) /* only procedures */
145 21 : return sql_error(sql, 01, SQLSTATE(42000) "Function calls are ignored");
146 : return res;
147 : }
148 :
149 : static list *
150 8459 : rel_psm_declare(mvc *sql, dnode *n)
151 : {
152 8459 : list *l = sa_list(sql->sa);
153 :
154 18077 : while (n) { /* list of 'identfiers with type' */
155 9621 : dnode *ids = n->data.sym->data.lval->h->data.lval->h;
156 9621 : sql_subtype *ctype = &n->data.sym->data.lval->h->next->data.typeval;
157 19260 : while (ids) {
158 9642 : dlist *qname = ids->data.lval;
159 9642 : const char *sname = qname_schema(qname);
160 9642 : const char *tname = qname_schema_object(qname);
161 9642 : sql_exp *r = NULL;
162 :
163 9642 : if (sname)
164 1 : return sql_error(sql, 01, SQLSTATE(42000) "DECLARE: Declared variables don't have a schema");
165 : /* find if there's a parameter with the same name */
166 9641 : if (sql->frame == 1 && sql_bind_param(sql, tname) >= 0)
167 2 : return sql_error(sql, 01, SQLSTATE(42000) "DECLARE: Variable '%s' declared as a parameter", tname);
168 : /* check if we overwrite a scope local variable declare x; declare x; */
169 9639 : if (frame_find_var(sql, tname))
170 0 : return sql_error(sql, 01, SQLSTATE(42000) "DECLARE: Variable '%s' already declared", tname);
171 : /* variables are put on stack, globals on a separate list */
172 9639 : if (!frame_push_var(sql, tname, ctype))
173 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
174 9639 : r = exp_var(sql->sa, NULL, sa_strdup(sql->sa, tname), ctype, sql->frame);
175 9639 : append(l, r);
176 9639 : ids = ids->next;
177 : }
178 9618 : n = n->next;
179 : }
180 : return l;
181 : }
182 :
183 : static sql_exp *
184 122 : rel_psm_declare_table(sql_query *query, dnode *n)
185 : {
186 122 : mvc *sql = query->sql;
187 122 : sql_rel *rel = NULL, *baset = NULL;
188 122 : dlist *qname = n->next->data.lval;
189 122 : const char *sname = qname_schema(qname);
190 122 : const char *name = qname_schema_object(qname);
191 122 : sql_table *t;
192 :
193 122 : if (sname)
194 1 : return sql_error(sql, 01, SQLSTATE(42000) "DECLARE TABLE: Declared tables don't have a schema");
195 :
196 121 : assert(n->next->next->next->type == type_int);
197 242 : rel = rel_create_table(query, SQL_DECLARED_TABLE, sname, name, false, n->next->next->data.sym,
198 : n->next->next->next->data.i_val, NULL, NULL, NULL, false, NULL,
199 121 : n->next->next->next->next->next->next->data.i_val);
200 :
201 121 : if (!rel)
202 : return NULL;
203 119 : if (rel->op == op_ddl) {
204 : baset = rel;
205 3 : } else if (rel->op == op_insert) {
206 3 : baset = rel->l;
207 : } else {
208 0 : assert(0);
209 : }
210 119 : assert(baset->flag == ddl_create_table);
211 119 : t = (sql_table*)((atom*)((sql_exp*)baset->exps->t->data)->l)->data.val.pval;
212 119 : if (!frame_push_table(sql, t))
213 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
214 119 : return exp_table(sql->sa, sa_strdup(sql->sa, name), t, sql->frame);
215 : }
216 :
217 : /* [ label: ]
218 : while (cond) do
219 : statement_list
220 : end [ label ]
221 : currently we only parse the labels, they cannot be used as there is no
222 :
223 : support for LEAVE and ITERATE (sql multi-level break and continue)
224 : */
225 : static sql_exp *
226 1035 : rel_psm_while_do( sql_query *query, sql_subtype *res, list *restypelist, dnode *w, int is_func )
227 : {
228 1035 : mvc *sql = query->sql;
229 1035 : if (!w)
230 : return NULL;
231 1035 : if (w->type == type_symbol) {
232 1035 : sql_exp *cond;
233 1035 : list *whilestmts;
234 1035 : dnode *n = w;
235 1035 : sql_rel *rel = NULL;
236 1035 : exp_kind ek = {type_value, card_value, FALSE};
237 :
238 1035 : if (!(cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek)))
239 : return NULL;
240 1035 : psm_zero_or_one(cond);
241 1035 : n = n->next;
242 1035 : if (!(whilestmts = sequential_block(query, res, restypelist, n->data.lval, n->next->data.sval, is_func)))
243 : return NULL;
244 :
245 1035 : return exp_while( sql->sa, cond, whilestmts );
246 : }
247 : return NULL;
248 : }
249 :
250 : /* if (cond) then statement_list
251 : [ elseif (cond) then statement_list ]*
252 : [ else statement_list ]
253 : end if
254 : */
255 : static list *
256 11787 : psm_if_then_else( sql_query *query, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
257 : {
258 11787 : mvc *sql = query->sql;
259 11787 : if (!elseif)
260 : return NULL;
261 11787 : assert(elseif->type == type_symbol);
262 11787 : if (elseif->data.sym && elseif->data.sym->token == SQL_IF) {
263 7 : sql_exp *cond;
264 7 : list *ifstmts, *elsestmts;
265 7 : dnode *n = elseif->data.sym->data.lval->h;
266 7 : sql_rel *rel = NULL;
267 7 : exp_kind ek = {type_value, card_value, FALSE};
268 :
269 7 : if (!(cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek)))
270 : return NULL;
271 7 : psm_zero_or_one(cond);
272 7 : n = n->next;
273 7 : if (!(ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func)))
274 : return NULL;
275 7 : n = n->next;
276 7 : elsestmts = psm_if_then_else( query, res, restypelist, n, is_func);
277 7 : if (sql->session->status)
278 : return NULL;
279 :
280 7 : return append(sa_list(sql->sa), exp_if( sql->sa, cond, ifstmts, elsestmts));
281 : } else { /* else */
282 11780 : symbol *e = elseif->data.sym;
283 :
284 11780 : if (e==NULL || (e->token != SQL_ELSE))
285 : return NULL;
286 1448 : return sequential_block(query, res, restypelist, e->data.lval, NULL, is_func);
287 : }
288 : }
289 :
290 : static sql_exp *
291 11781 : rel_psm_if_then_else( sql_query *query, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
292 : {
293 11781 : mvc *sql = query->sql;
294 11781 : if (!elseif)
295 : return NULL;
296 11781 : if (elseif->next && elseif->type == type_symbol) { /* if or elseif */
297 11781 : sql_exp *cond;
298 11781 : list *ifstmts, *elsestmts;
299 11781 : dnode *n = elseif;
300 11781 : sql_rel *rel = NULL;
301 11781 : exp_kind ek = {type_value, card_value, FALSE};
302 :
303 11781 : if (!(cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek)))
304 : return NULL;
305 11781 : psm_zero_or_one(cond);
306 11781 : n = n->next;
307 11781 : if (!(ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func)))
308 : return NULL;
309 11780 : n = n->next;
310 11780 : elsestmts = psm_if_then_else( query, res, restypelist, n, is_func);
311 11780 : if (sql->session->status)
312 : return NULL;
313 :
314 11780 : return exp_if( sql->sa, cond, ifstmts, elsestmts);
315 : }
316 : return NULL;
317 : }
318 :
319 : /* 1
320 : CASE
321 : WHEN search_condition THEN statements
322 : [ WHEN search_condition THEN statements ]
323 : [ ELSE statements ]
324 : END CASE
325 :
326 : 2
327 : CASE case_value
328 : WHEN when_value THEN statements
329 : [ WHEN when_value THEN statements ]
330 : [ ELSE statements ]
331 : END CASE
332 : */
333 : static sql_exp *
334 59 : rel_psm_case( sql_query *query, sql_subtype *res, list *restypelist, dnode *case_when, int is_func )
335 : {
336 59 : mvc *sql = query->sql;
337 59 : sql_exp *case_stmt = NULL, *last_if = NULL, *ifst = NULL;
338 59 : list *else_stmt = NULL;
339 :
340 59 : if (!case_when)
341 : return NULL;
342 :
343 : /* case 1 */
344 59 : if (case_when->type == type_symbol) {
345 12 : dnode *n = case_when;
346 12 : symbol *case_value = n->data.sym;
347 12 : dlist *when_statements = n->next->data.lval;
348 12 : dlist *else_statements = n->next->next->data.lval;
349 12 : sql_rel *rel = NULL;
350 12 : exp_kind ek = {type_value, card_value, FALSE};
351 12 : sql_exp *v = rel_value_exp(query, &rel, case_value, sql_sel | sql_psm, ek);
352 :
353 12 : psm_zero_or_one(v);
354 0 : if (!v)
355 0 : return NULL;
356 12 : if (else_statements && !(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func)))
357 : return NULL;
358 :
359 12 : n = when_statements->h;
360 60 : while(n) {
361 48 : dnode *m = n->data.sym->data.lval->h;
362 48 : sql_exp *cond=0, *when_value = rel_value_exp(query, &rel, m->data.sym, sql_sel | sql_psm, ek);
363 48 : list *if_stmts = NULL;
364 :
365 48 : psm_zero_or_one(when_value);
366 0 : if (!when_value ||
367 48 : (cond = rel_binop_(sql, rel, v, when_value, "sys", "=", card_value, false)) == NULL ||
368 48 : (if_stmts = sequential_block(query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) {
369 0 : return NULL;
370 : }
371 48 : psm_zero_or_one(cond);
372 48 : ifst = exp_if(sql->sa, cond, if_stmts, NULL);
373 48 : if (last_if) { /* chain if statements for case, keep the last if */
374 36 : last_if->f = list_append(sa_list(sql->sa), ifst);
375 36 : last_if = ifst;
376 : } else {
377 : case_stmt = last_if = ifst;
378 : }
379 48 : n = n->next;
380 : }
381 : } else {
382 : /* case 2 */
383 47 : dnode *n = case_when;
384 47 : dlist *whenlist = n->data.lval;
385 47 : dlist *else_statements = n->next->data.lval;
386 :
387 47 : if (else_statements && !(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func)))
388 : return NULL;
389 :
390 47 : n = whenlist->h;
391 97 : while(n) {
392 50 : dnode *m = n->data.sym->data.lval->h;
393 50 : sql_rel *rel = NULL;
394 50 : exp_kind ek = {type_value, card_value, FALSE};
395 50 : sql_exp *cond = rel_logical_value_exp(query, &rel, m->data.sym, sql_sel | sql_psm, ek);
396 50 : list *if_stmts = NULL;
397 :
398 50 : psm_zero_or_one(cond);
399 0 : if (!cond ||
400 50 : (if_stmts = sequential_block(query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) {
401 0 : return NULL;
402 : }
403 50 : ifst = exp_if(sql->sa, cond, if_stmts, NULL);
404 50 : if (last_if) { /* chain if statements for case, keep the last if */
405 3 : last_if->f = list_append(sa_list(sql->sa), ifst);
406 3 : last_if = ifst;
407 : } else {
408 : case_stmt = last_if = ifst;
409 : }
410 50 : n = n->next;
411 : }
412 : }
413 59 : if (else_stmt) {
414 51 : assert(case_stmt && last_if && !last_if->f);
415 51 : last_if->f = else_stmt;
416 : }
417 : return case_stmt;
418 : }
419 :
420 : /* return val;
421 : */
422 : static sql_exp *
423 24564 : rel_psm_return( sql_query *query, sql_subtype *restype, list *restypelist, symbol *return_sym )
424 : {
425 24564 : mvc *sql = query->sql;
426 24564 : exp_kind ek = {type_value, card_value, FALSE};
427 24564 : sql_exp *res = NULL;
428 24564 : sql_rel *rel = NULL;
429 24564 : bool requires_proj = false;
430 :
431 24564 : if (restypelist)
432 : ek.card = card_relation;
433 21658 : else if (return_sym->token == SQL_TABLE)
434 2 : return sql_error(sql, 02, SQLSTATE(42000) "RETURN: TABLE return not allowed for non table returning functions");
435 24562 : if (return_sym->token == SQL_COLUMN && restypelist) { /* RETURN x; where x is a reference to a table */
436 578 : dlist *l = return_sym->data.lval;
437 578 : const char *sname = qname_schema(l);
438 578 : const char *tname = qname_schema_object(l);
439 578 : sql_table *t = NULL;
440 :
441 578 : if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "RETURN", false)))
442 : return NULL;
443 577 : if (isDeclaredTable(t)) {
444 60 : rel = rel_table(sql, ddl_create_table, "sys", t, SQL_DECLARED_TABLE);
445 : } else {
446 517 : rel = rel_basetable(sql, t, t->base.name);
447 517 : rel = rel_base_add_columns(sql, rel);
448 : }
449 : } else { /* other cases */
450 23984 : res = rel_value_exp2(query, &rel, return_sym, sql_sel, ek);
451 23984 : if (!res)
452 : return NULL;
453 23974 : if (!rel && exp_is_rel(res)) {
454 6485 : rel = exp_rel_get_rel(sql->sa, res);
455 6485 : if (rel && !restypelist && !is_groupby(rel->op)) { /* On regular functions return zero or 1 rows for every row */
456 4375 : rel->card = CARD_MULTI;
457 4375 : rel = rel_return_zero_or_one(sql, rel, ek);
458 4375 : if (list_length(rel->exps) != 1)
459 0 : return sql_error(sql, 02, SQLSTATE(42000) "RETURN: must return a single column");
460 4375 : res = exp_ref(sql, (sql_exp*) rel->exps->t->data);
461 4375 : requires_proj = true;
462 : }
463 : }
464 : }
465 :
466 24551 : if (ek.card != card_relation && (!restype || (res = exp_check_type(sql, restype, rel, res, type_equal)) == NULL))
467 0 : return (!restype)?sql_error(sql, 02, SQLSTATE(42000) "RETURN: return type does not match"):NULL;
468 24551 : else if (ek.card == card_relation && !rel)
469 : return NULL;
470 :
471 24551 : if (requires_proj) {
472 4375 : rel = rel_project(sql->sa, rel, list_append(sa_list(sql->sa), res));
473 4375 : res = exp_rel(sql, rel);
474 : }
475 :
476 27390 : if (rel && !is_ddl(rel->op) && ek.card == card_relation) {
477 2840 : list *exps = sa_list(sql->sa), *oexps = rel->exps;
478 2840 : node *n, *m;
479 2840 : int isproject = (rel->op == op_project);
480 2840 : sql_rel *l = rel->l, *oexps_rel = rel;
481 :
482 2840 : if (is_topn(rel->op) || is_sample(rel->op)) {
483 14 : oexps_rel = l;
484 14 : oexps = l->exps;
485 : }
486 2840 : if (list_length(oexps) != list_length(restypelist))
487 1 : return sql_error(sql, 02, SQLSTATE(42000) "RETURN: number of columns do not match");
488 14312 : for (n = oexps->h, m = restypelist->h; n && m; n = n->next, m = m->next) {
489 11473 : sql_exp *e = n->data;
490 11473 : sql_arg *ce = m->data;
491 11473 : const char *cname = exp_name(e);
492 11473 : char name[16];
493 :
494 11473 : if (!cname)
495 106 : cname = sa_strdup(sql->sa, number2name(name, sizeof(name), ++sql->label));
496 11473 : if (!isproject)
497 1135 : e = exp_ref(sql, e);
498 11473 : e = exp_check_type(sql, &ce->type, oexps_rel, e, type_equal);
499 11473 : if (!e)
500 0 : return NULL;
501 11473 : append(exps, e);
502 : }
503 2839 : if (isproject)
504 2263 : rel->exps = exps;
505 : else
506 576 : rel = rel_project(sql->sa, rel, exps);
507 2839 : res = exp_rel(sql, rel);
508 21711 : } else if (rel && restypelist) { /* handle return table-var */
509 60 : list *exps = sa_list(sql->sa);
510 60 : sql_rel *bt = rel_ddl_basetable_get(rel);
511 60 : sql_table *t = rel_ddl_table_get(rel);
512 60 : node *n, *m;
513 60 : const char *tname = t->base.name;
514 :
515 60 : if (ol_length(t->columns) != list_length(restypelist))
516 1 : return sql_error(sql, 02, SQLSTATE(42000) "RETURN: number of columns do not match");
517 188 : for (n = ol_first_node(t->columns), m = restypelist->h; n && m; n = n->next, m = m->next) {
518 129 : sql_column *c = n->data;
519 129 : sql_arg *ce = m->data;
520 129 : sql_exp *e = exp_column(sql->sa, tname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
521 129 : e->nid = rel_base_nid(bt, c);
522 129 : e->alias.label = e->nid;
523 :
524 129 : e = exp_check_type(sql, &ce->type, rel, e, type_equal);
525 129 : if (!e)
526 : return NULL;
527 129 : append(exps, e);
528 : }
529 59 : rel = rel_project(sql->sa, rel, exps);
530 59 : res = exp_rel(sql, rel);
531 : }
532 24549 : res = exp_return(sql->sa, res, stack_nr_of_declared_tables(sql));
533 24549 : if (ek.card != card_relation)
534 21651 : res->card = CARD_ATOM;
535 : else
536 2898 : res->card = CARD_MULTI;
537 : return res;
538 : }
539 :
540 : static list *
541 1493 : rel_select_into( sql_query *query, symbol *sq, exp_kind ek)
542 : {
543 1493 : mvc *sql = query->sql;
544 1493 : SelectNode *sn = (SelectNode*)sq;
545 1493 : dlist *into = sn->into;
546 1493 : node *m;
547 1493 : dnode *n;
548 1493 : sql_rel *r;
549 1493 : list *nl = NULL;
550 :
551 : /* SELECT ... INTO var_list */
552 1493 : sn->into = NULL;
553 1493 : r = rel_subquery(query, sq, ek);
554 1493 : if (!r)
555 : return NULL;
556 1493 : if (!is_project(r->op))
557 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT INTO: The subquery is not a projection");
558 1493 : if (list_length(r->exps) != dlist_length(into))
559 2 : return sql_error(sql, 02, SQLSTATE(21S01) "SELECT INTO: number of values doesn't match number of variables to set");
560 1491 : r = rel_return_zero_or_one(sql, r, ek);
561 1491 : nl = sa_list(sql->sa);
562 1491 : append(nl, exp_rel(sql, r));
563 2989 : for (m = r->exps->h, n = into->h; m && n; m = m->next, n = n->next) {
564 1498 : dlist *qname = n->data.lval;
565 1498 : const char *sname = qname_schema(qname);
566 1498 : const char *vname = qname_schema_object(qname);
567 1498 : sql_exp *v = m->data;
568 1498 : int level;
569 1498 : sql_var *var;
570 1498 : sql_subtype *tpe;
571 1498 : sql_arg *a = NULL;
572 :
573 1498 : if (!find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SELECT INTO"))
574 0 : return NULL;
575 :
576 1498 : v = exp_ref(sql, v);
577 1498 : if (!(v = exp_check_type(sql, tpe, r, v, type_equal)))
578 : return NULL;
579 1498 : v = exp_set(sql->sa, var && var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, vname), v, level);
580 1498 : list_append(nl, v);
581 : }
582 : return nl;
583 : }
584 :
585 : extern sql_rel *
586 1 : rel_select_with_into(sql_query *query, symbol *sq)
587 : {
588 1 : exp_kind ek = {type_relation, card_value, TRUE};
589 1 : list *reslist = rel_select_into(query, sq, ek);
590 1 : if (!reslist)
591 : return NULL;
592 0 : return rel_psm_block(query->sql->sa, reslist);
593 : }
594 :
595 : static int has_return( list *l );
596 :
597 : static int
598 21739 : exp_has_return(sql_exp *e)
599 : {
600 21739 : if (e->type == e_psm) {
601 21255 : if (e->flag & PSM_RETURN)
602 : return 1;
603 4308 : if (e->flag & PSM_IF) /* for if, both sides must exist and both must have a return */
604 5154 : return has_return(e->r) && e->f && has_return(e->f);
605 : }
606 : return 0;
607 : }
608 :
609 : static int
610 21739 : has_return( list *l )
611 : {
612 21739 : node *n = l->t;
613 :
614 : /* last statement of sequential block */
615 21739 : if (n && exp_has_return(n->data))
616 : return 1;
617 : return 0;
618 : }
619 :
620 : static list *
621 60 : psm_analyze(sql_query *query, dlist *qname, dlist *columns)
622 : {
623 60 : mvc *sql = query->sql;
624 60 : const char *sname = qname_schema(qname), *tname = qname_schema_object(qname);
625 60 : list *tl = sa_list(sql->sa), *exps = sa_list(sql->sa), *analyze_calls = sa_list(sql->sa);
626 60 : sql_subfunc *f = NULL;
627 60 : sql_subtype tpe;
628 :
629 60 : if (!sql_find_subtype(&tpe, "varchar", 1024, 0))
630 0 : return sql_error(sql, 02, SQLSTATE(HY013) "varchar type missing?");
631 :
632 60 : if (sname && tname) {
633 53 : sql_table *t = NULL;
634 :
635 53 : if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "ANALYZE", false)))
636 : return NULL;
637 53 : if (isDeclaredTable(t))
638 0 : return sql_error(sql, 02, SQLSTATE(42000) "Cannot analyze a declared table");
639 53 : sname = t->s->base.name;
640 : }
641 : /* call analyze( [schema, [ table ]] ) */
642 60 : if (sname) {
643 53 : sql_exp *sname_exp = exp_atom_str(sql->sa, sname, &tpe);
644 :
645 53 : list_append(exps, sname_exp);
646 53 : list_append(tl, exp_subtype(sname_exp));
647 : }
648 60 : if (tname) {
649 60 : sql_exp *tname_exp = exp_atom_str(sql->sa, tname, &tpe);
650 :
651 60 : list_append(exps, tname_exp);
652 60 : list_append(tl, exp_subtype(tname_exp));
653 :
654 60 : if (columns)
655 7 : list_append(tl, exp_subtype(tname_exp));
656 : }
657 60 : if (!(f = sql_bind_func_(sql, "sys", "analyze", tl, F_PROC, true, false)))
658 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Analyze procedure missing");
659 60 : if (!execute_priv(sql, f->func))
660 0 : return sql_error(sql, 02, SQLSTATE(42000) "No privilege to call analyze procedure");
661 60 : if (!columns) {
662 53 : list_append(analyze_calls, exp_op(sql->sa, exps, f));
663 : } else {
664 7 : if (!sname || !tname)
665 2 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Analyze schema or table name missing");
666 17 : for(dnode *n = columns->h; n; n = n->next) {
667 12 : const char *cname = n->data.sval;
668 12 : list *nexps = list_dup(exps, NULL);
669 12 : sql_exp *cname_exp = exp_atom_str(sql->sa, cname, &tpe);
670 :
671 12 : list_append(nexps, cname_exp);
672 : /* call analyze(sname, tname, cname) */
673 12 : list_append(analyze_calls, exp_op(sql->sa, nexps, f));
674 : }
675 : }
676 : return analyze_calls;
677 : }
678 :
679 : static list *
680 36766 : sequential_block(sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_label, int is_func)
681 : {
682 36766 : mvc *sql = query->sql;
683 36766 : list *l=0;
684 36766 : dnode *n;
685 :
686 36766 : assert(!restype || !restypelist);
687 :
688 36766 : if (mvc_highwater(sql))
689 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
690 :
691 36766 : if (blk->h)
692 36766 : l = sa_list(sql->sa);
693 36766 : if (!stack_push_frame(sql, opt_label))
694 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
695 119907 : for (n = blk->h; n; n = n->next ) {
696 83184 : sql_exp *res = NULL;
697 83184 : list *reslist = NULL;
698 83184 : symbol *s = n->data.sym;
699 :
700 83184 : switch (s->token) {
701 14552 : case SQL_SET:
702 14552 : res = psm_set_exp(query, s->data.lval->h);
703 14552 : break;
704 8459 : case SQL_DECLARE:
705 8459 : reslist = rel_psm_declare(sql, s->data.lval->h);
706 8459 : break;
707 122 : case SQL_DECLARE_TABLE:
708 : case SQL_CREATE_TABLE:
709 122 : res = rel_psm_declare_table(query, s->data.lval->h);
710 122 : break;
711 1035 : case SQL_WHILE:
712 1035 : res = rel_psm_while_do(query, restype, restypelist, s->data.lval->h, is_func);
713 1035 : break;
714 11781 : case SQL_IF:
715 11781 : res = rel_psm_if_then_else(query, restype, restypelist, s->data.lval->h, is_func);
716 11781 : break;
717 59 : case SQL_CASE:
718 59 : res = rel_psm_case(query, restype, restypelist, s->data.lval->h, is_func);
719 59 : break;
720 20 : case SQL_ANALYZE: {
721 20 : dlist *l = s->data.lval;
722 :
723 20 : reslist = psm_analyze(query, l->h->data.lval /* qualified table name */, l->h->next->data.lval /* opt list of column */);
724 20 : } break;
725 1905 : case SQL_CALL:
726 1905 : assert(s->type == type_symbol);
727 1905 : res = rel_psm_call(query, s->data.sym);
728 1905 : break;
729 24564 : case SQL_RETURN:
730 : /*If it is not a function it cannot have a return statement*/
731 24564 : if (!is_func)
732 0 : res = sql_error(sql, 01, SQLSTATE(42000) "Return statement in the procedure body");
733 24564 : else if (n->next) /* should be last statement of a sequential_block */
734 0 : res = sql_error(sql, 01, SQLSTATE(42000) "Statement after return");
735 : else
736 24564 : res = rel_psm_return(query, restype, restypelist, s->data.sym);
737 : break;
738 1492 : case SQL_SELECT: { /* row selections (into variables) */
739 1492 : exp_kind ek = {type_value, card_row, TRUE};
740 1492 : reslist = rel_select_into(query, s, ek);
741 1492 : } break;
742 19195 : case SQL_COPYFROM:
743 : case SQL_BINCOPYFROM:
744 : case SQL_INSERT:
745 : case SQL_UPDATE:
746 : case SQL_DELETE:
747 : case SQL_TRUNCATE:
748 : case SQL_MERGE: {
749 19195 : sql_rel *r = rel_updates(query, s);
750 19195 : if (!r) {
751 8 : stack_pop_frame(sql);
752 8 : return NULL;
753 : }
754 19187 : res = exp_rel(sql, r);
755 19187 : } break;
756 0 : default:
757 0 : res = sql_error(sql, 01, SQLSTATE(42000) "Statement '%s' is not a valid flow control statement",
758 : token2string(s->token));
759 : }
760 83176 : if (!res && !reslist) {
761 : l = NULL;
762 : break;
763 : }
764 83141 : if (res)
765 73174 : list_append(l, res);
766 : else
767 9967 : list_merge(l, reslist, NULL);
768 : }
769 36758 : stack_pop_frame(sql);
770 36758 : return l;
771 : }
772 :
773 : static int
774 641834 : arg_cmp(void *A, void *N)
775 : {
776 641834 : sql_arg *a = A;
777 641834 : char *name = N;
778 641834 : return strcmp(a->name, name);
779 : }
780 :
781 : static list *
782 209475 : result_type(mvc *sql, symbol *res)
783 : {
784 209475 : if (res->token == SQL_TYPE) {
785 184033 : sql_subtype *st = &res->data.lval->h->data.typeval;
786 184033 : sql_arg *a = sql_create_arg(sql->sa, "result", st, ARG_OUT);
787 :
788 184033 : return list_append(sa_list(sql->sa), a);
789 25442 : } else if (res->token == SQL_TABLE) {
790 25442 : sql_arg *a;
791 25442 : dnode *n = res->data.lval->h;
792 25442 : list *types = sa_list(sql->sa);
793 :
794 188842 : for(;n; n = n->next->next) {
795 137959 : sql_subtype *ct = &n->next->data.typeval;
796 :
797 137959 : if (list_find(types, n->data.sval, &arg_cmp) != NULL)
798 1 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "CREATE FUNC: identifier '%s' ambiguous", n->data.sval);
799 :
800 137958 : a = sql_create_arg(sql->sa, n->data.sval, ct, ARG_OUT);
801 137958 : list_append(types, a);
802 : }
803 : return types;
804 : }
805 : return NULL;
806 : }
807 :
808 : static list *
809 346050 : create_type_list(mvc *sql, dlist *params, int param)
810 : {
811 346050 : sql_subtype *par_subtype;
812 346050 : list * type_list = sa_list(sql->sa);
813 346050 : dnode * n = NULL;
814 :
815 346050 : if (params) {
816 876325 : for (n = params->h; n; n = n->next) {
817 548449 : dnode *an = n;
818 :
819 548449 : if (param) {
820 388785 : an = n->data.lval->h;
821 388785 : par_subtype = &an->next->data.typeval;
822 388785 : if (par_subtype && !par_subtype->type) /* var arg */
823 : return type_list;
824 388781 : list_append(type_list, par_subtype);
825 : } else {
826 159664 : par_subtype = &an->data.typeval;
827 159664 : list_prepend(type_list, par_subtype);
828 : }
829 : }
830 : }
831 : return type_list;
832 : }
833 :
834 : static sql_rel*
835 239381 : rel_create_function(allocator *sa, const char *sname, sql_func *f, int replace)
836 : {
837 239381 : sql_rel *rel = rel_create(sa);
838 239381 : list *exps = new_exp_list(sa);
839 239381 : if(!rel || !exps)
840 : return NULL;
841 :
842 239381 : append(exps, exp_atom_clob(sa, sname));
843 239381 : if (f)
844 239381 : append(exps, exp_atom_clob(sa, f->base.name));
845 239381 : append(exps, exp_atom_ptr(sa, f));
846 239381 : append(exps, exp_atom_int(sa, replace));
847 239381 : rel->l = NULL;
848 239381 : rel->r = NULL;
849 239381 : rel->op = op_ddl;
850 239381 : rel->flag = ddl_create_function;
851 239381 : rel->exps = exps;
852 239381 : rel->card = 0;
853 239381 : rel->nrcols = 0;
854 239381 : return rel;
855 : }
856 :
857 : static bool
858 234 : has_generic_decimal(list *types)
859 : {
860 234 : if (!list_empty(types)) {
861 439 : for(node *n = types->h; n; n = n->next) {
862 269 : sql_subtype *st = n->data;
863 :
864 269 : if (st->type->eclass == EC_DEC && !st->digits && !st->scale)
865 : return true;
866 : }
867 : }
868 : return false;
869 : }
870 :
871 : static bool
872 232 : has_generic_decimal_result(list *types)
873 : {
874 232 : if (!list_empty(types)) {
875 508 : for(node *n = types->h; n; n = n->next) {
876 289 : sql_arg *a = n->data;
877 :
878 289 : if (a->type.type->eclass == EC_DEC && !a->type.digits && !a->type.scale)
879 : return true;
880 : }
881 : }
882 : return false;
883 : }
884 :
885 :
886 : static sql_rel *
887 248224 : rel_create_func(sql_query *query, dlist *qname, dlist *params, symbol *res, dlist *ext_name, dlist *body, sql_ftype type, sql_flang lang, int replace, int order_spec)
888 : {
889 248224 : mvc *sql = query->sql;
890 248224 : const char *fname = qname_schema_object(qname);
891 248224 : const char *sname = qname_schema(qname);
892 248224 : sql_schema *s = cur_schema(sql);
893 248224 : sql_func *f = NULL;
894 248224 : sql_subfunc *sf = NULL;
895 248224 : dnode *n;
896 248224 : list *type_list = NULL, *restype = NULL, *l = NULL;
897 248224 : int instantiate = (sql->emode == m_instantiate);
898 248224 : int deps = (sql->emode == m_deps);
899 248224 : int create = (!instantiate && !deps);
900 248224 : bit vararg = FALSE, union_err = 0;
901 248224 : char *F = NULL, *fn = NULL, is_func, *q = QUERY(sql->scanner);
902 248224 : bit order_required = (order_spec == 2);
903 248224 : bit opt_order = (order_spec == 1);
904 :
905 248224 : if (res && res->token == SQL_TABLE) {
906 25444 : if (type == F_FUNC)
907 : type = F_UNION;
908 : else
909 : union_err = 1;
910 : }
911 :
912 222781 : FUNC_TYPE_STR(type, F, fn)
913 :
914 248224 : is_func = (type != F_PROC && type != F_LOADER);
915 248224 : assert(lang != FUNC_LANG_INT);
916 :
917 248224 : if (create && store_readonly(sql->session->tr->store))
918 0 : return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
919 :
920 248224 : if (union_err)
921 1 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %ss cannot return tables", F, fn);
922 248223 : else if (res && type == F_PROC)
923 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: procedures cannot have return parameters", F);
924 248223 : else if (res && (type == F_FILT || type == F_LOADER))
925 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %s functions don't have to specify a return type", F, fn);
926 38736 : else if (!res && !(type == F_PROC || type == F_FILT || type == F_LOADER))
927 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %ss require a return type", F, fn);
928 248223 : else if (lang == FUNC_LANG_MAL && type == F_LOADER)
929 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %s functions creation via MAL not supported", F, fn);
930 248223 : else if (lang == FUNC_LANG_SQL && !(type == F_FUNC || type == F_PROC || type == F_UNION))
931 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %s functions creation via SQL not supported", F, fn);
932 248223 : else if (LANG_EXT(lang) && !(type == F_FUNC || type == F_AGGR || type == F_UNION || type == F_LOADER))
933 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %ss creation via external programming languages not supported", F, fn);
934 :
935 248223 : if (sname && !(s = mvc_bind_schema(sql, sname)))
936 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "CREATE %s: no such schema '%s'", F, sname);
937 248223 : if (create && !mvc_schema_privs(sql, s))
938 5 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: insufficient privileges for user '%s' in schema '%s'", F,
939 : get_string_global_var(sql, "current_user"), s->base.name);
940 :
941 248218 : type_list = create_type_list(sql, params, 1);
942 :
943 248218 : if ((sf = sql_bind_func_(sql, s->base.name, fname, type_list, type, true, true)) != NULL && create) {
944 31 : if (sf->func->private) { /* cannot create a function using a private name or replace a existing one */
945 2 : list_destroy(type_list);
946 2 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' cannot be used", F, fname);
947 : }
948 29 : if (!replace && params) {
949 0 : char *arg_list = NULL;
950 0 : node *n;
951 :
952 0 : for (n = type_list->h; n; n = n->next) {
953 0 : char *tpe = sql_subtype_string(sql->ta, (sql_subtype *) n->data);
954 :
955 0 : if (arg_list) {
956 0 : arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe);
957 : } else {
958 : arg_list = tpe;
959 : }
960 : }
961 0 : (void)sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' (%s) already in use", F, fname, arg_list ? arg_list : "");
962 0 : list_destroy(type_list);
963 0 : return NULL;
964 29 : } else if (!replace) {
965 2 : list_destroy(type_list);
966 2 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' already in use", F, fname);
967 27 : } else if (replace && !sf->func->s) {
968 0 : list_destroy(type_list);
969 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: cannot replace system function '%s'", F, fname);
970 : }
971 : } else {
972 248187 : sql->session->status = 0; /* if the function was not found clean the error */
973 248187 : sql->errstr[0] = '\0';
974 : }
975 :
976 248214 : if (create && (type == F_FUNC || type == F_AGGR || type == F_FILT)) {
977 83670 : sql_subfunc *found = NULL;
978 110526 : if ((found = sql_bind_func_(sql, s->base.name, fname, type_list, (type == F_FUNC || type == F_FILT) ? F_AGGR : F_FUNC, true, true))) {
979 2 : list_destroy(type_list);
980 2 : if (found->func->private) /* cannot create a function using a private name or replace a existing one */
981 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' cannot be used", F, fname);
982 2 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: there's %s with the name '%s' and the same parameters, which causes ambiguous calls", F,
983 2 : IS_AGGR(found->func) ? "an aggregate" : IS_FILT(found->func) ? "a filter function" : "a function", fname);
984 : }
985 83668 : sql->session->status = 0; /* if the function was not found clean the error */
986 83668 : sql->errstr[0] = '\0';
987 : }
988 248212 : if (lang > FUNC_LANG_SQL && has_generic_decimal(type_list))
989 2 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: the function '%s' uses a generic DECIMAL type, UDFs require precision and scale", F, fname);
990 :
991 248210 : list_destroy(type_list);
992 :
993 248210 : if (params) {
994 618819 : for (n = params->h; n; n = n->next) {
995 388777 : dnode *an = n->data.lval->h;
996 388777 : sql_add_param(sql, an->data.sval, &an->next->data.typeval);
997 : }
998 230042 : l = sql->params;
999 230042 : if (l && list_length(l) == 1) {
1000 110440 : sql_arg *a = l->h->data;
1001 :
1002 110440 : if (strcmp(a->name, "*") == 0) {
1003 : l = NULL;
1004 : vararg = TRUE;
1005 : }
1006 : }
1007 : }
1008 : if (!l)
1009 18172 : l = sa_list(sql->sa);
1010 248210 : if (res && !(restype = result_type(sql, res)))
1011 1 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: failed to get restype", F);
1012 :
1013 248209 : if (lang > FUNC_LANG_SQL && has_generic_decimal_result(restype))
1014 2 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: the function '%s' returns a generic DECIMAL type, UDFs require precision and scale", F, fname);
1015 248207 : if (body && LANG_EXT(lang)) {
1016 230 : const char *lang_body = body->h->data.sval, *mod = "unknown", *slang = "Unknown", *imp = "Unknown";
1017 230 : switch (lang) {
1018 : case FUNC_LANG_R:
1019 : mod = "rapi";
1020 : slang = "R";
1021 : break;
1022 43 : case FUNC_LANG_C:
1023 43 : mod = "capi";
1024 43 : slang = "C";
1025 43 : break;
1026 1 : case FUNC_LANG_CPP:
1027 1 : mod = "capi";
1028 1 : slang = "CPP";
1029 1 : break;
1030 0 : case FUNC_LANG_J:
1031 0 : mod = "japi";
1032 0 : slang = "Javascript";
1033 0 : break;
1034 149 : case FUNC_LANG_PY:
1035 : case FUNC_LANG_PY3:
1036 149 : mod = "pyapi3";
1037 149 : slang = "Python";
1038 149 : break;
1039 0 : default:
1040 0 : return sql_error(sql, 01, SQLSTATE(42000) "Function language without a MAL backend");
1041 : }
1042 230 : switch(type) {
1043 : case F_AGGR:
1044 : imp = "eval_aggr";
1045 : break;
1046 : case F_LOADER:
1047 11 : imp = "eval_loader";
1048 11 : break;
1049 : default: /* for every other function type at the moment */
1050 187 : imp = "eval";
1051 : }
1052 :
1053 198 : if (type == F_LOADER && !(lang == FUNC_LANG_PY || lang == FUNC_LANG_PY3))
1054 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: Language name \"Python[3]\" expected", F);
1055 :
1056 230 : sql->params = NULL;
1057 230 : if (create) {
1058 230 : bit side_effect = (list_empty(restype) || (!vararg && list_empty(l))); /* TODO make this more precise? */
1059 230 : switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, mod, imp, lang_body, (type == F_LOADER)?TRUE:FALSE, vararg, FALSE, side_effect, order_required, opt_order)) {
1060 0 : case -1:
1061 0 : return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1062 0 : case -2:
1063 : case -3:
1064 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: transaction conflict detected", F);
1065 : default:
1066 : break;
1067 : }
1068 0 : } else if (!sf) {
1069 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: %s function %s.%s not bound", F, slang, s->base.name, fname);
1070 : }
1071 247977 : } else if (body) { /* SQL implementation */
1072 17061 : sql_arg *ra = (restype && type != F_UNION)?restype->h->data:NULL;
1073 17061 : list *b = NULL;
1074 17061 : sql_schema *os = cur_schema(sql);
1075 :
1076 17061 : if (create) { /* needed for recursive functions */
1077 8277 : bit side_effect = list_empty(restype) == 1; /* TODO make this more precise? */
1078 8277 : q = query_cleaned(sql->ta, q);
1079 8277 : switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, sql_shared_module_name, NULL, q, FALSE, vararg, FALSE, side_effect, order_required, opt_order)) {
1080 0 : case -1:
1081 0 : return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1082 0 : case -2:
1083 : case -3:
1084 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: transaction conflict detected", F);
1085 : default:
1086 8277 : break;
1087 : }
1088 8277 : sql->forward = f;
1089 8784 : } else if (!sf) {
1090 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: SQL function %s.%s not bound", F, s->base.name, fname);
1091 : }
1092 17061 : sql->session->schema = s;
1093 17061 : b = sequential_block(query, (ra)?&ra->type:NULL, ra?NULL:restype, body, NULL, is_func);
1094 17061 : sql->forward = NULL;
1095 17061 : sql->session->schema = os;
1096 17061 : sql->params = NULL;
1097 17061 : if (!b)
1098 : return NULL;
1099 :
1100 : /* check if we have a return statement */
1101 17025 : if (is_func && restype && !has_return(b))
1102 4 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: missing return statement", F);
1103 17021 : if (!is_func && !restype && has_return(b))
1104 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: %ss cannot have return statements", F, fn);
1105 : /* in execute mode we instantiate the function */
1106 17021 : if (instantiate || deps)
1107 8782 : return rel_psm_block(sql->sa, b);
1108 : } else { /* MAL implementation */
1109 230916 : int clientid = sql->clientid;
1110 230916 : char *fmod = qname_module(ext_name);
1111 230916 : char *fnme = qname_schema_object(ext_name);
1112 :
1113 230916 : if (!fmod || !fnme)
1114 4 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: MAL module or function name missing", F);
1115 230916 : if (strlen(fmod) >= IDLENGTH)
1116 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: MAL module name '%s' too large for the backend", F, fmod);
1117 230916 : if (strlen(fnme) >= IDLENGTH)
1118 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: MAL function name '%s' too large for the backend", F, fnme);
1119 230916 : sql->params = NULL;
1120 230916 : if (create) {
1121 115460 : q = query_cleaned(sql->ta, q);
1122 115460 : switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, fmod, fnme, q, FALSE, vararg, FALSE, FALSE, order_required, opt_order)) {
1123 0 : case -1:
1124 4 : return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1125 0 : case -2:
1126 : case -3:
1127 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: transaction conflict detected", F);
1128 : default:
1129 115460 : break;
1130 : }
1131 :
1132 : /* instantiate MAL functions while being created. This also sets the side-effects flag */
1133 115460 : bool se = f->side_effect;
1134 115460 : if (!backend_resolve_function(&clientid, f, fnme, &se))
1135 4 : return sql_error(sql, 02, SQLSTATE(3F000) "CREATE %s: external name %s.%s not bound (%s.%s)", F, fmod, fnme, s->base.name, fname );
1136 115456 : f->side_effect = se;
1137 115456 : f->instantiated = TRUE;
1138 115456 : } else if (!sf) {
1139 0 : return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: external name %s.%s not bound (%s.%s)", F, fmod, fnme, s->base.name, fname );
1140 : }
1141 230912 : if (!f)
1142 115456 : f = sf->func;
1143 230912 : assert(f);
1144 : }
1145 239381 : return rel_create_function(sql->sa, s->base.name, f, replace);
1146 : }
1147 :
1148 : static sql_rel*
1149 688 : rel_drop_function(allocator *sa, const char *sname, const char *name, int nr, sql_ftype type, int action)
1150 : {
1151 688 : sql_rel *rel = rel_create(sa);
1152 688 : list *exps = new_exp_list(sa);
1153 688 : if(!rel || !exps)
1154 : return NULL;
1155 :
1156 688 : append(exps, exp_atom_clob(sa, sname));
1157 688 : append(exps, exp_atom_clob(sa, name));
1158 688 : append(exps, exp_atom_int(sa, nr));
1159 688 : append(exps, exp_atom_int(sa, (int) type));
1160 688 : append(exps, exp_atom_int(sa, action));
1161 688 : rel->l = NULL;
1162 688 : rel->r = NULL;
1163 688 : rel->op = op_ddl;
1164 688 : rel->flag = ddl_drop_function;
1165 688 : rel->exps = exps;
1166 688 : rel->card = 0;
1167 688 : rel->nrcols = 0;
1168 688 : return rel;
1169 : }
1170 :
1171 : sql_func *
1172 102239 : resolve_func(mvc *sql, const char *sname, const char *name, dlist *typelist, sql_ftype type, const char *op, int if_exists)
1173 : {
1174 102239 : sql_func *func = NULL;
1175 102239 : list *list_func = NULL, *type_list = NULL;
1176 102239 : char is_func = (type != F_PROC && type != F_LOADER), *F = NULL, *fn = NULL;
1177 :
1178 102239 : FUNC_TYPE_STR(type, F, fn)
1179 :
1180 102239 : if (typelist) {
1181 97832 : sql_subfunc *sub_func;
1182 :
1183 97832 : type_list = create_type_list(sql, typelist, 0);
1184 97832 : sub_func = sql_bind_func_(sql, sname, name, type_list, type, false, true);
1185 97832 : if (!sub_func && type == F_FUNC) {
1186 6157 : sql->session->status = 0; /* if the function was not found clean the error */
1187 6157 : sql->errstr[0] = '\0';
1188 6157 : sub_func = sql_bind_func_(sql, sname, name, type_list, F_UNION, false, true);
1189 6157 : type = sub_func?F_UNION:F_FUNC;
1190 : }
1191 97813 : if ( sub_func && sub_func->func->type == type)
1192 97809 : func = sub_func->func;
1193 : } else {
1194 4407 : list_func = sql_find_funcs_by_name(sql, sname, name, type, false);
1195 4407 : if (!list_func && type == F_FUNC) {
1196 1265 : sql->session->status = 0; /* if the function was not found clean the error */
1197 1265 : sql->errstr[0] = '\0';
1198 1265 : list_func = sql_find_funcs_by_name(sql, sname, name, F_UNION, false);
1199 : }
1200 4407 : if (list_func && list_func->cnt > 1) {
1201 3 : list_destroy(list_func);
1202 3 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: there are more than one %s called '%s', please use the full signature", op, F, fn, name);
1203 : }
1204 4397 : if (list_func && list_func->cnt == 1)
1205 4397 : func = (sql_func*) list_func->h->data;
1206 : }
1207 :
1208 102236 : if (!func) {
1209 30 : void *e = NULL;
1210 30 : if (typelist) {
1211 23 : char *arg_list = NULL;
1212 23 : node *n;
1213 :
1214 23 : if (type_list->cnt > 0) {
1215 49 : for (n = type_list->h; n; n = n->next) {
1216 30 : char *tpe = sql_subtype_string(sql->ta, (sql_subtype *) n->data);
1217 :
1218 30 : if (arg_list) {
1219 11 : arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe);
1220 : } else {
1221 : arg_list = tpe;
1222 : }
1223 : }
1224 19 : list_destroy(list_func);
1225 19 : list_destroy(type_list);
1226 19 : if (!if_exists)
1227 16 : e = sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: no such %s '%s' (%s)", op, F, fn, name, arg_list);
1228 19 : return e;
1229 : }
1230 4 : list_destroy(list_func);
1231 4 : list_destroy(type_list);
1232 4 : if (!if_exists)
1233 2 : e = sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: no such %s '%s' ()", op, F, fn, name);
1234 4 : return e;
1235 : } else {
1236 7 : if (!if_exists)
1237 5 : e = sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: no such %s '%s'", op, F, fn, name);
1238 7 : return e;
1239 : }
1240 102206 : } else if (((is_func && type != F_FILT) && !func->res) || (!is_func && func->res)) {
1241 0 : list_destroy(list_func);
1242 0 : list_destroy(type_list);
1243 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: cannot drop %s '%s'", op, F, fn, name);
1244 : }
1245 :
1246 102206 : list_destroy(list_func);
1247 102206 : list_destroy(type_list);
1248 102206 : return func;
1249 : }
1250 :
1251 : static sql_rel*
1252 686 : rel_drop_func(mvc *sql, dlist *qname, dlist *typelist, int drop_action, sql_ftype type, int if_exists)
1253 : {
1254 686 : const char *name = qname_schema_object(qname);
1255 686 : const char *sname = qname_schema(qname);
1256 686 : sql_func *func = NULL;
1257 686 : char *F = NULL, *fn = NULL;
1258 :
1259 686 : FUNC_TYPE_STR(type, F, fn)
1260 :
1261 686 : if (!(func = resolve_func(sql, sname, name, typelist, type, "DROP", if_exists))) {
1262 32 : if (if_exists) {
1263 7 : sql->errstr[0] = '\0'; /* reset function not found error */
1264 7 : sql->session->status = 0;
1265 7 : return rel_psm_block(sql->sa, new_exp_list(sql->sa));
1266 : }
1267 : return NULL;
1268 : }
1269 654 : if (!func->s) /* attempting to drop a system function */
1270 0 : return sql_error(sql, 02, SQLSTATE(42000) "DROP %s: cannot drop system %s '%s'", F, fn, name);
1271 654 : if (!mvc_schema_privs(sql, func->s))
1272 0 : return sql_error(sql, 02, SQLSTATE(42000) "DROP %s: insufficient privileges for user '%s' in schema '%s'", F, get_string_global_var(sql, "current_user"), func->s->base.name);
1273 654 : return rel_drop_function(sql->sa, func->s->base.name, name, func->base.id, type, drop_action);
1274 : }
1275 :
1276 : static sql_rel*
1277 111 : rel_drop_all_func(mvc *sql, dlist *qname, int drop_action, sql_ftype type)
1278 : {
1279 111 : const char *name = qname_schema_object(qname);
1280 111 : const char *sname = qname_schema(qname);
1281 111 : sql_schema *s = cur_schema(sql);
1282 111 : list *list_func = NULL;
1283 111 : char *F = NULL, *fn = NULL;
1284 :
1285 111 : FUNC_TYPE_STR(type, F, fn)
1286 :
1287 111 : if (sname && !(s = mvc_bind_schema(sql, sname)))
1288 0 : return sql_error(sql, 02, SQLSTATE(3F000) "DROP ALL %s: no such schema '%s'", F, sname);
1289 111 : if (!mvc_schema_privs(sql, s))
1290 0 : return sql_error(sql, 02, SQLSTATE(42000) "DROP ALL %s: insufficient privileges for user '%s' in schema '%s'", F, get_string_global_var(sql, "current_user"), s->base.name);
1291 :
1292 111 : if (!(list_func = sql_find_funcs_by_name(sql, s->base.name, name, type, false)) || list_empty(list_func)) {
1293 77 : list_destroy(list_func);
1294 77 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "DROP ALL %s: no such %s '%s'", F, fn, name);
1295 : }
1296 34 : list_destroy(list_func);
1297 34 : return rel_drop_function(sql->sa, s->base.name, name, -1, type, drop_action);
1298 : }
1299 :
1300 : static sql_rel *
1301 349 : rel_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, int replace)
1302 : {
1303 349 : sql_rel *rel = rel_create(sql->sa);
1304 349 : list *exps = new_exp_list(sql->sa);
1305 349 : if(!rel || !exps)
1306 : return NULL;
1307 :
1308 349 : append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
1309 349 : append(exps, exp_atom_str(sql->sa, tname, sql_bind_localtype("str") ));
1310 349 : append(exps, exp_atom_str(sql->sa, triggername, sql_bind_localtype("str") ));
1311 349 : append(exps, exp_atom_int(sql->sa, time));
1312 349 : append(exps, exp_atom_int(sql->sa, orientation));
1313 349 : append(exps, exp_atom_int(sql->sa, event));
1314 349 : append(exps, exp_atom_str(sql->sa, old_name, sql_bind_localtype("str") ));
1315 349 : append(exps, exp_atom_str(sql->sa, new_name, sql_bind_localtype("str") ));
1316 349 : (void)condition;
1317 349 : append(exps, exp_atom_str(sql->sa, NULL, sql_bind_localtype("str") ));
1318 349 : append(exps, exp_atom_str(sql->sa, query, sql_bind_localtype("str") ));
1319 349 : append(exps, exp_atom_int(sql->sa, replace));
1320 349 : rel->l = NULL;
1321 349 : rel->r = NULL;
1322 349 : rel->op = op_ddl;
1323 349 : rel->flag = ddl_create_trigger;
1324 349 : rel->exps = exps;
1325 349 : rel->card = CARD_MULTI;
1326 349 : rel->nrcols = 0;
1327 349 : return rel;
1328 : }
1329 :
1330 : static sql_rel_view*
1331 67 : _stack_push_table(mvc *sql, const char *tname, sql_table *t)
1332 : {
1333 67 : sql_rel *r = rel_basetable(sql, t, tname );
1334 67 : rel_base_use_all(sql, r);
1335 67 : r = rewrite_basetable(sql, r);
1336 67 : return stack_push_rel_view(sql, tname, r);
1337 : }
1338 :
1339 : static sql_rel *
1340 5645 : create_trigger(sql_query *query, dlist *qname, int time, symbol *trigger_event, dlist *tqname, dlist *opt_ref, dlist *triggered_action, int replace)
1341 : {
1342 5645 : mvc *sql = query->sql;
1343 5645 : const char *triggerschema = qname_schema(qname);
1344 5645 : const char *triggername = qname_schema_object(qname);
1345 5645 : char *sname = tqname? qname_schema(tqname) : NULL;
1346 5636 : char *tname = tqname? qname_schema_object(tqname) : NULL;
1347 5645 : int instantiate = (sql->emode == m_instantiate);
1348 5645 : int create = (!instantiate && sql->emode != m_deps), event, orientation;
1349 5645 : sql_schema *ss = cur_schema(sql), *old_schema = cur_schema(sql);
1350 5645 : sql_table *t = NULL;
1351 5645 : list *sq = NULL;
1352 5645 : sql_rel *r = NULL;
1353 5645 : char *q, *base = replace ? "CREATE OR REPLACE TRIGGER" : "CREATE TRIGGER";
1354 5645 : dlist *columns = trigger_event->data.lval;
1355 5645 : const char *old_name = NULL, *new_name = NULL;
1356 5645 : dlist *stmts = triggered_action->h->next->next->data.lval;
1357 5645 : symbol *condition = triggered_action->h->next->data.sym;
1358 5645 : bool old_useviews = sql->use_views;
1359 :
1360 5645 : if (opt_ref) {
1361 178 : dnode *dl = opt_ref->h;
1362 401 : for ( ; dl; dl = dl->next) {
1363 : /* list (new(1)/old(0)), char */
1364 223 : char *n = dl->data.lval->h->next->data.sval;
1365 :
1366 223 : assert(dl->data.lval->h->type == type_int);
1367 223 : if (!dl->data.lval->h->data.i_val) /*?l_val?*/
1368 : old_name = n;
1369 : else
1370 143 : new_name = n;
1371 : }
1372 : }
1373 :
1374 5645 : if (sname && !(ss = mvc_bind_schema(sql, sname)))
1375 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s: no such schema '%s'", base, sname);
1376 :
1377 5645 : if (create) {
1378 358 : if (triggerschema)
1379 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: a trigger will be placed on the respective table's schema, specify the schema on the table reference, ie ON clause instead", base);
1380 356 : if (tname) {
1381 352 : if (!(t = mvc_bind_table(sql, ss, tname)))
1382 4 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "%s: no such table %s%s%s'%s'", base, sname ? "'":"", sname ? sname : "", sname ? "'.":"", tname);
1383 350 : if (isView(t))
1384 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot create trigger on view '%s'", base, tname);
1385 349 : sname = t->s->base.name;
1386 349 : tname = t->base.name;
1387 : }
1388 353 : if (!mvc_schema_privs(sql, ss))
1389 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: access denied for %s to schema '%s'", base, get_string_global_var(sql, "current_user"), ss->base.name);
1390 352 : if (!replace && mvc_bind_trigger(sql, ss, triggername) != NULL)
1391 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: name '%s' already in use", base, triggername);
1392 352 : switch (trigger_event->token) {
1393 43 : case SQL_INSERT: {
1394 43 : if (old_name)
1395 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: old name not allowed at insert events", base);
1396 : event = 0;
1397 : } break;
1398 29 : case SQL_DELETE: {
1399 29 : if (new_name)
1400 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: new name not allowed at delete events", base);
1401 : event = 1;
1402 : } break;
1403 1 : case SQL_TRUNCATE: {
1404 1 : if (new_name)
1405 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: new name not allowed at truncate events", base);
1406 : event = 3;
1407 : } break;
1408 275 : case SQL_UPDATE: {
1409 275 : if (old_name && new_name && !strcmp(old_name, new_name))
1410 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: old and new names cannot be the same", base);
1411 274 : if (!old_name && new_name && !strcmp("old", new_name))
1412 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: old and new names cannot be the same", base);
1413 273 : if (!new_name && old_name && !strcmp("new", old_name))
1414 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: old and new names cannot be the same", base);
1415 : event = 2;
1416 : } break;
1417 : case SQL_LOGIN:
1418 : // TODO any checks here?
1419 : event = LOGIN_EVENT;
1420 : break;
1421 0 : default:
1422 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: invalid event: %s", base, token2string(trigger_event->token));
1423 : }
1424 :
1425 349 : assert(triggered_action->h->type == type_int);
1426 349 : orientation = triggered_action->h->data.i_val;
1427 349 : q = query_cleaned(sql->ta, QUERY(sql->scanner));
1428 349 : return rel_create_trigger(sql, sname, tname, triggername, time, orientation, event, old_name, new_name, condition, q, replace);
1429 : }
1430 :
1431 5287 : if (!instantiate) {
1432 348 : if (!stack_push_frame(sql, "%OLD-NEW"))
1433 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1434 348 : if (tname) {
1435 343 : if (!(t = mvc_bind_table(sql, ss, tname)))
1436 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "%s: no such table %s%s%s'%s'", base, sname ? "'":"", sname ? sname : "", sname ? "'.":"", tname);
1437 : /* we need to add the old and new tables */
1438 343 : if (new_name && !_stack_push_table(sql, new_name, t)) {
1439 0 : stack_pop_frame(sql);
1440 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1441 : }
1442 343 : if (old_name && !_stack_push_table(sql, old_name, t)) {
1443 0 : stack_pop_frame(sql);
1444 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1445 : }
1446 : }
1447 : }
1448 5287 : if (condition) {
1449 8 : sql_rel *rel = NULL;
1450 :
1451 8 : if (new_name) /* in case of updates same relations is available via both names */
1452 6 : rel = stack_find_rel_view(sql, new_name);
1453 8 : if (!rel && old_name)
1454 0 : rel = stack_find_rel_view(sql, old_name);
1455 8 : if (!rel)
1456 2 : rel = stack_find_rel_view(sql, "old");
1457 2 : if (!rel)
1458 2 : rel = stack_find_rel_view(sql, "new");
1459 8 : rel = rel_logical_exp(query, rel, condition, sql_where);
1460 8 : if (!rel) {
1461 2 : if (!instantiate)
1462 2 : stack_pop_frame(sql);
1463 2 : return NULL;
1464 : }
1465 : /* transition tables */
1466 : /* insert: rel_select(table [new], searchcondition) */
1467 : /* delete: rel_select(table [old], searchcondition) */
1468 : /* update: rel_select(table [old,new]), searchcondition) */
1469 6 : if (new_name)
1470 6 : stack_update_rel_view(sql, new_name, rel);
1471 6 : if (old_name)
1472 0 : stack_update_rel_view(sql, old_name, new_name?rel_dup(rel):rel);
1473 : }
1474 5285 : sql->use_views = true; /* leave the 'use_views' hack to where it belongs */
1475 5285 : sql->session->schema = ss;
1476 5285 : sq = sequential_block(query, NULL, NULL, stmts, NULL, 1);
1477 5285 : sql->session->schema = old_schema;
1478 5285 : sql->use_views = old_useviews;
1479 5285 : if (!sq) {
1480 6 : if (!instantiate)
1481 3 : stack_pop_frame(sql);
1482 6 : return NULL;
1483 : }
1484 5279 : r = rel_psm_block(sql->sa, sq);
1485 :
1486 5279 : if (!instantiate)
1487 343 : stack_pop_frame(sql);
1488 : /* todo trigger_columns */
1489 : (void)columns;
1490 : return r;
1491 : }
1492 :
1493 : static sql_rel *
1494 84 : rel_drop_trigger(mvc *sql, const char *sname, const char *tname, int if_exists)
1495 : {
1496 84 : sql_rel *rel = rel_create(sql->sa);
1497 84 : list *exps = new_exp_list(sql->sa);
1498 84 : if(!rel || !exps)
1499 : return NULL;
1500 :
1501 84 : append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
1502 84 : append(exps, exp_atom_str(sql->sa, tname, sql_bind_localtype("str") ));
1503 84 : append(exps, exp_atom_int(sql->sa, if_exists));
1504 84 : rel->l = NULL;
1505 84 : rel->r = NULL;
1506 84 : rel->op = op_ddl;
1507 84 : rel->flag = ddl_drop_trigger;
1508 84 : rel->exps = exps;
1509 84 : rel->card = CARD_MULTI;
1510 84 : rel->nrcols = 0;
1511 84 : return rel;
1512 : }
1513 :
1514 : static sql_rel *
1515 96 : drop_trigger(mvc *sql, dlist *qname, int if_exists)
1516 : {
1517 96 : const char *sname = qname_schema(qname);
1518 96 : const char *tname = qname_schema_object(qname);
1519 96 : sql_trigger *tr = NULL;
1520 :
1521 96 : if (!(tr = find_trigger_on_scope(sql, sname, tname, "DROP TRIGGER"))) {
1522 12 : if (if_exists) {
1523 1 : sql->errstr[0] = '\0'; /* reset trigger not found error */
1524 1 : sql->session->status = 0;
1525 1 : return rel_psm_block(sql->sa, new_exp_list(sql->sa));
1526 : }
1527 : return NULL;
1528 : }
1529 84 : if (tr->t && !mvc_schema_privs(sql, tr->t->s))
1530 0 : return sql_error(sql, 02, SQLSTATE(3F000) "DROP TRIGGER: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), tr->t->s->base.name);
1531 84 : return rel_drop_trigger(sql, tr->t?tr->t->s->base.name:NULL, tname, if_exists);
1532 : }
1533 :
1534 : static sql_rel*
1535 2 : create_table_from_loader(sql_query *query, dlist *qname, symbol *fcall)
1536 : {
1537 2 : mvc *sql = query->sql;
1538 2 : sql_schema *s = cur_schema(sql);
1539 2 : char *sname = qname_schema(qname);
1540 2 : char *tname = qname_schema_object(qname);
1541 2 : sql_subfunc *loader = NULL;
1542 2 : sql_rel *rel = NULL;
1543 2 : sql_table *t = NULL;
1544 :
1545 2 : if (sname && !(s = mvc_bind_schema(sql, sname)))
1546 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "CREATE TABLE FROM LOADER: no such schema '%s'", sname);
1547 2 : if ((t = mvc_bind_table(sql, s, tname)))
1548 0 : return sql_error(sql, 02, SQLSTATE(42S01) "CREATE TABLE FROM LOADER: name '%s' already in use", tname);
1549 2 : if (!mvc_schema_privs(sql, s))
1550 0 : return sql_error(sql, 02, SQLSTATE(42000) "CREATE TABLE FROM LOADER: insufficient privileges for user '%s' in schema '%s'", get_string_global_var(sql, "current_user"), s->base.name);
1551 :
1552 2 : rel = rel_loader_function(query, fcall, new_exp_list(sql->sa), &loader);
1553 2 : if (!rel || !loader)
1554 : return NULL;
1555 :
1556 1 : loader->sname = s ? sa_strdup(sql->sa, s->base.name) : NULL;
1557 1 : loader->tname = tname ? sa_strdup(sql->sa, tname) : NULL;
1558 :
1559 1 : return rel;
1560 : }
1561 :
1562 : static list *
1563 4 : rel_paramlist( sql_query *query, symbol *nop)
1564 : {
1565 4 : dnode *ops = nop->data.lval->h->next->next->data.lval->h;
1566 4 : list *exps = sa_list(query->sql->sa);
1567 4 : exp_kind iek = {type_value, card_column, FALSE};
1568 :
1569 9 : for (; ops; ops = ops->next) {
1570 6 : sql_exp *e = rel_value_exp(query, NULL, ops->data.sym, sql_farg, iek);
1571 6 : if (!e)
1572 : return NULL;
1573 6 : ops = ops->next;
1574 6 : sql_arg *a = sql_find_param(query->sql, ops->data.sval);
1575 6 : if (!a)
1576 1 : return sql_error(query->sql, 06, SQLSTATE(42000) "Named placeholder ('%s') not used in the query.", ops->data.sval);
1577 5 : a->type = *exp_subtype(e);
1578 5 : append(exps, e);
1579 : }
1580 : return exps;
1581 : }
1582 :
1583 :
1584 : sql_rel *
1585 296770 : rel_psm(sql_query *query, symbol *s)
1586 : {
1587 296770 : mvc *sql = query->sql;
1588 296770 : sql_rel *ret = NULL;
1589 :
1590 296770 : switch (s->token) {
1591 248224 : case SQL_CREATE_FUNC:
1592 : {
1593 248224 : dlist *l = s->data.lval;
1594 248224 : sql_ftype type = (sql_ftype) l->h->next->next->next->next->next->data.i_val;
1595 248224 : sql_flang lang = (sql_flang) l->h->next->next->next->next->next->next->data.i_val;
1596 248224 : int repl = l->h->next->next->next->next->next->next->next->data.i_val;
1597 248224 : int order_spec = l->h->next->next->next->next->next->next->next->next->data.i_val;
1598 :
1599 248224 : 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, order_spec);
1600 248224 : sql->type = Q_SCHEMA;
1601 248224 : } break;
1602 797 : case SQL_DROP_FUNC:
1603 : {
1604 797 : dlist *l = s->data.lval;
1605 797 : dlist *qname = l->h->data.lval;
1606 797 : dlist *typelist = l->h->next->data.lval;
1607 797 : sql_ftype type = (sql_ftype) l->h->next->next->data.i_val;
1608 797 : int if_exists = l->h->next->next->next->data.i_val;
1609 797 : int all = l->h->next->next->next->next->data.i_val;
1610 797 : int drop_action = l->h->next->next->next->next->next->data.i_val;
1611 :
1612 797 : if (store_readonly(sql->session->tr->store))
1613 0 : return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
1614 :
1615 797 : if (all)
1616 111 : ret = rel_drop_all_func(sql, qname, drop_action, type);
1617 : else
1618 686 : ret = rel_drop_func(sql, qname, typelist, drop_action, type, if_exists);
1619 :
1620 797 : sql->type = Q_SCHEMA;
1621 797 : } break;
1622 398 : case SQL_SET:
1623 398 : ret = rel_psm_stmt(sql->sa, psm_set_exp(query, s->data.lval->h));
1624 398 : sql->type = Q_SCHEMA;
1625 398 : break;
1626 10 : case SQL_DECLARE:
1627 10 : return sql_error(sql, 02, SQLSTATE(42000) "Variables cannot be declared on the global scope");
1628 41558 : case SQL_CALL:
1629 41558 : sql->type = Q_UPDATE;
1630 41558 : if (s->type == type_list) {
1631 4 : list *params = rel_paramlist( query, s->data.lval->h->next->data.sym);
1632 4 : if (!params)
1633 : return NULL;
1634 3 : ret = rel_semantic(query, s->data.lval->h->data.sym);
1635 3 : query->last_rel = ret;
1636 3 : if (ret)
1637 3 : ret = rel_psm_stmt(sql->sa, rel_psm_call(query, s->data.lval->h->next->data.sym));
1638 3 : ret = rel_list(sql->sa, query->last_rel, ret);
1639 : } else
1640 41554 : ret = rel_psm_stmt(sql->sa, rel_psm_call(query, s->data.sym));
1641 : break;
1642 2 : case SQL_CREATE_TABLE_LOADER:
1643 : {
1644 2 : dlist *l = s->data.lval;
1645 2 : dlist *qname = l->h->data.lval;
1646 2 : symbol *sym = l->h->next->data.sym;
1647 :
1648 2 : ret = create_table_from_loader(query, qname, sym);
1649 2 : if (ret == NULL)
1650 : return NULL;
1651 1 : ret = rel_psm_stmt(sql->sa, exp_rel(sql, ret));
1652 1 : sql->type = Q_SCHEMA;
1653 1 : } break;
1654 5645 : case SQL_CREATE_TRIGGER:
1655 : {
1656 5645 : dlist *l = s->data.lval;
1657 :
1658 5645 : assert(l->h->next->type == type_int);
1659 5645 : 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);
1660 5645 : sql->type = Q_SCHEMA;
1661 5645 : } break;
1662 96 : case SQL_DROP_TRIGGER:
1663 : {
1664 96 : dlist *l = s->data.lval;
1665 96 : dlist *qname = l->h->data.lval;
1666 96 : int if_exists = l->h->next->data.i_val;
1667 :
1668 96 : ret = drop_trigger(sql, qname, if_exists);
1669 96 : sql->type = Q_SCHEMA;
1670 96 : } break;
1671 40 : case SQL_ANALYZE: {
1672 40 : dlist *l = s->data.lval;
1673 :
1674 : /* Jan2022 update: The 'sample' and 'minmax' parameters are now ignored because they are no longer used in the backend */
1675 40 : list *calls = psm_analyze(query, l->h->data.lval /* qualified table name */, l->h->next->data.lval /* opt list of column */);
1676 40 : ret = rel_psm_block(sql->sa, calls);
1677 40 : sql->type = Q_UPDATE;
1678 40 : } break;
1679 0 : default:
1680 0 : return sql_error(sql, 01, SQLSTATE(42000) "Schema statement unknown symbol(%p)->token = %s", s, token2string(s->token));
1681 : }
1682 : return ret;
1683 : }
|