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