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_select.h"
15 : #include "sql_tokens.h"
16 : #include "sql_privileges.h"
17 : #include "sql_env.h"
18 : #include "sql_decimal.h"
19 : #include "sql_qc.h"
20 : #include "rel_rel.h"
21 : #include "rel_basetable.h"
22 : #include "rel_exp.h"
23 : #include "rel_xml.h"
24 : #include "rel_dump.h"
25 : #include "rel_prop.h"
26 : #include "rel_psm.h"
27 : #include "rel_schema.h"
28 : #include "rel_unnest.h"
29 : #include "rel_sequence.h"
30 : #include "rel_file_loader.h"
31 : #include "rel_optimizer_private.h"
32 :
33 : #define VALUE_FUNC(f) (f->func->type == F_FUNC || f->func->type == F_FILT)
34 : #define check_card(card,f) ((card == card_none && !f->res) || (CARD_VALUE(card) && f->res && VALUE_FUNC(f)) || card == card_loader || (card == card_relation && f->func->type == F_UNION))
35 :
36 : /* return all expressions, with table name == tname */
37 : static list *
38 57355 : rel_table_projections( mvc *sql, sql_rel *rel, char *tname, int level )
39 : {
40 57872 : list *exps;
41 :
42 57872 : if (mvc_highwater(sql))
43 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
44 :
45 57872 : if (!rel)
46 : return NULL;
47 :
48 57872 : if (!tname)
49 42277 : return _rel_projections(sql, rel, NULL, 1, 0, 1);
50 :
51 15595 : switch(rel->op) {
52 525 : case op_join:
53 : case op_left:
54 : case op_right:
55 : case op_full:
56 525 : exps = rel_table_projections( sql, rel->l, tname, level+1);
57 525 : if (exps)
58 : return exps;
59 15 : return rel_table_projections( sql, rel->r, tname, level+1);
60 502 : case op_semi:
61 : case op_anti:
62 : case op_select:
63 502 : return rel_table_projections( sql, rel->l, tname, level+1);
64 :
65 58 : case op_topn:
66 : case op_sample:
67 : case op_groupby:
68 : case op_union:
69 : case op_except:
70 : case op_inter:
71 : case op_project:
72 58 : if (!is_processed(rel) && level == 0)
73 0 : return rel_table_projections( sql, rel->l, tname, level+1);
74 : /* fall through */
75 : case op_munion:
76 64 : if (!is_processed(rel) && level == 0) {
77 0 : node *n = ((list*)rel->l)->h;
78 0 : if (n)
79 0 : return rel_table_projections(sql, n->data, tname, level+1);
80 : }
81 : /* fall through */
82 : case op_table:
83 : case op_basetable:
84 14568 : if (is_basetable(rel->op) && !rel->exps)
85 14002 : return rel_base_project_all(sql, rel, tname);
86 566 : if (rel->exps) {
87 566 : int rename = 0;
88 566 : node *en;
89 :
90 : /* first check alias */
91 566 : if (!is_base(rel->op) && !level) {
92 54 : list *exps = sa_list(sql->sa);
93 :
94 409 : for (en = rel->exps->h; en && !rename; en = en->next) {
95 355 : sql_exp *e = en->data;;
96 :
97 355 : if ((is_basecol(e) && exp_relname(e) && strcmp(exp_relname(e), tname) == 0) ||
98 138 : (is_basecol(e) && !exp_relname(e) && e->l && strcmp(e->l, tname) == 0)) {
99 217 : if (exp_name(e) && exps_bind_column2(exps, tname, exp_name(e), NULL))
100 : rename = 1;
101 : else
102 217 : append(exps, e);
103 : }
104 : }
105 : }
106 :
107 566 : exps = new_exp_list(sql->sa);
108 4958 : for (en = rel->exps->h; en; en = en->next) {
109 4392 : sql_exp *e = en->data;
110 4392 : if (is_basecol(e) && exp_relname(e) && strcmp(exp_relname(e), tname) == 0) {
111 4250 : if (rename)
112 0 : append(exps, exp_alias_ref(sql, e));
113 : else {
114 4250 : sql_exp *ne = exp_ref(sql, e);
115 4250 : exp_setname(sql, ne, tname, exp_name(e));
116 4250 : append(exps, ne);
117 : }
118 : }
119 4392 : if (is_basecol(e) && !exp_relname(e) && e->l && strcmp(e->l, tname) == 0) {
120 0 : if (rename)
121 0 : append(exps, exp_alias_ref(sql, e));
122 : else {
123 0 : sql_exp *ne = exp_ref(sql, e);
124 0 : exp_setname(sql, ne, tname, exp_name(e));
125 0 : append(exps, ne);
126 : }
127 : }
128 :
129 : }
130 566 : if (exps && list_length(exps))
131 : return exps;
132 : }
133 : /* fall through */
134 : default:
135 : return NULL;
136 : }
137 : }
138 :
139 : static sql_exp *
140 0 : rel_lastexp(mvc *sql, sql_rel *rel )
141 : {
142 0 : sql_exp *e;
143 :
144 0 : if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
145 0 : rel = rel_parent(rel);
146 0 : assert(list_length(rel->exps));
147 0 : if (rel->op == op_project) {
148 0 : list_hash_clear(rel->exps);
149 0 : return exp_ref(sql, rel->exps->t->data);
150 : }
151 0 : assert(is_project(rel->op));
152 0 : e = rel->exps->t->data;
153 0 : return exp_ref(sql, e);
154 : }
155 :
156 : static sql_rel *
157 37057 : rel_orderby(mvc *sql, sql_rel *l)
158 : {
159 37057 : sql_rel *rel = rel_create(sql->sa);
160 37057 : if (!rel)
161 : return NULL;
162 :
163 37057 : assert(l->op == op_project && !l->r);
164 37057 : rel->l = l;
165 37057 : rel->r = NULL;
166 37057 : rel->op = op_project;
167 37057 : rel->exps = rel_projections(sql, l, NULL, 1, 0);
168 37057 : rel->card = l->card;
169 37057 : rel->nrcols = l->nrcols;
170 37057 : return rel;
171 : }
172 :
173 : /* forward refs */
174 : static sql_rel * rel_setquery(sql_query *query, symbol *sq);
175 : static sql_rel * rel_joinquery(sql_query *query, symbol *sq, list *refs);
176 :
177 : static sql_rel *
178 209369 : rel_table_optname(mvc *sql, sql_rel *sq, symbol *optname, list *refs)
179 : {
180 209369 : sql_rel *osq = sq;
181 209369 : node *ne;
182 :
183 209369 : if (optname && optname->token == SQL_NAME) {
184 17068 : dlist *columnrefs = NULL;
185 17068 : char *tname = optname->data.lval->h->data.sval;
186 17068 : list *l = sa_list(sql->sa);
187 :
188 17068 : columnrefs = optname->data.lval->h->next->data.lval;
189 17068 : if (is_topn(sq->op) || is_sample(sq->op) || ((is_simple_project(sq->op) || is_groupby(sq->op)) && sq->r) || is_base(sq->op)) {
190 138 : sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 0));
191 138 : osq = sq;
192 : }
193 17068 : if (columnrefs && dlist_length(columnrefs) != list_length(sq->exps))
194 6 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: The number of aliases don't match the number of columns (%d != %d)", dlist_length(columnrefs), sq->nrcols);
195 3859 : if (columnrefs && sq->exps) {
196 3859 : dnode *d = columnrefs->h;
197 :
198 3859 : ne = sq->exps->h;
199 3859 : list_hash_clear(sq->exps);
200 16128 : for (; d && ne; d = d->next, ne = ne->next) {
201 8411 : sql_exp *e = ne->data;
202 :
203 8411 : if (exps_bind_column2(l, tname, d->data.sval, NULL))
204 1 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: Duplicate column name '%s.%s'", tname, d->data.sval);
205 8410 : exp_setname(sql, e, tname, d->data.sval );
206 8410 : if (!is_intern(e))
207 8410 : set_basecol(e);
208 8410 : append(l, e);
209 : }
210 : }
211 17061 : if (!columnrefs && sq->exps) {
212 13203 : ne = sq->exps->h;
213 13203 : list_hash_clear(sq->exps);
214 125942 : for (; ne; ne = ne->next) {
215 99536 : sql_exp *e = ne->data;
216 99536 : char *name = NULL;
217 :
218 99536 : if (!is_intern(e)) {
219 99536 : if (!exp_name(e))
220 109 : name = make_label(sql->sa, ++sql->label);
221 99536 : noninternexp_setname(sql, e, tname, name);
222 99536 : set_basecol(e);
223 : }
224 : }
225 : }
226 17061 : if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
227 17011 : if (list_find(refs, tname, (fcmp) &strcmp))
228 6 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", tname);
229 17005 : assert(tname);
230 17005 : list_append(refs, tname);
231 : }
232 : } else {
233 192301 : if (!is_project(sq->op) || is_topn(sq->op) || is_sample(sq->op) || ((is_simple_project(sq->op) || is_groupby(sq->op)) && sq->r)) {
234 59251 : sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 1));
235 59251 : osq = sq;
236 : }
237 2404163 : for (ne = osq->exps->h; ne; ne = ne->next) {
238 2211862 : sql_exp *e = ne->data;
239 :
240 2211862 : if (!is_intern(e))
241 2081185 : set_basecol(e);
242 : }
243 : }
244 : return osq;
245 : }
246 :
247 : static sql_rel *
248 101903 : rel_subquery_optname(sql_query *query, symbol *ast, list *refs)
249 : {
250 101903 : mvc *sql = query->sql;
251 101903 : SelectNode *sn = (SelectNode *) ast;
252 101903 : exp_kind ek = {type_value, card_relation, TRUE};
253 101903 : sql_rel *sq = rel_subquery(query, ast, ek);
254 :
255 101903 : assert(ast->token == SQL_SELECT);
256 101903 : if (!sq)
257 : return NULL;
258 :
259 101882 : return rel_table_optname(sql, sq, sn->name, refs);
260 : }
261 :
262 : static void
263 10064 : rel_rename(mvc *sql, sql_rel *nrel, char *rname, sql_rel *brel)
264 : {
265 10064 : assert(is_project(nrel->op));
266 10064 : if (brel) {
267 154 : if (is_project(nrel->op) && nrel->exps) {
268 364 : for (node *ne = nrel->exps->h, *be = brel->exps->h; ne && be; ne = ne->next, be = be->next) {
269 210 : sql_exp *e = ne->data;
270 210 : sql_exp *b = be->data;
271 210 : char *name = NULL;
272 :
273 210 : if (!is_intern(e)) {
274 210 : if (!exp_name(e))
275 0 : name = make_label(sql->sa, ++sql->label);
276 210 : noninternexp_setname(sql, e, rname, name);
277 210 : set_basecol(e);
278 210 : e->alias.label = b->alias.label;
279 : }
280 : }
281 : }
282 154 : list_hash_clear(nrel->exps);
283 9910 : } else if (is_project(nrel->op) && nrel->exps) {
284 9910 : node *ne = nrel->exps->h;
285 :
286 40945 : for (; ne; ne = ne->next) {
287 31035 : sql_exp *e = ne->data;
288 31035 : char *name = NULL;
289 :
290 31035 : if (!is_intern(e)) {
291 31035 : if (!exp_name(e))
292 17 : name = make_label(sql->sa, ++sql->label);
293 31035 : noninternexp_setname(sql, e, rname, name);
294 31035 : set_basecol(e);
295 : }
296 : }
297 9910 : list_hash_clear(nrel->exps);
298 : }
299 10064 : }
300 :
301 : sql_rel *
302 5870 : rel_with_query(sql_query *query, symbol *q )
303 : {
304 5870 : mvc *sql = query->sql;
305 5870 : dnode *d = q->data.lval->h;
306 5870 : symbol *next = d->next->data.sym;
307 5870 : bool recursive = d->next->next->data.i_val;
308 5870 : sql_rel *rel;
309 :
310 5870 : if (!stack_push_frame(sql, NULL))
311 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
312 : /* first handle all with's (ie inlined views) */
313 15857 : for (d = d->data.lval->h; d; d = d->next) {
314 10007 : symbol *sym = d->data.sym;
315 10007 : dnode *dn = sym->data.lval->h->next;
316 10007 : char *rname = qname_schema_object(dn->data.lval);
317 10007 : sql_rel *nrel, *base_rel = NULL;
318 10007 : symbol *recursive_part = NULL;
319 10007 : sql_rel_view *recursive_union = NULL;
320 10007 : int recursive_distinct = 0;
321 :
322 10007 : if (frame_find_rel_view(sql, rname)) {
323 3 : stack_pop_frame(sql);
324 3 : return sql_error(sql, 01, SQLSTATE(42000) "View '%s' already declared", rname);
325 : }
326 10004 : if (recursive) {
327 102 : symbol *union_stmt = dn->next->next->data.sym;
328 102 : if (union_stmt->token == SQL_UNION) { /* split in base and recursive part */
329 77 : dnode *n = union_stmt->data.lval->h;
330 77 : symbol *base = n->data.sym;
331 77 : recursive_distinct = n->next->data.i_val;
332 77 : dlist *corresponding = n->next->next->data.lval;
333 77 : recursive_part = n->next->next->next->data.sym;
334 77 : if (corresponding)
335 0 : return sql_error(sql, 01, SQLSTATE(42000) "Recursive with corresponding is not supported");
336 77 : dn->next->next->data.sym = base;
337 : }
338 : }
339 10004 : nrel = rel_semantic(query, sym);
340 10004 : if (!nrel) {
341 17 : stack_pop_frame(sql);
342 17 : return NULL;
343 : }
344 9987 : if (!(recursive_union = stack_push_rel_view(sql, rname, nrel))) {
345 0 : stack_pop_frame(sql);
346 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
347 : }
348 9987 : if (recursive && recursive_part) {
349 77 : base_rel = nrel;
350 77 : rel_rename(sql, base_rel, rname, base_rel);
351 77 : dn->next->next->data.sym = recursive_part;
352 77 : set_processed(nrel);
353 77 : nrel = rel_semantic(query, sym);
354 77 : if (!nrel) {
355 0 : stack_pop_frame(sql);
356 0 : return NULL;
357 : }
358 77 : list *ls = rel_projections(sql, base_rel, NULL, 0, 1);
359 77 : list *rs = rel_projections(sql, nrel, NULL, 0, 1);
360 :
361 77 : if (!rel_is_ref(base_rel)) { /* not recursive */
362 3 : nrel = rel_setop_n_ary_check_types(sql, base_rel, nrel, ls, rs, op_munion);
363 : } else {
364 74 : base_rel->used |= statistics_gathered;
365 74 : prop *p = base_rel->p = prop_create(sql->sa, PROP_COUNT, base_rel->p);
366 74 : p->value.lval = 1000000; /* random ? */
367 :
368 : /* down cast the recursive side (on errors users should add casts on the base side) */
369 74 : list *nrs = new_exp_list(sql->sa);
370 74 : if(!nrs)
371 : return NULL;
372 :
373 172 : for (node *n = ls->h, *m = rs->h; n && m; n = n->next, m = m->next) {
374 98 : sql_subtype *t = exp_subtype(n->data);
375 98 : append(nrs, exp_check_type(sql, t, nrel, m->data, type_equal));
376 : }
377 74 : nrel = rel_project(sql->sa, nrel, nrs);
378 74 : nrel = rel_setop_n_ary(sql->sa, append(append(sa_list(sql->sa), base_rel), nrel), op_munion);
379 74 : set_recursive(nrel);
380 : }
381 77 : if (recursive_distinct)
382 33 : set_distinct(nrel);
383 77 : rel_setop_n_ary_set_exps(sql, nrel, rel_projections(sql, nrel, NULL, 0, 1), false);
384 77 : set_processed(nrel);
385 77 : recursive_union->rel_view = rel_dup(nrel); /* extra incref for independent flow */
386 : }
387 9987 : if (!is_project(nrel->op)) {
388 0 : if (is_topn(nrel->op) || is_sample(nrel->op)) {
389 0 : nrel = rel_project(sql->sa, nrel, rel_projections(sql, nrel, NULL, 1, 1));
390 : } else {
391 0 : stack_pop_frame(sql);
392 0 : return NULL;
393 : }
394 : }
395 9987 : rel_rename(sql, nrel, rname, base_rel);
396 : }
397 5850 : rel = rel_semantic(query, next);
398 5850 : stack_pop_frame(sql);
399 5850 : return rel;
400 : }
401 :
402 : static sql_rel *
403 60353 : query_exp_optname(sql_query *query, symbol *q, list *refs)
404 : {
405 60353 : mvc *sql = query->sql;
406 60353 : switch (q->token) {
407 982 : case SQL_WITH:
408 : {
409 982 : sql_rel *tq = rel_with_query(query, q);
410 :
411 982 : if (!tq)
412 : return NULL;
413 982 : if (q->data.lval->t->type == type_symbol)
414 982 : return rel_table_optname(sql, tq, q->data.lval->t->data.sym, refs);
415 : return tq;
416 : }
417 59371 : case SQL_JOIN:
418 : {
419 59371 : sql_rel *tq = rel_joinquery(query, q, refs);
420 :
421 59371 : if (!tq)
422 : return NULL;
423 59330 : return rel_table_optname(sql, tq, q->data.lval->t->data.sym, NULL);
424 : }
425 0 : default:
426 0 : (void) sql_error(sql, 02, SQLSTATE(42000) "case %d %s", (int) q->token, token2string(q->token));
427 : }
428 0 : return NULL;
429 : }
430 :
431 : static sql_subfunc *
432 110448 : bind_func_(mvc *sql, char *sname, char *fname, list *ops, sql_ftype type, bool private, bool *found, bool exact)
433 : {
434 110448 : sql_subfunc *sf = NULL;
435 :
436 110674 : if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 &&
437 226 : list_cmp(sql->forward->ops, ops, (fcmp)&arg_subtype_cmp) == 0 &&
438 0 : execute_priv(sql, sql->forward) && type == sql->forward->type)
439 0 : return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
440 110448 : sf = sql_bind_func_(sql, sname, fname, ops, type, private, exact);
441 110448 : if (found)
442 109915 : *found |= sf != NULL;
443 110448 : if (sf && execute_priv(sql, sf->func))
444 : return sf;
445 : return NULL;
446 : }
447 :
448 : static sql_subfunc *
449 630163 : bind_func(mvc *sql, char *sname, char *fname, sql_subtype *t1, sql_subtype *t2, int nr, sql_ftype type, bool private, bool *found, bool exact)
450 : {
451 630163 : list *tl = sa_list(sql->sa);
452 630163 : assert(nr >= 1 && nr <= 2);
453 630163 : append(tl, t1);
454 630163 : if (nr == 2)
455 534772 : append(tl, t2);
456 630163 : sql_subfunc *sf = NULL;
457 :
458 630163 : if (sql->forward) {
459 136765 : if (execute_priv(sql, sql->forward) &&
460 136765 : strcmp(fname, sql->forward->base.name) == 0 &&
461 231 : ((!t1 && list_length(sql->forward->ops) == 0) ||
462 233 : (!t2 && list_length(sql->forward->ops) == 1 && arg_subtype_cmp(sql->forward->ops->h->data, t1) == 0) ||
463 229 : (list_length(sql->forward->ops) == 2 &&
464 0 : arg_subtype_cmp(sql->forward->ops->h->data, t1) == 0 &&
465 2 : arg_subtype_cmp(sql->forward->ops->h->next->data, t2) == 0)) && type == sql->forward->type) {
466 2 : return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
467 : }
468 : }
469 630161 : sf = sql_bind_func_(sql, sname, fname, tl, type, private, exact);
470 630161 : if (found)
471 630161 : *found |= sf != NULL;
472 630161 : if (sf && execute_priv(sql, sf->func))
473 : return sf;
474 : return NULL;
475 : }
476 :
477 : static sql_subfunc *
478 648496 : find_func(mvc *sql, char *sname, char *fname, int len, sql_ftype type, bool private, sql_subfunc *prev, bool *found)
479 : {
480 648496 : sql_subfunc *sf = NULL;
481 :
482 648496 : if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 && list_length(sql->forward->ops) == len && execute_priv(sql, sql->forward) && type == sql->forward->type)
483 0 : return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
484 648496 : sf = sql_find_func(sql, sname, fname, len, type, private, prev);
485 648496 : if (found)
486 0 : *found |= sf != NULL;
487 648496 : if (sf && execute_priv(sql, sf->func))
488 : return sf;
489 : return NULL;
490 : }
491 :
492 : static sql_exp *
493 711191 : exp_fix_scale(mvc *sql, sql_subtype *ct, sql_exp *e)
494 : {
495 711191 : sql_subtype *et = exp_subtype(e);
496 :
497 711191 : if (ct->type->scale == SCALE_FIX && et->type->scale == SCALE_FIX) {
498 85157 : int scale_diff = ((int) ct->scale - (int) et->scale);
499 :
500 85157 : if (scale_diff) {
501 132 : if (scale_diff < 0)
502 : return e;
503 102 : sql_subtype st;
504 102 : int scale = ct->scale;
505 102 : int digits = ((et->type->eclass == EC_NUM)?bits2digits(et->digits):et->digits)-et->scale+scale;
506 102 : (void)sql_find_subtype(&st, ct->type->base.name, digits, scale);
507 102 : return exp_convert(sql, e, et, &st);
508 : }
509 : }
510 : return e;
511 : }
512 :
513 : static lng
514 9730 : rel_get_count(sql_rel *rel)
515 : {
516 31316 : if (!rel)
517 : return 0;
518 31312 : prop *p = NULL;
519 31312 : if (rel->p && (p = find_prop(rel->p, PROP_COUNT)) != NULL)
520 3070 : return p->value.lval;
521 28242 : else if(is_munion(rel->op)) {
522 174 : lng cnt = 0;
523 174 : list *l = rel->l;
524 522 : for (node *n = l->h; n; n = n->next) {
525 348 : lng lcnt = rel_get_count(n->data);
526 348 : if (lcnt == BUN_MAX)
527 : return BUN_MAX;
528 348 : cnt += lcnt;
529 : }
530 174 : return cnt;
531 28068 : } else if(rel->l) {
532 25384 : if (is_select(rel->op) || is_project(rel->op))
533 : return rel_get_count(rel->l);
534 : }
535 : return 0;
536 : }
537 :
538 : #define is_sum_aggr(f) (f->type == F_AGGR && strcmp(f->base.name, "sum") == 0)
539 :
540 : list *
541 750968 : check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, sql_subfunc *sf, int maybe_zero_or_one, bool internal)
542 : {
543 750968 : list *nexps = new_exp_list(sql->sa);
544 750968 : sql_subtype *atp = NULL, super, *res = !list_empty(sf->res) ? sf->res->h->data: NULL;
545 750968 : unsigned int digits = 0, scale = 0;
546 :
547 : /* find largest any type argument */
548 2221604 : for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) {
549 1470636 : sql_arg *a = m->data;
550 1470636 : sql_exp *e = n->data;
551 1470636 : sql_subtype *t = exp_subtype(e);
552 :
553 1470636 : if (a->type.type->eclass == EC_ANY) {
554 267765 : if (t && atp) {
555 117390 : supertype(&super, t, atp);
556 117390 : atp = &super;
557 150375 : } else if (t) {
558 : atp = t;
559 : }
560 : }
561 1470633 : if (t && sf->func->fix_scale == SCALE_FIX && t->type->eclass == EC_DEC) {
562 1264 : if (digits < t->digits)
563 : digits = t->digits;
564 1264 : if (scale < t->scale)
565 : scale = t->scale;
566 : }
567 : }
568 750968 : if (!atp && !list_empty(exps))
569 600594 : atp = exp_subtype(exps->h->data);
570 :
571 750969 : if ((atp && atp->type->localtype == TYPE_void) || !atp) /* NULL */
572 10066 : atp = sql_bind_localtype("str");
573 :
574 750969 : node *n, *m;
575 2221605 : for (n = exps->h, m = sf->func->ops->h; n && m; n = n->next, m = m->next) {
576 1470636 : sql_arg *a = m->data;
577 1470636 : sql_exp *e = n->data;
578 1470636 : sql_subtype *ntp = &a->type, *t = exp_subtype(e);
579 :
580 1470635 : if (!t) {
581 38 : if (a->type.type->eclass == EC_ANY && atp)
582 3 : ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
583 61 : rel_set_type_param(sql, ntp, rel, e, sf->func->fix_scale != INOUT && !UDF_LANG(sf->func->lang));
584 1470597 : } else if (a->type.type->eclass == EC_ANY && atp) {
585 267762 : ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
586 1202835 : } else if (t && ntp->digits == 0 && EC_VARCHAR(a->type.type->eclass)) {
587 526422 : ntp = sql_create_subtype(sql->sa, a->type.type, type_digits_to_char_digits(t), 0);
588 676413 : } else if (t && ntp->digits > 0 && a->type.type->eclass == EC_NUM && t->type->eclass == EC_NUM) {
589 365202 : ntp = sql_create_subtype(sql->sa, a->type.type, t->digits, 0);
590 311211 : } else if (t && ntp->scale == 0 && ntp->type->eclass == EC_DEC && EC_VARCHAR(t->type->eclass)) {
591 0 : sql_subtype *res = SA_NEW(sql->sa, sql_subtype);
592 0 : int digits = t->digits?t->digits+3:ntp->digits;
593 0 : (void)sql_find_subtype(res, a->type.type->base.name, digits, 3);
594 0 : ntp = res;
595 311211 : } else if (t && ntp->scale == 0 && ntp->type->eclass == EC_DEC) {
596 4879 : ntp = sql_create_subtype(sql->sa, a->type.type, t->type->eclass == EC_NUM?bits2digits(t->digits):t->digits, t->scale);
597 306332 : } else if (t->type == ntp->type) {
598 304228 : ntp = t;
599 : }
600 1470635 : if (!(e = exp_check_type(sql, ntp, rel, e, type_equal)))
601 : return NULL;
602 1470637 : if (sf->func->fix_scale == SCALE_FIX) {
603 534083 : ntp = sql_create_subtype(sql->sa, a->type.type->localtype?a->type.type:t?t->type:atp->type, digits, scale);
604 534083 : e = exp_fix_scale(sql, ntp, e);
605 936554 : } else if (sf->func->fix_scale == SCALE_EQ) {
606 177109 : e = exp_fix_scale(sql, &a->type, e);
607 : }
608 1470636 : if (maybe_zero_or_one && e->card > CARD_ATOM) {
609 22 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", exp_subtype(e), NULL, F_AGGR, true, false);
610 22 : e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e));
611 : }
612 1470636 : append(nexps, e);
613 : }
614 : /* handle any extra arguments for rel_dump/analytic funcs */
615 751188 : for ( ; n; n = n->next)
616 219 : append(nexps, n->data);
617 750969 : if (sf->func->fix_scale == SCALE_FIX || IS_ANALYTIC(sf->func)) {
618 269544 : exps_scale_fix(sf, nexps, atp);
619 481425 : } else if (sf->func->fix_scale == MAX_BITS) {
620 113666 : exps_max_bits(sf, nexps);
621 367759 : } else if (sf->func->fix_scale == SCALE_MUL) {
622 25266 : exps_sum_scales(sf, nexps);
623 342493 : } else if (!internal && sf->func->fix_scale == SCALE_DIV) {
624 2613 : if (!exps_scale_algebra(sql, sf, rel, nexps))
625 : return NULL;
626 339880 : } else if (sf->func->fix_scale == DIGITS_ADD) {
627 186616 : exps_digits_add(sf, nexps);
628 153264 : } else if (sf->func->fix_scale == INOUT) {
629 19444 : exps_inout(sf, nexps);
630 133820 : } else if (is_sum_aggr(sf->func))
631 9382 : exps_largest_int(sf, nexps, rel_get_count(rel));
632 :
633 : /* dirty hack */
634 750967 : if (sf->func->type != F_PROC && sf->func->type != F_UNION && sf->func->type != F_LOADER && res) {
635 746114 : if (res->type->eclass == EC_ANY && atp)
636 73 : sf->res->h->data = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
637 : }
638 : return nexps;
639 : }
640 :
641 : static char *
642 32 : nary_function_arg_types_2str(mvc *sql, list* types, int N)
643 : {
644 32 : char *arg_list = NULL;
645 32 : int i = 0;
646 :
647 116 : for (node *n = types->h; n && i < N; n = n->next) {
648 84 : sql_subtype *t = (sql_subtype *) n->data;
649 84 : char *tpe = t ? sql_subtype_string(sql->ta, t) : "?";
650 :
651 84 : if (arg_list) {
652 52 : arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe);
653 : } else {
654 : arg_list = tpe;
655 : }
656 84 : i++;
657 : }
658 32 : return arg_list;
659 : }
660 :
661 : static char *
662 35 : file_loader_add_table_column_types(mvc *sql, sql_subfunc *f, list *exps, list *res_exps, char *tname)
663 : {
664 35 : sql_exp *file = exps->h->data;
665 35 : if (!exp_is_atom(file))
666 : return "Filename missing";
667 :
668 35 : atom *a = file->l;
669 35 : if (a->data.vtype != TYPE_str || !a->data.val.sval)
670 : return "Filename missing";
671 :
672 35 : char *filename = a->data.val.sval;
673 35 : if (strcmp(filename, "") == 0)
674 : return "Filename missing";
675 :
676 33 : char *ext = strrchr(filename, '.'), *ep = ext;
677 :
678 33 : if (ext) {
679 30 : ext = ext + 1;
680 30 : ext = mkLower(sa_strdup(sql->sa, ext));
681 : }
682 30 : if (!ext)
683 3 : return "Filename extension missing";
684 :
685 30 : file_loader_t *fl = fl_find(ext);
686 30 : if (!fl) {
687 : /* maybe compressed */
688 10 : char *p = ep - 1;
689 66 : while (p > filename && *p != '.')
690 56 : p--;
691 10 : if (p != filename) {
692 8 : ext = p + 1;
693 8 : ext = sa_strdup(sql->sa, ext);
694 8 : char *d = strchr(ext, '.');
695 8 : assert(d);
696 8 : *d = 0;
697 8 : fl = fl_find(ext);
698 : }
699 10 : if (!fl) /* fallback */
700 2 : fl = fl_find("csv");
701 2 : if (!fl) /* not expected */
702 0 : return sa_message(sql->ta, "Filename extension '%s' missing", ext?ext:"");
703 : }
704 30 : str err = fl->add_types(sql, f, filename, res_exps, tname);
705 30 : if (err)
706 : return err;
707 16 : sql_subtype *st = sql_bind_localtype("str");
708 16 : sql_exp *ext_exp = exp_atom(sql->sa, atom_string(sql->sa, st, ext));
709 16 : if (!ext_exp)
710 : return MAL_MALLOC_FAIL;
711 16 : append(exps, ext_exp);
712 16 : return NULL;
713 : }
714 :
715 : static sql_rel *
716 35 : rel_file_loader(mvc *sql, list *exps, list *tl, char *tname)
717 : {
718 35 : sql_subfunc *f = NULL;
719 35 : bool found = false;
720 :
721 35 : if ((f = bind_func_(sql, NULL, "file_loader", tl, F_UNION, true, &found, false))) {
722 35 : list *nexps = exps;
723 35 : if (list_empty(tl) || f->func->vararg || (nexps = check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1, false))) {
724 35 : list *res_exps = sa_list(sql->sa);
725 35 : if (list_length(exps) == 1 && f && f->func->varres && strlen(f->func->mod) == 0 && strlen(f->func->imp) == 0) {
726 35 : char *err = file_loader_add_table_column_types(sql, f, nexps, res_exps, tname);
727 35 : if (err)
728 19 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: file_loader function failed '%s'", err);
729 : }
730 16 : sql_exp *e = exp_op(sql->sa, nexps, f);
731 16 : sql_rel *rel = rel_table_func(sql->sa, NULL, e, res_exps, TABLE_PROD_FUNC);
732 16 : if (rel)
733 16 : rel = rel_project(sql->sa, rel, exps_alias(sql, res_exps));
734 16 : return rel;
735 : }
736 : }
737 : return NULL;
738 : }
739 :
740 : sql_exp *
741 10806 : find_table_function(mvc *sql, char *sname, char *fname, list *exps, list *tl, sql_ftype type)
742 : {
743 10806 : bool found = false;
744 10806 : sql_subfunc *f = NULL;
745 :
746 10806 : assert(type == F_UNION || type == F_LOADER);
747 10806 : if ((f = bind_func_(sql, sname, fname, tl, type, false, &found, false))) {
748 10786 : list *nexps = exps;
749 10786 : if (list_empty(tl) || f->func->vararg || (nexps = check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1, false)))
750 10786 : return exp_op(sql->sa, nexps, f);
751 0 : found = false;
752 : }
753 20 : char *arg_list = list_length(tl) ? nary_function_arg_types_2str(sql, tl, list_length(tl)) : NULL;
754 55 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s %s function %s%s%s'%s'(%s)",
755 20 : found ? "insufficient privileges for" : "no such", type == F_UNION ? "table returning" : "loader", sname ? "'":"", sname ? sname : "",
756 : sname ? "'.":"", fname, arg_list ? arg_list : "");
757 : }
758 :
759 : static sql_rel *
760 10822 : rel_named_table_function(sql_query *query, sql_rel *rel, symbol *ast, int lateral, list *refs)
761 : {
762 10822 : mvc *sql = query->sql;
763 10822 : list *exps = NULL, *tl;
764 10822 : node *m;
765 10822 : exp_kind ek = {type_value, card_relation, TRUE};
766 10822 : sql_rel *sq = NULL, *outer = NULL;
767 10822 : sql_exp *e = NULL;
768 10822 : sql_subfunc *sf = NULL;
769 10822 : symbol *sym = ast->data.lval->h->data.sym, *subquery = NULL;
770 10822 : dnode *l = sym->data.lval->h, *n;
771 10822 : char *tname = NULL;
772 10822 : char *fname = qname_schema_object(l->data.lval);
773 10822 : char *sname = qname_schema(l->data.lval);
774 :
775 10822 : tl = sa_list(sql->sa);
776 10822 : exps = sa_list(sql->sa);
777 10822 : if (l->next)
778 10822 : l = l->next; /* skip distinct */
779 10822 : if (l->next) { /* table call with subquery */
780 1059 : int is_value = 1;
781 1059 : if (l->next->type == type_symbol || l->next->type == type_list) {
782 1059 : exp_kind iek = {type_value, card_set, TRUE};
783 1059 : int count = 0;
784 :
785 1059 : if (l->next->type == type_symbol)
786 : n = l->next;
787 : else
788 676 : n = l->next->data.lval->h;
789 :
790 3745 : for (dnode *m = n; m; m = m->next) {
791 2686 : if (m->type == type_symbol && m->data.sym->token == SQL_SELECT)
792 2686 : subquery = m->data.sym;
793 2686 : count++;
794 : }
795 1059 : if (subquery && count > 1)
796 17 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: The input for the table returning function %s%s%s'%s' must be either a single sub query, or a list of values",
797 : sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
798 :
799 1054 : if (subquery) {
800 40 : if (!(sq = rel_subquery(query, subquery, ek)))
801 : return NULL;
802 : is_value = 0;
803 : } else {
804 3639 : for ( ; n; n = n->next) {
805 2631 : sql_exp *e = rel_value_exp(query, &outer, n->data.sym, sql_sel | sql_from, iek);
806 :
807 2631 : if (!e)
808 : return NULL;
809 2625 : append(exps, e);
810 2625 : is_value &= exp_is_atom(e);
811 : }
812 1008 : if (!is_value || (lateral && outer))
813 14 : sq = rel_project(sql->sa, NULL, exps);
814 14 : if (lateral && outer) {
815 0 : sq = rel_crossproduct(sql->sa, sq, outer, op_join);
816 0 : set_dependent(sq);
817 0 : set_processed(sq);
818 : }
819 : }
820 : }
821 1047 : if (!is_value && (!sq || (!lateral && outer)))
822 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such table returning function %s%s%s'%s'", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
823 1047 : if (!is_value) {
824 53 : if (list_length(exps))
825 14 : exps = sa_list(sql->sa);
826 171 : for (node *en = sq->exps->h; en; en = en->next) {
827 118 : sql_exp *e = en->data;
828 :
829 118 : if (!e->alias.label)
830 28 : exp_label(sql->sa, e, ++sql->label);
831 118 : sql_exp *ne = exp_ref(sql, e);
832 : /* allow for table functions with table input */
833 118 : ne->card = CARD_ATOM;
834 118 : exp_setname(sql, ne, tname, exp_name(e));
835 118 : append(exps, ne);
836 118 : append(tl, exp_subtype(e));
837 : }
838 : } else {
839 3594 : for (node *en = exps->h; en; en = en->next)
840 2600 : append(tl, exp_subtype(en->data));
841 : }
842 : }
843 :
844 10810 : rel = NULL;
845 10810 : if (ast->data.lval->t->type == type_symbol && ast->data.lval->t->data.sym)
846 1219 : tname = ast->data.lval->t->data.sym->data.lval->h->data.sval;
847 : else
848 9591 : tname = make_label(sql->sa, ++sql->label);
849 :
850 10810 : if (!sname && strcmp(fname, "file_loader") == 0) {
851 35 : rel = rel_file_loader(sql, exps, tl, tname);
852 35 : if (!rel)
853 : return NULL;
854 20538 : } else if (!(e = find_table_function(sql, sname, fname, list_empty(exps) ? NULL : exps, tl, F_UNION)))
855 : return NULL;
856 :
857 10756 : if (!rel) {
858 10756 : rel = sq;
859 :
860 : /* column or table function */
861 10756 : sf = e->f;
862 10756 : if (e->type != e_func || sf->func->type != F_UNION)
863 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: '%s' does not return a table", exp_func_name(e));
864 :
865 10756 : if (sq) {
866 171 : for (node *n = sq->exps->h, *m = sf->func->ops->h ; n && m ; n = n->next, m = m->next) {
867 118 : sql_exp *e = (sql_exp*) n->data;
868 118 : sql_arg *a = (sql_arg*) m->data;
869 118 : if (!exp_subtype(e) && rel_set_type_param(sql, &(a->type), sq, e, 0) < 0)
870 : return NULL;
871 : }
872 : }
873 :
874 : /* for each column add table.column name */
875 10756 : exps = new_exp_list(sql->sa);
876 106175 : for (m = sf->func->res->h; m; m = m->next) {
877 95419 : sql_arg *a = m->data;
878 95419 : sql_exp *e = exp_column(sql->sa, tname, a->name, &a->type, CARD_MULTI, 1, 0, 0);
879 95419 : e->alias.label = -(sql->nid++);
880 :
881 95419 : set_basecol(e);
882 95419 : append(exps, e);
883 : }
884 21459 : rel = rel_table_func(sql->sa, rel, e, exps, (sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
885 : }
886 10772 : if (ast->data.lval->t->type == type_symbol && ast->data.lval->t->data.sym && ast->data.lval->t->data.sym->data.lval->h->next->data.lval) {
887 49 : rel = rel_table_optname(sql, rel, ast->data.lval->t->data.sym, refs);
888 10723 : } else if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
889 10723 : if (list_find(refs, tname, (fcmp) &strcmp))
890 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", tname);
891 10723 : list_append(refs, tname);
892 : }
893 : return rel;
894 : }
895 :
896 : static sql_exp *
897 1868 : rel_op_(mvc *sql, char *sname, char *fname, exp_kind ek)
898 : {
899 1868 : bool found = false;
900 1868 : sql_subfunc *f = NULL;
901 1868 : sql_ftype type = (ek.card == card_loader)?F_LOADER:((ek.card == card_none)?F_PROC:
902 : ((ek.card == card_relation)?F_UNION:F_FUNC));
903 :
904 1868 : if ((f = bind_func_(sql, sname, fname, NULL, type, false, &found, true))) {
905 1851 : if (check_card(ek.card, f))
906 1851 : return exp_op(sql->sa, NULL, f);
907 0 : found = false;
908 : }
909 34 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s operator %s%s%s'%s'()",
910 17 : found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
911 : }
912 :
913 : static sql_exp*
914 4161 : exp_tuples_set_supertype(mvc *sql, list *tuple_values, sql_exp *tuples)
915 : {
916 4161 : assert(is_values(tuples));
917 4161 : list *vals = exp_get_values(tuples);
918 4161 : if (!vals || !vals->h)
919 : return NULL;
920 :
921 4161 : int tuple_width = list_length(tuple_values), i;
922 4161 : sql_subtype *types = SA_NEW_ARRAY(sql->sa, sql_subtype, tuple_width);
923 4161 : bool *has_type = SA_NEW_ARRAY(sql->sa, bool, tuple_width);
924 4161 : node *n;
925 :
926 4161 : memset(has_type, 0, sizeof(bool)*tuple_width);
927 13555 : for(n = tuple_values->h, i = 0; n; n = n->next, i++) {
928 9394 : sql_exp *e = n->data;
929 9394 : if (exp_subtype(e)) {
930 9392 : types[i] = *exp_subtype(e);
931 9392 : has_type[i] = 1;
932 : }
933 : }
934 :
935 8324 : for (node *m = vals->h; m; m = m->next) {
936 4163 : sql_exp *tuple = m->data;
937 4163 : if (is_values(tuple)) {
938 3 : list *exps = tuple->f;
939 9 : for(n = exps->h, i = 0; n; n = n->next, i++) {
940 6 : sql_subtype *tpe;
941 6 : sql_exp *e = n->data;
942 :
943 6 : if (has_type[i] && e->type == e_atom && !e->l && !e->r && !e->f && !e->tpe.type) {
944 0 : if (set_type_param(sql, types+i, e->flag) == 0)
945 0 : e->tpe = types[i];
946 : else
947 : return NULL;
948 : }
949 6 : tpe = exp_subtype(e);
950 6 : if (!tpe)
951 : return NULL;
952 6 : if (has_type[i] && tpe) {
953 6 : supertype(types+i, types+i, tpe);
954 : } else {
955 0 : has_type[i] = 1;
956 0 : types[i] = *tpe;
957 : }
958 : }
959 : } else {
960 4160 : sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
961 :
962 13552 : for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
963 9392 : sql_subtype *tpe;
964 9392 : sql_exp *e = n->data;
965 :
966 9392 : if (has_type[i] && e->type == e_atom && !e->l && !e->r && !e->f && !e->tpe.type) {
967 5 : if (set_type_param(sql, types+i, e->flag) == 0)
968 5 : e->tpe = types[i];
969 : else
970 : return NULL;
971 : }
972 9392 : tpe = exp_subtype(e);
973 9392 : if (!tpe)
974 : return NULL;
975 9392 : if (has_type[i] && tpe) {
976 9390 : cmp_supertype(types+i, types+i, tpe);
977 : } else {
978 2 : has_type[i] = 1;
979 2 : types[i] = *tpe;
980 : }
981 : }
982 : }
983 : }
984 :
985 8324 : for (node *m = vals->h; m; m = m->next) {
986 4163 : sql_exp *tuple = m->data;
987 4163 : if (is_values(tuple)) {
988 3 : list *exps = tuple->f;
989 3 : list *nexps = sa_list(sql->sa);
990 9 : for(n = exps->h, i = 0; n; n = n->next, i++) {
991 6 : sql_exp *e = n->data;
992 :
993 6 : e = exp_check_type(sql, types+i, NULL, e, type_equal);
994 6 : if (!e)
995 : return NULL;
996 6 : exp_label(sql->sa, e, ++sql->label);
997 6 : append(nexps, e);
998 : }
999 3 : tuple->f = nexps;
1000 : } else {
1001 4160 : sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
1002 :
1003 4160 : list *nexps = sa_list(sql->sa);
1004 13552 : for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
1005 9392 : sql_exp *e = n->data;
1006 :
1007 9392 : e = exp_check_type(sql, types+i, NULL, e, type_equal);
1008 9392 : if (!e)
1009 : return NULL;
1010 9392 : append(nexps, e);
1011 : }
1012 4160 : tuple_relation->exps = nexps;
1013 : }
1014 : }
1015 : return tuples;
1016 : }
1017 :
1018 : static int
1019 9394 : rel_binop_check_types(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, int upcast)
1020 : {
1021 9394 : sql_subtype *t1 = exp_subtype(ls), *t2 = exp_subtype(rs);
1022 :
1023 9394 : if (!t1 || !t2) {
1024 2 : if (t2 && !t1 && rel_set_type_param(sql, t2, rel, ls, upcast) < 0)
1025 : return -1;
1026 2 : if (t1 && !t2 && rel_set_type_param(sql, t1, rel, rs, upcast) < 0)
1027 : return -1;
1028 : }
1029 9394 : if (!exp_subtype(ls) && !exp_subtype(rs)) {
1030 0 : (void) sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
1031 0 : return -1;
1032 : }
1033 : return 0;
1034 : }
1035 :
1036 : static list *
1037 4161 : tuples_check_types(mvc *sql, list *tuple_values, sql_exp *tuples)
1038 : {
1039 4161 : list *tuples_list = exp_get_values(tuples);
1040 4161 : sql_exp *first_tuple = tuples_list->h->data;
1041 4161 : list *nvalues = sa_list(sql->sa);
1042 4161 : if (is_values(first_tuple)) {
1043 1 : list *vals = first_tuple->f;
1044 :
1045 3 : for (node *n = tuple_values->h, *m = vals->h; n && m; n = n->next, m = m->next) {
1046 2 : sql_exp *le = n->data, *re = m->data;
1047 :
1048 2 : if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
1049 : return NULL;
1050 2 : if ((le = exp_check_type(sql, exp_subtype(re), NULL, le, type_equal)) == NULL)
1051 : return NULL;
1052 2 : append(nvalues, le);
1053 : }
1054 : return nvalues;
1055 : } else {
1056 4160 : sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, first_tuple);
1057 :
1058 4160 : assert(list_length(tuple_values) == list_length(tuple_relation->exps));
1059 13552 : for (node *n = tuple_values->h, *m = tuple_relation->exps->h; n && m; n = n->next, m = m->next) {
1060 9392 : sql_exp *le = n->data, *re = m->data;
1061 :
1062 9392 : if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
1063 : return NULL;
1064 9392 : if ((le = exp_check_type(sql, exp_subtype(re), NULL, le, type_equal)) == NULL)
1065 : return NULL;
1066 9392 : append(nvalues, le);
1067 : }
1068 : return nvalues;
1069 : }
1070 : return tuple_values;
1071 : }
1072 :
1073 : static sql_rel *
1074 3836 : rel_values(sql_query *query, symbol *tableref, list *refs)
1075 : {
1076 3836 : mvc *sql = query->sql;
1077 3836 : sql_rel *r = NULL;
1078 3836 : dlist *rowlist = tableref->data.lval->h->data.lval;
1079 3836 : symbol *optname = tableref->data.lval->t->type == type_symbol ? tableref->data.lval->t->data.sym : NULL;
1080 3836 : node *m;
1081 3836 : list *exps = sa_list(sql->sa);
1082 3836 : exp_kind ek = {type_value, card_value, TRUE};
1083 :
1084 15397 : for (dnode *o = rowlist->h; o; o = o->next) {
1085 11571 : dlist *values = o->data.lval;
1086 :
1087 11571 : if (!list_empty(exps) && list_length(exps) != dlist_length(values)) {
1088 3 : return sql_error(sql, 02, SQLSTATE(42000) "VALUES: number of columns doesn't match between rows");
1089 : } else {
1090 11568 : dnode *n;
1091 :
1092 11568 : if (list_empty(exps)) {
1093 10982 : for (n = values->h; n; n = n->next) {
1094 7146 : sql_exp *vals = exp_values(sql->sa, sa_list(sql->sa));
1095 :
1096 7147 : exp_label(sql->sa, vals, ++sql->label);
1097 7147 : list_append(exps, vals);
1098 : }
1099 : }
1100 35453 : for (n = values->h, m = exps->h; n && m; n = n->next, m = m->next) {
1101 23892 : sql_exp *vals = m->data;
1102 23892 : list *vals_list = vals->f;
1103 23892 : sql_exp *e = rel_value_exp(query, NULL, n->data.sym, sql_sel | sql_values, ek);
1104 23894 : if (!e)
1105 : return NULL;
1106 23887 : list_append(vals_list, e);
1107 : }
1108 : }
1109 : }
1110 :
1111 : /* loop to check types and cardinality */
1112 3826 : unsigned int card = exps->h && list_length(((sql_exp*)exps->h->data)->f) > 1 ? CARD_MULTI : CARD_ATOM;
1113 10956 : for (m = exps->h; m; m = m->next) {
1114 7133 : sql_exp *e = m->data;
1115 :
1116 7133 : if (!(e = exp_values_set_supertype(sql, e, NULL)))
1117 : return NULL;
1118 7130 : e->card = card;
1119 7130 : m->data = e;
1120 : }
1121 :
1122 3823 : r = rel_project(sql->sa, NULL, exps);
1123 3823 : r->nrcols = list_length(exps);
1124 3823 : r->card = card;
1125 3823 : return rel_table_optname(sql, r, optname, refs);
1126 : }
1127 :
1128 : static int
1129 509054 : check_is_lateral(symbol *tableref)
1130 : {
1131 509054 : if (tableref->token == SQL_NAME || tableref->token == SQL_TABLE ||
1132 : tableref->token == SQL_VALUES) {
1133 458601 : if (dlist_length(tableref->data.lval) == 3)
1134 457768 : return tableref->data.lval->h->next->data.i_val;
1135 : return 0;
1136 : } else if (tableref->token == SQL_WITH) {
1137 980 : if (dlist_length(tableref->data.lval) == 5)
1138 15 : return tableref->data.lval->h->next->next->next->data.i_val;
1139 : return 0;
1140 : } else if (tableref->token == SQL_SELECT) {
1141 2292 : SelectNode *sn = (SelectNode *) tableref;
1142 2292 : return sn->lateral;
1143 : } else if (tableref->token == SQL_EXCEPT || tableref->token == SQL_INTERSECT ||
1144 : tableref->token == SQL_UNION) {
1145 10987 : if (dlist_length(tableref->data.lval) == 6)
1146 9252 : return tableref->data.lval->h->next->next->next->next->data.i_val;
1147 : return 0;
1148 : } else {
1149 : return 0;
1150 : }
1151 : }
1152 :
1153 : static sql_rel *
1154 25 : rel_reduce_on_column_privileges(mvc *sql, sql_rel *rel, sql_table *t)
1155 : {
1156 25 : list *exps = sa_list(sql->sa);
1157 :
1158 99 : for (node *n = rel->exps->h, *m = ol_first_node(t->columns); n && m; n = n->next, m = m->next) {
1159 74 : sql_exp *e = n->data;
1160 74 : sql_column *c = m->data;
1161 :
1162 74 : if (column_privs(sql, c, PRIV_SELECT))
1163 12 : append(exps, e);
1164 : }
1165 25 : if (!list_empty(exps)) {
1166 9 : rel->exps = exps;
1167 9 : return rel;
1168 : }
1169 : return NULL;
1170 : }
1171 :
1172 : sql_rel *
1173 697622 : table_ref(sql_query *query, symbol *tableref, int lateral, list *refs)
1174 : {
1175 697622 : mvc *sql = query->sql;
1176 697622 : char *tname = NULL;
1177 697622 : sql_table *t = NULL;
1178 697622 : sql_rel *res = NULL;
1179 :
1180 697622 : if (tableref->token == SQL_NAME) {
1181 479889 : dlist *name = tableref->data.lval->h->data.lval;
1182 479889 : sql_rel *temp_table = NULL;
1183 479889 : char *sname = qname_schema(name);
1184 479904 : int allowed = 1;
1185 :
1186 479904 : tname = qname_schema_object(name);
1187 :
1188 479903 : if (dlist_length(name) > 2)
1189 4 : return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: only a schema and table name expected");
1190 :
1191 479896 : if (!sname)
1192 109570 : temp_table = stack_find_rel_view(sql, tname);
1193 109563 : if (!temp_table)
1194 467059 : t = find_table_or_view_on_scope(sql, NULL, sname, tname, "SELECT", false);
1195 479895 : if (!t && !temp_table)
1196 : return NULL;
1197 479790 : if (!temp_table && !table_privs(sql, t, PRIV_SELECT))
1198 479774 : allowed = 0;
1199 :
1200 479774 : if (tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym) /* AS */
1201 283676 : tname = tableref->data.lval->t->data.sym->data.lval->h->data.sval;
1202 479774 : if (temp_table && !t) {
1203 12830 : node *n;
1204 12830 : int needed = !is_simple_project(temp_table->op);
1205 :
1206 12830 : if (is_basetable(temp_table->op) && !temp_table->exps) {
1207 0 : if (strcmp(rel_base_name(temp_table), tname) != 0)
1208 0 : rel_base_rename(temp_table, tname);
1209 : } else {
1210 42019 : for (n = temp_table->exps->h; n && !needed; n = n->next) {
1211 29189 : sql_exp *e = n->data;
1212 :
1213 29189 : if (!exp_relname(e) || strcmp(exp_relname(e), tname) != 0)
1214 : needed = 1;
1215 : }
1216 :
1217 12830 : if (needed) {
1218 5765 : list *exps = rel_projections(sql, temp_table, NULL, 1, 1);
1219 :
1220 5765 : temp_table = rel_project(sql->sa, temp_table, exps);
1221 18544 : for (n = exps->h; n; n = n->next) {
1222 12779 : sql_exp *e = n->data;
1223 :
1224 12779 : noninternexp_setname(sql, e, tname, NULL);
1225 12779 : set_basecol(e);
1226 : }
1227 5765 : list_hash_clear(exps);
1228 : }
1229 : }
1230 12830 : if (temp_table && tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym && tableref->data.lval->t->data.sym->data.lval->h->next->data.lval) /* AS with column aliases */
1231 10 : temp_table = rel_table_optname(sql, temp_table, tableref->data.lval->t->data.sym, refs);
1232 12830 : if (allowed)
1233 : return temp_table;
1234 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: access denied for %s to table '%s'", get_string_global_var(sql, "current_user"), tname);
1235 466944 : } else if (isView(t)) {
1236 : /* instantiate base view */
1237 71336 : node *n,*m;
1238 71336 : sql_rel *rel;
1239 :
1240 71336 : if (sql->emode == m_deps) {
1241 25016 : rel = rel_basetable(sql, t, tname);
1242 25016 : if (!allowed)
1243 0 : rel_base_disallow(rel);
1244 : } else {
1245 : /* when recreating a view, the view itself can't be found */
1246 46320 : if (sql->objid && sql->objid == t->base.id)
1247 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: attempting to recursively bind view '%s'.'%s'", t->s->base.name, tname);
1248 46319 : rel = rel_parse(sql, t->s, t->query, m_instantiate);
1249 46319 : if (rel && sql->emode == m_deps)
1250 0 : rel = rel_unnest(sql, rel);
1251 : }
1252 :
1253 71333 : if (!rel)
1254 2 : return NULL;
1255 : /* Rename columns of the rel_parse relation */
1256 71333 : if (sql->emode != m_deps) {
1257 46317 : assert(is_project(rel->op));
1258 46317 : set_processed(rel);
1259 46317 : if (is_mset(rel->op) || is_simple_project(rel->op) || (is_groupby(rel->op) && !list_empty(rel->r))) {
1260 : /* it's unsafe to set the projection names because of possible dependent sorting/grouping columns */
1261 46317 : rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 0, 0));
1262 46317 : set_processed(rel);
1263 : }
1264 416743 : for (n = ol_first_node(t->columns), m = rel->exps->h; n && m; n = n->next, m = m->next) {
1265 370426 : sql_column *c = n->data;
1266 370426 : sql_exp *e = m->data;
1267 :
1268 370426 : exp_setname(sql, e, tname, c->base.name);
1269 370426 : set_basecol(e);
1270 : }
1271 46317 : list_hash_clear(rel->exps);
1272 : }
1273 71333 : if (rel && !allowed && t->query && (rel = rel_reduce_on_column_privileges(sql, rel, t)) == NULL)
1274 16 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: access denied for %s to view '%s.%s'", get_string_global_var(sql, "current_user"), t->s->base.name, tname);
1275 71317 : return rel;
1276 : }
1277 395608 : if ((isMergeTable(t) || isReplicaTable(t)) && list_length(t->members)==0)
1278 14 : return sql_error(sql, 02, SQLSTATE(42000) "%s '%s'.'%s' should have at least one table associated",
1279 14 : TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->s->base.name, tname);
1280 395594 : res = rel_basetable(sql, t, tname);
1281 395619 : if (!allowed) {
1282 53 : rel_base_disallow(res);
1283 53 : if (rel_base_has_column_privileges(sql, res) == 0)
1284 62 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: access denied for %s to %s '%s.%s'", get_string_global_var(sql, "current_user"), isView(t) ? "view" : "table", t->s->base.name, tname);
1285 : }
1286 395588 : if (tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym && tableref->data.lval->t->data.sym->data.lval->h->next->data.lval) { /* AS with column aliases */
1287 12 : res = rel_table_optname(sql, res, tableref->data.lval->t->data.sym, refs);
1288 395576 : } else if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
1289 395571 : if (list_find(refs, tname, (fcmp) &strcmp))
1290 7 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", tname);
1291 395564 : assert(tname);
1292 395564 : list_append(refs, tname);
1293 : }
1294 395580 : return res;
1295 : } else if (tableref->token == SQL_VALUES) {
1296 1369 : return rel_values(query, tableref, refs);
1297 : } else if (tableref->token == SQL_TABLE) {
1298 10822 : return rel_named_table_function(query, NULL, tableref, lateral, refs);
1299 : } else if (tableref->token == SQL_SELECT) {
1300 101903 : return rel_subquery_optname(query, tableref, refs);
1301 : } else if (tableref->token == SQL_UNION || tableref->token == SQL_EXCEPT || tableref->token == SQL_INTERSECT) {
1302 : /* subqueries will be called, ie no need to test for duplicate references */
1303 43286 : sql_rel *tq = rel_setquery(query, tableref);
1304 :
1305 43286 : if (!tq)
1306 : return NULL;
1307 : /* look for lateral joins */
1308 43281 : symbol *optname = tableref->data.lval->t->type == type_symbol ? tableref->data.lval->t->data.sym : NULL;
1309 43281 : return rel_table_optname(sql, tq, optname, refs);
1310 : } else {
1311 60353 : return query_exp_optname(query, tableref, refs);
1312 : }
1313 : }
1314 :
1315 : static sql_exp *
1316 121409 : rel_exp_variable_on_scope(mvc *sql, const char *sname, const char *vname)
1317 : {
1318 121409 : sql_subtype *tpe = NULL;
1319 121409 : sql_var *var = NULL;
1320 121409 : sql_arg *a = NULL;
1321 121409 : int level = 1;
1322 :
1323 121409 : if (find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SELECT")) {
1324 120460 : if (var) /* if variable is known from the stack or a global var */
1325 37504 : return exp_param_or_declared(sql->sa, var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, var->name), &(var->var.tpe), level);
1326 87954 : if (a) /* if variable is a parameter */
1327 87954 : return exp_param_or_declared(sql->sa, NULL, sa_strdup(sql->sa, vname), &(a->type), level);
1328 : }
1329 : return NULL;
1330 : }
1331 :
1332 : static sql_exp *
1333 9256 : exps_get_exp(list *exps, int nth)
1334 : {
1335 9256 : node *n = NULL;
1336 9256 : int i = 0;
1337 :
1338 9256 : if (exps)
1339 27179 : for (n=exps->h, i=1; n && i<nth; n=n->next, i++)
1340 : ;
1341 9256 : if (n && i == nth)
1342 9253 : return n->data;
1343 : return NULL;
1344 : }
1345 :
1346 : static sql_rel *
1347 30954 : rel_find_groupby(sql_rel *groupby)
1348 : {
1349 30954 : if (groupby && !is_processed(groupby) && !is_base(groupby->op)) {
1350 40640 : while(!is_processed(groupby) && !is_base(groupby->op)) {
1351 32767 : if (is_groupby(groupby->op) || !groupby->l)
1352 : break;
1353 : if (groupby->l)
1354 : groupby = groupby->l;
1355 : }
1356 30830 : if (groupby && is_groupby(groupby->op))
1357 22957 : return groupby;
1358 : }
1359 : return NULL;
1360 : }
1361 :
1362 : static int
1363 306 : is_groupby_col(sql_rel *gb, sql_exp *e)
1364 : {
1365 306 : gb = rel_find_groupby(gb);
1366 :
1367 306 : if (gb) {
1368 174 : if (exp_relname(e)) {
1369 163 : if (exp_name(e) && exps_bind_column2(gb->r, exp_relname(e), exp_name(e), NULL))
1370 : return 1;
1371 : } else {
1372 11 : if (exp_name(e) && exps_bind_column(gb->r, exp_name(e), NULL, NULL, 1))
1373 : return 1;
1374 : }
1375 : }
1376 : return 0;
1377 : }
1378 :
1379 : static void
1380 4813 : set_dependent_( sql_rel *r)
1381 : {
1382 4813 : if (is_select(r->op))
1383 3641 : r = r->l;
1384 4813 : if (r && is_join(r->op))
1385 1226 : set_dependent(r);
1386 4813 : }
1387 :
1388 : static
1389 15 : sql_rel* find_union(visitor *v, sql_rel *rel) {
1390 15 : if (rel->op == op_union || rel->op == op_munion)
1391 1 : v->data = rel;
1392 15 : return rel;
1393 : }
1394 :
1395 : static inline
1396 54 : bool group_by_pk_project_uk_cond(mvc* sql, sql_rel* inner, sql_exp* exp,const char* sname, const char* tname) {
1397 54 : sql_table* t = find_table_or_view_on_scope(sql, NULL, sname, tname, "SELECT", false);
1398 54 : bool allow = false;
1399 54 : if (t) {
1400 17 : sql_idx* pki = NULL;
1401 17 : list *ukil = sa_list(sql->sa);
1402 :
1403 23 : for (node * n = ol_first_node(t->idxs); n; n = n->next) {
1404 6 : sql_idx *i = n->data;
1405 6 : if (!i->key)
1406 1 : continue;
1407 5 : switch (i->key->type) {
1408 3 : case pkey:
1409 3 : pki = i;
1410 3 : continue;
1411 2 : case ukey:
1412 : case unndkey:
1413 2 : list_append(ukil, i);
1414 2 : continue;
1415 0 : default:
1416 0 : continue;
1417 : }
1418 : }
1419 17 : if (pki && pki->columns->cnt == 1 && inner->r && ((list*) inner->r)->cnt == 1) {
1420 : /* for now only check simple case where primary key and group by expression is a single column*/
1421 3 : sql_exp* gbe = ((list*) inner->r)->h->data;
1422 3 : sql_column* pkc = ((sql_kc *)pki->columns->h->data)->c;
1423 3 : if (gbe->type == e_column && strcmp(gbe->alias.name, pkc->base.name) == 0) {
1424 2 : node *n;
1425 2 : for (n = ukil->h; n; n = n->next){
1426 2 : sql_idx* uki = n->data;
1427 2 : if (uki->columns->cnt == 1) {
1428 : /* for now only check simple case where unique key is a single column*/
1429 2 : sql_column* ukc = ((sql_kc *)uki->columns->h->data)->c;
1430 2 : if (strcmp(exp->alias.name, ukc->base.name) == 0) {
1431 : allow = true;
1432 : break;
1433 : }
1434 : }
1435 : }
1436 : }
1437 : }
1438 :
1439 2 : if (allow) {
1440 : /* sufficiency condition: abort if relation contains union subrelation
1441 : * because it may break functional dependency between pk and uk */
1442 2 : visitor v = {.sql=sql};
1443 2 : rel_visitor_topdown(&v, inner, &find_union);
1444 2 : if (v.data)
1445 1 : allow = false;
1446 : }
1447 : }
1448 :
1449 54 : return allow;
1450 :
1451 : }
1452 :
1453 : static sql_exp *
1454 2375383 : rel_column_ref(sql_query *query, sql_rel **rel, symbol *column_r, int f)
1455 : {
1456 2375383 : mvc *sql = query->sql;
1457 2375383 : sql_exp *exp = NULL;
1458 2375383 : dlist *l = NULL;
1459 2375383 : sql_rel *inner = rel?*rel:NULL, *outer = NULL;
1460 2375383 : int used_lower_after_processed = 0;
1461 :
1462 2375383 : assert((column_r->token == SQL_COLUMN || column_r->token == SQL_IDENT) && column_r->type == type_list);
1463 2375383 : l = column_r->data.lval;
1464 :
1465 2375383 : if (dlist_length(l) == 1) {
1466 1102950 : const char *name = l->h->data.sval;
1467 :
1468 1102950 : if (!exp && inner)
1469 1008175 : if (!(exp = rel_bind_column(sql, inner, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
1470 : return NULL;
1471 1102936 : if (!exp && inner && ((is_sql_aggr(f) && (is_groupby(inner->op) || is_select(inner->op))) ||
1472 24026 : (is_groupby(inner->op) && inner->flag))) {
1473 : /* if inner is selection, ie having clause, get the left relation to reach group by */
1474 : sql_rel *gp = inner;
1475 258 : while (gp && is_select(gp->op))
1476 27 : gp = gp->l;
1477 231 : if (gp && !is_basetable(gp->op) && gp->l && !(exp = rel_bind_column(sql, gp->l, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
1478 : return NULL;
1479 : }
1480 1102936 : if (!exp && query && query_has_outer(query)) {
1481 469 : int i;
1482 :
1483 522 : for (i=query_has_outer(query)-1; i>= 0 && !exp && (outer = query_fetch_outer(query,i)); i--) {
1484 493 : if (!(exp = rel_bind_column(sql, outer, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
1485 : return NULL;
1486 84 : if (!exp && is_groupby(outer->op)) {
1487 31 : if (!(exp = rel_bind_column(sql, outer->l, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
1488 : return NULL;
1489 : else
1490 31 : used_lower_after_processed = is_processed(outer);
1491 : }
1492 493 : if (exp && is_simple_project(outer->op) && !rel_find_exp(outer, exp))
1493 0 : exp = rel_project_add_exp(sql, outer, exp);
1494 440 : if (exp)
1495 : break;
1496 : }
1497 469 : if (exp && exp->card != CARD_AGGR && is_groupby(outer->op) && !is_sql_aggr(f) && rel_find_exp(outer->l, exp))
1498 5 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
1499 464 : if (exp && outer && outer->card <= CARD_AGGR && exp->card > CARD_AGGR && !is_sql_aggr(f))
1500 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
1501 464 : if (exp && outer && !is_sql_aggr(f) && !is_sql_aggr(query_fetch_outer_state(query, i))) {
1502 296 : if (used_lower_after_processed || query_outer_used_exp( query, i, exp, f)) {
1503 0 : sql_exp *lu = used_lower_after_processed?exp:query_outer_last_used(query, i);
1504 0 : if (exp_name(lu) && exp_relname(lu) && !has_label(lu))
1505 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu));
1506 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
1507 : }
1508 : }
1509 464 : if (exp) {
1510 435 : int of = query_fetch_outer_state(query, i);
1511 435 : if (is_groupby(outer->op) && !is_sql_aggr(f)) {
1512 37 : exp = rel_groupby_add_aggr(sql, outer, exp);
1513 37 : exp->card = CARD_ATOM;
1514 398 : } else if (is_groupby(outer->op) && is_sql_aggr(f) && exps_any_match(outer->exps, exp))
1515 57 : exp = exp_ref(sql, exp);
1516 : else
1517 341 : exp->card = CARD_ATOM;
1518 435 : set_freevar(exp, i);
1519 : /*
1520 : if (exp->alias.label == exp->nid)
1521 : exp->alias.label = -(sql->nid++);
1522 : */
1523 435 : if (!is_sql_where(of) && !is_sql_aggr(of) && !is_sql_aggr(f) && !outer->grouped)
1524 146 : set_outer(outer);
1525 : }
1526 464 : if (exp && outer && (is_select(outer->op) || is_join(outer->op)))
1527 43 : set_dependent_(outer);
1528 : }
1529 :
1530 : /* some views are just in the stack, like before and after updates views */
1531 1102931 : if (rel && sql->use_views) {
1532 13 : sql_rel *v = NULL;
1533 13 : int dup = stack_find_rel_view_projection_columns(sql, name, &v); /* trigger views are basetables relations, so those may conflict */
1534 :
1535 13 : if (dup < 0 || (v && exp && *rel && is_base(v->op) && v != *rel)) /* comparing pointers, ugh */
1536 2 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", name);
1537 11 : if (v && !exp) {
1538 4 : if (*rel)
1539 1 : *rel = rel_crossproduct(sql->sa, *rel, rel_dup(v), op_join);
1540 : else
1541 3 : *rel = rel_dup(v);
1542 4 : exp = rel_bind_column(sql, *rel, name, f, 0);
1543 : }
1544 : }
1545 1102929 : if (!exp) /* If no column was found, try a variable or parameter */
1546 118390 : exp = rel_exp_variable_on_scope(sql, NULL, name);
1547 :
1548 118390 : if (!exp) {
1549 949 : if (inner && !is_sql_aggr(f) && is_groupby(inner->op) && inner->l && (exp = rel_bind_column(sql, inner->l, name, f, 0)))
1550 49 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
1551 : }
1552 :
1553 1101980 : if (!exp)
1554 900 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: identifier '%s' unknown", name);
1555 1101980 : if (exp && inner && inner->card <= CARD_AGGR && exp->card > CARD_AGGR && (is_sql_sel(f) || is_sql_having(f)) && (!is_sql_aggr(f) && !(inner->flag)))
1556 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
1557 1101980 : if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && !is_freevar(exp) && !inner->flag)
1558 26121 : exp = rel_groupby_add_aggr(sql, inner, exp);
1559 1272433 : } else if (dlist_length(l) == 2 || dlist_length(l) == 3) {
1560 1272433 : const char *sname = NULL;
1561 1272433 : const char *tname = l->h->data.sval;
1562 1272433 : const char *cname = l->h->next->data.sval;
1563 1272433 : if (dlist_length(l) == 3) {
1564 1 : sname = l->h->data.sval;
1565 1 : tname = l->h->next->data.sval;
1566 1 : cname = l->h->next->next->data.sval;
1567 : }
1568 :
1569 1272433 : if (!exp && rel && inner)
1570 1272306 : if (!(exp = rel_bind_column3(sql, inner, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
1571 : return NULL;
1572 1272432 : if (!exp && inner && is_sql_aggr(f) && (is_groupby(inner->op) || is_select(inner->op))) {
1573 : /* if inner is selection, ie having clause, get the left relation to reach group by */
1574 : sql_rel *gp = inner;
1575 56 : while (gp && is_select(gp->op))
1576 4 : gp = gp->l;
1577 52 : if (gp && !is_basetable(gp->op) && gp->l && !(exp = rel_bind_column3(sql, gp->l, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
1578 : return NULL;
1579 : }
1580 1272432 : if (!exp && query && query_has_outer(query)) {
1581 12002 : int i;
1582 :
1583 12212 : for (i=query_has_outer(query)-1; i>= 0 && !exp && (outer = query_fetch_outer(query,i)); i--) {
1584 12211 : if (!(exp = rel_bind_column3(sql, outer, sname, tname, cname, f | sql_outer)) && sql->session->status == -ERR_AMBIGUOUS)
1585 : return NULL;
1586 293 : if (!exp && is_groupby(outer->op)) {
1587 102 : if (!(exp = rel_bind_column3(sql, outer->l, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
1588 : return NULL;
1589 : else
1590 102 : used_lower_after_processed = is_processed(outer);
1591 : }
1592 12211 : if (exp && is_simple_project(outer->op) && !rel_find_exp(outer, exp))
1593 0 : exp = rel_project_add_exp(sql, outer, exp);
1594 12001 : if (exp)
1595 : break;
1596 : }
1597 12002 : if (exp && exp->card != CARD_AGGR && is_groupby(outer->op) && !is_sql_aggr(f) && rel_find_exp(outer->l, exp))
1598 6 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
1599 11996 : if (exp && outer && outer->card <= CARD_AGGR && exp->card > CARD_AGGR && !is_sql_aggr(f))
1600 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
1601 11996 : if (exp && outer && !is_sql_aggr(f)) {
1602 11721 : if (used_lower_after_processed || query_outer_used_exp( query, i, exp, f)) {
1603 0 : sql_exp *lu = used_lower_after_processed?exp:query_outer_last_used(query, i);
1604 0 : if (exp_name(lu) && exp_relname(lu) && !has_label(lu))
1605 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu));
1606 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
1607 : }
1608 : }
1609 11996 : if (exp) {
1610 11995 : int of = query_fetch_outer_state(query, i);
1611 11995 : if (is_groupby(outer->op) && !is_sql_aggr(f)) {
1612 64 : exp = rel_groupby_add_aggr(sql, outer, exp);
1613 64 : exp->card = CARD_ATOM;
1614 11931 : } else if (is_groupby(outer->op) && is_sql_aggr(f) && exps_any_match(outer->exps, exp))
1615 52 : exp = exp_ref(sql, exp);
1616 : else
1617 11879 : exp->card = CARD_ATOM;
1618 11995 : set_freevar(exp, i);
1619 : /*
1620 : if (exp->alias.label == exp->nid)
1621 : exp->alias.label = -(sql->nid++);
1622 : */
1623 11995 : if (!is_sql_where(of) && !is_sql_aggr(of) && !is_sql_aggr(f) && !outer->grouped)
1624 10283 : set_outer(outer);
1625 : }
1626 11996 : if (exp && outer && (is_select(outer->op) || is_join(outer->op)))
1627 4770 : set_dependent_(outer);
1628 : }
1629 :
1630 : /* some views are just in the stack, like before and after updates views */
1631 1272426 : if (rel && sql->use_views) {
1632 40 : sql_rel *v = stack_find_rel_view(sql, tname);
1633 :
1634 40 : if (v && exp && *rel && is_base(v->op) && v != *rel) /* trigger views are basetables relations, so those may conflict */
1635 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous", tname, cname);
1636 40 : if (v && !exp) {
1637 20 : if (*rel)
1638 0 : *rel = rel_crossproduct(sql->sa, *rel, rel_dup(v), op_join);
1639 : else
1640 20 : *rel = rel_dup(v);
1641 20 : if (!(exp = rel_bind_column3(sql, *rel, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
1642 : return NULL;
1643 : }
1644 : }
1645 1272406 : if (!exp) { /* If no column was found, try a global variable */
1646 67017 : sql_var *var = NULL;
1647 67017 : sql_subtype *tpe = NULL;
1648 67017 : int level = 0;
1649 67017 : sql_arg *a = NULL;
1650 :
1651 67017 : if (find_variable_on_scope(sql, tname, cname, &var, &a, &tpe, &level, "SELECT")) { /* search schema with table name, ugh */
1652 10 : assert(level == 0);
1653 10 : exp = exp_param_or_declared(sql->sa, sa_strdup(sql->sa, var->sname), sa_strdup(sql->sa, var->name), &(var->var.tpe), 0);
1654 : }
1655 : }
1656 67017 : if (!exp) {
1657 67007 : if (inner && !is_sql_aggr(f) && is_groupby(inner->op) && inner->l && (exp = rel_bind_column3(sql, inner->l, sname, tname, cname, f))) {
1658 54 : if (group_by_pk_project_uk_cond(sql, inner, exp, sname, tname)) {
1659 : /* SQL23 feature: very special case where primary key is used in GROUP BY expression and
1660 : * unique key is in the project list or ORDER BY clause */
1661 1 : sql->session->status = 0;
1662 1 : sql->errstr[0] = 0;
1663 1 : exp->card = CARD_AGGR;
1664 1 : list_append(inner->exps, exp);
1665 : }
1666 : else
1667 53 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
1668 : }
1669 : }
1670 :
1671 1 : if (!exp)
1672 66953 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "SELECT: no such column '%s.%s'", tname, cname);
1673 1205420 : if (exp && inner && inner->card <= CARD_AGGR && exp->card > CARD_AGGR && (is_sql_sel(f) || is_sql_having(f)) && !is_sql_aggr(f))
1674 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
1675 1205420 : if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && !is_freevar(exp))
1676 17531 : exp = rel_groupby_add_aggr(sql, inner, exp);
1677 0 : } else if (dlist_length(l) > 3) {
1678 0 : return sql_error(sql, 02, SQLSTATE(42000) "cross-database references are not implemented");
1679 : }
1680 2307400 : if (exp && !exp_is_atom(exp) && rel && !outer) {
1681 2177525 : if (query->last_exp && query->last_rel == *rel && !is_sql_aggr(query->last_state) && is_sql_aggr(f)) {
1682 55 : if (!is_groupby(query->last_rel->op) || list_empty(query->last_rel->r) || !exps_find_exp(query->last_rel->r, query->last_exp)) {
1683 34 : if (exp_relname(query->last_exp) && exp_name(query->last_exp) && !has_label(query->last_exp))
1684 34 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(query->last_exp), exp_name(query->last_exp));
1685 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
1686 : }
1687 : }
1688 2177491 : query->prev = query->last_exp;
1689 2177491 : query->last_exp = exp;
1690 2177491 : query->last_state = f;
1691 2177491 : query->last_rel = *rel;
1692 : }
1693 : return exp;
1694 : }
1695 :
1696 : int
1697 1006127 : rel_convert_types(mvc *sql, sql_rel *ll, sql_rel *rr, sql_exp **L, sql_exp **R, int scale_fixing, check_type tpe)
1698 : {
1699 1006127 : sql_exp *ls = *L;
1700 1006127 : sql_exp *rs = *R;
1701 1006127 : sql_subtype *lt = exp_subtype(ls);
1702 1006127 : sql_subtype *rt = exp_subtype(rs);
1703 :
1704 1006127 : if (!rt && !lt) {
1705 2 : sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
1706 2 : return -1;
1707 : }
1708 1006125 : if (rt && (!lt || !lt->type))
1709 7 : return rel_set_type_param(sql, rt, ll, ls, 0);
1710 1006118 : if (lt && (!rt || !rt->type))
1711 648 : return rel_set_type_param(sql, lt, rr, rs, 0);
1712 :
1713 1005470 : if (rt && lt) {
1714 1005470 : sql_subtype *i = lt;
1715 1005470 : sql_subtype *r = rt;
1716 :
1717 1005470 : if (subtype_cmp(lt, rt) != 0 || (tpe == type_equal_no_any && (lt->type->localtype==0 || rt->type->localtype==0))) {
1718 277504 : sql_subtype super;
1719 :
1720 277504 : cmp_supertype(&super, r, i);
1721 277504 : if (scale_fixing) {
1722 : /* convert ls to super type */
1723 277504 : ls = exp_check_type(sql, &super, ll, ls, tpe);
1724 : /* convert rs to super type */
1725 277504 : rs = exp_check_type(sql, &super, rr, rs, tpe);
1726 : } else {
1727 : /* convert ls to super type */
1728 0 : super.scale = lt->scale;
1729 0 : ls = exp_check_type(sql, &super, ll, ls, tpe);
1730 : /* convert rs to super type */
1731 0 : super.scale = rt->scale;
1732 0 : rs = exp_check_type(sql, &super, rr, rs, tpe);
1733 : }
1734 : }
1735 1005470 : *L = ls;
1736 1005470 : *R = rs;
1737 1005470 : if (!ls || !rs)
1738 : return -1;
1739 : return 0;
1740 : }
1741 : return -1;
1742 : }
1743 :
1744 : static sql_rel *
1745 108007 : push_select_exp(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *ls, int f)
1746 : {
1747 108007 : if (is_outerjoin(rel->op)) {
1748 1182 : if ((is_left(rel->op) || is_full(rel->op)) && rel_find_exp(rel->l, ls)) {
1749 38 : rel_join_add_exp(sql->sa, rel, e);
1750 38 : return rel;
1751 1144 : } else if ((is_right(rel->op) || is_full(rel->op)) && rel_find_exp(rel->r, ls)) {
1752 5 : rel_join_add_exp(sql->sa, rel, e);
1753 5 : return rel;
1754 : }
1755 1139 : if (is_left(rel->op) && rel_find_exp(rel->r, ls)) {
1756 1113 : rel->r = rel_push_select(sql, rel->r, ls, e, f);
1757 1113 : return rel;
1758 26 : } else if (is_right(rel->op) && rel_find_exp(rel->l, ls)) {
1759 11 : rel->l = rel_push_select(sql, rel->l, ls, e, f);
1760 11 : return rel;
1761 : }
1762 : }
1763 : /* push select into the given relation */
1764 106840 : return rel_push_select(sql, rel, ls, e, f);
1765 : }
1766 :
1767 : static sql_rel *
1768 209675 : push_join_exp(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *L, sql_exp *R, sql_exp *R2, int f)
1769 : {
1770 209675 : sql_rel *r;
1771 209675 : if (/*is_semi(rel->op) ||*/ (is_outerjoin(rel->op) && !is_processed((rel)))) {
1772 21212 : rel_join_add_exp(sql->sa, rel, e);
1773 21212 : return rel;
1774 : }
1775 : /* push join into the given relation */
1776 188463 : if ((r = rel_push_join(sql, rel, L, R, R2, e, f)) != NULL)
1777 : return r;
1778 0 : rel_join_add_exp(sql->sa, rel, e);
1779 0 : return rel;
1780 : }
1781 :
1782 : static sql_rel *
1783 3736 : rel_select_push_filter_exp_down(mvc *sql, sql_rel *rel, sql_exp *e, list *l, list *r, int ff)
1784 : {
1785 3736 : sql_exp *ll;
1786 3736 : if (exps_card(r) <= CARD_ATOM && (exps_are_atoms(r) || exps_have_freevar(sql, r) || exps_have_freevar(sql, l))) {
1787 3639 : if (exps_card(l) == exps_card(r) || rel->processed) /* bin compare op */
1788 98 : return rel_select(sql->sa, rel, e);
1789 3541 : if ((ll = exps_find_one_multi_exp(l)))
1790 3541 : return push_select_exp(sql, rel, e, ll, ff);
1791 : }
1792 97 : if (is_outerjoin(rel->op))
1793 8 : return rel_select(sql->sa, rel, e);
1794 89 : return rel_select_add_exp(sql->sa, rel, e);
1795 : }
1796 :
1797 : static sql_rel *
1798 3619 : rel_filter(mvc *sql, sql_rel *rel, list *l, list *r, char *sname, char *filter_op, int anti, int ff)
1799 : {
1800 3619 : node *n;
1801 3619 : sql_exp *e = NULL;
1802 3619 : sql_subfunc *f = NULL;
1803 3619 : list *tl = sa_list(sql->sa);
1804 3619 : bool found = false;
1805 :
1806 7238 : for (n = l->h; n; n = n->next){
1807 3619 : sql_exp *e = n->data;
1808 :
1809 3619 : list_append(tl, exp_subtype(e));
1810 : }
1811 14399 : for (n = r->h; n; n = n->next){
1812 10780 : sql_exp *e = n->data;
1813 :
1814 10780 : list_append(tl, exp_subtype(e));
1815 : }
1816 : /* find filter function */
1817 3619 : f = bind_func_(sql, sname, filter_op, tl, F_FILT, false, &found, false);
1818 3619 : if (f) {
1819 3617 : node *n,*m = f->func->ops->h;
1820 3617 : list *nexps = sa_list(sql->sa);
1821 :
1822 7234 : for(n=l->h; m && n; m = m->next, n = n->next) {
1823 3617 : sql_arg *a = m->data;
1824 3617 : sql_exp *e = n->data;
1825 :
1826 3617 : e = exp_check_type(sql, &a->type, rel, e, type_equal);
1827 3617 : if (!e)
1828 : return NULL;
1829 3617 : list_append(nexps, e);
1830 : }
1831 3617 : l = nexps;
1832 3617 : nexps = sa_list(sql->sa);
1833 14389 : for(n=r->h; m && n; m = m->next, n = n->next) {
1834 10772 : sql_arg *a = m->data;
1835 10772 : sql_exp *e = n->data;
1836 :
1837 10772 : e = exp_check_type(sql, &a->type, rel, e, type_equal);
1838 10772 : if (!e)
1839 : return NULL;
1840 10772 : list_append(nexps, e);
1841 : }
1842 : r = nexps;
1843 : }
1844 3619 : if (!f)
1845 4 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s FILTER function %s%s%s'%s'",
1846 2 : found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", filter_op);
1847 3617 : e = exp_filter(sql->sa, l, r, f, anti);
1848 :
1849 3617 : if (exps_one_is_rel(l) || exps_one_is_rel(r)) /* uncorrelated subquery case */
1850 9 : return rel_select(sql->sa, rel, e);
1851 : /* atom or row => select */
1852 7216 : for (node *n=l->h; n; n = n->next) {
1853 3608 : sql_exp *ls = n->data;
1854 :
1855 3608 : if (ls->card > rel->card) {
1856 0 : if (exp_name(ls) && !has_label(ls))
1857 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(ls));
1858 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
1859 : }
1860 : }
1861 14353 : for (node *n=r->h; n; n = n->next) {
1862 10745 : sql_exp *rs = n->data;
1863 :
1864 10745 : if (rs->card > rel->card) {
1865 0 : if (exp_name(rs) && !has_label(rs))
1866 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(rs));
1867 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
1868 : }
1869 : }
1870 3608 : return rel_select_push_filter_exp_down(sql, rel, e, l, r, ff);
1871 : }
1872 :
1873 : static sql_rel *
1874 3559 : rel_filter_exp_(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *r1, sql_exp *r2, sql_exp *r3, char *filter_op, int anti, int f)
1875 : {
1876 3559 : list *l = sa_list(sql->sa);
1877 3559 : list *r = sa_list(sql->sa);
1878 :
1879 3559 : list_append(l, ls);
1880 3559 : list_append(r, r1);
1881 3559 : if (r2)
1882 3559 : list_append(r, r2);
1883 3559 : if (r3)
1884 3559 : list_append(r, r3);
1885 3559 : return rel_filter(sql, rel, l, r, "sys", filter_op, anti, f);
1886 : }
1887 :
1888 : static sql_rel *
1889 382308 : rel_select_push_compare_exp_down(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *ls, sql_exp *rs, sql_exp *rs2, int f)
1890 : {
1891 382308 : if (!is_join(rel->op) && !is_select(rel->op))
1892 85540 : return rel_select(sql->sa, rel, e);
1893 384407 : if ((rs->card <= CARD_ATOM || (rs2 && ls->card <= CARD_ATOM)) &&
1894 175278 : (exp_is_atom(rs) || (rs2 && exp_is_atom(ls)) || exp_has_freevar(sql, rs) || exp_has_freevar(sql, ls)) &&
1895 485 : (!rs2 || (rs2->card <= CARD_ATOM && (exp_is_atom(rs2) || exp_has_freevar(sql, rs2))))) {
1896 87093 : if (ls->card == rs->card || (rs2 && (ls->card == rs2->card || rs->card == rs2->card)) || rel->processed) /* bin compare op */
1897 1006 : return rel_select(sql->sa, rel, e);
1898 :
1899 86087 : return push_select_exp(sql, rel, e, ls, f);
1900 : } else { /* join */
1901 209675 : return push_join_exp(sql, rel, e, ls, rs, rs2, f);
1902 : }
1903 : return rel;
1904 : }
1905 :
1906 : static sql_rel *
1907 357909 : rel_compare_exp_(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, int type, int anti, int quantifier, int f, int symmetric, int is_semantics)
1908 : {
1909 357909 : mvc *sql = query->sql;
1910 357909 : sql_exp *e = NULL;
1911 :
1912 357909 : if (quantifier || exp_is_rel(ls) || exp_is_rel(rs) || (rs2 && exp_is_rel(rs2))) {
1913 3501 : if (rs2) {
1914 7 : e = exp_compare2(sql->sa, ls, rs, rs2, type, symmetric);
1915 7 : if (anti)
1916 0 : set_anti(e);
1917 : } else {
1918 3494 : assert(!symmetric);
1919 3494 : if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
1920 : return NULL;
1921 3494 : e = exp_compare_func(sql, ls, rs, compare_func((comp_type)type, anti), quantifier);
1922 : }
1923 3501 : return rel_select(sql->sa, rel, e);
1924 354408 : } else if (!rs2) {
1925 351461 : assert(!symmetric);
1926 351461 : if (ls->card < rs->card) {
1927 12640 : sql_exp *swap = ls;
1928 12640 : ls = rs;
1929 12640 : rs = swap;
1930 12640 : type = (int)swap_compare((comp_type)type);
1931 : }
1932 351461 : if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
1933 : return NULL;
1934 351458 : e = exp_compare(sql->sa, ls, rs, type);
1935 351458 : if (is_semantics) set_semantics(e);
1936 : } else {
1937 2947 : assert(rs2);
1938 2947 : if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
1939 : return NULL;
1940 2947 : if (!(rs2 = exp_check_type(sql, exp_subtype(ls), rel, rs2, type_equal)))
1941 : return NULL;
1942 2947 : e = exp_compare2(sql->sa, ls, rs, rs2, type, symmetric);
1943 : }
1944 354405 : if (anti)
1945 847 : set_anti(e);
1946 :
1947 354405 : if (!rel)
1948 0 : return rel_select(sql->sa, rel_project_exp(sql, exp_atom_bool(sql->sa, 1)), e);
1949 :
1950 : /* atom or row => select */
1951 354405 : if (ls->card > rel->card || rs->card > rel->card || (rs2 && rs2->card > rel->card)) {
1952 0 : sql_exp *e = ls->card > rel->card ? ls : rs->card > rel->card ? rs : rs2;
1953 0 : if (exp_name(e) && !has_label(e))
1954 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(e));
1955 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
1956 : }
1957 354405 : return rel_select_push_compare_exp_down(sql, rel, e, ls, rs, rs2, f);
1958 : }
1959 :
1960 : static sql_rel *
1961 354955 : rel_compare_exp(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, char *compare_op, int reduce, int quantifier, int need_not, int f, int is_semantics)
1962 : {
1963 354955 : mvc *sql = query->sql;
1964 354955 : comp_type type = cmp_equal;
1965 :
1966 354955 : if (!ls || !rs)
1967 : return NULL;
1968 :
1969 354955 : if (!quantifier && ((!rel && !query_has_outer(query)) || !reduce)) {
1970 : /* TODO to handle filters here */
1971 0 : sql_exp *e;
1972 :
1973 0 : if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
1974 : return NULL;
1975 0 : e = rel_binop_(sql, rel, ls, rs, "sys", compare_op, card_value, true);
1976 :
1977 0 : if (!e)
1978 : return NULL;
1979 0 : if (!reduce) {
1980 0 : if (rel->op == op_project) {
1981 0 : append(rel->exps, e);
1982 : } else {
1983 0 : list *exps = new_exp_list(sql->sa);
1984 :
1985 0 : append(exps, e);
1986 0 : return rel_project(sql->sa, rel, exps);
1987 : }
1988 : } else {
1989 0 : return rel_select(sql->sa, rel, e);
1990 : }
1991 : }
1992 354955 : type = compare_str2type(compare_op);
1993 354955 : assert(type != cmp_filter);
1994 354955 : return rel_compare_exp_(query, rel, ls, rs, NULL, type, need_not, quantifier, f, 0, is_semantics);
1995 : }
1996 :
1997 : static sql_rel *
1998 354931 : rel_compare(sql_query *query, sql_rel *rel, symbol *sc, symbol *lo, symbol *ro, char *compare_op, int f, exp_kind k, int quantifier, int is_semantics)
1999 : {
2000 354931 : mvc *sql = query->sql;
2001 354931 : sql_exp *rs = NULL, *ls;
2002 354931 : comp_type cmp_type = compare_str2type(compare_op);
2003 354931 : exp_kind ek = {type_value, card_column, FALSE};
2004 354931 : int need_not = 0;
2005 :
2006 354931 : if ((quantifier == 1 && cmp_type == cmp_equal) ||
2007 354896 : (quantifier == 2 && cmp_type == cmp_notequal)) {
2008 63 : dnode *n = sc->data.lval->h;
2009 63 : dlist *dl = dlist_create(sql->sa);
2010 : /* map into IN/NOT IN */
2011 63 : sc->token = cmp_type==cmp_equal?SQL_IN:SQL_NOT_IN;
2012 63 : n->next->type = type_list;
2013 63 : n->next->data.lval = dl;
2014 63 : n->next->next->next = NULL; /* remove quantifier */
2015 63 : dl->h = n->next->next;
2016 63 : n->next->next = NULL; /* (remove comparison) moved righthand side */
2017 63 : return rel_logical_exp(query, rel, sc, f);
2018 : }
2019 : /* <> ANY -> NOT (= ALL) */
2020 354868 : if (quantifier == 1 && cmp_type == cmp_notequal) {
2021 5 : need_not = 1;
2022 5 : quantifier = 2;
2023 5 : cmp_type = cmp_equal;
2024 5 : compare_op = "=";
2025 : }
2026 :
2027 354868 : if ((lo->token == SQL_SELECT || lo->token == SQL_UNION || lo->token == SQL_EXCEPT || lo->token == SQL_INTERSECT || lo->token == SQL_VALUES) &&
2028 43 : (ro->token != SQL_SELECT && ro->token != SQL_UNION && ro->token != SQL_EXCEPT && ro->token != SQL_INTERSECT && ro->token != SQL_VALUES)) {
2029 30 : symbol *tmp = lo; /* swap subquery to the right hand side */
2030 :
2031 30 : lo = ro;
2032 30 : ro = tmp;
2033 :
2034 30 : if (compare_op[0] == '>')
2035 16 : compare_op[0] = '<';
2036 14 : else if (compare_op[0] == '<' && compare_op[1] != '>')
2037 1 : compare_op[0] = '>';
2038 30 : cmp_type = swap_compare(cmp_type);
2039 : }
2040 :
2041 354868 : ls = rel_value_exp(query, &rel, lo, f|sql_farg, ek);
2042 354868 : if (!ls)
2043 : return NULL;
2044 354819 : if (ls && rel && exp_has_freevar(sql, ls) && is_sql_sel(f))
2045 0 : ls = rel_project_add_exp(sql, rel, ls);
2046 354819 : if (quantifier)
2047 58 : ek.card = card_set;
2048 :
2049 354819 : rs = rel_value_exp(query, &rel, ro, f|sql_farg, ek);
2050 354819 : if (!rs)
2051 : return NULL;
2052 354791 : if (ls->card > rs->card && rs->card == CARD_AGGR && is_sql_having(f)) {
2053 0 : if (exp_name(ls) && exp_relname(ls) && !has_label(ls))
2054 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(ls), exp_name(ls));
2055 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
2056 : }
2057 354791 : if (rs->card > ls->card && ls->card == CARD_AGGR && is_sql_having(f)) {
2058 0 : if (exp_name(rs) && exp_relname(rs) && !has_label(rs))
2059 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(rs), exp_name(rs));
2060 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
2061 : }
2062 354791 : return rel_compare_exp(query, rel, ls, rs, compare_op, k.reduce, quantifier, need_not, f, is_semantics);
2063 : }
2064 :
2065 : static sql_exp*
2066 80936 : _rel_nop(mvc *sql, char *sname, char *fname, list *tl, sql_rel *rel, list *exps, exp_kind ek)
2067 : {
2068 80936 : bool found = false;
2069 80936 : int table_func = (ek.card == card_relation);
2070 80936 : sql_ftype type = (ek.card == card_loader)?F_LOADER:((ek.card == card_none)?F_PROC:
2071 : ((ek.card == card_relation)?F_UNION:F_FUNC));
2072 :
2073 80936 : sql_subfunc *f = bind_func_(sql, sname, fname, tl, type, false, &found, false);
2074 80936 : if (f && !(exps = check_arguments_and_find_largest_any_type(sql, rel, exps, f, table_func, false)))
2075 : f = NULL;
2076 :
2077 80920 : if (f)
2078 80920 : return exp_op(sql->sa, exps, f);
2079 16 : char *arg_list = nary_function_arg_types_2str(sql, tl, list_length(tl));
2080 32 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s operator %s%s%s'%s'(%s)",
2081 16 : found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname, arg_list ? arg_list : "");
2082 : }
2083 :
2084 : static sql_exp *
2085 2096 : exp_exist(sql_query *query, sql_rel *rel, sql_exp *le, int exists)
2086 : {
2087 2096 : mvc *sql = query->sql;
2088 2096 : sql_subfunc *exists_func = NULL;
2089 2096 : sql_subtype *t;
2090 2096 : sql_exp *res;
2091 :
2092 2096 : if (!exp_name(le))
2093 753 : exp_label(sql->sa, le, ++sql->label);
2094 2096 : if (exp_is_rel(le)) { /* for the subquery case, propagate to the inner query */
2095 2096 : sql_rel *r = exp_rel_get_rel(sql->sa, le);
2096 2096 : if (is_project(r->op) && !list_empty(r->exps)) {
2097 6109 : for (node *n = r->exps->h; n; n = n->next)
2098 4013 : if (!exp_subtype(n->data) && rel_set_type_param(sql, sql_bind_localtype("bit"), r, n->data, 0) < 0) /* workaround */
2099 : return NULL;
2100 2096 : le->tpe = *exp_subtype(r->exps->h->data); /* just take the first expression type */
2101 : }
2102 0 : } else if (!exp_subtype(le) && rel_set_type_param(sql, sql_bind_localtype("bit"), rel, le, 0) < 0) /* workaround */
2103 : return NULL;
2104 2096 : t = exp_subtype(le);
2105 :
2106 2157 : if (!(exists_func = sql_bind_func(sql, "sys", exists ? "sql_exists" : "sql_not_exists", t, NULL, F_FUNC, true, true)))
2107 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "exist operator on type %s missing", t ? t->type->base.name : "unknown");
2108 2096 : res = exp_unop(sql->sa, le, exists_func);
2109 2096 : set_has_no_nil(res);
2110 2096 : return res;
2111 : }
2112 :
2113 : static sql_exp *
2114 1093 : rel_exists_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f)
2115 : {
2116 1093 : exp_kind ek = {type_value, card_exists, FALSE};
2117 1093 : sql_exp *le, *e;
2118 :
2119 1093 : le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
2120 1093 : if (!le)
2121 : return NULL;
2122 1092 : if (!(e = exp_exist(query, rel ? *rel : NULL, le, sc->token == SQL_EXISTS)))
2123 : return NULL;
2124 : /* only freevar should have CARD_AGGR */
2125 1092 : e->card = CARD_ATOM;
2126 1092 : return e;
2127 : }
2128 :
2129 : static sql_rel *
2130 1010 : rel_exists_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
2131 : {
2132 1010 : exp_kind ek = {type_value, card_exists, TRUE};
2133 1010 : mvc *sql = query->sql;
2134 1010 : sql_rel *sq = NULL;
2135 :
2136 1010 : if (is_psm_call(f) || is_sql_merge(f))
2137 3 : return sql_error(sql, 02, SQLSTATE(42000) "%s: subqueries not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
2138 1009 : if (rel) {
2139 1009 : query_processed(query);
2140 1009 : query_push_outer(query, rel, f);
2141 : }
2142 1009 : sq = rel_subquery(query, sc->data.sym, ek);
2143 1009 : if (rel)
2144 1009 : rel = query_pop_outer(query);
2145 1009 : assert(!is_sql_sel(f));
2146 1009 : if (sq) {
2147 1004 : sql_exp *e = exp_rel(sql, sq);
2148 1004 : if (!(e = exp_exist(query, rel, e, sc->token == SQL_EXISTS)))
2149 : return NULL;
2150 : /* only freevar should have CARD_AGGR */
2151 1004 : e->card = CARD_ATOM;
2152 1004 : rel = rel_select_add_exp(sql->sa, rel, e);
2153 1004 : return rel;
2154 : }
2155 : return NULL;
2156 : }
2157 :
2158 : static int
2159 8598 : is_project_true(sql_rel *r)
2160 : {
2161 8598 : if (r && !r->l && list_length(r->exps) == 1) {
2162 82 : sql_exp *e = r->exps->h->data;
2163 82 : if (exp_is_atom(e) && exp_is_true(e))
2164 : return 1;
2165 : }
2166 : return 0;
2167 : }
2168 :
2169 : static sql_exp *
2170 64474 : rel_in_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f)
2171 : {
2172 64474 : mvc *sql = query->sql;
2173 64474 : exp_kind ek = {type_value, card_column, TRUE};
2174 64474 : dlist *dl = sc->data.lval;
2175 64474 : symbol *lo = NULL;
2176 64474 : dnode *n = dl->h->next, *dn = NULL;
2177 64474 : sql_exp *le = NULL, *re, *e = NULL;
2178 64474 : list *ll = sa_list(sql->sa);
2179 64474 : int is_tuple = 0, add_select = 0;
2180 :
2181 : /* complex case */
2182 64474 : if (dl->h->type == type_list) { /* (a,b..) in (.. ) */
2183 4170 : dn = dl->h->data.lval->h;
2184 4170 : lo = dn->data.sym;
2185 4170 : dn = dn->next;
2186 : } else {
2187 60304 : lo = dl->h->data.sym;
2188 : }
2189 203898 : for( ; lo; lo = dn?dn->data.sym:NULL, dn = dn?dn->next:NULL ) {
2190 69716 : le = rel_value_exp(query, rel, lo, f|sql_farg, ek);
2191 69716 : if (!le)
2192 : return NULL;
2193 69712 : append(ll, le);
2194 : }
2195 64470 : if (list_length(ll) == 1) {
2196 60300 : le = ll->h->data;
2197 60300 : ek.card = card_set;
2198 : } else {
2199 4170 : le = exp_values(sql->sa, ll);
2200 4170 : exp_label(sql->sa, le, ++sql->label);
2201 4170 : ek.type = list_length(ll);
2202 4170 : is_tuple = list_length(ll);
2203 : }
2204 : /* list of values or subqueries */
2205 : /* 3 right hand side cases,
2206 : * 1 - value/tuple list of atoms
2207 : * 2 - list of scalar sub queries (needs check on 1 row/column per query)
2208 : * 3 - single tabular ie. multi column, multi row query
2209 : */
2210 64470 : if (n->type == type_list) {
2211 64470 : sql_exp *values;
2212 64470 : list *vals = sa_list(sql->sa);
2213 :
2214 64470 : n = dl->h->next;
2215 64470 : n = n->data.lval->h;
2216 :
2217 316348 : for (; n; n = n->next) {
2218 251911 : if (n->type == type_list) {
2219 3 : dnode *m = n->data.lval->h;
2220 3 : list *rl = sa_list(sql->sa);
2221 12 : for (; m; m = m->next) {
2222 6 : assert(m->type == type_symbol);
2223 6 : sql_exp *re = rel_value_exp(query, rel, m->data.sym, f|sql_farg, ek);
2224 6 : if (!re)
2225 : return NULL;
2226 6 : append(rl, re);
2227 : }
2228 3 : re = exp_values(sql->sa, rl);
2229 : } else {
2230 251908 : assert(n->type == type_symbol);
2231 251908 : re = rel_value_exp(query, rel, n->data.sym, f|sql_farg, ek);
2232 : }
2233 251911 : if (!re)
2234 : return NULL;
2235 251887 : if (is_tuple && (!exp_is_rel(re) && !is_values(re)))
2236 0 : return sql_error(sql, 02, SQLSTATE(42000) "Cannot match a tuple to a single value");
2237 8332 : if (is_tuple && exp_is_rel(re)) {
2238 4169 : sql_rel *r = exp_rel_get_rel(sql->sa, re);
2239 :
2240 4169 : if (!r)
2241 0 : return sql_error(sql, 02, SQLSTATE(42000) "Subquery missing");
2242 4169 : if (r->nrcols != ek.type)
2243 12 : return sql_error(sql, 02, SQLSTATE(42000) "Subquery has too %s columns", (r->nrcols < ek.type) ? "few" : "many");
2244 4160 : re = exp_rel_label(sql, re);
2245 247718 : } else if (exp_is_rel(re)) {
2246 8599 : sql_rel *r = exp_rel_get_rel(sql->sa, re);
2247 8599 : add_select = 1;
2248 8599 : if (rel && *rel && is_join((*rel)->op))
2249 4471 : set_dependent((*rel));
2250 8599 : if (is_project(r->op) && is_project_true(r->l) && list_length(r->exps) == 1)
2251 80 : re = r->exps->h->data;
2252 239119 : } else if (is_values(re) && is_tuple != list_length(exp_get_values(re))) {
2253 0 : return sql_error(sql, 02, SQLSTATE(42000) "Tuple sizes do not match");
2254 : }
2255 251878 : append(vals, re);
2256 : }
2257 :
2258 64437 : if (list_empty(vals))
2259 0 : return sql_error(sql, 02, SQLSTATE(42000) "The list of values for IN operator cannot be empty");
2260 :
2261 64437 : values = exp_values(sql->sa, vals);
2262 64437 : exp_label(sql->sa, values, ++sql->label);
2263 64437 : if (is_tuple) {
2264 4161 : if (!(values = exp_tuples_set_supertype(sql, exp_get_values(le), values)))
2265 : return NULL;
2266 4161 : if (!(le->f = tuples_check_types(sql, exp_get_values(le), values)))
2267 : return NULL;
2268 : } else { /* if it's not a tuple, enforce coercion on the type for every element on the list */
2269 60276 : sql_subtype super, *le_tpe = exp_subtype(le), *values_tpe = NULL;
2270 :
2271 307990 : for (node *m = vals->h; m; m = m->next) { /* first get values supertype */
2272 247714 : sql_exp *e = m->data;
2273 247714 : sql_subtype *tpe = exp_subtype(e);
2274 :
2275 247714 : if (values_tpe && tpe) {
2276 187435 : cmp_supertype(&super, values_tpe, tpe);
2277 187435 : *values_tpe = super;
2278 60279 : } else if (!values_tpe && tpe) {
2279 60272 : super = *tpe;
2280 60272 : values_tpe = &super;
2281 : }
2282 : }
2283 60276 : if (!le_tpe)
2284 2 : le_tpe = values_tpe;
2285 60276 : if (!values_tpe)
2286 4 : values_tpe = le_tpe;
2287 60276 : if (!le_tpe || !values_tpe)
2288 1 : return sql_error(sql, 01, SQLSTATE(42000) "For the IN operator, both sides must have a type defined");
2289 60275 : cmp_supertype(&super, values_tpe, le_tpe); /* compute supertype */
2290 :
2291 : /* on selection/join cases we can generate cmp expressions instead of anyequal for trivial cases */
2292 60275 : if ((is_sql_where(f) || is_sql_having(f)) && !is_sql_farg(f) && !exp_has_rel(le) && exps_are_atoms(vals)) {
2293 23837 : if (list_length(vals) == 1) { /* use cmp_equal instead of cmp_in for 1 expression */
2294 116 : sql_exp *first = vals->h->data;
2295 116 : if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &le, &first, 1, type_equal_no_any) < 0)
2296 0 : return NULL;
2297 141 : e = exp_compare(sql->sa, le, first, (sc->token == SQL_IN) ? cmp_equal : cmp_notequal);
2298 : } else { /* use cmp_in instead of anyequal for n simple expressions */
2299 120707 : for (node *n = vals->h ; n ; n = n->next)
2300 96986 : if ((n->data = exp_check_type(sql, &super, rel ? *rel : NULL, n->data, type_equal)) == NULL)
2301 : return NULL;
2302 23721 : if ((le = exp_check_type(sql, &super, rel ? *rel : NULL, le, type_equal)) == NULL)
2303 : return NULL;
2304 32405 : e = exp_in(sql->sa, le, vals, (sc->token == SQL_IN) ? cmp_in : cmp_notin);
2305 : }
2306 : }
2307 23837 : if (!e) { /* after computing supertype, check types for each IN value */
2308 187049 : for (node *n = vals->h ; n ; n = n->next)
2309 150611 : if ((n->data = exp_check_type(sql, &super, rel ? *rel : NULL, n->data, type_equal)) == NULL)
2310 : return NULL;
2311 36438 : values->tpe = *exp_subtype(vals->h->data);
2312 36438 : if (!(le = exp_check_type(sql, &super, rel ? *rel : NULL, le, type_equal)))
2313 : return NULL;
2314 : }
2315 : }
2316 60275 : if (!e) {
2317 40599 : if (add_select && rel && *rel && !is_project((*rel)->op) && !is_select((*rel)->op) && !is_base((*rel)->op))
2318 4470 : *rel = rel_select(sql->sa, *rel, NULL);
2319 40599 : if ((rel && *rel) || exp_has_rel(le) || exp_has_rel(values))
2320 35013 : e = exp_in_func(sql, le, values, (sc->token == SQL_IN), is_tuple);
2321 : else
2322 5586 : e = exp_in_aggr(sql, le, values, (sc->token == SQL_IN), is_tuple);
2323 : }
2324 : }
2325 : return e;
2326 : }
2327 :
2328 : static sql_rel *
2329 34030 : rel_in_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
2330 : {
2331 34030 : mvc *sql = query->sql;
2332 34030 : sql_exp *e = rel_in_value_exp(query, &rel, sc, f);
2333 :
2334 34030 : assert(!is_sql_sel(f));
2335 34030 : if (!e || !rel)
2336 : return NULL;
2337 :
2338 34006 : if (e->type == e_cmp) { /* it's a exp_in or cmp_equal of simple expressions, push down early on if possible */
2339 23835 : sql_exp *ls = e->l;
2340 23835 : bool rlist = (e->flag == cmp_in || e->flag == cmp_notin);
2341 23835 : unsigned int rcard = rlist ? exps_card(e->r) : exp_card(e->r);
2342 23835 : int r_is_atoms = rlist ? exps_are_atoms(e->r) : exp_is_atom(e->r);
2343 23835 : int r_has_freevar = rlist ? exps_have_freevar(sql, e->r) : exp_has_freevar(sql, e->r);
2344 :
2345 23835 : if (rcard <= CARD_ATOM && (r_is_atoms || r_has_freevar || exp_has_freevar(sql, ls))) {
2346 23835 : if ((exp_card(ls) == rcard) || rel->processed) /* bin compare op */
2347 5456 : return rel_select(sql->sa, rel, e);
2348 :
2349 18379 : return push_select_exp(sql, rel, e, ls, f);
2350 : } else { /* join */
2351 0 : sql_exp *rs = rlist ? exps_find_one_multi_exp(e->r) : e->r;
2352 0 : if (rs)
2353 0 : return push_join_exp(sql, rel, e, ls, rs, NULL, f);
2354 : }
2355 : }
2356 10171 : if (is_outerjoin(rel->op))
2357 13 : return rel_select(sql->sa, rel, e);
2358 10158 : return rel_select_add_exp(sql->sa, rel, e);
2359 : }
2360 :
2361 : static bool
2362 53573 : not_symbol_can_be_propagated(mvc *sql, symbol *sc)
2363 : {
2364 53573 : switch (sc->token) {
2365 : case SQL_IN:
2366 : case SQL_NOT_IN:
2367 : case SQL_EXISTS:
2368 : case SQL_NOT_EXISTS:
2369 : case SQL_LIKE:
2370 : case SQL_NOT_LIKE:
2371 : case SQL_BETWEEN:
2372 : case SQL_NOT_BETWEEN:
2373 : case SQL_IS_NULL:
2374 : case SQL_IS_NOT_NULL:
2375 : case SQL_NOT:
2376 : case SQL_COMPARE:
2377 : return true;
2378 6822 : case SQL_AND:
2379 : case SQL_OR: {
2380 6822 : symbol *lo = sc->data.lval->h->data.sym;
2381 6822 : symbol *ro = sc->data.lval->h->next->data.sym;
2382 6826 : return not_symbol_can_be_propagated(sql, lo) && not_symbol_can_be_propagated(sql, ro);
2383 : }
2384 37503 : default:
2385 37503 : return false;
2386 : }
2387 : }
2388 :
2389 : /* Warning, this function assumes the entire bison tree can be negated, so call it after 'not_symbol_can_be_propagated' */
2390 : static symbol *
2391 16065 : negate_symbol_tree(mvc *sql, symbol *sc)
2392 : {
2393 16065 : switch (sc->token) {
2394 1454 : case SQL_IN:
2395 1454 : sc->token = SQL_NOT_IN;
2396 1454 : break;
2397 22 : case SQL_NOT_IN:
2398 22 : sc->token = SQL_IN;
2399 22 : break;
2400 0 : case SQL_EXISTS:
2401 0 : sc->token = SQL_NOT_EXISTS;
2402 0 : break;
2403 0 : case SQL_NOT_EXISTS:
2404 0 : sc->token = SQL_EXISTS;
2405 0 : break;
2406 7 : case SQL_LIKE:
2407 7 : sc->token = SQL_NOT_LIKE;
2408 7 : break;
2409 0 : case SQL_NOT_LIKE:
2410 0 : sc->token = SQL_LIKE;
2411 0 : break;
2412 17 : case SQL_BETWEEN:
2413 17 : sc->token = SQL_NOT_BETWEEN;
2414 17 : break;
2415 11 : case SQL_NOT_BETWEEN:
2416 11 : sc->token = SQL_BETWEEN;
2417 11 : break;
2418 32 : case SQL_IS_NULL:
2419 32 : sc->token = SQL_IS_NOT_NULL;
2420 32 : break;
2421 15 : case SQL_IS_NOT_NULL:
2422 15 : sc->token = SQL_IS_NULL;
2423 15 : break;
2424 27 : case SQL_NOT: { /* nested NOTs eliminate each other */
2425 27 : if (sc->data.sym->token == SQL_ATOM) {
2426 5 : AtomNode *an = (AtomNode*) sc->data.sym;
2427 5 : sc = newAtomNode(sql->sa, an->a);
2428 22 : } else if (sc->data.sym->token == SQL_SELECT) {
2429 2 : SelectNode *sn = (SelectNode*) sc->data.sym;
2430 2 : sc = newSelectNode(sql->sa, sn->distinct, sn->selection, sn->into, sn->from, sn->where, sn->groupby, sn->having,
2431 : sn->orderby, sn->name, sn->limit, sn->offset, sn->sample, sn->seed, sn->window);
2432 : } else {
2433 20 : memmove(sc, sc->data.sym, sizeof(symbol));
2434 : }
2435 : } break;
2436 7662 : case SQL_COMPARE: {
2437 7662 : dnode *cmp_n = sc->data.lval->h;
2438 7662 : comp_type neg_cmp_type = negate_compare(compare_str2type(cmp_n->next->data.sval)); /* negate the comparator */
2439 7662 : if (cmp_n->next->next->next) {
2440 22 : switch(cmp_n->next->next->next->data.i_val)
2441 : {
2442 12 : case 0: /* negating ANY/ALL */
2443 12 : cmp_n->next->next->next->data.i_val = 1;
2444 12 : break;
2445 7 : case 1: /* negating ANY/ALL */
2446 7 : cmp_n->next->next->next->data.i_val = 0;
2447 7 : break;
2448 2 : case 2: /* negating IS [NOT] DINSTINCT FROM */
2449 2 : cmp_n->next->next->next->data.i_val = 3;
2450 2 : break;
2451 1 : case 3: /* negating IS [NOT] DINSTINCT FROM */
2452 1 : cmp_n->next->next->next->data.i_val = 2;
2453 1 : break;
2454 : }
2455 : }
2456 7662 : cmp_n->next->data.sval = sa_strdup(sql->sa, compare_func(neg_cmp_type, 0));
2457 7662 : } break;
2458 6818 : case SQL_AND:
2459 : case SQL_OR: {
2460 6818 : sc->data.lval->h->data.sym = negate_symbol_tree(sql, sc->data.lval->h->data.sym);
2461 6818 : sc->data.lval->h->next->data.sym= negate_symbol_tree(sql, sc->data.lval->h->next->data.sym);
2462 6818 : sc->token = sc->token == SQL_AND ? SQL_OR : SQL_AND;
2463 6818 : } break;
2464 : default:
2465 : break;
2466 : }
2467 16065 : return sc;
2468 : }
2469 :
2470 : static int
2471 3111 : exp_between_check_types(sql_subtype *res, sql_subtype *t1, sql_subtype *t2, sql_subtype *t3)
2472 : {
2473 3111 : bool type_found = false;
2474 3111 : sql_subtype super;
2475 :
2476 3111 : if (t1 && t2) {
2477 3105 : cmp_supertype(&super, t2, t1);
2478 3105 : type_found = true;
2479 6 : } else if (t1) {
2480 3 : super = *t1;
2481 3 : type_found = true;
2482 3 : } else if (t2) {
2483 1 : super = *t2;
2484 1 : type_found = true;
2485 : }
2486 3111 : if (t3) {
2487 3108 : if (type_found)
2488 3107 : cmp_supertype(&super, t3, &super);
2489 : else
2490 1 : super = *t3;
2491 : type_found = true;
2492 : }
2493 3 : if (!type_found)
2494 : return -1;
2495 3110 : *res = super;
2496 3110 : return 0;
2497 : }
2498 :
2499 : static bool
2500 119061 : exp_is_null_no_value_opt(sql_exp *e)
2501 : {
2502 119061 : if (!e)
2503 : return false;
2504 122986 : while (is_convert(e->type))
2505 3925 : e = e->l;
2506 238095 : return e->type == e_atom && e->l && atom_null(e->l);
2507 : }
2508 :
2509 : sql_exp *
2510 2670881 : rel_logical_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f, exp_kind ek)
2511 : {
2512 2670980 : mvc *sql = query->sql;
2513 :
2514 2670980 : if (!sc)
2515 : return NULL;
2516 :
2517 2670980 : if (mvc_highwater(sql))
2518 74 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2519 :
2520 2671518 : switch (sc->token) {
2521 52432 : case SQL_OR:
2522 : case SQL_AND:
2523 : {
2524 52432 : symbol *lo = sc->data.lval->h->data.sym;
2525 52432 : symbol *ro = sc->data.lval->h->next->data.sym;
2526 52432 : sql_exp *ls, *rs;
2527 :
2528 52432 : if (!(ls = rel_value_exp(query, rel, lo, f|sql_farg, ek)))
2529 : return NULL;
2530 52431 : if (!(rs = rel_value_exp(query, rel, ro, f|sql_farg, ek)))
2531 : return NULL;
2532 92644 : return rel_binop_(sql, rel ? *rel : NULL, ls, rs, "sys", sc->token == SQL_OR ? "or": "and", card_value, false);
2533 : }
2534 5 : case SQL_FILTER:
2535 : /* [ x,..] filter [ y,..] */
2536 : /* todo add anti, [ x,..] not filter [ y,...] */
2537 : /* no correlation */
2538 : {
2539 5 : dnode *ln = sc->data.lval->h->data.lval->h;
2540 5 : dnode *rn = sc->data.lval->h->next->next->data.lval->h;
2541 5 : dlist *filter_op = sc->data.lval->h->next->data.lval;
2542 5 : char *fname = qname_schema_object(filter_op);
2543 5 : char *sname = qname_schema(filter_op);
2544 5 : list *exps, *tl;
2545 5 : sql_subtype *obj_type = NULL;
2546 :
2547 5 : exps = sa_list(sql->sa);
2548 5 : tl = sa_list(sql->sa);
2549 15 : for (; ln; ln = ln->next) {
2550 5 : symbol *sym = ln->data.sym;
2551 :
2552 5 : sql_exp *e = rel_value_exp(query, rel, sym, f|sql_farg, ek);
2553 5 : if (!e)
2554 : return NULL;
2555 5 : if (!obj_type)
2556 5 : obj_type = exp_subtype(e);
2557 5 : list_append(exps, e);
2558 5 : append(tl, exp_subtype(e));
2559 : }
2560 13 : for (; rn; rn = rn->next) {
2561 10 : symbol *sym = rn->data.sym;
2562 :
2563 10 : sql_exp *e = rel_value_exp(query, rel, sym, f|sql_farg, ek);
2564 10 : if (!e)
2565 : return NULL;
2566 8 : list_append(exps, e);
2567 8 : append(tl, exp_subtype(e));
2568 : }
2569 : /* find the predicate filter function */
2570 3 : return _rel_nop(sql, sname, fname, tl, rel ? *rel : NULL, exps, ek);
2571 : }
2572 118778 : case SQL_COMPARE:
2573 : {
2574 118778 : dnode *n = sc->data.lval->h;
2575 118778 : symbol *lo = n->data.sym;
2576 118778 : symbol *ro = n->next->next->data.sym;
2577 118778 : char *compare_op = n->next->data.sval;
2578 118778 : int quantifier = 0, need_not = 0;
2579 118778 : sql_exp *rs = NULL, *ls;
2580 118778 : comp_type cmp_type = compare_str2type(compare_op);
2581 118778 : bool is_not_distinct_from = false;
2582 118778 : bool is_distinct_from = false;
2583 :
2584 : /*
2585 : * = ANY -> IN, <> ALL -> NOT( = ANY) -> NOT IN
2586 : * = ALL -> all(groupby(all, nil)), <> ANY -> NOT ( = ALL )
2587 : */
2588 118778 : if (n->next->next->next)
2589 257 : quantifier = n->next->next->next->data.i_val + 1;
2590 257 : assert(quantifier == 0 || quantifier == 1 || quantifier == 2 || quantifier == 3 || quantifier == 4);
2591 :
2592 : /* [NOT] DISTINCT FROM */
2593 118778 : if (quantifier == 3) {
2594 : is_not_distinct_from = true;
2595 : quantifier = 0;
2596 : }
2597 118764 : else if (quantifier == 4) {
2598 14 : is_distinct_from = true;
2599 14 : quantifier = 0;
2600 : }
2601 :
2602 118778 : if ((quantifier == 1 && cmp_type == cmp_equal) ||
2603 118712 : (quantifier == 2 && cmp_type == cmp_notequal)) {
2604 93 : dlist *dl = dlist_create(sql->sa);
2605 : /* map into IN/NOT IN */
2606 93 : sc->token = cmp_type==cmp_equal?SQL_IN:SQL_NOT_IN;
2607 93 : n->next->type = type_list;
2608 93 : n->next->data.lval = dl;
2609 93 : n->next->next->next = NULL; /* remove quantifier */
2610 93 : dl->h = n->next->next;
2611 93 : n->next->next = NULL; /* (remove comparison) moved righthand side */
2612 93 : return rel_logical_value_exp(query, rel, sc, f, ek);
2613 : }
2614 : /* <> ANY -> NOT (= ALL) */
2615 118685 : if (quantifier == 1 && cmp_type == cmp_notequal) {
2616 15 : need_not = 1;
2617 15 : quantifier = 2;
2618 15 : cmp_type = cmp_equal;
2619 15 : compare_op = "=";
2620 : }
2621 :
2622 118685 : ls = rel_value_exp(query, rel, lo, f|sql_farg, ek);
2623 118685 : if (!ls)
2624 : return NULL;
2625 118673 : if (quantifier)
2626 136 : ek.card = card_set;
2627 :
2628 118673 : rs = rel_value_exp(query, rel, ro, f|sql_farg, ek);
2629 118673 : if (!rs)
2630 : return NULL;
2631 :
2632 118663 : if (is_distinct_from || is_not_distinct_from) {
2633 28 : if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0)
2634 : return NULL;
2635 42 : sql_exp* e = exp_compare(sql->sa, ls, rs, is_not_distinct_from?cmp_equal:cmp_notequal);
2636 28 : set_semantics(e);
2637 28 : return e;
2638 : }
2639 :
2640 118635 : if (rs->type == e_atom)
2641 107182 : quantifier = 0;
2642 :
2643 118635 : if (!exp_is_rel(ls) && !exp_is_rel(rs) && ls->card < rs->card) {
2644 14 : sql_exp *swap = ls; /* has to swap parameters like in the rel_logical_exp case */
2645 14 : ls = rs;
2646 14 : rs = swap;
2647 14 : cmp_type = swap_compare(cmp_type);
2648 : }
2649 :
2650 118635 : if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0)
2651 : return NULL;
2652 118632 : if (exp_is_null_no_value_opt(ls) && exp_is_null_no_value_opt(rs))
2653 7 : return exp_atom(sql->sa, atom_general(sql->sa, sql_bind_localtype("bit"), NULL, 0));
2654 :
2655 118625 : return exp_compare_func(sql, ls, rs, compare_func(cmp_type, need_not), quantifier);
2656 : }
2657 : /* Set Member ship */
2658 30444 : case SQL_IN:
2659 : case SQL_NOT_IN:
2660 30444 : return rel_in_value_exp(query, rel, sc, f);
2661 1093 : case SQL_EXISTS:
2662 : case SQL_NOT_EXISTS:
2663 1093 : return rel_exists_value_exp(query, rel, sc, f);
2664 347 : case SQL_LIKE:
2665 : case SQL_NOT_LIKE:
2666 : {
2667 347 : symbol *lo = sc->data.lval->h->data.sym;
2668 347 : symbol *ro = sc->data.lval->h->next->data.sym;
2669 347 : int insensitive = sc->data.lval->h->next->next->data.i_val;
2670 347 : int anti = (sc->token == SQL_NOT_LIKE) != (sc->data.lval->h->next->next->next->data.i_val != 0);
2671 347 : sql_subtype *st = sql_bind_localtype("str");
2672 347 : sql_exp *le = rel_value_exp(query, rel, lo, f|sql_farg, ek), *re, *ee = NULL, *ie = exp_atom_bool(sql->sa, insensitive);
2673 :
2674 347 : if (!le)
2675 : return NULL;
2676 :
2677 347 : if (!exp_subtype(le))
2678 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameter not allowed on "
2679 : "left hand side of LIKE operator");
2680 :
2681 347 : lo = ro->data.lval->h->data.sym;
2682 : /* like uses a single string pattern */
2683 347 : ek.card = card_value;
2684 347 : re = rel_value_exp(query, rel, lo, f|sql_farg, ek);
2685 347 : if (!re)
2686 : return NULL;
2687 343 : if ((re = exp_check_type(sql, st, rel ? *rel : NULL, re, type_equal)) == NULL)
2688 0 : return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
2689 343 : if ((le = exp_check_type(sql, st, rel ? *rel : NULL, le, type_equal)) == NULL)
2690 0 : return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
2691 : /* Do we need to escape ? */
2692 343 : if (dlist_length(ro->data.lval) == 2) {
2693 63 : char *escape = ro->data.lval->h->next->data.sval;
2694 63 : ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, escape)));
2695 : } else {
2696 280 : ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, "")));
2697 : }
2698 573 : return rel_nop_(sql, rel ? *rel : NULL, le, re, ee, ie, "sys", anti ? "not_like" : "like", card_value);
2699 : }
2700 164 : case SQL_BETWEEN:
2701 : case SQL_NOT_BETWEEN:
2702 : {
2703 164 : symbol *lo = sc->data.lval->h->data.sym;
2704 164 : int symmetric = sc->data.lval->h->next->data.i_val;
2705 164 : symbol *ro1 = sc->data.lval->h->next->next->data.sym;
2706 164 : symbol *ro2 = sc->data.lval->h->next->next->next->data.sym;
2707 164 : sql_exp *le, *re1, *re2;
2708 164 : sql_subtype super;
2709 :
2710 164 : assert(sc->data.lval->h->next->type == type_int);
2711 :
2712 164 : if (!(le = rel_value_exp(query, rel, lo, f|sql_farg, ek)))
2713 : return NULL;
2714 163 : if (!(re1 = rel_value_exp(query, rel, ro1, f|sql_farg, ek)))
2715 : return NULL;
2716 160 : if (!(re2 = rel_value_exp(query, rel, ro2, f|sql_farg, ek)))
2717 : return NULL;
2718 :
2719 155 : if (exp_between_check_types(&super, exp_subtype(le), exp_subtype(re1), exp_subtype(re2)) < 0)
2720 0 : return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
2721 :
2722 155 : if ((le = exp_check_type(sql, &super, rel ? *rel:NULL, le, type_equal)) == NULL ||
2723 155 : (re1 = exp_check_type(sql, &super, rel ? *rel:NULL, re1, type_equal)) == NULL ||
2724 155 : (re2 = exp_check_type(sql, &super, rel ? *rel:NULL, re2, type_equal)) == NULL)
2725 0 : return NULL;
2726 :
2727 155 : le = exp_compare2(sql->sa, le, re1, re2, 3, symmetric);
2728 155 : if (sc->token == SQL_NOT_BETWEEN)
2729 56 : set_anti(le);
2730 : return le;
2731 : }
2732 15227 : case SQL_IS_NULL:
2733 : case SQL_IS_NOT_NULL:
2734 : /* is (NOT) NULL */
2735 : {
2736 15227 : sql_exp *le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
2737 :
2738 15227 : if (!le)
2739 : return NULL;
2740 19527 : le = rel_unop_(sql, rel ? *rel : NULL, le, "sys", sc->token == SQL_IS_NULL ? "isnull" : "isnotnull", card_value);
2741 15224 : if (!le)
2742 : return NULL;
2743 15224 : set_has_no_nil(le);
2744 15224 : return le;
2745 : }
2746 19251 : case SQL_NOT: {
2747 19251 : if (not_symbol_can_be_propagated(sql, sc->data.sym)) {
2748 99 : sc->data.sym = negate_symbol_tree(sql, sc->data.sym);
2749 99 : return rel_logical_value_exp(query, rel, sc->data.sym, f, ek);
2750 : }
2751 19152 : sql_exp *le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
2752 :
2753 19152 : if (!le)
2754 : return NULL;
2755 19151 : return rel_unop_(sql, rel ? *rel : NULL, le, "sys", "not", card_value);
2756 : }
2757 : case SQL_ATOM: {
2758 2412496 : AtomNode *an = (AtomNode *) sc;
2759 2412496 : assert(an && an->a);
2760 2412496 : return exp_atom(sql->sa, an->a);
2761 : }
2762 20761 : case SQL_IDENT:
2763 : case SQL_COLUMN:
2764 20761 : return rel_column_ref(query, rel, sc, f);
2765 201 : case SQL_UNION:
2766 : case SQL_EXCEPT:
2767 : case SQL_INTERSECT: {
2768 201 : sql_rel *sq;
2769 :
2770 201 : if (is_psm_call(f) || is_sql_merge(f))
2771 4 : return sql_error(sql, 02, SQLSTATE(42000) "%s: subqueries not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
2772 199 : if (rel && *rel)
2773 141 : query_push_outer(query, *rel, f);
2774 199 : sq = rel_setquery(query, sc);
2775 199 : if (rel && *rel) {
2776 141 : *rel = query_pop_outer(query);
2777 141 : if (is_sql_join(f) && is_groupby((*rel)->op)) {
2778 0 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
2779 141 : } else if (is_sql_where(f) && is_groupby((*rel)->op)) {
2780 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
2781 141 : } else if ((is_sql_update_set(f) || is_sql_psm(f)) && is_groupby((*rel)->op)) {
2782 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
2783 : }
2784 : }
2785 199 : if (!sq)
2786 : return NULL;
2787 197 : if (ek.type == type_value && ek.card <= card_set && is_project(sq->op) && list_length(sq->exps) > 1)
2788 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column");
2789 196 : if (ek.type == type_relation && is_project(sq->op) && list_length(sq->exps) != ek.type)
2790 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery has too %s columns", list_length(sq->exps) < ek.type ? "few" : "many");
2791 302 : if (ek.type == type_value && ek.card < card_set && sq->card >= CARD_AGGR && (is_sql_sel(f) | is_sql_having(f) | is_sql_farg(f) |
2792 106 : ( is_sql_where(f) && rel && (!*rel || is_basetable((*rel)->op) || is_simple_project((*rel)->op) || is_joinop((*rel)->op)))))
2793 106 : sq = rel_zero_or_one(sql, sq, ek);
2794 196 : return exp_rel(sql, sq);
2795 : }
2796 1 : case SQL_DEFAULT:
2797 1 : return sql_error(sql, 02, SQLSTATE(42000) "DEFAULT keyword not allowed outside insert and update statements");
2798 318 : default: {
2799 318 : sql_exp *le = rel_value_exp(query, rel, sc, f|sql_farg, ek);
2800 318 : sql_subtype bt;
2801 :
2802 318 : if (!le)
2803 : return NULL;
2804 316 : sql_find_subtype(&bt, "boolean", 0, 0);
2805 316 : if ((le = exp_check_type(sql, &bt, rel ? *rel : NULL, le, type_equal)) == NULL)
2806 : return NULL;
2807 316 : return rel_binop_(sql, rel ? *rel : NULL, le, exp_atom_bool(sql->sa, 1), "sys", "=", 0, true);
2808 : }
2809 : }
2810 : /* never reached, as all switch cases have a `return` */
2811 : }
2812 :
2813 : sql_rel *
2814 640697 : rel_logical_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
2815 : {
2816 640697 : mvc *sql = query->sql;
2817 640697 : exp_kind ek = {type_value, card_column, TRUE};
2818 :
2819 640697 : if (!sc)
2820 : return NULL;
2821 :
2822 640697 : if (mvc_highwater(sql))
2823 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2824 :
2825 640697 : switch (sc->token) {
2826 17675 : case SQL_OR:
2827 : {
2828 17675 : list *exps = NULL, *lexps = NULL, *rexps = NULL;
2829 17675 : symbol *lo = sc->data.lval->h->data.sym;
2830 17675 : symbol *ro = sc->data.lval->h->next->data.sym;
2831 17675 : sql_rel *lr, *rr;
2832 :
2833 17675 : if (!rel)
2834 : return NULL;
2835 :
2836 17675 : lr = rel;
2837 17675 : rr = rel_dup(lr);
2838 :
2839 17675 : if (is_outerjoin(rel->op) && !is_processed(rel)) {
2840 44 : exps = rel->exps;
2841 :
2842 44 : lr = rel_select_copy(sql->sa, lr, sa_list(sql->sa));
2843 44 : lr = rel_logical_exp(query, lr, lo, f | sql_or);
2844 44 : if (!lr)
2845 : return NULL;
2846 43 : query_processed(query);
2847 43 : rr = rel_select_copy(sql->sa, rr, sa_list(sql->sa));
2848 43 : rr = rel_logical_exp(query, rr, ro, f | sql_or);
2849 43 : if (!rr)
2850 : return NULL;
2851 42 : if (lr->l == rr->l) {
2852 42 : lexps = lr->exps;
2853 42 : lr = lr->l;
2854 42 : rexps = rr->exps;
2855 42 : rr = rr->l;
2856 : }
2857 42 : rel = NULL;
2858 : } else {
2859 17631 : lr = rel_logical_exp(query, lr, lo, f | sql_or);
2860 17631 : if (!lr)
2861 : return NULL;
2862 17629 : rr = rel_logical_exp(query, rr, ro, f | sql_or);
2863 : }
2864 :
2865 17671 : if (!lr || !rr)
2866 : return NULL;
2867 17671 : return rel_or(sql, rel, lr, rr, exps, lexps, rexps);
2868 : }
2869 196070 : case SQL_AND:
2870 : {
2871 196070 : symbol *lo = sc->data.lval->h->data.sym;
2872 196070 : symbol *ro = sc->data.lval->h->next->data.sym;
2873 196070 : rel = rel_logical_exp(query, rel, lo, f);
2874 196070 : if (!rel)
2875 : return NULL;
2876 196063 : return rel_logical_exp(query, rel, ro, f);
2877 : }
2878 60 : case SQL_FILTER:
2879 : /* [ x,..] filter [ y,..] */
2880 : /* todo add anti, [ x,..] NOT filter [ y,...] */
2881 : /* no correlation */
2882 : {
2883 60 : dnode *ln = sc->data.lval->h->data.lval->h;
2884 60 : dnode *rn = sc->data.lval->h->next->next->data.lval->h;
2885 60 : dlist *filter_op = sc->data.lval->h->next->data.lval;
2886 60 : char *fname = qname_schema_object(filter_op);
2887 60 : char *sname = qname_schema(filter_op);
2888 60 : list *l, *r;
2889 :
2890 60 : l = sa_list(sql->sa);
2891 60 : r = sa_list(sql->sa);
2892 180 : for (; ln; ln = ln->next) {
2893 60 : symbol *sym = ln->data.sym;
2894 :
2895 60 : sql_exp *e = rel_value_exp(query, &rel, sym, f|sql_farg, ek);
2896 60 : if (!e)
2897 : return NULL;
2898 60 : list_append(l, e);
2899 : }
2900 163 : for (; rn; rn = rn->next) {
2901 103 : symbol *sym = rn->data.sym;
2902 :
2903 103 : sql_exp *e = rel_value_exp(query, &rel, sym, f|sql_farg, ek);
2904 103 : if (!e)
2905 : return NULL;
2906 103 : list_append(r, e);
2907 : }
2908 60 : return rel_filter(sql, rel, l, r, sname, fname, 0, f);
2909 : }
2910 354931 : case SQL_COMPARE:
2911 : {
2912 354931 : dnode *n = sc->data.lval->h;
2913 354931 : symbol *lo = n->data.sym;
2914 354931 : symbol *ro = n->next->next->data.sym;
2915 354931 : char *compare_op = n->next->data.sval;
2916 354931 : int quantifier = 0;
2917 354931 : int is_semantics = 0;
2918 :
2919 354931 : if (n->next->next->next)
2920 131 : quantifier = n->next->next->next->data.i_val + 1;
2921 131 : assert(quantifier == 0 || quantifier == 1 || quantifier == 2 || quantifier == 3 || quantifier == 4);
2922 :
2923 354931 : if (quantifier >= 3) {
2924 10 : if (quantifier == 4)
2925 6 : compare_op = "<>";
2926 : quantifier = 0;
2927 : is_semantics = 1;
2928 : }
2929 354931 : return rel_compare(query, rel, sc, lo, ro, compare_op, f, ek, quantifier, is_semantics);
2930 : }
2931 : /* Set Member ship */
2932 34030 : case SQL_IN:
2933 : case SQL_NOT_IN:
2934 34030 : return rel_in_exp(query, rel, sc, f);
2935 1010 : case SQL_EXISTS:
2936 : case SQL_NOT_EXISTS:
2937 1010 : return rel_exists_exp(query, rel , sc, f);
2938 3562 : case SQL_LIKE:
2939 : case SQL_NOT_LIKE:
2940 : {
2941 3562 : symbol *lo = sc->data.lval->h->data.sym;
2942 3562 : symbol *ro = sc->data.lval->h->next->data.sym;
2943 3562 : int insensitive = sc->data.lval->h->next->next->data.i_val;
2944 3562 : int anti = (sc->token == SQL_NOT_LIKE) != (sc->data.lval->h->next->next->next->data.i_val != 0);
2945 3562 : sql_subtype *st = sql_bind_localtype("str");
2946 3562 : sql_exp *le = rel_value_exp(query, &rel, lo, f|sql_farg, ek), *re, *ee = NULL, *ie = exp_atom_bool(sql->sa, insensitive);
2947 :
2948 3562 : if (!le)
2949 : return NULL;
2950 :
2951 3560 : if (!exp_subtype(le))
2952 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameter not allowed on "
2953 : "left hand side of LIKE operator");
2954 :
2955 : /* Do we need to escape ? */
2956 3560 : if (dlist_length(ro->data.lval) == 2) {
2957 82 : char *escape = ro->data.lval->h->next->data.sval;
2958 82 : ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, escape)));
2959 : } else {
2960 3478 : ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, "")));
2961 : }
2962 3560 : ro = ro->data.lval->h->data.sym;
2963 3560 : re = rel_value_exp(query, &rel, ro, f|sql_farg, ek);
2964 3560 : if (!re)
2965 : return NULL;
2966 3559 : if ((re = exp_check_type(sql, st, rel, re, type_equal)) == NULL)
2967 0 : return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
2968 3559 : if ((le = exp_check_type(sql, st, rel, le, type_equal)) == NULL)
2969 0 : return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
2970 3559 : return rel_filter_exp_(sql, rel, le, re, ee, ie, "like", anti, f);
2971 : }
2972 2960 : case SQL_BETWEEN:
2973 : case SQL_NOT_BETWEEN:
2974 : {
2975 2960 : symbol *lo = sc->data.lval->h->data.sym;
2976 2960 : int symmetric = sc->data.lval->h->next->data.i_val;
2977 2960 : symbol *ro1 = sc->data.lval->h->next->next->data.sym;
2978 2960 : symbol *ro2 = sc->data.lval->h->next->next->next->data.sym;
2979 2960 : sql_exp *le, *re1, *re2;
2980 2960 : sql_subtype super;
2981 :
2982 2960 : assert(sc->data.lval->h->next->type == type_int);
2983 :
2984 2960 : if (!(le = rel_value_exp(query, &rel, lo, f|sql_farg, ek)))
2985 : return NULL;
2986 2958 : if (!(re1 = rel_value_exp(query, &rel, ro1, f|sql_farg, ek)))
2987 : return NULL;
2988 2956 : if (!(re2 = rel_value_exp(query, &rel, ro2, f|sql_farg, ek)))
2989 : return NULL;
2990 :
2991 2956 : if (exp_between_check_types(&super, exp_subtype(le), exp_subtype(re1), exp_subtype(re2)) < 0)
2992 1 : return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
2993 :
2994 2955 : if ((le = exp_check_type(sql, &super, rel, le, type_equal)) == NULL ||
2995 2955 : (re1 = exp_check_type(sql, &super, rel, re1, type_equal)) == NULL ||
2996 2955 : (re2 = exp_check_type(sql, &super, rel, re2, type_equal)) == NULL)
2997 1 : return NULL;
2998 :
2999 2954 : return rel_compare_exp_(query, rel, le, re1, re2, 3, sc->token == SQL_NOT_BETWEEN ? 1 : 0, 0, f, symmetric, 0);
3000 : }
3001 7926 : case SQL_IS_NULL:
3002 : case SQL_IS_NOT_NULL:
3003 : /* is (NOT) NULL */
3004 : {
3005 7926 : sql_exp *le = rel_value_exp(query, &rel, sc->data.sym, f|sql_farg, ek);
3006 7926 : sql_subtype *t;
3007 :
3008 7926 : if (!le)
3009 : return NULL;
3010 7922 : if (!(t = exp_subtype(le)))
3011 1 : return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for IS%s NULL operator", sc->token == SQL_IS_NOT_NULL ? " NOT" : "");
3012 7921 : le = exp_compare(sql->sa, le, exp_atom(sql->sa, atom_general(sql->sa, t, NULL, 0)), cmp_equal);
3013 7921 : if (sc->token == SQL_IS_NOT_NULL)
3014 2602 : set_anti(le);
3015 7921 : set_has_no_nil(le);
3016 7921 : set_semantics(le);
3017 7921 : return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
3018 : }
3019 20681 : case SQL_NOT: {
3020 20681 : if (not_symbol_can_be_propagated(sql, sc->data.sym)) {
3021 2330 : sc->data.sym = negate_symbol_tree(sql, sc->data.sym);
3022 2330 : return rel_logical_exp(query, rel, sc->data.sym, f);
3023 : }
3024 18351 : sql_exp *le = rel_value_exp(query, &rel, sc->data.sym, f|sql_farg, ek);
3025 18351 : sql_subtype bt;
3026 :
3027 18351 : sql_find_subtype(&bt, "boolean", 0, 0);
3028 18351 : if (!le || !(le = exp_check_type(sql, &bt, rel, le, type_equal)))
3029 1 : return NULL;
3030 18350 : le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 0), cmp_equal);
3031 18350 : return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
3032 : }
3033 628 : case SQL_ATOM: {
3034 : /* TRUE or FALSE */
3035 628 : sql_rel *or = rel;
3036 628 : AtomNode *an = (AtomNode *) sc;
3037 628 : sql_exp *e = exp_atom(sql->sa, an->a);
3038 :
3039 628 : if (e) {
3040 628 : sql_subtype bt;
3041 :
3042 628 : sql_find_subtype(&bt, "boolean", 0, 0);
3043 628 : e = exp_check_type(sql, &bt, rel, e, type_equal);
3044 : }
3045 628 : if (!e || or != rel)
3046 2 : return NULL;
3047 626 : e = exp_compare(sql->sa, e, exp_atom_bool(sql->sa, 1), cmp_equal);
3048 626 : return rel_select_push_compare_exp_down(sql, rel, e, e->l, e->r, NULL, f);
3049 : }
3050 710 : case SQL_IDENT:
3051 : case SQL_COLUMN: {
3052 710 : sql_rel *or = rel;
3053 710 : sql_exp *e = rel_column_ref(query, &rel, sc, f);
3054 :
3055 710 : if (e) {
3056 707 : sql_subtype bt;
3057 :
3058 707 : sql_find_subtype(&bt, "boolean", 0, 0);
3059 707 : e = exp_check_type(sql, &bt, rel, e, type_equal);
3060 : }
3061 707 : if (!e || or != rel)
3062 3 : return NULL;
3063 707 : e = exp_compare(sql->sa, e, exp_atom_bool(sql->sa, 1), cmp_equal);
3064 707 : return rel_select_push_compare_exp_down(sql, rel, e, e->l, e->r, NULL, f);
3065 : }
3066 12 : case SQL_UNION:
3067 : case SQL_EXCEPT:
3068 : case SQL_INTERSECT: {
3069 12 : sql_rel *sq;
3070 :
3071 12 : if (is_psm_call(f) || is_sql_merge(f))
3072 3 : return sql_error(sql, 02, SQLSTATE(42000) "%s: set operations not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
3073 11 : if (rel)
3074 11 : query_push_outer(query, rel, f);
3075 11 : sq = rel_setquery(query, sc);
3076 11 : if (rel) {
3077 11 : rel = query_pop_outer(query);
3078 11 : if (is_sql_join(f) && is_groupby(rel->op)) {
3079 0 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
3080 11 : } else if (is_sql_where(f) && is_groupby(rel->op)) {
3081 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
3082 11 : } else if ((is_sql_update_set(f) || is_sql_psm(f)) && is_groupby(rel->op)) {
3083 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
3084 : }
3085 : }
3086 11 : if (!sq)
3087 : return NULL;
3088 11 : assert(ek.type == type_value); /* I don't expect IN tuple matching calls to land here */
3089 11 : if (is_sql_where(f) && is_groupby(rel->op))
3090 0 : assert(0);
3091 11 : if (ek.card <= card_set && is_project(sq->op) && list_length(sq->exps) > 1)
3092 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column");
3093 10 : if (!rel)
3094 : return sq;
3095 10 : sq = rel_zero_or_one(sql, sq, ek);
3096 10 : if (is_sql_where(f) || is_sql_having(f)) {
3097 10 : sql_exp *le = exp_rel(sql, sq);
3098 10 : sql_subtype bt;
3099 :
3100 10 : sql_find_subtype(&bt, "boolean", 0, 0);
3101 10 : le = exp_check_type(sql, &bt, rel, le, type_equal);
3102 10 : if (!le)
3103 : return NULL;
3104 10 : le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 1), cmp_equal);
3105 10 : return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
3106 : } else {
3107 0 : sq = rel_crossproduct(sql->sa, rel, sq, (f==sql_sel || is_single(sq))?op_left:op_join);
3108 0 : set_processed(sq);
3109 : }
3110 0 : return sq;
3111 : }
3112 0 : case SQL_DEFAULT:
3113 0 : return sql_error(sql, 02, SQLSTATE(42000) "DEFAULT keyword not allowed outside insert and update statements");
3114 442 : default: {
3115 442 : sql_exp *le = rel_value_exp(query, &rel, sc, f|sql_farg, ek);
3116 442 : sql_subtype bt;
3117 :
3118 442 : if (!le)
3119 : return NULL;
3120 417 : if (le && (!is_compare(le->type) || le->flag > cmp_filter)) {
3121 288 : sql_find_subtype(&bt, "boolean", 0, 0);
3122 288 : if (!(le = exp_check_type(sql, &bt, rel, le, type_equal)))
3123 : return NULL;
3124 288 : le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 1), cmp_equal);
3125 : }
3126 417 : if (le->flag == cmp_filter)
3127 128 : return rel_select_push_filter_exp_down(sql, rel, le, le->l, le->r, f);
3128 : else
3129 289 : return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, le->f, f);
3130 : }
3131 : }
3132 : /* never reached, as all switch cases have a `return` */
3133 : }
3134 :
3135 : static sql_exp * _rel_aggr(sql_query *query, sql_rel **rel, int distinct, char *sname, char *aname, dnode *arguments, int f);
3136 : static sql_exp *rel_aggr(sql_query *query, sql_rel **rel, symbol *se, int f);
3137 :
3138 : static sql_exp *
3139 1868 : rel_op(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek )
3140 : {
3141 1868 : mvc *sql = query->sql;
3142 1868 : dnode *l = se->data.lval->h;
3143 1868 : char *fname = qname_schema_object(l->data.lval);
3144 1868 : char *sname = qname_schema(l->data.lval);
3145 :
3146 1868 : if (find_func(sql, sname, fname, 0, F_AGGR, false, NULL, NULL))
3147 0 : return _rel_aggr(query, rel, 0, sname, fname, NULL, f);
3148 1868 : sql->session->status = 0; /* if the function was not found clean the error */
3149 1868 : sql->errstr[0] = '\0';
3150 1868 : return rel_op_(sql, sname, fname, ek);
3151 : }
3152 :
3153 : sql_exp *
3154 95391 : rel_unop_(mvc *sql, sql_rel *rel, sql_exp *e, char *sname, char *fname, int card)
3155 : {
3156 95391 : bool found = false;
3157 95391 : sql_subtype *t = exp_subtype(e);
3158 95391 : sql_ftype type = (card == card_loader)?F_LOADER:((card == card_none)?F_PROC:
3159 : ((card == card_relation)?F_UNION:F_FUNC));
3160 :
3161 95391 : sql_subfunc *f = bind_func(sql, sname, fname, t, NULL, 1, type, false, &found, false);
3162 95391 : if (f && !f->func->vararg) {
3163 95319 : sql_arg *a = f->func->ops->h->data;
3164 95319 : t = &a->type;
3165 : }
3166 95391 : if (f && t && type_has_tz(t) && f->func->fix_scale == SCALE_FIX) {
3167 : /* set timezone (using msec (.3)) */
3168 0 : sql_subtype *intsec = sql_bind_subtype(sql->sa, "sec_interval", 10 /*hour to second */, 3);
3169 0 : atom *a = atom_int(sql->sa, intsec, sql->timezone);
3170 0 : sql_exp *tz = exp_atom(sql->sa, a);
3171 :
3172 0 : e = rel_binop_(sql, rel, e, tz, "sys", "sql_add", card, true);
3173 0 : if (!e)
3174 : return NULL;
3175 : }
3176 95369 : if (f) {
3177 95320 : if (check_card(card, f)) {
3178 95320 : list *args = list_append(sa_list(sql->sa), e);
3179 95320 : if (!f->func->vararg)
3180 190638 : args = check_arguments_and_find_largest_any_type(sql, rel, args, f, card == card_relation && e->card > CARD_ATOM, false);
3181 95320 : if (args)
3182 95320 : return exp_op(sql->sa, args, f);
3183 : }
3184 0 : found = false; /* reset found */
3185 0 : f = NULL;
3186 : }
3187 : /* reset error */
3188 71 : sql->session->status = 0;
3189 71 : sql->errstr[0] = '\0';
3190 212 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s unary operator %s%s%s'%s'(%s)",
3191 141 : found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname, t ? t->type->base.name : "?");
3192 : }
3193 :
3194 : static sql_exp *
3195 77815 : rel_unop(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
3196 : {
3197 77815 : mvc *sql = query->sql;
3198 77815 : dnode *l = se->data.lval->h;
3199 77815 : char *fname = qname_schema_object(l->data.lval);
3200 77815 : char *sname = qname_schema(l->data.lval);
3201 77815 : exp_kind iek = {type_value, card_column, FALSE};
3202 77815 : sql_exp *e = NULL;
3203 :
3204 77815 : if (find_func(sql, sname, fname, 1, F_AGGR, false, NULL, NULL))
3205 17579 : return rel_aggr(query, rel, se, f);
3206 :
3207 60236 : sql->session->status = 0; /* if the function was not found clean the error */
3208 60236 : sql->errstr[0] = '\0';
3209 60236 : if (!(e = rel_value_exp(query, rel, l->next->next->data.sym, f|sql_farg, iek)))
3210 : return NULL;
3211 60222 : return rel_unop_(sql, rel ? *rel : NULL, e, sname, fname, ek.card);
3212 : }
3213 :
3214 : sql_exp *
3215 534772 : rel_binop_(mvc *sql, sql_rel *rel, sql_exp *l, sql_exp *r, char *sname, char *fname, int card, bool exact)
3216 : {
3217 534772 : sql_subtype *t1 = exp_subtype(l), *t2 = exp_subtype(r);
3218 534772 : sql_ftype type = (card == card_loader)?F_LOADER:((card == card_none)?F_PROC:((card == card_relation)?F_UNION:F_FUNC));
3219 534772 : bool found = false;
3220 :
3221 534772 : if (card == card_loader)
3222 0 : card = card_none;
3223 :
3224 534772 : if (is_commutative(sname, fname) && l->card < r->card) { /* move constants to the right if possible */
3225 : sql_subtype *tmp = t1;
3226 534772 : t1 = t2;
3227 534772 : t2 = tmp;
3228 : sql_exp *res = l;
3229 534772 : l = r;
3230 534772 : r = res;
3231 : }
3232 : /* swap complex types (intervals) to left side of +, * */
3233 534772 : if (t1 && t2 && is_commutative(sname, fname)) {
3234 123302 : if ((EC_INTERVAL(t1->type->eclass) && EC_TEMP(t2->type->eclass)) ||
3235 123300 : ((!EC_TEMP(t1->type->eclass) && !EC_INTERVAL(t1->type->eclass)) && EC_INTERVAL(t2->type->eclass))) {
3236 : sql_subtype *tmp = t1;
3237 534772 : t1 = t2;
3238 534772 : t2 = tmp;
3239 : sql_exp *res = l;
3240 534772 : l = r;
3241 534772 : r = res;
3242 : }
3243 : }
3244 :
3245 534772 : sql_subfunc *f = bind_func(sql, sname, fname, t1, t2, 2, type, false, &found, exact);
3246 534772 : if (f && check_card(card,f)) {
3247 534609 : t1 = exp_subtype(l);
3248 534609 : t2 = exp_subtype(r);
3249 534609 : list *args = list_append(list_append(sa_list(sql->sa), l), r);
3250 534609 : if (!f->func->vararg)
3251 534608 : args = check_arguments_and_find_largest_any_type(sql, rel, args, f, 0, false);
3252 534609 : if (args)
3253 534607 : return exp_op(sql->sa, args, f);
3254 : return NULL;
3255 : }
3256 :
3257 163 : if (!exp_subtype(l) || !exp_subtype(r))
3258 0 : return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
3259 163 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s binary operator %s%s%s'%s'(%s,%s)",
3260 163 : found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname,
3261 163 : exp_subtype(l)->type->base.name, exp_subtype(r)->type->base.name);
3262 : }
3263 :
3264 : static sql_exp *
3265 382599 : rel_binop(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
3266 : {
3267 382599 : mvc *sql = query->sql;
3268 382599 : dnode *dl = se->data.lval->h;
3269 382599 : sql_exp *l, *r;
3270 382599 : char *fname = qname_schema_object(dl->data.lval);
3271 382599 : char *sname = qname_schema(dl->data.lval);
3272 382599 : exp_kind iek = {type_value, card_column, FALSE};
3273 :
3274 382599 : if (find_func(sql, sname, fname, 2, F_AGGR, false, NULL, NULL))
3275 4287 : return rel_aggr(query, rel, se, f);
3276 :
3277 378312 : sql->session->status = 0; /* if the function was not found clean the error */
3278 378312 : sql->errstr[0] = '\0';
3279 378312 : if (!(l = rel_value_exp(query, rel, dl->next->next->data.sym, f|sql_farg, iek)))
3280 : return NULL;
3281 378283 : if (!(r = rel_value_exp(query, rel, dl->next->next->next->data.sym, f|sql_farg, iek)))
3282 : return NULL;
3283 378244 : return rel_binop_(sql, rel ? *rel : NULL, l, r, sname, fname, ek.card, false);
3284 : }
3285 :
3286 : sql_exp *
3287 533 : rel_nop_(mvc *sql, sql_rel *rel, sql_exp *a1, sql_exp *a2, sql_exp *a3, sql_exp *a4, char *sname, char *fname, int card)
3288 : {
3289 533 : list *tl = sa_list(sql->sa);
3290 533 : sql_subfunc *f = NULL;
3291 533 : sql_ftype type = (card == card_none)?F_PROC:((card == card_relation)?F_UNION:F_FUNC);
3292 :
3293 : /* rel_nop_ should only be called for functions available to everyone, ie defined at sql_types! */
3294 533 : (void) rel;
3295 533 : append(tl, exp_subtype(a1));
3296 533 : append(tl, exp_subtype(a2));
3297 533 : append(tl, exp_subtype(a3));
3298 533 : if (a4)
3299 371 : append(tl, exp_subtype(a4));
3300 :
3301 533 : if (!(f = bind_func_(sql, sname, fname, tl, type, false, NULL, true)))
3302 : return NULL;
3303 533 : if (!a4)
3304 162 : return exp_op3(sql->sa, a1,a2,a3,f);
3305 371 : return exp_op4(sql->sa, a1,a2,a3,a4,f);
3306 : }
3307 :
3308 : static sql_func *
3309 3 : inplace_func(mvc *sql)
3310 : {
3311 3 : sql_func *f = SA_NEW(sql->sa, sql_func);
3312 :
3313 3 : *f = (sql_func) {
3314 : .mod = "",
3315 : .imp = "",
3316 : .type = F_PROC,
3317 : .lang = FUNC_LANG_INT,
3318 : .query = NULL,
3319 3 : .ops = sql->params,
3320 : .res = NULL,
3321 : };
3322 3 : base_init(sql->sa, &f->base, 0, true, NULL);
3323 3 : f->base.new = 1;
3324 3 : f->base.id = -1;
3325 3 : f->base.name = "-1";
3326 3 : f->instantiated = TRUE;
3327 3 : return f;
3328 : }
3329 :
3330 : static list *
3331 3 : reorder_args(mvc *sql, list *exps, list *names, list *params)
3332 : {
3333 3 : list *nexps = sa_list(sql->sa);
3334 8 : for(node *n = params->h; n; n = n->next) {
3335 5 : sql_arg *a = n->data;
3336 5 : int found =0;
3337 7 : for(node *m = names->h, *o = exps->h; m && o; m = m->next, o = o->next) {
3338 7 : if (strcmp(m->data, a->name) == 0) {
3339 5 : append(nexps, o->data);
3340 5 : found = 1;
3341 5 : break;
3342 : }
3343 : }
3344 5 : if (!found)
3345 : return NULL;
3346 : }
3347 : return nexps;
3348 : }
3349 :
3350 : static sql_exp *
3351 86848 : rel_nop(sql_query *query, sql_rel **rel, symbol *se, int fs, exp_kind ek)
3352 : {
3353 86848 : mvc *sql = query->sql;
3354 86848 : int nr_args = 0, err = 0;
3355 86848 : dnode *l = se->data.lval->h;
3356 86848 : dnode *ops = l->next->next->data.lval?l->next->next->data.lval->h:NULL;
3357 86848 : list *exps = sa_list(sql->sa), *tl = sa_list(sql->sa);
3358 86848 : exp_kind iek = {type_value, card_column, FALSE};
3359 86848 : char buf[ERRSIZE];
3360 86848 : int split = (l->type == type_int && l->data.i_val == -1);
3361 86848 : list *names = NULL;
3362 :
3363 3 : if (split)
3364 3 : names = sa_list(sql->sa);
3365 357164 : for (; ops; ops = ops->next, nr_args++) {
3366 270316 : if (!err) { /* we need the nr_args count at the end, but if an error is found, stop calling rel_value_exp */
3367 270294 : sql_exp *e = rel_value_exp(query, rel, ops->data.sym, fs|sql_farg, iek);
3368 270294 : if (!e) {
3369 6 : err = sql->session->status;
3370 6 : strcpy(buf, sql->errstr);
3371 6 : continue;
3372 : }
3373 270288 : if (split) {
3374 5 : ops = ops->next;
3375 5 : append(names, ops->data.sval);
3376 : }
3377 270288 : append(exps, e);
3378 270288 : append(tl, exp_subtype(e));
3379 : }
3380 : }
3381 86848 : if (l->type == type_int) {
3382 : /* exec nr (ops)*/
3383 5909 : int nr = l->data.i_val;
3384 5909 : cq *q = NULL;
3385 :
3386 5909 : if (err)
3387 : return NULL;
3388 5908 : if (nr == -1 || (q = qc_find(sql->qc, nr))) {
3389 5906 : list *nexps = new_exp_list(sql->sa);
3390 5906 : sql_func *f = q?q->f:inplace_func(sql);
3391 5906 : list *ops = q?f->ops:sql->params;
3392 :
3393 5906 : tl = sa_list(sql->sa);
3394 5906 : if (list_length(ops) != list_length(exps))
3395 3 : return sql_error(sql, 02, SQLSTATE(42000) "EXEC called with wrong number of arguments: expected %d, got %d", list_length(ops), list_length(exps));
3396 5903 : if (split) {
3397 3 : exps = reorder_args(sql, exps, names, ops);
3398 3 : if (!exps)
3399 0 : return sql_error(sql, 02, SQLSTATE(42000) "EXEC called with wrong arguments");
3400 : }
3401 5903 : if (exps->h && ops) {
3402 21927 : for (node *n = exps->h, *m = ops->h; n && m; n = n->next, m = m->next) {
3403 16115 : sql_arg *a = m->data;
3404 16115 : sql_exp *e = n->data;
3405 16115 : sql_subtype *ntp = &a->type;
3406 :
3407 16115 : if (ntp && ntp->type)
3408 16115 : e = exp_check_type(sql, ntp, NULL, e, type_equal);
3409 : else
3410 0 : a->type = *exp_subtype(e);
3411 16115 : if (!e) {
3412 1 : err = sql->session->status;
3413 1 : strcpy(buf, sql->errstr);
3414 1 : break;
3415 : }
3416 16114 : append(nexps, e);
3417 16114 : append(tl, exp_subtype(e));
3418 : }
3419 : }
3420 :
3421 5903 : if (err)
3422 : return NULL;
3423 5902 : if (q)
3424 5899 : sql->type = q->type;
3425 5992 : return exp_op(sql->sa, list_empty(nexps) ? NULL : nexps, sql_dup_subfunc(sql->sa, f, tl, NULL));
3426 : } else {
3427 2 : return sql_error(sql, 02, SQLSTATE(42000) "EXEC: PREPARED Statement missing '%d'", nr);
3428 : }
3429 : }
3430 80939 : char *fname = qname_schema_object(l->data.lval);
3431 80939 : char *sname = qname_schema(l->data.lval);
3432 :
3433 80939 : if (!sname && strcmp(fname, "field") == 0) { /* map into join */
3434 2 : if (err)
3435 2 : return NULL;
3436 1 : if (list_length(exps) < 2)
3437 1 : return sql_error(sql, 02, SQLSTATE(42000) "Field function called with not enough arguments");
3438 0 : sql_exp *le = exps->h->data;
3439 0 : set_freevar(le, 1);
3440 0 : list_remove_data(exps, NULL, le);
3441 0 : sql_exp *re = exp_values(sql->sa, exps);
3442 0 : exp_label(sql->sa, re, ++sql->label);
3443 0 : sql_rel *r = rel_project(sql->sa, NULL, append(sa_list(sql->sa), re));
3444 0 : sql_exp *id = NULL;
3445 0 : rel_add_identity(sql, r, &id);
3446 0 : re = exp_ref(sql, re);
3447 0 : id = exp_ref(sql, id);
3448 0 : if (r) {
3449 0 : r->nrcols = list_length(exps);
3450 0 : sql_exp *e = exp_compare(sql->sa, le, re, cmp_equal);
3451 0 : r = rel_select(sql->sa, r, e);
3452 0 : r = rel_project(sql->sa, r, append(sa_list(sql->sa), exp_convert(sql, id, exp_subtype(id), sql_bind_localtype("int"))));
3453 0 : re = exp_rel(sql, r);
3454 0 : return re;
3455 : }
3456 : }
3457 : /* first try aggregate */
3458 80937 : if (find_func(sql, sname, fname, nr_args, F_AGGR, false, NULL, NULL)) { /* We have to pass the arguments properly, so skip call to rel_aggr */
3459 : /* reset error */
3460 2 : sql->session->status = 0;
3461 2 : sql->errstr[0] = '\0';
3462 2 : return _rel_aggr(query, rel, l->next->data.i_val, sname, fname, l->next->next->data.lval->h, fs);
3463 : }
3464 80935 : if (err) {
3465 2 : sql->session->status = err;
3466 2 : strcpy(sql->errstr, buf);
3467 2 : return NULL;
3468 : }
3469 80933 : sql->session->status = 0; /* if the function was not found clean the error */
3470 80933 : sql->errstr[0] = '\0';
3471 80933 : return _rel_nop(sql, sname, fname, tl, rel ? *rel : NULL, exps, ek);
3472 : }
3473 :
3474 : typedef struct aggr_input {
3475 : sql_query *query;
3476 : int groupby;
3477 : char *err;
3478 : } aggr_input;
3479 :
3480 : static sql_exp *
3481 372 : exp_valid(visitor *v, sql_rel *rel, sql_exp *e, int depth)
3482 : {
3483 372 : aggr_input *ai = v->data;
3484 372 : (void)rel; (void)depth;
3485 :
3486 372 : int vf = is_freevar(e);
3487 372 : if (!v->changes && vf && vf < ai->groupby) { /* check need with outer query */
3488 14 : sql_rel *sq = query_fetch_outer(ai->query, vf-1);
3489 :
3490 : /* problem freevar have cardinality CARD_ATOM */
3491 14 : if (sq->card <= CARD_AGGR && exp_card(e) != CARD_AGGR && is_alias(e->type)) {
3492 4 : if (!exps_bind_column(sq->exps, e->l, e->r, NULL, 0)) {
3493 1 : v->changes = 1;
3494 1 : ai->err = SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query";
3495 : }
3496 : }
3497 358 : } else if (!v->changes && vf && vf == ai->groupby) { /* check if input is already aggregated */
3498 279 : sql_rel *sq = query_fetch_outer(ai->query, vf-1);
3499 279 : sql_exp *a = NULL;
3500 :
3501 279 : if (sq->card <= CARD_AGGR && is_alias(e->type)) {
3502 187 : if ((a = exps_bind_column(sq->exps, e->l, e->r, NULL, 0)) && is_aggr(a->type)) { /* aggregate */
3503 9 : v->changes = 1;
3504 9 : ai->err = SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested";
3505 : }
3506 : }
3507 : }
3508 372 : return e;
3509 : }
3510 :
3511 : static char *
3512 272 : exps_valid(sql_query *query, list *exps, int groupby)
3513 : {
3514 272 : aggr_input ai = { .query = query, .groupby = groupby };
3515 272 : visitor v = { .sql = query->sql, .data = &ai };
3516 :
3517 272 : exps_exp_visitor_topdown(&v, NULL, exps, 0, &exp_valid, true);
3518 272 : if (v.changes)
3519 10 : return ai.err;
3520 : return NULL;
3521 : }
3522 :
3523 : static list * rel_order_by(sql_query *query, sql_rel **R, symbol *orderby, int needs_distinct, int f);
3524 :
3525 : static sql_exp *
3526 45735 : _rel_aggr(sql_query *query, sql_rel **rel, int distinct, char *sname, char *aname, dnode *args, int f)
3527 : {
3528 45735 : mvc *sql = query->sql;
3529 45735 : exp_kind ek = {type_value, card_column, FALSE};
3530 45735 : sql_subfunc *a = NULL;
3531 45735 : int no_nil = 0, group = 0, all_aggr = query_has_outer(query), i;
3532 45735 : unsigned int all_freevar = 0;
3533 45735 : sql_rel *groupby = rel ? *rel : NULL, *sel = NULL, *gr, *og = NULL, *res = groupby;
3534 45735 : sql_rel *subquery = NULL;
3535 45735 : list *exps = NULL, *ungrouped_cols = NULL;
3536 45735 : bool is_grouping = !strcmp(aname, "grouping"), has_args = false, found = false, used_rel = false;
3537 :
3538 45735 : if (!all_aggr) {
3539 30794 : if (!groupby) {
3540 4 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3541 4 : return sql_error(sql, 02, SQLSTATE(42000) "%s: missing group by", toUpperCopy(uaname, aname));
3542 30790 : } else if (is_sql_groupby(f)) {
3543 8 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3544 8 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate function '%s' not allowed in GROUP BY clause", toUpperCopy(uaname, aname), aname);
3545 30782 : } else if (is_sql_values(f)) {
3546 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3547 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed on an unique value", toUpperCopy(uaname, aname));
3548 30781 : } else if (is_sql_join(f)) { /* the is_sql_join test must come before is_sql_where, because the join conditions are handled with sql_where */
3549 3 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3550 3 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in JOIN conditions", toUpperCopy(uaname, aname));
3551 30778 : } else if (is_sql_where(f)) {
3552 4 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3553 4 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", toUpperCopy(uaname, aname));
3554 30774 : } else if (is_sql_update_set(f) || is_sql_psm(f)) {
3555 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3556 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses (use subquery)", toUpperCopy(uaname, aname));
3557 30773 : } else if (is_sql_aggr(f)) {
3558 4 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3559 4 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
3560 30769 : } else if (is_psm_call(f)) {
3561 0 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3562 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed inside CALL", toUpperCopy(uaname, aname));
3563 30769 : } else if (is_sql_from(f)) {
3564 0 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3565 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in functions in FROM", toUpperCopy(uaname, aname));
3566 : }
3567 : }
3568 :
3569 45710 : exps = sa_list(sql->sa);
3570 45710 : if (args && args->data.sym) {
3571 26368 : bool arguments_correlated = true, all_const = true;
3572 :
3573 26368 : all_freevar = all_aggr?1:0;
3574 61452 : for (i = 0; args && args->data.sym && args->data.sym->token != SQL_ORDERBY; args = args->next, i++) {
3575 35144 : int base = (!groupby || !is_project(groupby->op) || is_base(groupby->op) || is_processed(groupby));
3576 27188 : sql_rel *gl = base?groupby:groupby->l, *ogl = gl; /* handle case of subqueries without correlation */
3577 35144 : sql_exp *e = rel_value_exp(query, &gl, args->data.sym, (f | sql_aggr)& ~sql_farg, ek);
3578 35144 : bool found_one_freevar = false;
3579 :
3580 35144 : if (!e)
3581 60 : return NULL;
3582 35090 : used_rel |= (rel_has_exp(gl, e, true) == 0);
3583 35090 : has_args = true;
3584 35090 : if (gl && gl != ogl) {
3585 5 : if (gl->grouped) {
3586 5 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3587 5 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
3588 : }
3589 0 : if (!base)
3590 0 : groupby->l = subquery = gl;
3591 : else
3592 : groupby = subquery = gl;
3593 : }
3594 35085 : sql_subtype *t = exp_subtype(e);
3595 35085 : if (!t) { /* we also do not expect parameters here */
3596 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3597 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: parameters not allowed as arguments to aggregate functions", toUpperCopy(uaname, aname));
3598 : }
3599 35084 : if (!t->type->localtype) {
3600 47 : if (e->type == e_atom && !e->f) {
3601 44 : t = sql_bind_localtype("bte");
3602 44 : e->tpe = *t;
3603 44 : if (e->l)
3604 44 : e->l = atom_set_type(sql->sa, e->l, t);
3605 : }
3606 : }
3607 :
3608 35084 : all_aggr &= (exp_card(e) <= CARD_AGGR && !exp_is_atom(e) && is_aggr(e->type) && !is_func(e->type) && (!groupby || !is_groupby(groupby->op) || !groupby->r || !exps_find_exp(groupby->r, e)));
3609 35084 : exp_only_freevar(query, e, &arguments_correlated, &found_one_freevar, &ungrouped_cols);
3610 35084 : all_freevar &= (arguments_correlated && found_one_freevar) || (is_atom(e->type)?all_freevar:0); /* no uncorrelated variables must be found, plus at least one correlated variable to push this aggregate to an outer query */
3611 35084 : all_const &= is_atom(e->type);
3612 35084 : list_append(exps, e);
3613 : }
3614 26308 : if (all_const)
3615 203 : all_freevar = 0;
3616 : }
3617 45650 : if (!all_freevar) {
3618 45358 : if (is_sql_groupby(f)) {
3619 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3620 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate function '%s' not allowed in GROUP BY clause", toUpperCopy(uaname, aname), aname);
3621 45357 : } else if (is_sql_from(f)) {
3622 2 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3623 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in functions in FROM", toUpperCopy(uaname, aname));
3624 45355 : } else if (is_sql_aggr(f) && groupby->grouped) {
3625 2 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3626 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
3627 45353 : } else if (is_sql_values(f)) {
3628 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3629 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed on an unique value", toUpperCopy(uaname, aname));
3630 45352 : } else if (is_sql_join(f)) { /* the is_sql_join test must come before is_sql_where, because the join conditions are handled with sql_where */
3631 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3632 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in JOIN conditions", toUpperCopy(uaname, aname));
3633 45351 : } else if (is_sql_where(f)) {
3634 5 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3635 5 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", toUpperCopy(uaname, aname));
3636 45346 : } else if (!all_aggr && !list_empty(ungrouped_cols)) {
3637 123 : for (node *n = ungrouped_cols->h ; n ; n = n->next) {
3638 66 : sql_rel *outer;
3639 66 : sql_exp *e = (sql_exp*) n->data;
3640 :
3641 66 : if ((outer = query_fetch_outer(query, is_freevar(e)-1))) {
3642 66 : int of = query_fetch_outer_state(query, is_freevar(e)-1);
3643 66 : if (outer->grouped) {
3644 24 : bool err = false, was_processed = false;
3645 :
3646 24 : if (is_processed(outer)) {
3647 5 : was_processed = true;
3648 5 : reset_processed(outer);
3649 : }
3650 24 : if (!is_groupby_col(outer, e))
3651 3 : err = true;
3652 24 : if (was_processed)
3653 5 : set_processed(outer);
3654 24 : if (err) {
3655 3 : if (exp_name(e) && exp_relname(e) && !has_label(e))
3656 3 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(e), exp_name(e));
3657 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
3658 : }
3659 42 : } else if (!used_rel && is_sql_where(of)) {
3660 2 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3661 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", toUpperCopy(uaname, aname));
3662 40 : } else if (!is_sql_aggr(of)) {
3663 36 : set_outer(outer);
3664 : }
3665 : }
3666 : }
3667 : }
3668 : }
3669 :
3670 45633 : if (all_freevar) { /* case 2, ie use outer */
3671 292 : int card;
3672 292 : sql_exp *exp = NULL;
3673 : /* find proper groupby relation */
3674 591 : for (node *n = exps->h; n; n = n->next) {
3675 299 : sql_exp *e = n->data;
3676 :
3677 299 : int vf = exp_freevar_offset(sql, e);
3678 299 : if (vf > (int)all_freevar)
3679 23 : all_freevar = vf;
3680 299 : exp = e;
3681 : }
3682 292 : if (query_has_outer(query) >= all_freevar) {
3683 292 : int sql_state = query_fetch_outer_state(query,all_freevar-1);
3684 292 : res = groupby = query_fetch_outer(query, all_freevar-1);
3685 292 : card = query_outer_used_card(query, all_freevar-1);
3686 : /* given groupby validate all input expressions */
3687 292 : char *err;
3688 292 : if (groupby && !is_groupby(groupby->op)) {
3689 111 : sql_exp *p = query_outer_last_used(query, all_freevar-1);
3690 111 : if (p && !is_aggr(p->type) && !is_groupby_col(groupby, p)) {
3691 20 : if (p->type == e_column)
3692 20 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", (char*)p->l, (char*)p->r);
3693 0 : if (exp_name(p) && exp_relname(p) && !has_label(p))
3694 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(p), exp_name(p));
3695 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
3696 : }
3697 : }
3698 272 : if ((err = exps_valid(query, exps, all_freevar)) != NULL) {
3699 10 : strcpy(sql->errstr, err);
3700 10 : sql->session->status = -ERR_GROUPBY;
3701 10 : return NULL;
3702 : }
3703 262 : if (exp && !is_groupby_col(res, exp)) {
3704 191 : if (is_sql_groupby(sql_state))
3705 2 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate function '%s' not allowed in GROUP BY clause", aname);
3706 189 : if (is_sql_aggr(sql_state) && groupby->grouped) {
3707 3 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3708 3 : return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
3709 : }
3710 186 : if (is_sql_values(sql_state))
3711 0 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed on an unique value");
3712 186 : if (is_sql_update_set(sql_state) || is_sql_psm(f))
3713 2 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
3714 184 : if (is_sql_join(sql_state))
3715 4 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
3716 180 : if (is_sql_where(sql_state))
3717 3 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
3718 177 : if (is_psm_call(sql_state))
3719 0 : return sql_error(sql, 05, SQLSTATE(42000) "CALL: aggregate functions not allowed inside CALL");
3720 177 : if (is_sql_from(sql_state))
3721 0 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in functions in FROM");
3722 177 : if (card > CARD_AGGR) { /* used an expression before on the non grouped relation */
3723 0 : sql_exp *lu = query_outer_last_used(query, all_freevar-1);
3724 0 : if (lu->type == e_column)
3725 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", (char*)lu->l, (char*)lu->r);
3726 0 : if (exp_name(lu) && exp_relname(lu) && !has_label(lu))
3727 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu));
3728 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
3729 : }
3730 177 : if (is_outer(groupby))
3731 2 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
3732 : }
3733 : } else {
3734 : all_freevar = 0;
3735 : }
3736 45341 : } else if (!subquery && groupby && is_outer(groupby) && !is_groupby(groupby->op))
3737 1 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
3738 :
3739 : /* find having select */
3740 45586 : if (!subquery && groupby && !is_processed(groupby) && is_sql_having(f)) {
3741 108 : og = groupby;
3742 108 : while(!is_processed(groupby) && !is_base(groupby->op)) {
3743 63 : if (is_select(groupby->op) || !groupby->l)
3744 : break;
3745 : if (groupby->l)
3746 : groupby = groupby->l;
3747 : }
3748 67 : if (groupby && is_select(groupby->op) && !is_processed(groupby)) {
3749 22 : group = 1;
3750 22 : sel = groupby;
3751 : /* At the end we switch back to the old projection relation og.
3752 : * During the partitioning and ordering we add the expressions to the intermediate relations. */
3753 : }
3754 22 : if (!sel)
3755 : groupby = og;
3756 22 : if (sel && sel->l)
3757 22 : groupby = sel->l;
3758 : }
3759 :
3760 : /* find groupby */
3761 45586 : if (!subquery && groupby && !is_processed(groupby) && !is_base(groupby->op)) {
3762 30648 : og = groupby;
3763 30648 : groupby = rel_find_groupby(groupby);
3764 30648 : if (groupby)
3765 : group = 1;
3766 : else
3767 : groupby = og;
3768 : }
3769 :
3770 7865 : if (!groupby && exps_card(exps) > CARD_ATOM) {
3771 0 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3772 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: missing group by", toUpperCopy(uaname, aname));
3773 : }
3774 :
3775 45586 : if (!subquery && groupby && groupby->op != op_groupby) { /* implicit groupby */
3776 21067 : if (!all_freevar && query->last_exp && !is_sql_aggr(query->last_state)) {
3777 9 : if (exp_relname(query->last_exp) && exp_name(query->last_exp) && !has_label(query->last_exp))
3778 9 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(query->last_exp), exp_name(query->last_exp));
3779 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
3780 : }
3781 21058 : res = groupby = rel_groupby(sql, groupby, NULL);
3782 : }
3783 45577 : if (subquery) {
3784 0 : assert(!all_freevar);
3785 0 : res = groupby;
3786 0 : if (is_sql_sel(f) && is_left(subquery->op) && !is_groupby(groupby->op)) {
3787 0 : res = groupby = rel_groupby(sql, groupby, NULL);
3788 0 : exps_set_freevar(sql, exps, groupby); /* mark free variables */
3789 0 : } else if (!is_groupby(groupby->op)) {
3790 0 : res = groupby = rel_groupby(sql, groupby, NULL);
3791 : }
3792 0 : assert(!is_base(groupby->op));
3793 : }
3794 45577 : if ((!exps || exps_card(exps) > CARD_ATOM) && (!res || !groupby))
3795 : return NULL;
3796 :
3797 45577 : list *obe = NULL;
3798 45577 : bool handled_order = true;
3799 45577 : if (args && args->data.sym && args->data.sym->token != SQL_ORDERBY)
3800 : return NULL;
3801 23748 : if (args && args->data.sym) { /* handle order by */
3802 4410 : int base = (!groupby || !is_project(groupby->op) || is_base(groupby->op) || is_processed(groupby));
3803 4410 : sql_rel *gl = base?groupby:groupby->l;//, *ogl = gl; /* handle case of subqueries without correlation */
3804 4410 : obe = rel_order_by(query, &gl, args->data.sym, 0, f);
3805 4410 : if (!obe)
3806 0 : return NULL;
3807 4410 : handled_order = false;
3808 : }
3809 :
3810 45577 : if (all_freevar) {
3811 246 : query_update_outer(query, res, all_freevar-1);
3812 45331 : } else if (rel) {
3813 45331 : *rel = res;
3814 45331 : if (query->last_rel != res) {
3815 41392 : query->last_rel = res;
3816 41392 : query->last_state |= sql_aggr;
3817 : }
3818 : }
3819 :
3820 45577 : if (!has_args) { /* count(*) case */
3821 19338 : obe = NULL; /* no errors, although the order by is useless */
3822 19338 : sql_exp *e;
3823 :
3824 19338 : if (strcmp(aname, "count") != 0) {
3825 2 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3826 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: unable to perform '%s(*)'", toUpperCopy(uaname, aname), aname);
3827 : }
3828 19336 : a = sql_bind_func(sql, "sys", aname, sql_bind_localtype("void"), NULL, F_AGGR, true, true);
3829 19336 : e = exp_aggr(sql->sa, NULL, a, distinct, 0, groupby?groupby->card:CARD_ATOM, 0);
3830 :
3831 19336 : if (!groupby)
3832 : return e;
3833 19336 : if (all_freevar)
3834 0 : query_outer_used_exp(query, all_freevar-1, e, sql_aggr);
3835 19336 : e = rel_groupby_add_aggr(sql, groupby, e);
3836 19336 : if (!group && !all_freevar)
3837 : return e;
3838 3213 : if (all_freevar) {
3839 0 : assert(!is_simple_project(res->op));
3840 0 : e->card = CARD_ATOM;
3841 0 : set_freevar(e, all_freevar-1);
3842 0 : return e;
3843 : }
3844 : return e;
3845 : }
3846 :
3847 : /* use cnt as nils shouldn't be counted */
3848 26239 : no_nil = 1;
3849 :
3850 26239 : gr = groupby;
3851 26239 : if (gr && gr->op == op_project && gr->l)
3852 : gr = gr->l;
3853 :
3854 26239 : if (is_grouping) {
3855 109 : sql_subtype *tpe;
3856 109 : list *l = (list*) groupby->r;
3857 :
3858 109 : if (list_length(l) <= 7)
3859 107 : tpe = sql_bind_localtype("bte");
3860 2 : else if (list_length(l) <= 15)
3861 2 : tpe = sql_bind_localtype("sht");
3862 0 : else if (list_length(l) <= 31)
3863 0 : tpe = sql_bind_localtype("int");
3864 0 : else if (list_length(l) <= 63)
3865 0 : tpe = sql_bind_localtype("lng");
3866 : #ifdef HAVE_HGE
3867 0 : else if (list_length(l) <= 127)
3868 0 : tpe = sql_bind_localtype("hge");
3869 : #endif
3870 : else
3871 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: GROUPING the number of grouping columns is larger"
3872 : " than the maximum number of representable bits from this server (%d > %d)", list_length(l),
3873 : #ifdef HAVE_HGE
3874 : 127
3875 : #else
3876 : 63
3877 : #endif
3878 : );
3879 109 : a = sql_bind_func_result(sql, sname, aname, F_AGGR, true, tpe, 1, exp_subtype(exps->h->data));
3880 : } else {
3881 26130 : a = sql_bind_func_(sql, sname, aname, exp_types(sql->sa, exps), F_AGGR, false, false);
3882 26130 : if (!a && obe && list_length(obe) == 1) { /* try to find aggregation function with requires order by column */
3883 0 : list *nexps = append(sa_list(sql->sa), obe->h->data);
3884 0 : nexps = list_merge(nexps, exps, (fdup) NULL);
3885 0 : a = sql_bind_func_(sql, sname, aname, exp_types(sql->sa, nexps), F_AGGR, false, false);
3886 0 : if (a && a->func->order_required) {
3887 : /* reset error */
3888 0 : handled_order = true;
3889 0 : sql->session->status = 0;
3890 0 : sql->errstr[0] = '\0';
3891 0 : exps = nexps;
3892 0 : obe = NULL;
3893 : }
3894 : }
3895 : }
3896 :
3897 26239 : if (a) {
3898 26234 : found = true;
3899 26234 : if (!execute_priv(sql, a->func))
3900 0 : a = NULL;
3901 26234 : if (!is_grouping && a && !(exps = check_arguments_and_find_largest_any_type(sql, rel ? *rel : NULL, exps, a, 0, false)))
3902 0 : a = NULL;
3903 : }
3904 :
3905 26239 : if (a) {
3906 26234 : bool hasnil = have_nil(exps) || (strcmp(aname, "count") != 0 && (!groupby || list_empty(groupby->r))); /* for global case, the aggregate may return NULL */
3907 26234 : sql_exp *e = exp_aggr(sql->sa, exps, a, distinct, no_nil, groupby?groupby->card:CARD_ATOM, hasnil);
3908 :
3909 26234 : if (!obe && a->func->order_required && !handled_order) {
3910 : /* TODO preper error on missing order by */
3911 : return NULL;
3912 : }
3913 4410 : if (obe && !a->func->order_required && !a->func->opt_order)
3914 : obe = NULL;
3915 4410 : if (obe) /* add order by expressions */
3916 4410 : e->r = append(sa_list(sql->sa), obe);
3917 26234 : if (!groupby)
3918 : return e;
3919 26234 : if (all_freevar)
3920 246 : query_outer_aggregated(query, all_freevar-1, e);
3921 26234 : e = rel_groupby_add_aggr(sql, groupby, e);
3922 26234 : if (!group && !all_freevar)
3923 : return e;
3924 19687 : if (all_freevar) {
3925 246 : rel_bind_vars(sql, groupby->l, exps);
3926 246 : assert(!is_simple_project(res->op));
3927 246 : e->card = CARD_ATOM;
3928 246 : set_freevar(e, all_freevar-1);
3929 246 : return e;
3930 : }
3931 : return e;
3932 : }
3933 5 : const char *type = "unknown";
3934 5 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
3935 :
3936 5 : if (!list_empty(exps)) {
3937 5 : sql_exp *e = exps->h->data;
3938 5 : type = exp_subtype(e)->type->base.name;
3939 : }
3940 15 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s: %s aggregate %s%s%s'%s'(%s)", toUpperCopy(uaname, aname), found ? "insufficient privileges for" : "no such",
3941 : sname ? "'":"", sname ? sname : "", sname ? "'.":"", aname, type);
3942 : }
3943 :
3944 : static sql_exp *
3945 45733 : rel_aggr(sql_query *query, sql_rel **rel, symbol *se, int f)
3946 : {
3947 45733 : dlist *l = se->data.lval;
3948 45733 : dnode *d = l->h->next->next;
3949 45733 : int distinct = l->h->next->data.i_val;
3950 45733 : char *aname = qname_schema_object(l->h->data.lval);
3951 45733 : char *sname = qname_schema(l->h->data.lval);
3952 :
3953 45733 : return _rel_aggr(query, rel, distinct, sname, aname, d, f);
3954 : }
3955 :
3956 : static sql_exp *
3957 101276 : rel_case(sql_query *query, sql_rel **rel, symbol *opt_cond, dlist *when_search_list, symbol *opt_else, int f)
3958 : {
3959 101276 : mvc *sql = query->sql;
3960 101276 : sql_subtype *tpe = NULL;
3961 101276 : list *conds = new_exp_list(sql->sa), *results = new_exp_list(sql->sa);
3962 101276 : sql_subtype *restype = NULL, *condtype = NULL, ctype, rtype, bt;
3963 101276 : sql_exp *res = NULL, *opt_cond_exp = NULL;
3964 101276 : exp_kind ek = {type_value, card_column, FALSE};
3965 :
3966 101276 : if (opt_cond) {
3967 9532 : if (!(opt_cond_exp = rel_value_exp(query, rel, opt_cond, f, ek)))
3968 : return NULL;
3969 9531 : condtype = exp_subtype(opt_cond_exp);
3970 : }
3971 :
3972 250121 : for (dnode *dn = when_search_list->h; dn; dn = dn->next) {
3973 148855 : sql_exp *cond = NULL, *result = NULL;
3974 148855 : dlist *when = dn->data.sym->data.lval;
3975 :
3976 148855 : if (opt_cond)
3977 45936 : cond = rel_value_exp(query, rel, when->h->data.sym, f, ek);
3978 : else
3979 102919 : cond = rel_logical_value_exp(query, rel, when->h->data.sym, f, ek);
3980 148855 : if (!cond)
3981 : return NULL;
3982 148849 : append(conds, cond);
3983 148849 : tpe = exp_subtype(cond);
3984 148849 : if (tpe && condtype) {
3985 57105 : result_datatype(&ctype, condtype, tpe);
3986 57105 : condtype = &ctype;
3987 91744 : } else if (tpe) {
3988 91742 : condtype = tpe;
3989 : }
3990 :
3991 148849 : if (!(result = rel_value_exp(query, rel, when->h->next->data.sym, f, ek)))
3992 : return NULL;
3993 148846 : append(results, result);
3994 148846 : tpe = exp_subtype(result);
3995 148846 : if (tpe && restype) {
3996 47577 : result_datatype(&rtype, restype, tpe);
3997 47577 : restype = &rtype;
3998 101269 : } else if (tpe) {
3999 101263 : restype = tpe;
4000 : }
4001 : }
4002 101266 : if (opt_else) {
4003 98672 : if (!(res = rel_value_exp(query, rel, opt_else, f, ek)))
4004 : return NULL;
4005 :
4006 98672 : tpe = exp_subtype(res);
4007 98672 : if (tpe && restype) {
4008 98667 : result_datatype(&rtype, restype, tpe);
4009 98667 : restype = &rtype;
4010 5 : } else if (tpe) {
4011 : restype = tpe;
4012 : }
4013 :
4014 98670 : if (!restype)
4015 2 : return sql_error(sql, 02, SQLSTATE(42000) "Result type missing");
4016 98670 : if (restype->type->localtype == TYPE_void) /* NULL */
4017 0 : restype = sql_bind_localtype("str");
4018 :
4019 98670 : if (!(res = exp_check_type(sql, restype, rel ? *rel : NULL, res, type_equal)))
4020 : return NULL;
4021 : } else {
4022 2594 : if (!restype)
4023 0 : return sql_error(sql, 02, SQLSTATE(42000) "Result type missing");
4024 2594 : if (restype->type->localtype == TYPE_void) /* NULL */
4025 7 : restype = sql_bind_localtype("str");
4026 2594 : res = exp_null(sql->sa, restype);
4027 : }
4028 :
4029 101264 : if (!condtype)
4030 0 : return sql_error(sql, 02, SQLSTATE(42000) "Condition type missing");
4031 101264 : if (condtype->type->localtype == TYPE_void) /* NULL */
4032 0 : condtype = sql_bind_localtype("str");
4033 101264 : if (opt_cond_exp && !(opt_cond_exp = exp_check_type(sql, condtype, rel ? *rel : NULL, opt_cond_exp, type_equal)))
4034 : return NULL;
4035 101264 : sql_find_subtype(&bt, "boolean", 0, 0);
4036 101264 : list *args = sa_list(sql->sa);
4037 101264 : if (opt_cond_exp)
4038 9525 : append(args, opt_cond_exp);
4039 250103 : for (node *n = conds->h, *m = results->h; n && m; n = n->next, m = m->next) {
4040 148840 : sql_exp *cond = n->data;
4041 148840 : sql_exp *result = m->data;
4042 :
4043 148840 : if (!(result = exp_check_type(sql, restype, rel ? *rel : NULL, result, type_equal)))
4044 : return NULL;
4045 :
4046 148840 : if (!(cond = exp_check_type(sql, condtype, rel ? *rel : NULL, cond, type_equal)))
4047 : return NULL;
4048 148839 : if (!opt_cond_exp && !(cond = exp_check_type(sql, &bt, rel ? *rel : NULL, cond, type_equal)))
4049 : return NULL;
4050 148839 : append(args, cond);
4051 148839 : append(args, result);
4052 : }
4053 101263 : assert(res);
4054 101263 : list_append(args, res);
4055 101263 : list *types = sa_list(sql->sa);
4056 101263 : types = append(append(types, restype), restype);
4057 193002 : sql_subfunc *case_func = find_func(sql, NULL, opt_cond_exp?"casewhen":"case", list_length(types), F_FUNC, true, NULL, NULL);
4058 101263 : res = exp_op(sql->sa, args, case_func);
4059 101263 : ((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(sql->sa, restype->type, restype->digits, restype->scale);
4060 101263 : return res;
4061 : }
4062 :
4063 : static sql_exp *
4064 4027 : rel_complex_case(sql_query *query, sql_rel **rel, dlist *case_args, int f, str func)
4065 : {
4066 4027 : exp_kind ek = {type_value, card_column, FALSE};
4067 4027 : list *args = sa_list(query->sql->sa);
4068 4027 : sql_subtype *restype = NULL, rtype;
4069 4027 : sql_exp *res;
4070 :
4071 : /* generate nested func calls */
4072 12537 : for(dnode *dn = case_args->h; dn; dn = dn->next) {
4073 8523 : sql_exp *a = rel_value_exp(query, rel, dn->data.sym, f, ek);
4074 8523 : if (!a)
4075 : return NULL;
4076 8510 : append(args, a);
4077 : /* all arguments should have the same type */
4078 8510 : sql_subtype *tpe = exp_subtype(a);
4079 8510 : if (tpe && restype) {
4080 4485 : result_datatype(&rtype, restype, tpe);
4081 4485 : restype = &rtype;
4082 4025 : } else if (tpe) {
4083 4025 : restype = tpe;
4084 : }
4085 : }
4086 4014 : if (!restype)
4087 0 : return sql_error(query->sql, 02, SQLSTATE(42000) "Result type missing");
4088 4014 : if (restype->type->localtype == TYPE_void) /* NULL */
4089 0 : restype = sql_bind_localtype("str");
4090 4014 : list *nargs = sa_list(query->sql->sa);
4091 12509 : for (node *m = args->h; m; m = m->next) {
4092 8495 : sql_exp *result = m->data;
4093 :
4094 8495 : if (!(result = exp_check_type(query->sql, restype, rel ? *rel : NULL, result, type_equal)))
4095 : return NULL;
4096 8495 : append(nargs, result);
4097 : }
4098 4014 : list *types = append(append(sa_list(query->sql->sa), restype), restype);
4099 4014 : sql_subfunc *fnc = find_func(query->sql, NULL, func, list_length(types), F_FUNC, true, NULL, NULL);
4100 4014 : res = exp_op(query->sql->sa, nargs, fnc);
4101 4014 : ((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(query->sql->sa, restype->type, restype->digits, restype->scale);
4102 4014 : return res;
4103 : }
4104 :
4105 : static sql_exp *
4106 105303 : rel_case_exp(sql_query *query, sql_rel **rel, symbol *se, int f)
4107 : {
4108 105303 : dlist *l = se->data.lval;
4109 :
4110 105303 : if (se->token == SQL_COALESCE) {
4111 3876 : return rel_complex_case(query, rel, l, f | sql_farg, "coalesce");
4112 101427 : } else if (se->token == SQL_NULLIF) {
4113 151 : return rel_complex_case(query, rel, l, f | sql_farg, "nullif");
4114 101276 : } else if (l->h->type == type_list) {
4115 91744 : dlist *when_search_list = l->h->data.lval;
4116 91744 : symbol *opt_else = l->h->next->data.sym;
4117 :
4118 91744 : return rel_case(query, rel, NULL, when_search_list, opt_else, f | sql_farg);
4119 : } else {
4120 9532 : symbol *scalar_exp = l->h->data.sym;
4121 9532 : dlist *when_value_list = l->h->next->data.lval;
4122 9532 : symbol *opt_else = l->h->next->next->data.sym;
4123 :
4124 9532 : return rel_case(query, rel, scalar_exp, when_value_list, opt_else, f | sql_farg);
4125 : }
4126 : }
4127 :
4128 : #define E_ATOM_STRING(e) ((atom*)(e)->l)->data.val.sval
4129 :
4130 : static sql_exp *
4131 172566 : rel_cast(sql_query *query, sql_rel **rel, symbol *se, int f)
4132 : {
4133 172566 : mvc *sql = query->sql;
4134 172566 : dlist *dl = se->data.lval;
4135 172566 : symbol *s = dl->h->data.sym;
4136 172566 : sql_subtype *tpe = &dl->h->next->data.typeval;
4137 172566 : exp_kind ek = {type_value, card_column, FALSE};
4138 172566 : sql_exp *e = rel_value_exp(query, rel, s, f|sql_farg, ek);
4139 :
4140 172566 : if (!e)
4141 : return NULL;
4142 :
4143 : /* strings may need to be truncated */
4144 172551 : if (EC_VARCHAR(tpe->type->eclass) && tpe->digits > 0) {
4145 84358 : sql_subtype *et = exp_subtype(e);
4146 : /* truncate only if the number of digits are smaller or from clob */
4147 84358 : if (et && EC_VARCHAR(et->type->eclass) && (tpe->digits < et->digits || et->digits == 0)) {
4148 2882 : sql_subfunc *c = sql_bind_func(sql, "sys", "truncate", et, sql_bind_localtype("int"), F_FUNC, true, true);
4149 2882 : if (c)
4150 2882 : e = exp_binop(sql->sa, e, exp_atom_int(sql->sa, tpe->digits), c);
4151 : }
4152 : }
4153 :
4154 172551 : if (tpe->type->eclass == EC_DEC) {
4155 447 : sql_subtype *et = exp_subtype(e);
4156 447 : if (e->type == e_atom && !tpe->digits) {
4157 9 : if (et->type->eclass == EC_NUM || et->type->eclass == EC_DEC) {
4158 6 : tpe->digits = atom_num_digits(e->l);
4159 6 : tpe = sql_bind_subtype(sql->sa, "decimal", tpe->digits, et->scale);
4160 3 : } else if (EC_VARCHAR(et->type->eclass)) {
4161 2 : char *s = E_ATOM_STRING(e);
4162 2 : unsigned int min_precision = 0, min_scale = 0;
4163 2 : bool dot_seen = false;
4164 16 : for (size_t i = 0; i < strlen(s); i++) {
4165 14 : if (isdigit(s[i])) {
4166 12 : min_precision++;
4167 12 : if (dot_seen)
4168 10 : min_scale++;
4169 2 : } else if (s[i] == '.') {
4170 2 : dot_seen = true;
4171 : }
4172 : }
4173 2 : tpe = sql_bind_subtype(sql->sa, "decimal", min_precision, min_scale);
4174 : } else { /* fallback */
4175 1 : tpe = sql_bind_subtype(sql->sa, "decimal", 18, 3);
4176 : }
4177 438 : } else if (!tpe->digits && !tpe->scale) {
4178 105 : if (et->type->eclass == EC_NUM)
4179 36 : tpe = sql_bind_subtype(sql->sa, "decimal", et->digits, 0);
4180 : else /* fallback */
4181 69 : tpe = sql_bind_subtype(sql->sa, "decimal", 18, 3);
4182 : }
4183 : }
4184 :
4185 172551 : if (e)
4186 172551 : e = exp_check_type(sql, tpe, rel ? *rel : NULL, e, type_cast);
4187 :
4188 172551 : if (e && e->type == e_convert)
4189 49062 : exp_label(sql->sa, e, ++sql->label);
4190 :
4191 : return e;
4192 : }
4193 :
4194 : static sql_exp *
4195 1590 : rel_next_value_for( mvc *sql, symbol *se )
4196 : {
4197 1590 : char *sname = qname_schema(se->data.lval);
4198 1590 : char *seqname = qname_schema_object(se->data.lval);
4199 1590 : sql_sequence *seq = NULL;
4200 1590 : sql_subtype t;
4201 1590 : sql_subfunc *f;
4202 :
4203 1590 : if (!sname)
4204 225 : sname = "sys";
4205 1590 : if (!stack_find_rel_view(sql, seqname)) {
4206 1389 : if (!(seq = find_sequence_on_scope(sql, sname, seqname, "NEXT VALUE FOR")))
4207 : return NULL;
4208 1387 : if (!mvc_schema_privs(sql, seq->s))
4209 0 : return sql_error(sql, 02, SQLSTATE(42000) "NEXT VALUE FOR: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), seq->s->base.name);
4210 : }
4211 1588 : sql_find_subtype(&t, "varchar", 0, 0);
4212 1588 : f = sql_bind_func(sql, "sys", "next_value_for", &t, &t, F_FUNC, true, true);
4213 1588 : assert(f);
4214 : /* sequence found in the stack, ie just created. use given schema? */
4215 1588 : return exp_binop(sql->sa, exp_atom_str(sql->sa, seq && seq->s ? seq->s->base.name : sname, &t), exp_atom_str(sql->sa, seqname, &t), f);
4216 : }
4217 :
4218 : /* some users like to use aliases already in the groupby */
4219 : static sql_exp *
4220 165 : rel_selection_ref(sql_query *query, sql_rel **rel, char *name, dlist *selection)
4221 : {
4222 165 : allocator *sa = query->sql->sa;
4223 165 : dlist *nl;
4224 165 : exp_kind ek = {type_value, card_column, FALSE};
4225 165 : sql_exp *res = NULL;
4226 165 : symbol *nsym;
4227 :
4228 165 : if (!selection)
4229 : return NULL;
4230 :
4231 679 : for (dnode *n = selection->h; n; n = n->next) {
4232 : /* we only look for columns */
4233 517 : tokens to = n->data.sym->token;
4234 517 : if (to == SQL_COLUMN || to == SQL_IDENT) {
4235 515 : dlist *l = n->data.sym->data.lval;
4236 : /* AS name */
4237 515 : if (l->h->next->data.sval && strcmp(l->h->next->data.sval, name) == 0) {
4238 146 : sql_exp *ve = rel_value_exp(query, rel, l->h->data.sym, sql_sel|sql_groupby, ek);
4239 146 : if (ve) {
4240 145 : if (res)
4241 1 : return sql_error(query->sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", name);
4242 144 : res = ve;
4243 :
4244 144 : nl = dlist_create(sa);
4245 144 : exp_setname(query->sql, ve, NULL, name);
4246 : /* now we should rewrite the selection such that it uses the new group by column */
4247 144 : dlist_append_string(sa, nl, sa_strdup(sa, name));
4248 144 : nsym = symbol_create_list(sa, to, nl);
4249 144 : nl = dlist_create(sa);
4250 144 : dlist_append_symbol(sa, nl, nsym);
4251 : /* no alias */
4252 144 : dlist_append_symbol(sa, nl, NULL);
4253 144 : n->data.sym = symbol_create_list(sa, to, nl);
4254 : }
4255 : }
4256 : }
4257 : }
4258 : return res;
4259 : }
4260 :
4261 : static char*
4262 197 : symbol_get_identifier(symbol *sym)
4263 : {
4264 197 : dlist *syml;
4265 :
4266 197 : if (sym->token != SQL_COLUMN && sym->token != SQL_IDENT)
4267 : return NULL;
4268 182 : syml = sym->data.lval;
4269 182 : if (dlist_length(syml) > 1)
4270 : return NULL;
4271 :
4272 165 : return syml->h->data.sval;
4273 : }
4274 :
4275 : static sql_exp*
4276 36414 : rel_group_column(sql_query *query, sql_rel **rel, symbol *grp, dlist *selection, list *exps, int f)
4277 : {
4278 36414 : sql_query *lquery = query_create(query->sql);
4279 36414 : mvc *sql = query->sql;
4280 36414 : exp_kind ek = {type_value, card_value, TRUE};
4281 36414 : sql_exp *e = rel_value_exp2(lquery, rel, grp, f, ek);
4282 :
4283 36414 : if (e && exp_is_atom(e)) {
4284 34 : sql_subtype *tpe = exp_subtype(e);
4285 34 : if (!is_atom(e->type) ||!tpe || tpe->type->eclass != EC_NUM) {
4286 2 : if (!tpe)
4287 2 : return sql_error(sql, 02, SQLSTATE(42000) "Cannot have a parameter (?) for group by column");
4288 3 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: non-integer constant in GROUP BY");
4289 : }
4290 : }
4291 :
4292 192 : if (!e) {
4293 192 : char buf[ERRSIZE], *name;
4294 192 : int status = sql->session->status;
4295 192 : strcpy(buf, sql->errstr);
4296 : /* reset error */
4297 192 : sql->session->status = 0;
4298 192 : sql->errstr[0] = '\0';
4299 :
4300 192 : if ((name = symbol_get_identifier(grp))) {
4301 163 : e = rel_selection_ref(query, rel, name, selection);
4302 163 : if (!e) { /* attempt to find in the existing list of group by expressions */
4303 29 : for (node *n = exps->h ; n && !e ; n = n->next) {
4304 9 : sql_exp *ge = (sql_exp *) n->data;
4305 9 : const char *gen = exp_name(ge);
4306 :
4307 9 : if (gen && strcmp(name, gen) == 0)
4308 5 : e = exp_ref(sql, ge);
4309 : }
4310 : }
4311 : }
4312 49 : if (!e && query_has_outer(query)) {
4313 : /* reset error */
4314 32 : sql->session->status = 0;
4315 32 : sql->errstr[0] = '\0';
4316 32 : e = rel_value_exp2(query, rel, grp, f, ek);
4317 : }
4318 44 : if (!e) {
4319 13 : if (sql->errstr[0] == 0) {
4320 10 : sql->session->status = status;
4321 10 : strcpy(sql->errstr, buf);
4322 : }
4323 13 : return NULL;
4324 : }
4325 : }
4326 36396 : if (!exp_subtype(e))
4327 0 : return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for group by column");
4328 : return e;
4329 : }
4330 :
4331 : static list*
4332 44 : list_power_set(allocator *sa, list* input) /* cube */
4333 : {
4334 44 : list *res = sa_list(sa);
4335 : /* N stores total number of subsets */
4336 44 : int N = (int) pow(2, input->cnt);
4337 :
4338 : /* generate each subset one by one */
4339 266 : for (int i = 0; i < N; i++) {
4340 222 : list *ll = sa_list(sa);
4341 222 : int j = 0; /* check every bit of i */
4342 844 : for (node *n = input->h ; n ; n = n->next) {
4343 : /* if j'th bit of i is set, then append */
4344 622 : if (i & (1 << j))
4345 311 : list_prepend(ll, n->data);
4346 622 : j++;
4347 : }
4348 222 : list_prepend(res, ll);
4349 : }
4350 44 : return res;
4351 : }
4352 :
4353 : static list*
4354 61 : list_rollup(allocator *sa, list* input)
4355 : {
4356 61 : list *res = sa_list(sa);
4357 :
4358 188 : for (int counter = input->cnt; counter > 0; counter--) {
4359 127 : list *ll = sa_list(sa);
4360 127 : int j = 0;
4361 376 : for (node *n = input->h; n && j < counter; j++, n = n->next)
4362 249 : list_append(ll, n->data);
4363 127 : list_append(res, ll);
4364 : }
4365 61 : list_append(res, sa_list(sa)); /* global aggregate case */
4366 61 : return res;
4367 : }
4368 :
4369 : static int
4370 320 : list_equal(list* list1, list* list2)
4371 : {
4372 375 : for (node *n = list1->h; n ; n = n->next) {
4373 328 : sql_exp *e = (sql_exp*) n->data;
4374 328 : if (!exps_find_exp(list2, e))
4375 : return 1;
4376 : }
4377 78 : for (node *n = list2->h; n ; n = n->next) {
4378 47 : sql_exp *e = (sql_exp*) n->data;
4379 47 : if (!exps_find_exp(list1, e))
4380 : return 1;
4381 : }
4382 : return 0;
4383 : }
4384 :
4385 : static list*
4386 26 : lists_cartesian_product_and_distinct(allocator *sa, list *l1, list *l2)
4387 : {
4388 26 : list *res = sa_list(sa);
4389 :
4390 : /* for each list of l2, merge into each list of l1 while removing duplicates */
4391 116 : for (node *n = l1->h ; n ; n = n->next) {
4392 90 : list *sub_list = (list*) n->data;
4393 :
4394 279 : for (node *m = l2->h ; m ; m = m->next) {
4395 189 : list *other = (list*) m->data;
4396 189 : list_append(res, list_distinct(list_merge(list_dup(sub_list, (fdup) NULL), other, (fdup) NULL), (fcmp) list_equal, (fdup) NULL));
4397 : }
4398 : }
4399 26 : return res;
4400 : }
4401 :
4402 : static list*
4403 13439 : rel_groupings(sql_query *query, sql_rel **rel, symbol *groupby, dlist *selection, int f, bool grouping_sets, list **sets)
4404 : {
4405 13439 : mvc *sql = query->sql;
4406 13439 : list *exps = new_exp_list(sql->sa);
4407 :
4408 13439 : if (mvc_highwater(sql))
4409 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
4410 :
4411 49761 : for (dnode *o = groupby->data.lval->h; o; o = o->next) {
4412 36341 : symbol *grouping = o->data.sym;
4413 36341 : list *next_set = NULL;
4414 :
4415 36341 : if (grouping->token == SQL_GROUPING_SETS) { /* call recursively, and merge the generated sets */
4416 39 : list *other = rel_groupings(query, rel, grouping, selection, f, true, &next_set);
4417 39 : if (!other)
4418 19 : return NULL;
4419 39 : exps = list_distinct(list_merge(exps, other, (fdup) NULL), (fcmp) exp_equal, (fdup) NULL);
4420 : } else {
4421 36302 : dlist *dl = grouping->data.lval;
4422 36302 : if (dl) {
4423 36276 : list *set_cols = new_exp_list(sql->sa); /* columns and combination of columns to be used for the next set */
4424 :
4425 72642 : for (dnode *oo = dl->h; oo; oo = oo->next) {
4426 36384 : symbol *grp = oo->data.sym;
4427 36384 : list *next_tuple = new_exp_list(sql->sa); /* next tuple of columns */
4428 :
4429 36384 : if (grp->token == SQL_COLUMN_GROUP) { /* set of columns */
4430 71 : assert(is_sql_group_totals(f));
4431 172 : for (dnode *ooo = grp->data.lval->h; ooo; ooo = ooo->next) {
4432 101 : symbol *elm = ooo->data.sym;
4433 101 : sql_exp *e = rel_group_column(query, rel, elm, selection, exps, f);
4434 101 : if (!e)
4435 : return NULL;
4436 101 : assert(e->type == e_column);
4437 101 : list_append(next_tuple, e);
4438 101 : list_append(exps, e);
4439 : }
4440 : } else { /* single column or expression */
4441 36313 : sql_exp *e = rel_group_column(query, rel, grp, selection, exps, f);
4442 36313 : if (!e)
4443 : return NULL;
4444 36295 : if (e->type != e_column && !exp_is_atom(e)) { /* store group by expressions in the stack */
4445 142 : if (is_sql_group_totals(f))
4446 0 : return sql_error(sql, 02, SQLSTATE(42000) "GROUP BY: grouping expressions not possible with ROLLUP, CUBE and GROUPING SETS");
4447 142 : if (!exp_has_rel(e) && !frame_push_groupby_expression(sql, grp, e))
4448 : return NULL;
4449 : }
4450 36295 : list_append(next_tuple, e);
4451 36295 : list_append(exps, e);
4452 : }
4453 36366 : list_append(set_cols, next_tuple);
4454 : }
4455 36258 : if (is_sql_group_totals(f)) {
4456 178 : if (grouping->token == SQL_ROLLUP)
4457 61 : next_set = list_rollup(sql->sa, set_cols);
4458 117 : else if (grouping->token == SQL_CUBE)
4459 44 : next_set = list_power_set(sql->sa, set_cols);
4460 : else /* the list of sets is not used in the "GROUP BY a, b, ..." case */
4461 73 : next_set = list_append(new_exp_list(sql->sa), set_cols);
4462 : }
4463 26 : } else if (is_sql_group_totals(f) && grouping_sets) /* The GROUP BY () case is the global aggregate which is always added by ROLLUP and CUBE */
4464 17 : next_set = list_append(new_exp_list(sql->sa), new_exp_list(sql->sa));
4465 : }
4466 36323 : if (is_sql_group_totals(f)) { /* if there are no sets, set the found one, otherwise calculate cartesian product and merge the distinct ones */
4467 235 : if (!next_set)
4468 1 : return sql_error(sql, 02, SQLSTATE(42000) "GROUP BY: GROUPING SETS is empty");
4469 234 : if (!*sets)
4470 157 : *sets = next_set;
4471 : else
4472 77 : *sets = grouping_sets ? list_merge(*sets, next_set, (fdup) NULL) : lists_cartesian_product_and_distinct(sql->sa, *sets, next_set);
4473 : }
4474 : }
4475 : return exps;
4476 : }
4477 :
4478 : static list*
4479 2321 : rel_partition_groupings(sql_query *query, sql_rel **rel, symbol *partitionby, dlist *selection, int f)
4480 : {
4481 2321 : mvc *sql = query->sql;
4482 2321 : dnode *o = partitionby->data.lval->h;
4483 2321 : list *exps = new_exp_list(sql->sa);
4484 :
4485 6994 : for (; o; o = o->next) {
4486 2360 : symbol *grp = o->data.sym;
4487 2360 : exp_kind ek = {type_value, card_value, TRUE};
4488 2360 : sql_exp *e = rel_value_exp2(query, rel, grp, f, ek);
4489 :
4490 2360 : if (!e) {
4491 5 : int status = sql->session->status;
4492 5 : char buf[ERRSIZE], *name;
4493 :
4494 : /* reset error */
4495 5 : sql->session->status = 0;
4496 5 : strcpy(buf, sql->errstr);
4497 5 : sql->errstr[0] = '\0';
4498 :
4499 5 : if ((name = symbol_get_identifier(grp))) {
4500 2 : e = rel_selection_ref(query, rel, name, selection);
4501 2 : if (!e) { /* attempt to find in the existing list of partition by expressions */
4502 3 : for (node *n = exps->h ; n ; n = n->next) {
4503 1 : sql_exp *ge = (sql_exp *) n->data;
4504 1 : const char *gen = exp_name(ge);
4505 :
4506 1 : if (gen && strcmp(name, gen) == 0) {
4507 0 : e = exp_ref(sql, ge);
4508 0 : break;
4509 : }
4510 : }
4511 : }
4512 : }
4513 5 : if (!e) {
4514 5 : if (sql->errstr[0] == 0) {
4515 5 : sql->session->status = status;
4516 5 : strcpy(sql->errstr, buf);
4517 : }
4518 5 : return NULL;
4519 : }
4520 : }
4521 :
4522 2355 : if (exp_has_rel(e))
4523 3 : return sql_error(sql, 02, SQLSTATE(42000) "PARTITION BY: subqueries not allowed in PARTITION BY clause");
4524 :
4525 2352 : if (e->type != e_column) { /* store group by expressions in the stack */
4526 42 : if (!frame_push_groupby_expression(sql, grp, e))
4527 : return NULL;
4528 : }
4529 :
4530 2352 : if (e->card > CARD_AGGR)
4531 2230 : e->card = CARD_AGGR;
4532 2352 : append(exps, e);
4533 : }
4534 : return exps;
4535 : }
4536 :
4537 : /* find selection expressions matching the order by column expression */
4538 : /* complex columns only */
4539 : static sql_exp *
4540 67744 : rel_order_by_column_exp(sql_query *query, sql_rel **R, symbol *column_r, int needs_distinct, int f)
4541 : {
4542 67744 : mvc *sql = query->sql;
4543 67744 : sql_rel *r = *R, *p = NULL;
4544 67744 : sql_exp *e = NULL, *found = NULL;
4545 67744 : exp_kind ek = {type_value, card_column, FALSE};
4546 :
4547 67744 : if (!r)
4548 : return e;
4549 :
4550 67744 : if (is_simple_project(r->op) && r->l && is_processed(r)) {
4551 67682 : p = r;
4552 67682 : r = r->l;
4553 : }
4554 :
4555 67744 : e = rel_value_exp(query, &r, column_r, f, ek);
4556 :
4557 67744 : if (r && !p)
4558 62 : *R = r;
4559 67682 : else if (r)
4560 67682 : p->l = r;
4561 67744 : if (e && p) {
4562 67655 : if (is_project(p->op) && (found = exps_any_match(p->exps, e))) { /* if one of the projections matches, return a reference to it */
4563 60010 : e = exp_ref(sql, found);
4564 : } else {
4565 7645 : if (needs_distinct)
4566 2 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
4567 7643 : e = rel_project_add_exp(sql, p, e);
4568 7643 : if (r) {
4569 125346 : for (node *n = p->exps->h ; n ; n = n->next) {
4570 117705 : sql_exp *ee = n->data;
4571 :
4572 117705 : if (ee->card > r->card) {
4573 2 : if (exp_name(ee) && !has_label(ee))
4574 2 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(ee));
4575 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
4576 : }
4577 : }
4578 : }
4579 : }
4580 67651 : return e;
4581 : }
4582 89 : if (e && r && is_project(r->op)) {
4583 28 : sql_exp *found = exps_find_exp(r->exps, e);
4584 :
4585 28 : if (!found) {
4586 8 : if (needs_distinct)
4587 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
4588 8 : if (!is_simple_project(r->op) && !is_groupby(r->op))
4589 1 : *R = r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 0));
4590 8 : append(r->exps, e);
4591 : } else {
4592 : e = found;
4593 : }
4594 28 : e = exp_ref(sql, e);
4595 : }
4596 : return e;
4597 : }
4598 :
4599 : static dlist *
4600 114440 : simple_selection(symbol *sq)
4601 : {
4602 114440 : if (sq->token == SQL_SELECT) {
4603 13 : SelectNode *sn;
4604 13 : sn = (SelectNode *) sq;
4605 :
4606 13 : if (!sn->from && !sn->where && !sn->distinct && !sn->window && dlist_length(sn->selection) == 1)
4607 7 : return sn->selection;
4608 : }
4609 : return NULL;
4610 : }
4611 :
4612 : static list *
4613 44495 : rel_order_by(sql_query *query, sql_rel **R, symbol *orderby, int needs_distinct, int f)
4614 : {
4615 44495 : mvc *sql = query->sql;
4616 44495 : sql_rel *rel = *R, *or = rel; /* the order by relation */
4617 44495 : list *exps = new_exp_list(sql->sa);
4618 :
4619 44495 : if (!orderby->data.lval) { /* by all */
4620 6 : if (is_sql_orderby(f)) {
4621 6 : assert(is_project(rel->op));
4622 22 : for(node *n = rel->exps->h; n; n = n->next) {
4623 16 : sql_exp *e = n->data;
4624 16 : append(exps, exp_ref(sql, e));
4625 : }
4626 : return exps;
4627 : }
4628 : return NULL;
4629 : }
4630 :
4631 44489 : dnode *o = orderby->data.lval->h;
4632 44489 : dlist *selection = NULL;
4633 :
4634 44489 : if (is_sql_orderby(f)) {
4635 37051 : assert(is_project(rel->op));
4636 37051 : rel = rel->l;
4637 : }
4638 :
4639 158882 : for (; o; o = o->next) {
4640 114440 : symbol *order = o->data.sym;
4641 :
4642 114440 : if (order->token == SQL_COLUMN || order->token == SQL_IDENT) {
4643 114440 : symbol *col = order->data.lval->h->data.sym;
4644 114440 : int direction = order->data.lval->h->next->data.i_val;
4645 114440 : sql_exp *e = NULL;
4646 :
4647 114440 : assert(order->data.lval->h->next->type == type_int);
4648 114440 : if ((selection = simple_selection(col)) != NULL) {
4649 7 : dnode *o = selection->h;
4650 7 : order = o->data.sym;
4651 7 : if (order->data.lval->h->type == type_symbol)
4652 6 : col = order->data.lval->h->data.sym;
4653 : /* remove optional name from selection */
4654 7 : order->data.lval->h->next = NULL;
4655 : }
4656 :
4657 114440 : if (col->token == SQL_COLUMN || col->token == SQL_IDENT || col->token == SQL_ATOM) {
4658 114218 : exp_kind ek = {type_value, card_column, FALSE};
4659 :
4660 114218 : e = rel_value_exp2(query, &rel, col, f, ek);
4661 :
4662 114218 : if (e && e->card <= CARD_ATOM) {
4663 9373 : sql_subtype *tpe = exp_subtype(e);
4664 : /* integer atom on the stack */
4665 9373 : if (!is_sql_window(f) && e->type == e_atom &&
4666 9265 : tpe->type->eclass == EC_NUM) {
4667 9256 : atom *a = e->l;
4668 9256 : int nr = (int)atom_get_int(a);
4669 :
4670 9256 : e = exps_get_exp(rel->exps, nr);
4671 9256 : if (!e)
4672 3 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: the order by column number (%d) is not in the number of projections range (%d)", nr, list_length(rel->exps));
4673 9253 : e = exp_ref(sql, e);
4674 : }
4675 37318 : } else if (e && exp_card(e) > rel->card) {
4676 0 : if (exp_name(e) && !has_label(e))
4677 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(e));
4678 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
4679 : }
4680 114215 : if (e && !exp_name(e))
4681 23 : exp_label(sql->sa, e, ++sql->label);
4682 46688 : if (e && rel && is_project(rel->op)) {
4683 39751 : sql_exp *found = exps_find_exp(rel->exps, e);
4684 :
4685 39751 : if (!found) {
4686 33 : if (needs_distinct)
4687 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
4688 33 : if (!is_freevar(e))
4689 16 : append(rel->exps, e);
4690 : } else {
4691 : e = found;
4692 : }
4693 39751 : if (!is_freevar(e))
4694 39734 : e = exp_ref(sql, e);
4695 : }
4696 : }
4697 :
4698 114437 : if (rel && !e && sql->session->status != -ERR_AMBIGUOUS) {
4699 : /* reset error */
4700 67744 : sql->session->status = 0;
4701 67744 : sql->errstr[0] = '\0';
4702 :
4703 67744 : e = rel_order_by_column_exp(query, &rel, col, needs_distinct, sql_sel | sql_orderby | (f & sql_group_totals) | (f & sql_window));
4704 : }
4705 67749 : if (!e)
4706 : return NULL;
4707 114394 : if (!exp_subtype(e))
4708 1 : return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for order by column");
4709 114393 : set_direction(e, direction);
4710 114393 : list_append(exps, e);
4711 : } else {
4712 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: order not of type SQL_COLUMN");
4713 : }
4714 : }
4715 44442 : if (is_sql_orderby(f) && or != rel)
4716 37011 : or->l = rel;
4717 44442 : if (is_sql_window(f))
4718 3021 : *R = rel;
4719 : return exps;
4720 : }
4721 :
4722 : static int
4723 814 : generate_window_bound(tokens sql_token, bool first_half)
4724 : {
4725 814 : switch (sql_token) {
4726 408 : case SQL_PRECEDING:
4727 408 : return first_half ? BOUND_FIRST_HALF_PRECEDING : BOUND_SECOND_HALF_PRECEDING;
4728 284 : case SQL_FOLLOWING:
4729 284 : return first_half ? BOUND_FIRST_HALF_FOLLOWING : BOUND_SECOND_HALF_FOLLOWING;
4730 122 : case SQL_CURRENT_ROW:
4731 122 : return first_half ? CURRENT_ROW_PRECEDING : CURRENT_ROW_FOLLOWING;
4732 : default:
4733 0 : assert(0);
4734 : }
4735 : return 0;
4736 : }
4737 :
4738 : /* window functions */
4739 : static sql_exp*
4740 407 : generate_window_bound_call(mvc *sql, sql_exp **estart, sql_exp **eend, sql_exp *pe, sql_exp *e,
4741 : sql_exp *start, sql_exp *fend, int frame_type, int excl, tokens t1, tokens t2)
4742 : {
4743 407 : list *rargs1 = sa_list(sql->sa), *rargs2 = sa_list(sql->sa), *targs1 = sa_list(sql->sa), *targs2 = sa_list(sql->sa);
4744 407 : sql_subfunc *dc1, *dc2;
4745 407 : sql_subtype *it = sql_bind_localtype("int");
4746 :
4747 407 : if (pe) {
4748 186 : append(targs1, exp_subtype(pe));
4749 186 : append(targs2, exp_subtype(pe));
4750 186 : append(rargs1, exp_copy(sql, pe));
4751 186 : append(rargs2, exp_copy(sql, pe));
4752 : }
4753 407 : append(rargs1, exp_copy(sql, e));
4754 407 : append(rargs2, exp_copy(sql, e));
4755 407 : append(targs1, exp_subtype(e));
4756 407 : append(targs2, exp_subtype(e));
4757 407 : append(targs1, it);
4758 407 : append(targs2, it);
4759 407 : append(targs1, it);
4760 407 : append(targs2, it);
4761 407 : append(targs1, it);
4762 407 : append(targs2, it);
4763 407 : append(targs1, exp_subtype(start));
4764 407 : append(targs2, exp_subtype(fend));
4765 :
4766 407 : dc1 = sql_bind_func_(sql, "sys", "window_bound", targs1, F_ANALYTIC, true, false);
4767 407 : dc2 = sql_bind_func_(sql, "sys", "window_bound", targs2, F_ANALYTIC, true, false);
4768 407 : if (!dc1 || !dc2)
4769 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: function 'window_bound' not found");
4770 407 : append(rargs1, exp_atom_int(sql->sa, frame_type));
4771 407 : append(rargs2, exp_atom_int(sql->sa, frame_type));
4772 407 : append(rargs1, exp_atom_int(sql->sa, generate_window_bound(t1, true)));
4773 407 : append(rargs2, exp_atom_int(sql->sa, generate_window_bound(t2, false)));
4774 407 : append(rargs1, exp_atom_int(sql->sa, excl));
4775 407 : append(rargs2, exp_atom_int(sql->sa, excl));
4776 407 : append(rargs1, start);
4777 407 : append(rargs2, fend);
4778 :
4779 407 : *estart = exp_op(sql->sa, rargs1, dc1);
4780 407 : *eend = exp_op(sql->sa, rargs2, dc2);
4781 407 : return e; /* return something to say there were no errors */
4782 : }
4783 :
4784 : #define EC_NUMERIC(e) (e==EC_NUM||EC_INTERVAL(e)||e==EC_DEC||e==EC_FLT)
4785 :
4786 : static sql_exp*
4787 601 : calculate_window_bound(sql_query *query, sql_rel *p, tokens token, symbol *bound, sql_exp *ie, int frame_type, int f)
4788 : {
4789 601 : mvc *sql = query->sql;
4790 601 : sql_subtype *bt, *bound_tp = sql_bind_localtype("lng"), *iet = exp_subtype(ie);
4791 601 : sql_exp *res = NULL;
4792 :
4793 792 : if ((bound->token == SQL_PRECEDING || bound->token == SQL_FOLLOWING || bound->token == SQL_CURRENT_ROW) && bound->type == type_int) {
4794 191 : atom *a = NULL;
4795 191 : bt = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? bound_tp : iet;
4796 :
4797 191 : if ((bound->data.i_val == UNBOUNDED_PRECEDING_BOUND || bound->data.i_val == UNBOUNDED_FOLLOWING_BOUND)) {
4798 69 : a = atom_max_value(sql->sa, EC_NUMERIC(bt->type->eclass) ? bt : bound_tp);
4799 122 : } else if (bound->data.i_val == CURRENT_ROW_BOUND) {
4800 124 : a = atom_zero_value(sql->sa, EC_NUMERIC(bt->type->eclass) ? bt : bound_tp);
4801 : } else {
4802 0 : assert(0);
4803 : }
4804 191 : res = exp_atom(sql->sa, a);
4805 : } else { /* arbitrary expression case */
4806 410 : exp_kind ek = {type_value, card_column, FALSE};
4807 410 : const char *bound_desc = (token == SQL_PRECEDING) ? "PRECEDING" : "FOLLOWING";
4808 :
4809 410 : assert(token == SQL_PRECEDING || token == SQL_FOLLOWING);
4810 410 : if (!(res = rel_value_exp2(query, &p, bound, f, ek)))
4811 3 : return NULL;
4812 410 : if (!(bt = exp_subtype(res))) { /* frame bound is a parameter */
4813 3 : sql_subtype *t = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? bound_tp : iet;
4814 3 : if (rel_set_type_param(sql, t, p, res, 0) < 0) /* workaround */
4815 : return NULL;
4816 3 : bt = exp_subtype(res);
4817 : }
4818 410 : if (exp_is_null_no_value_opt(res))
4819 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s offset must not be NULL", bound_desc);
4820 409 : if ((frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) && bt->type->eclass != EC_NUM && !(res = exp_check_type(sql, bound_tp, p, res, type_equal)))
4821 : return NULL;
4822 409 : if (frame_type == FRAME_RANGE) {
4823 70 : sql_class iet_class = iet->type->eclass;
4824 :
4825 70 : if (!EC_NUMERIC(iet_class) && !EC_TEMP(iet_class))
4826 1 : return sql_error(sql, 02, SQLSTATE(42000) "Ranges with arbitrary expressions are available to numeric, interval and temporal types only");
4827 12 : if (EC_NUMERIC(iet_class) && !(res = exp_check_type(sql, iet, p, res, type_equal)))
4828 : return NULL;
4829 69 : if ((iet_class == EC_TIME || iet_class == EC_TIME_TZ) && bt->type->eclass != EC_SEC) {
4830 1 : (void) sql_error(sql, 02, SQLSTATE(42000) "For %s input the %s boundary must be an interval type up to the day", subtype2string2(sql->ta, iet), bound_desc);
4831 1 : sa_reset(sql->ta);
4832 1 : return NULL;
4833 : }
4834 68 : if (EC_TEMP(iet->type->eclass) && !EC_INTERVAL(bt->type->eclass)) {
4835 0 : (void) sql_error(sql, 02, SQLSTATE(42000) "For %s input the %s boundary must be an interval type", subtype2string2(sql->ta, iet), bound_desc);
4836 0 : sa_reset(sql->ta);
4837 0 : return NULL;
4838 : }
4839 : }
4840 : }
4841 : return res;
4842 : }
4843 :
4844 : static dlist*
4845 16 : get_window_clauses(mvc *sql, char* ident, symbol **partition_by_clause, symbol **order_by_clause, symbol **frame_clause)
4846 : {
4847 16 : dlist *window_specification = NULL;
4848 16 : char *window_ident;
4849 16 : int pos;
4850 :
4851 16 : if (mvc_highwater(sql))
4852 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
4853 :
4854 16 : if ((window_specification = frame_get_window_def(sql, ident, &pos)) == NULL)
4855 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: window '%s' not found", ident);
4856 :
4857 : /* avoid infinite lookups */
4858 15 : if (frame_check_var_visited(sql, pos))
4859 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: cyclic references to window '%s' found", ident);
4860 14 : frame_set_var_visited(sql, pos);
4861 :
4862 14 : if (window_specification->h->next->data.sym) {
4863 2 : if (*partition_by_clause)
4864 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: redefinition of PARTITION BY clause from window '%s'", ident);
4865 2 : *partition_by_clause = window_specification->h->next->data.sym;
4866 : }
4867 14 : if (window_specification->h->next->next->data.sym) {
4868 4 : if (*order_by_clause)
4869 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: redefinition of ORDER BY clause from window '%s'", ident);
4870 3 : *order_by_clause = window_specification->h->next->next->data.sym;
4871 : }
4872 13 : if (window_specification->h->next->next->next->data.sym) {
4873 0 : if (*frame_clause)
4874 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: redefinition of frame clause from window '%s'", ident);
4875 0 : *frame_clause = window_specification->h->next->next->next->data.sym;
4876 : }
4877 :
4878 13 : window_ident = window_specification->h->data.sval;
4879 13 : if (window_ident && !get_window_clauses(sql, window_ident, partition_by_clause, order_by_clause, frame_clause))
4880 : return NULL; /* the error was already set */
4881 :
4882 : return window_specification; /* return something to say there were no errors */
4883 : }
4884 :
4885 : /*
4886 : * select x, y, rank_op() over (partition by x order by y) as, ...
4887 : aggr_op(z) over (partition by y order by x) as, ...
4888 : * from table [x,y,z,w,v]
4889 : *
4890 : * project and order by over x,y / y,x
4891 : * a = project( table ) [ x, y, z, w, v ], [ x, y]
4892 : * b = project( table ) [ x, y, z, w, v ], [ y, x]
4893 : *
4894 : * project with order dependent operators, ie combined prev/current value
4895 : * aa = project (a) [ x, y, r = rank_op(diff(x) (marks a new partition), rediff(diff(x), y) (marks diff value with in partition)), z, w, v ]
4896 : * project(aa) [ aa.x, aa.y, aa.r ] -- only keep current output list
4897 : * bb = project (b) [ x, y, a = aggr_op(z, diff(y), rediff(diff(y), x)), z, w, v ]
4898 : * project(bb) [ bb.x, bb.y, bb.a ] -- only keep current output list
4899 : */
4900 : static sql_exp *
4901 12706 : rel_rankop(sql_query *query, sql_rel **rel, symbol *se, int f)
4902 : {
4903 12706 : mvc *sql = query->sql;
4904 12706 : node *n;
4905 12706 : dlist *l = se->data.lval, *window_specification = NULL;
4906 12706 : symbol *window_function = l->h->data.sym, *partition_by_clause = NULL, *order_by_clause = NULL, *frame_clause = NULL;
4907 12706 : char *aname = NULL, *sname = NULL, *window_ident = NULL;
4908 12706 : sql_subfunc *wf = NULL;
4909 12706 : sql_exp *in = NULL, *pe = NULL, *oe = NULL, *call = NULL, *start = NULL, *eend = NULL, *fstart = NULL, *fend = NULL, *ie = NULL;
4910 12706 : sql_rel *p;
4911 12706 : list *gbe = NULL, *obe = NULL, *args = NULL, *types = NULL, *fargs = NULL;
4912 12706 : dnode *dn = window_function->data.lval->h, *dargs = NULL;
4913 12706 : int distinct = 0, frame_type, pos, nf = f, nfargs = 0;
4914 12706 : bool is_nth_value, supports_frames, found = false;
4915 :
4916 12706 : frame_clear_visited_flag(sql); /* clear visited flags before iterating */
4917 :
4918 12706 : if (l->h->next->type == type_list) {
4919 12690 : window_specification = l->h->next->data.lval;
4920 16 : } else if (l->h->next->type == type_string) {
4921 16 : const char* window_alias = l->h->next->data.sval;
4922 16 : if ((window_specification = frame_get_window_def(sql, window_alias, &pos)) == NULL)
4923 1 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: window '%s' not found", window_alias);
4924 15 : frame_set_var_visited(sql, pos);
4925 : } else {
4926 0 : assert(0);
4927 : }
4928 :
4929 12705 : window_ident = window_specification->h->data.sval;
4930 12705 : partition_by_clause = window_specification->h->next->data.sym;
4931 12705 : order_by_clause = window_specification->h->next->next->data.sym;
4932 12705 : frame_clause = window_specification->h->next->next->next->data.sym;
4933 :
4934 12705 : if (window_ident && !get_window_clauses(sql, window_ident, &partition_by_clause, &order_by_clause, &frame_clause))
4935 : return NULL;
4936 :
4937 12702 : frame_type = frame_clause ? frame_clause->data.lval->h->next->next->data.i_val : FRAME_RANGE;
4938 12702 : aname = qname_schema_object(dn->data.lval);
4939 12702 : sname = qname_schema(dn->data.lval);
4940 :
4941 12702 : is_nth_value = !strcmp(aname, "nth_value");
4942 12702 : bool is_value = is_nth_value || !strcmp(aname, "first_value") || !strcmp(aname, "last_value");
4943 12702 : supports_frames = window_function->token != SQL_RANK || is_value;
4944 :
4945 12702 : if (is_sql_update_set(f) || is_sql_psm(f) || is_sql_values(f) || is_sql_join(f) || is_sql_where(f) || is_sql_groupby(f) || is_sql_having(f) || is_psm_call(f) || is_sql_from(f)) {
4946 13 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
4947 13 : const char *clause = is_sql_update_set(f)||is_sql_psm(f)?"in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses (use subquery)":is_sql_values(f)?"on an unique value":
4948 8 : is_sql_join(f)?"in JOIN conditions":is_sql_where(f)?"in WHERE clause":is_sql_groupby(f)?"in GROUP BY clause":
4949 4 : is_psm_call(f)?"in CALL":is_sql_from(f)?"in functions in FROM":"in HAVING clause";
4950 13 : return sql_error(sql, 02, SQLSTATE(42000) "%s: window function '%s' not allowed %s", toUpperCopy(uaname, aname), aname, clause);
4951 12689 : } else if (is_sql_aggr(f)) {
4952 2 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
4953 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: window functions not allowed inside aggregation functions", toUpperCopy(uaname, aname));
4954 12687 : } else if (is_sql_window(f)) {
4955 6 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
4956 6 : return sql_error(sql, 02, SQLSTATE(42000) "%s: window functions cannot be nested", toUpperCopy(uaname, aname));
4957 : }
4958 12681 : if (window_function->token == SQL_UNOP || window_function->token == SQL_OP) {
4959 1443 : window_function->token = SQL_NOP;
4960 1443 : dn->next->next->data.lval = dlist_append_symbol(sql->sa, dlist_create( sql->sa ), dn->next->next->data.sym); /* make a list */
4961 : }
4962 12681 : if (window_function->token == SQL_BINOP) {
4963 1064 : window_function->token = SQL_NOP;
4964 1064 : dn->next->next->data.lval = dlist_append_symbol(sql->sa, dlist_append_symbol(sql->sa, dlist_create( sql->sa ), dn->next->next->data.sym), dn->next->next->next->data.sym); /* make a list */
4965 1064 : dn->next->next->next = dn->next->next->next->next; /* skip second arg */
4966 : }
4967 12681 : if (window_function->token == SQL_AGGR)
4968 106 : dn->next->next->data.lval = dlist_append_symbol(sql->sa, dlist_create( sql->sa ), dn->next->next->data.sym); /* make a list */
4969 12681 : if (window_function->token == SQL_NOP)
4970 2509 : window_function->token = SQL_AGGR;
4971 12681 : if (window_function->token != SQL_RANK && window_function->token != SQL_AGGR) {
4972 0 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
4973 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: window function '%s' unknown", toUpperCopy(uaname, aname));
4974 : }
4975 :
4976 : /* window operations are only allowed in the projection */
4977 12681 : if (!is_sql_sel(f))
4978 0 : return sql_error(sql, 02, SQLSTATE(42000) "OVER: only possible within the selection");
4979 :
4980 12681 : p = *rel;
4981 : /* Partition By */
4982 12681 : if (partition_by_clause) {
4983 2321 : gbe = rel_partition_groupings(query, &p, partition_by_clause, NULL /* cannot use (selection) column references, as this result is a selection column */, nf | sql_window);
4984 2321 : if (!gbe)
4985 : return NULL;
4986 4662 : for (n = gbe->h ; n ; n = n->next) {
4987 2349 : sql_exp *en = n->data;
4988 :
4989 2349 : set_ascending(en);
4990 2349 : set_nulls_first(en);
4991 : }
4992 : }
4993 :
4994 : /* Order By */
4995 12673 : if (order_by_clause) {
4996 3028 : obe = rel_order_by(query, &p, order_by_clause, 0, sql_window);
4997 3028 : if (!obe)
4998 : return NULL;
4999 : }
5000 :
5001 12666 : fargs = sa_list(sql->sa);
5002 12666 : if (window_function->token == SQL_RANK) { /* rank function call */
5003 10061 : dlist *dl = dn->next->next->data.lval;
5004 10061 : bool is_lag = !strcmp(aname, "lag"), is_lead = !strcmp(aname, "lead"),
5005 10061 : extra_input = !strcmp(aname, "ntile") || !strcmp(aname, "rank") || !strcmp(aname, "dense_rank") || !strcmp(aname, "row_number") || !strcmp(aname, "percent_rank") || !strcmp(aname, "cume_dist");
5006 :
5007 10061 : distinct = dn->next->data.i_val;
5008 10061 : if (extra_input) { /* pass an input column for analytic functions that don't require it */
5009 9877 : sql_subfunc *star = sql_bind_func(sql, "sys", "star", NULL, NULL, F_FUNC, true, true);
5010 9877 : in = exp_op(sql->sa, NULL, star);
5011 9877 : append(fargs, in);
5012 : }
5013 10061 : if (dl)
5014 593 : for (dargs = dl->h ; dargs ; dargs = dargs->next) {
5015 339 : exp_kind ek = {type_value, card_column, FALSE};
5016 339 : sql_subtype *empty = sql_bind_localtype("void"), *bte = sql_bind_localtype("bte");
5017 :
5018 339 : in = rel_value_exp2(query, &p, dargs->data.sym, f | sql_window | sql_farg, ek);
5019 339 : if (!in)
5020 0 : return NULL;
5021 339 : if (!exp_subtype(in)) { /* we also do not expect parameters here */
5022 0 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
5023 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: parameters not allowed as arguments to window functions", toUpperCopy(uaname, aname));
5024 : }
5025 339 : if (!exp_name(in))
5026 151 : exp_label(sql->sa, in, ++sql->label);
5027 :
5028 : /* corner case, if the argument is null convert it into something countable such as bte */
5029 339 : if (subtype_cmp(exp_subtype(in), empty) == 0)
5030 20 : in = exp_convert(sql, in, empty, bte);
5031 339 : if ((is_lag || is_lead) && nfargs == 2) { /* lag and lead 3rd arg must have same type as 1st arg */
5032 10 : sql_exp *first = (sql_exp*) fargs->h->data;
5033 10 : if (!(in = exp_check_type(sql, exp_subtype(first), p, in, type_equal)))
5034 : return NULL;
5035 : }
5036 329 : if (!in)
5037 : return NULL;
5038 :
5039 339 : append(fargs, in);
5040 339 : in = exp_ref_save(sql, in);
5041 339 : nfargs++;
5042 : }
5043 : } else { /* aggregation function call */
5044 2605 : distinct = dn->next->data.i_val;
5045 6161 : for (dargs = dn->next->next->data.lval->h ; dargs && dargs->data.sym ; dargs = dargs->next) {
5046 3564 : exp_kind ek = {type_value, card_column, FALSE};
5047 3564 : sql_subtype *empty = sql_bind_localtype("void"), *bte = sql_bind_localtype("bte");
5048 :
5049 3564 : in = rel_value_exp2(query, &p, dargs->data.sym, f | sql_window | sql_farg, ek);
5050 3564 : if (!in)
5051 8 : return NULL;
5052 3557 : if (!exp_subtype(in)) { /* we also do not expect parameters here */
5053 1 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
5054 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: parameters not allowed as arguments to window functions", toUpperCopy(uaname, aname));
5055 : }
5056 3556 : if (!exp_name(in))
5057 1942 : exp_label(sql->sa, in, ++sql->label);
5058 :
5059 : /* corner case, if the argument is null convert it into something countable such as bte */
5060 3556 : if (subtype_cmp(exp_subtype(in), empty) == 0)
5061 46 : in = exp_convert(sql, in, empty, bte);
5062 3556 : if (!in)
5063 : return NULL;
5064 :
5065 3556 : append(fargs, in);
5066 3556 : in = exp_ref_save(sql, in);
5067 3556 : nfargs++;
5068 :
5069 3556 : if (!strcmp(aname, "count"))
5070 86 : append(fargs, exp_atom_bool(sql->sa, 1)); /* ignore nills */
5071 : }
5072 :
5073 2597 : if (!nfargs) { /* count(*) */
5074 109 : if (window_function->token == SQL_AGGR && strcmp(aname, "count") != 0) {
5075 2 : char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
5076 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: unable to perform '%s(*)'", toUpperCopy(uaname, aname), aname);
5077 : }
5078 107 : sql_subfunc *star = sql_bind_func(sql, "sys", "star", NULL, NULL, F_FUNC, true, true);
5079 107 : in = exp_op(sql->sa, NULL, star);
5080 107 : append(fargs, in);
5081 107 : append(fargs, exp_atom_bool(sql->sa, 0)); /* don't ignore nills */
5082 : }
5083 : }
5084 :
5085 12656 : if (distinct)
5086 4 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: DISTINCT clause is not implemented for window functions");
5087 :
5088 : /* diff for partitions */
5089 12652 : if (gbe) {
5090 2304 : sql_subtype *bt = sql_bind_localtype("bit");
5091 :
5092 4643 : for( n = gbe->h; n; n = n->next) {
5093 2340 : sql_subfunc *df;
5094 2340 : sql_exp *e = n->data;
5095 :
5096 2340 : if (!exp_subtype(e))
5097 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameters not allowed at PARTITION BY clause from window functions");
5098 :
5099 2339 : e = exp_copy(sql, e);
5100 2339 : args = sa_list(sql->sa);
5101 2339 : if (pe) {
5102 36 : df = sql_bind_func(sql, "sys", "diff", bt, exp_subtype(e), F_ANALYTIC, true, true);
5103 36 : append(args, pe);
5104 : } else {
5105 2303 : df = sql_bind_func(sql, "sys", "diff", exp_subtype(e), NULL, F_ANALYTIC, true, true);
5106 : }
5107 2339 : if (!df)
5108 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: function 'diff' not found");
5109 2339 : append(args, e);
5110 2339 : pe = exp_op(sql->sa, args, df);
5111 : }
5112 : } else {
5113 10348 : pe = exp_atom_bool(sql->sa, 0);
5114 : }
5115 :
5116 : /* diff for orderby */
5117 12651 : if (obe) {
5118 3019 : sql_subtype *bt = sql_bind_localtype("bit");
5119 :
5120 6194 : for( n = obe->h; n; n = n->next) {
5121 3175 : sql_subfunc *df;
5122 3175 : sql_exp *e = n->data;
5123 :
5124 3175 : if (!exp_subtype(e))
5125 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameters not allowed at ORDER BY clause from window functions");
5126 :
5127 3175 : e = exp_copy(sql, e);
5128 3175 : args = sa_list(sql->sa);
5129 3175 : if (oe) {
5130 156 : df = sql_bind_func(sql, "sys", "diff", bt, exp_subtype(e), F_ANALYTIC, true, true);
5131 156 : append(args, oe);
5132 : } else {
5133 3019 : df = sql_bind_func(sql, "sys", "diff", exp_subtype(e), NULL, F_ANALYTIC, true, true);
5134 : }
5135 3175 : if (!df)
5136 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: function 'diff' not found");
5137 3175 : append(args, e);
5138 3175 : oe = exp_op(sql->sa, args, df);
5139 : }
5140 : } else {
5141 9632 : oe = exp_atom_bool(sql->sa, 0);
5142 : }
5143 :
5144 12651 : if (frame_clause || supports_frames) {
5145 2708 : if (frame_type == FRAME_RANGE)
5146 2397 : ie = obe ? (sql_exp*) obe->t->data : in;
5147 : else
5148 311 : ie = obe ? oe : in;
5149 : }
5150 12651 : assert(oe && pe);
5151 :
5152 12651 : types = exp_types(sql->sa, fargs);
5153 12651 : wf = bind_func_(sql, sname, aname, types, F_ANALYTIC, false, &found, false);
5154 12651 : if (wf && !list_empty(fargs) && !(fargs = check_arguments_and_find_largest_any_type(sql, NULL, fargs, wf, 0, false)))
5155 : wf = NULL;
5156 12646 : if (!wf) {
5157 5 : char *arg_list = nfargs ? nary_function_arg_types_2str(sql, types, nfargs) : NULL;
5158 10 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s window function %s%s%s'%s'(%s)",
5159 5 : found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", aname, arg_list ? arg_list : "");
5160 : }
5161 :
5162 : /* Frame */
5163 12646 : if (frame_clause) {
5164 410 : dnode *d = frame_clause->data.lval->h;
5165 410 : symbol *wstart = d->data.sym, *wend = d->next->data.sym, *rstart = wstart->data.lval->h->data.sym,
5166 410 : *rend = wend->data.lval->h->data.sym;
5167 410 : int excl = d->next->next->next->data.i_val;
5168 410 : bool shortcut = false;
5169 :
5170 410 : if (!supports_frames)
5171 4 : return sql_error(sql, 02, SQLSTATE(42000) "OVER: frame extend only possible with aggregation and first_value, last_value and nth_value functions");
5172 406 : if (excl != EXCLUDE_NONE)
5173 0 : return sql_error(sql, 02, SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented");
5174 406 : if (list_empty(obe) && frame_type == FRAME_GROUPS)
5175 2 : return sql_error(sql, 02, SQLSTATE(42000) "GROUPS frame requires an order by expression");
5176 404 : if (wstart->token == SQL_FOLLOWING && wend->token == SQL_PRECEDING)
5177 1 : return sql_error(sql, 02, SQLSTATE(42000) "FOLLOWING offset must come after PRECEDING offset");
5178 403 : if (wstart->token == SQL_CURRENT_ROW && wend->token == SQL_PRECEDING)
5179 1 : return sql_error(sql, 02, SQLSTATE(42000) "CURRENT ROW offset must come after PRECEDING offset");
5180 402 : if (wstart->token == SQL_FOLLOWING && wend->token == SQL_CURRENT_ROW)
5181 1 : return sql_error(sql, 02, SQLSTATE(42000) "FOLLOWING offset must come after CURRENT ROW offset");
5182 401 : if (wstart->token != SQL_CURRENT_ROW && wend->token != SQL_CURRENT_ROW && wstart->token == wend->token && frame_type != FRAME_ROWS)
5183 4 : return sql_error(sql, 02, SQLSTATE(42000) "Non-centered windows are only supported in row frames");
5184 367 : if (frame_type == FRAME_RANGE) {
5185 97 : if (((wstart->token == SQL_PRECEDING || wstart->token == SQL_FOLLOWING) && rstart->token != SQL_PRECEDING && rstart->token != SQL_CURRENT_ROW && rstart->token != SQL_FOLLOWING) ||
5186 59 : ((wend->token == SQL_PRECEDING || wend->token == SQL_FOLLOWING) && rend->token != SQL_PRECEDING && rend->token != SQL_CURRENT_ROW && rend->token != SQL_FOLLOWING)) {
5187 40 : if (list_empty(obe))
5188 2 : return sql_error(sql, 02, SQLSTATE(42000) "RANGE frame with PRECEDING/FOLLOWING offset requires an order by expression");
5189 38 : if (list_length(obe) > 1)
5190 0 : return sql_error(sql, 02, SQLSTATE(42000) "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column");
5191 : }
5192 : }
5193 :
5194 395 : if (list_empty(obe) && frame_type == FRAME_RANGE) { /* window functions are weird */
5195 : frame_type = FRAME_ALL;
5196 : shortcut = true;
5197 383 : } else if (!is_value && (rstart->token == SQL_PRECEDING || rstart->token == SQL_CURRENT_ROW || rstart->token == SQL_FOLLOWING) && rstart->type == type_int &&
5198 150 : (rend->token == SQL_PRECEDING || rend->token == SQL_CURRENT_ROW || rend->token == SQL_FOLLOWING) && rend->type == type_int) {
5199 : /* special cases, don't calculate bounds */
5200 146 : if (frame_type != FRAME_ROWS && rstart->data.i_val == UNBOUNDED_PRECEDING_BOUND && rend->data.i_val == CURRENT_ROW_BOUND) {
5201 : frame_type = FRAME_UNBOUNDED_TILL_CURRENT_ROW;
5202 : shortcut = true;
5203 21 : } else if (frame_type != FRAME_ROWS && rstart->data.i_val == CURRENT_ROW_BOUND && rend->data.i_val == UNBOUNDED_FOLLOWING_BOUND) {
5204 : frame_type = FRAME_CURRENT_ROW_TILL_UNBOUNDED;
5205 : shortcut = true;
5206 86 : } else if (rstart->data.i_val == UNBOUNDED_PRECEDING_BOUND && rend->data.i_val == UNBOUNDED_FOLLOWING_BOUND) {
5207 : frame_type = FRAME_ALL;
5208 : shortcut = true;
5209 76 : } else if (rstart->data.i_val == CURRENT_ROW_BOUND && rend->data.i_val == CURRENT_ROW_BOUND) {
5210 395 : frame_type = FRAME_CURRENT_ROW;
5211 395 : shortcut = true;
5212 : }
5213 : }
5214 395 : if (!shortcut) {
5215 302 : if (!(fstart = calculate_window_bound(query, p, wstart->token, rstart, ie, frame_type, f | sql_window)))
5216 : return NULL;
5217 299 : if (!(fend = calculate_window_bound(query, p, wend->token, rend, ie, frame_type, f | sql_window)))
5218 : return NULL;
5219 471 : if (!generate_window_bound_call(sql, &start, &eend, gbe ? pe : NULL, ie, fstart, fend, frame_type, excl,
5220 : wstart->token, wend->token))
5221 : return NULL;
5222 : }
5223 12236 : } else if (supports_frames) { /* for analytic functions with no frame clause, we use the standard default values */
5224 2295 : if (is_value) {
5225 108 : sql_subtype *bound_tp = sql_bind_localtype("lng"), *bt = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? bound_tp : exp_subtype(ie);
5226 108 : unsigned char sclass = bt->type->eclass;
5227 :
5228 136 : fstart = exp_atom(sql->sa, atom_max_value(sql->sa, EC_NUMERIC(sclass) ? bt : bound_tp));
5229 108 : fend = order_by_clause ? exp_atom(sql->sa, atom_zero_value(sql->sa, EC_NUMERIC(sclass) ? bt : bound_tp)) :
5230 23 : exp_atom(sql->sa, atom_max_value(sql->sa, EC_NUMERIC(sclass) ? bt : bound_tp));
5231 :
5232 157 : if (generate_window_bound_call(sql, &start, &eend, gbe ? pe : NULL, ie, fstart, fend, frame_type, EXCLUDE_NONE, SQL_PRECEDING, SQL_FOLLOWING) == NULL)
5233 : return NULL;
5234 : } else {
5235 2187 : frame_type = list_empty(obe) ? FRAME_ALL : FRAME_UNBOUNDED_TILL_CURRENT_ROW;
5236 : }
5237 : }
5238 :
5239 12628 : args = sa_list(sql->sa);
5240 26650 : for (node *n = fargs->h ; n ; n = n->next)
5241 14022 : list_append(args, n->data);
5242 12628 : list_append(args, pe);
5243 12628 : list_append(args, oe);
5244 12628 : if (supports_frames) {
5245 2687 : list_append(args, exp_atom_int(sql->sa, frame_type));
5246 2687 : list_append(args, start ? start : exp_atom_oid(sql->sa, 1));
5247 2687 : list_append(args, eend ? eend : exp_atom_oid(sql->sa, 1));
5248 : }
5249 12628 : call = exp_rank_op(sql->sa, list_empty(args) ? NULL : args, gbe, obe, wf);
5250 12628 : *rel = p;
5251 12628 : return call;
5252 : }
5253 :
5254 : sql_exp *
5255 5937470 : rel_value_exp2(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
5256 : {
5257 5937470 : mvc *sql = query->sql;
5258 5937470 : if (!se)
5259 : return NULL;
5260 :
5261 5937470 : if (mvc_highwater(sql))
5262 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
5263 :
5264 5937644 : if (rel && *rel && (*rel)->card == CARD_AGGR) { /* group by expression case, handle it before */
5265 136262 : sql_exp *exp = NULL;
5266 136262 : if (!is_sql_aggr(f) && !is_sql_window(f))
5267 135803 : exp = frame_get_groupby_expression(sql, se);
5268 136262 : if (sql->errstr[0] != '\0')
5269 : return NULL;
5270 136262 : if (exp) {
5271 80 : sql_exp *res = exp_ref(sql, exp);
5272 80 : res->card = (*rel)->card;
5273 80 : if (se->token == SQL_AGGR) {
5274 0 : dlist *l = se->data.lval;
5275 0 : int distinct = l->h->next->data.i_val;
5276 0 : if (distinct)
5277 0 : set_distinct(res);
5278 : }
5279 80 : if (!query_has_outer(query) && is_groupby((*rel)->op))
5280 76 : res = rel_groupby_add_aggr(sql, *rel, res);
5281 80 : return res;
5282 : }
5283 : }
5284 :
5285 5937564 : switch (se->token) {
5286 1868 : case SQL_OP:
5287 1868 : return rel_op(query, rel, se, f, ek);
5288 77815 : case SQL_UNOP:
5289 77815 : return rel_unop(query, rel, se, f, ek);
5290 382599 : case SQL_BINOP:
5291 382599 : return rel_binop(query, rel, se, f, ek);
5292 86848 : case SQL_NOP:
5293 86848 : return rel_nop(query, rel, se, f, ek);
5294 23867 : case SQL_AGGR:
5295 23867 : return rel_aggr(query, rel, se, f);
5296 12706 : case SQL_WINDOW:
5297 12706 : return rel_rankop(query, rel, se, f);
5298 2353912 : case SQL_IDENT:
5299 : case SQL_COLUMN:
5300 2353912 : return rel_column_ref(query, rel, se, f );
5301 3019 : case SQL_NAME: {
5302 3019 : dlist *l = se->data.lval;
5303 3019 : const char *sname = qname_schema(l);
5304 3019 : const char *vname = qname_schema_object(l);
5305 3019 : return rel_exp_variable_on_scope(sql, sname, vname);
5306 : }
5307 50885 : case SQL_VALUES:
5308 : case SQL_WITH:
5309 : case SQL_SELECT: {
5310 50885 : sql_rel *r = NULL;
5311 :
5312 50885 : if (is_psm_call(f) || is_sql_merge(f))
5313 8 : return sql_error(sql, 02, SQLSTATE(42000) "%s: subqueries not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
5314 50881 : if (rel && *rel)
5315 36766 : query_push_outer(query, *rel, f);
5316 50881 : if (se->token == SQL_WITH) {
5317 36 : r = rel_with_query(query, se);
5318 50845 : } else if (se->token == SQL_VALUES) {
5319 237 : r = rel_values(query, se, NULL);
5320 : } else {
5321 50608 : assert(se->token == SQL_SELECT);
5322 50608 : exp_kind nek = ek;
5323 50608 : nek.aggr = is_sql_aggr(f);
5324 50608 : if (is_sql_no_subquery(f))
5325 3 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery not allowed");
5326 :
5327 50605 : r = rel_subquery(query, se, nek);
5328 50605 : if (r)
5329 50505 : exps_label(sql, r->exps);
5330 : }
5331 50878 : if (rel && *rel) {
5332 36763 : *rel = query_pop_outer(query);
5333 36763 : if (is_sql_join(f) && is_groupby((*rel)->op)) {
5334 0 : return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
5335 36763 : } else if (is_sql_where(f) && is_groupby((*rel)->op)) {
5336 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
5337 36763 : } else if ((is_sql_update_set(f) || is_sql_psm(f)) && is_groupby((*rel)->op)) {
5338 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
5339 : }
5340 : }
5341 50878 : if (!r)
5342 : return NULL;
5343 50775 : if (ek.type == type_value && ek.card <= card_set && is_project(r->op) && list_length(r->exps) > 1)
5344 16 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column");
5345 50759 : if (ek.type == type_relation && is_project(r->op) && list_length(r->exps) != ek.type)
5346 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery has too %s columns", list_length(r->exps) < ek.type ? "few" : "many");
5347 50759 : if (ek.type == type_value && list_length(r->exps) == 1 && !is_sql_psm(f)) /* for now don't rename multi attribute results */
5348 38505 : r = rel_zero_or_one(sql, r, ek);
5349 50759 : return exp_rel(sql, r);
5350 : }
5351 215 : case SQL_TABLE: {
5352 : /* turn a subquery into a tabular result */
5353 215 : *rel = rel_selects(query, se->data.sym);
5354 215 : if (*rel)
5355 213 : return lastexp(*rel);
5356 : return NULL;
5357 : }
5358 1612 : case SQL_PARAMETER: {
5359 1612 : assert(se->type == type_int);
5360 1612 : sql_arg *a = sql_bind_paramnr(sql, se->data.i_val);
5361 1612 : if (sql->emode != m_prepare) {
5362 1 : if (a && a->name && a->name[0])
5363 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: named placeholder ('%s') but named values list is missing", a->name);
5364 : else
5365 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameters ('?') not allowed in normal queries, use PREPARE");
5366 : }
5367 1611 : return exp_atom_ref(sql->sa, se->data.i_val, a?&a->type:NULL);
5368 : }
5369 107840 : case SQL_NULL:
5370 107840 : return exp_null(sql->sa, sql_bind_localtype("void"));
5371 1590 : case SQL_NEXT:
5372 1590 : return rel_next_value_for(sql, se);
5373 172566 : case SQL_CAST:
5374 172566 : return rel_cast(query, rel, se, f);
5375 105303 : case SQL_CASE:
5376 : case SQL_COALESCE:
5377 : case SQL_NULLIF:
5378 105303 : return rel_case_exp(query, rel, se, f);
5379 1 : case SQL_RANK:
5380 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: window function %s requires an OVER clause", qname_schema_object(se->data.lval->h->data.lval));
5381 25 : case SQL_XMLELEMENT:
5382 : case SQL_XMLFOREST:
5383 : case SQL_XMLCOMMENT:
5384 : case SQL_XMLATTRIBUTE:
5385 : case SQL_XMLCONCAT:
5386 : case SQL_XMLDOCUMENT:
5387 : case SQL_XMLPI:
5388 : case SQL_XMLTEXT:
5389 25 : return rel_xml(query, rel, se, f, ek);
5390 2554893 : default:
5391 2554893 : return rel_logical_value_exp(query, rel, se, f, ek);
5392 : }
5393 : }
5394 :
5395 : static int exps_has_rank(list *exps);
5396 :
5397 : static int
5398 : exp_has_rank(sql_exp *e)
5399 : {
5400 : switch(e->type) {
5401 : case e_convert:
5402 : return exp_has_rank(e->l);
5403 : case e_func:
5404 : if (e->r)
5405 : return 1;
5406 : /* fall through */
5407 : case e_aggr:
5408 : return exps_has_rank(e->l);
5409 : case e_cmp:
5410 : if (e->flag == cmp_or || e->flag == cmp_filter)
5411 : return exps_has_rank(e->l) || exps_has_rank(e->r);
5412 : if (e->flag == cmp_in || e->flag == cmp_notin)
5413 : return exp_has_rank(e->l) || exps_has_rank(e->r);
5414 : return exp_has_rank(e->l) || exp_has_rank(e->r) || (e->f && exp_has_rank(e->f));
5415 : default:
5416 : return 0;
5417 : }
5418 : }
5419 :
5420 : /* TODO create exps_has (list, fptr ) */
5421 : static int
5422 : exps_has_rank(list *exps)
5423 : {
5424 : if (!exps || list_empty(exps))
5425 : return 0;
5426 : for(node *n = exps->h; n; n=n->next){
5427 : sql_exp *e = n->data;
5428 :
5429 : if (exp_has_rank(e))
5430 : return 1;
5431 : }
5432 : return 0;
5433 : }
5434 :
5435 : sql_exp *
5436 4510610 : rel_value_exp(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
5437 : {
5438 4510610 : if (!se)
5439 : return NULL;
5440 :
5441 4510610 : if (mvc_highwater(query->sql))
5442 0 : return sql_error(query->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
5443 :
5444 4510670 : sql_exp *e = rel_value_exp2(query, rel, se, f, ek);
5445 4510695 : if (e && (se->token == SQL_SELECT || se->token == SQL_TABLE) && !exp_is_rel(e)) {
5446 0 : assert(*rel);
5447 0 : return rel_lastexp(query->sql, *rel);
5448 : }
5449 : return e;
5450 : }
5451 :
5452 : static sql_exp *
5453 1325086 : column_exp(sql_query *query, sql_rel **rel, symbol *column_e, int f)
5454 : {
5455 1325086 : dlist *l = column_e->data.lval;
5456 1325086 : exp_kind ek = {type_value, card_column, FALSE};
5457 1325086 : sql_exp *ve;
5458 :
5459 1325086 : if (f == sql_sel && rel && *rel && (*rel)->card < CARD_AGGR)
5460 82618 : ek.card = card_value;
5461 1325086 : ve = rel_value_exp(query, rel, l->h->data.sym, f, ek);
5462 1325153 : if (!ve)
5463 : return NULL;
5464 : /* AS name */
5465 1324032 : if (ve && l->h->next->data.sval)
5466 507180 : exp_setname(query->sql, ve, NULL, l->h->next->data.sval);
5467 : return ve;
5468 : }
5469 :
5470 : static int
5471 843509 : exp_is_not_intern(sql_exp *e)
5472 : {
5473 843509 : return is_intern(e)?-1:0;
5474 : }
5475 :
5476 : static void
5477 129318 : rel_remove_internal_exp(sql_rel *rel)
5478 : {
5479 129318 : if (rel->exps) {
5480 129318 : list *n_exps = list_select(rel->exps, rel, (fcmp)&exp_is_not_intern, (fdup)NULL);
5481 :
5482 129318 : rel->exps = n_exps;
5483 : }
5484 129318 : }
5485 :
5486 : static inline int
5487 16 : exp_key(sql_exp *e)
5488 : {
5489 16 : if (e->alias.name)
5490 16 : return hash_key(e->alias.name);
5491 : return 0;
5492 : }
5493 :
5494 : static list *
5495 5 : group_merge_exps(mvc *sql, list *gexps, list *exps)
5496 : {
5497 5 : int nexps = list_length(gexps) + list_length(exps);
5498 :
5499 5 : sql_hash *ht = hash_new(sql->ta, nexps, (fkeyvalue)&exp_key);
5500 :
5501 9 : for (node *n = gexps->h; n ; n = n->next) { /* first add grouping expressions */
5502 4 : sql_exp *e = n->data;
5503 4 : int key = ht->key(e);
5504 :
5505 4 : hash_add(ht, key, e);
5506 : }
5507 :
5508 17 : for (node *n = exps->h; n ; n = n->next) { /* then test if the new grouping expressions are already there */
5509 12 : sql_exp *e = n->data;
5510 12 : int key = ht->key(e);
5511 12 : sql_hash_e *he = ht->buckets[key&(ht->size-1)];
5512 12 : bool duplicates = false;
5513 :
5514 16 : for (; he && !duplicates; he = he->chain) {
5515 4 : sql_exp *f = he->value;
5516 :
5517 4 : if (!exp_equal(e, f))
5518 4 : duplicates = true;
5519 : }
5520 12 : hash_add(ht, key, e);
5521 12 : if (!duplicates) {
5522 8 : list_append(gexps, e);
5523 8 : n->data = exp_ref(sql, e);
5524 : }
5525 : }
5526 5 : return gexps;
5527 : }
5528 :
5529 : static list *
5530 58430 : rel_table_exp(sql_query *query, sql_rel **rel, symbol *column_e, bool single_exp )
5531 : {
5532 58430 : mvc *sql = query->sql;
5533 58430 : if (column_e->token == SQL_TABLE && column_e->data.lval->h->type == type_symbol) {
5534 0 : sql_rel *r;
5535 :
5536 0 : if (!is_project((*rel)->op))
5537 : return NULL;
5538 0 : r = rel_named_table_function(query, (*rel)->l, column_e, 0, NULL);
5539 0 : if (!r)
5540 : return NULL;
5541 0 : *rel = r;
5542 0 : return sa_list(sql->sa);
5543 58430 : } else if (column_e->token == SQL_TABLE) {
5544 57320 : char *tname = column_e->data.lval->h->data.sval;
5545 57320 : list *exps = NULL;
5546 57320 : sql_rel *project = *rel, *groupby = NULL;
5547 :
5548 : /* if there's a group by relation in the tree, skip it for the '*' case and use the underlying projection */
5549 57320 : if (project) {
5550 66626 : while (is_groupby(project->op) || is_select(project->op)) {
5551 9306 : if (is_groupby(project->op))
5552 5 : groupby = project;
5553 9306 : if (project->l)
5554 9306 : project = project->l;
5555 : }
5556 : assert(project);
5557 : }
5558 :
5559 57320 : if (project->op == op_project && project->l && project == *rel && !tname && !rel_is_ref(project) && !need_distinct(project) && single_exp) {
5560 497 : sql_rel *l = project->l;
5561 497 : if (!l || !is_project(l->op) || list_length(project->exps) == list_length(l->exps)) {
5562 490 : rel_remove_internal_exp(*rel);
5563 490 : exps = project->exps;
5564 490 : *rel = project->l;
5565 : }
5566 : }
5567 57320 : if ((exps || (exps = rel_table_projections(sql, project, tname, 0)) != NULL) && !list_empty(exps)) {
5568 57316 : if (!(exps = check_distinct_exp_names(sql, exps)))
5569 0 : return sql_error(sql, 02, SQLSTATE(42000) "Duplicate column names in table%s%s%s projection list", tname ? " '" : "", tname ? tname : "", tname ? "'" : "");
5570 57315 : if (groupby) {
5571 5 : groupby->exps = group_merge_exps(sql, groupby->exps, exps);
5572 8 : for (node *n = groupby->exps->h ; n ; n = n->next) {
5573 8 : sql_exp *e = n->data;
5574 :
5575 8 : if (e->card > groupby->card) {
5576 4 : if (exp_name(e) && !has_label(e))
5577 4 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(e));
5578 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
5579 : }
5580 : }
5581 : }
5582 57310 : return exps;
5583 : }
5584 4 : if (!tname)
5585 2 : return sql_error(sql, 02, SQLSTATE(42000) "Table expression without table name");
5586 2 : return sql_error(sql, 02, SQLSTATE(42000) "Column expression Table '%s' unknown", tname);
5587 : }
5588 : return NULL;
5589 : }
5590 :
5591 : sql_exp *
5592 1382400 : rel_column_exp(sql_query *query, sql_rel **rel, symbol *column_e, int f)
5593 : {
5594 1382400 : if (column_e->token == SQL_COLUMN || column_e->token == SQL_IDENT)
5595 1325091 : return column_exp(query, rel, column_e, f);
5596 : return NULL;
5597 : }
5598 :
5599 : static sql_rel*
5600 374499 : rel_where_groupby_nodes(sql_query *query, sql_rel *rel, SelectNode *sn, int *group_totals)
5601 : {
5602 374499 : mvc *sql = query->sql;
5603 :
5604 374499 : if (sn->where) {
5605 146683 : rel = rel_logical_exp(query, rel, sn->where, sql_where);
5606 146683 : if (!rel) {
5607 73 : if (sql->errstr[0] == 0)
5608 0 : return sql_error(sql, 02, SQLSTATE(42000) "Subquery result missing");
5609 : return NULL;
5610 : }
5611 : }
5612 374426 : query_processed(query);
5613 :
5614 374431 : if (rel && sn->groupby) {
5615 13408 : list *gbe = NULL, *sets = NULL;
5616 13408 : int all = 0;
5617 13408 : if (sn->groupby->data.lval == NULL) { /* ALL */
5618 : all = 1;
5619 : } else {
5620 49514 : for (dnode *o = sn->groupby->data.lval->h; o ; o = o->next) {
5621 36233 : symbol *grouping = o->data.sym;
5622 36233 : if (grouping->token == SQL_ROLLUP || grouping->token == SQL_CUBE || grouping->token == SQL_GROUPING_SETS) {
5623 119 : *group_totals |= sql_group_totals;
5624 119 : break;
5625 : }
5626 : }
5627 13400 : gbe = rel_groupings(query, &rel, sn->groupby, sn->selection, sql_sel | sql_groupby | *group_totals, false, &sets);
5628 13400 : if (!gbe)
5629 19 : return NULL;
5630 : }
5631 13389 : rel = rel_groupby(sql, rel, gbe);
5632 13389 : if (rel && all)
5633 8 : rel->flag = 2;
5634 13389 : if (sets && list_length(sets) > 1) { /* if there is only one combination, there is no reason to generate unions */
5635 114 : prop *p = prop_create(sql->sa, PROP_GROUPINGS, rel->p);
5636 114 : p->value.pval = sets;
5637 114 : rel->p = p;
5638 : }
5639 : }
5640 :
5641 374412 : if (rel && sn->having) {
5642 : /* having implies group by, ie if not supplied do a group by */
5643 1766 : if (rel->op != op_groupby)
5644 128 : rel = rel_groupby(sql, rel, NULL);
5645 : }
5646 374412 : query_processed(query);
5647 374427 : return rel;
5648 : }
5649 :
5650 : static sql_rel*
5651 373297 : rel_having_limits_nodes(sql_query *query, sql_rel *rel, SelectNode *sn, exp_kind ek, int group_totals)
5652 : {
5653 373297 : mvc *sql = query->sql;
5654 373297 : sql_rel *inner = NULL;
5655 373297 : int single_value = 1;
5656 :
5657 373297 : if (is_project(rel->op) && rel->l) {
5658 373297 : inner = rel->l;
5659 373297 : single_value = 0;
5660 : }
5661 :
5662 373297 : if (sn->having) {
5663 1754 : if (inner && is_groupby(inner->op))
5664 1754 : set_processed(inner);
5665 1754 : if (!(inner = rel_logical_exp(query, inner, sn->having, sql_having | group_totals)))
5666 : return NULL;
5667 1715 : if (inner->exps && exps_card(inner->exps) > CARD_AGGR)
5668 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: cannot compare sets with values, probably an aggregate function missing");
5669 1715 : if (!single_value)
5670 1715 : rel->l = inner;
5671 : }
5672 :
5673 373258 : if (rel && sn->distinct)
5674 1029 : rel = rel_distinct(rel);
5675 :
5676 373258 : if (rel && sn->orderby) {
5677 37057 : list *obe = NULL;
5678 37057 : sql_rel *sel = NULL, *l = rel->l;
5679 :
5680 : /* project( select ) */
5681 37057 : if (sn->having && is_select(l->op)) {
5682 52 : sel = l;
5683 52 : rel->l = l->l;
5684 : }
5685 37057 : rel = rel_orderby(sql, rel);
5686 37057 : set_processed(rel);
5687 37057 : obe = rel_order_by(query, &rel, sn->orderby, sn->distinct, sql_orderby | group_totals);
5688 37057 : if (!obe)
5689 : return NULL;
5690 37017 : rel->r = obe;
5691 37017 : if (sel) {
5692 51 : sql_rel *o = rel, *p = o->l;
5693 51 : p->l = sel;
5694 : }
5695 : }
5696 373218 : if (!rel)
5697 : return NULL;
5698 :
5699 373218 : if (sn->limit || sn->offset) {
5700 16377 : sql_subtype *lng = sql_bind_localtype("lng");
5701 16376 : list *exps = new_exp_list(sql->sa);
5702 :
5703 16375 : if (sn->limit) {
5704 16349 : sql_exp *l = rel_value_exp(query, NULL, sn->limit, 0, ek);
5705 :
5706 16353 : if (!l || !(l=exp_check_type(sql, lng, NULL, l, type_equal)))
5707 0 : return NULL;
5708 16353 : if ((ek.card != card_relation && sn->limit) &&
5709 : (ek.card == card_value && sn->limit)) {
5710 11 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", exp_subtype(l), NULL, F_AGGR, true, true);
5711 11 : l = exp_aggr1(sql->sa, l, zero_or_one, 0, 0, CARD_ATOM, has_nil(l));
5712 : }
5713 16353 : list_append(exps, l);
5714 : } else
5715 26 : list_append(exps, exp_atom(sql->sa, atom_general(sql->sa, lng, NULL, 0)));
5716 16376 : if (sn->offset) {
5717 85 : sql_exp *o = rel_value_exp( query, NULL, sn->offset, 0, ek);
5718 85 : if (!o || !(o=exp_check_type(sql, lng, NULL, o, type_equal)))
5719 0 : return NULL;
5720 85 : list_append(exps, o);
5721 : }
5722 16376 : rel = rel_topn(sql->sa, rel, exps);
5723 : }
5724 :
5725 373218 : if (sn->sample || sn->seed) {
5726 16 : list *exps = new_exp_list(sql->sa);
5727 :
5728 24 : if (sn->sample) {
5729 23 : sql_exp *s = rel_value_exp(query, NULL, sn->sample, 0, ek);
5730 23 : if (!s)
5731 : return NULL;
5732 23 : if (!exp_subtype(s) && rel_set_type_param(sql, sql_bind_localtype("lng"), NULL, s, 0) < 0)
5733 : return NULL;
5734 23 : list_append(exps, s);
5735 : } else {
5736 1 : assert(sn->seed);
5737 1 : return sql_error(sql, 02, SQLSTATE(42000) "SEED: cannot have SEED without SAMPLE");
5738 : }
5739 23 : if (sn->seed) {
5740 12 : sql_exp *e = rel_value_exp(query, NULL, sn->seed, 0, ek);
5741 12 : if (!e || !(e=exp_check_type(sql, sql_bind_localtype("int"), NULL, e, type_equal)))
5742 0 : return NULL;
5743 12 : list_append(exps, e);
5744 : }
5745 23 : rel = rel_sample(sql->sa, rel, exps);
5746 : }
5747 :
5748 : /* after parsing the current query, set the group by relation as processed */
5749 373225 : if (!sn->having && inner && is_groupby(inner->op))
5750 32676 : set_processed(inner);
5751 373225 : if (rel)
5752 373225 : set_processed(rel);
5753 : return rel;
5754 : }
5755 :
5756 : static sql_rel *
5757 60 : join_on_column_name(sql_query *query, sql_rel *rel, sql_rel *t1, sql_rel *t2, int op, int l_nil, int r_nil)
5758 : {
5759 60 : mvc *sql = query->sql;
5760 60 : int found = 0, full = (op == op_full), right = (op == op_right);
5761 60 : list *exps = rel_projections(sql, t1, NULL, 1, 0);
5762 60 : list *r_exps = rel_projections(sql, t2, NULL, 1, 0);
5763 60 : list *outexps = new_exp_list(sql->sa);
5764 :
5765 60 : if (!exps || !r_exps)
5766 : return NULL;
5767 236 : for (node *n = exps->h; n; n = n->next) {
5768 179 : sql_exp *le = n->data;
5769 179 : int multi = 0;
5770 179 : const char *rname = exp_relname(le), *name = exp_name(le);
5771 179 : sql_exp *re = exps_bind_column(r_exps, name, NULL, &multi, 0);
5772 :
5773 179 : if (re) {
5774 136 : if (multi)
5775 3 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "NATURAL JOIN: common column name '%s' appears more than once in right table", rname);
5776 134 : multi = 0;
5777 134 : le = exps_bind_column(exps, name, NULL, &multi, 0);
5778 134 : if (multi)
5779 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "NATURAL JOIN: common column name '%s' appears more than once in left table", rname);
5780 :
5781 134 : found = 1;
5782 134 : if (!(rel = rel_compare_exp(query, rel, le, re, "=", TRUE, 0, 0, 0, 0)))
5783 : return NULL;
5784 133 : list_remove_data(r_exps, NULL, re);
5785 133 : if (full) {
5786 12 : sql_exp *cond = rel_unop_(sql, rel, le, "sys", "isnull", card_value);
5787 12 : if (!cond)
5788 : return NULL;
5789 12 : set_has_no_nil(cond);
5790 12 : if (rel_convert_types(sql, NULL, NULL, &le, &re, 1, type_equal_no_any) < 0)
5791 : return NULL;
5792 12 : if (!(le = rel_nop_(sql, rel, cond, re, le, NULL, "sys", "ifthenelse", card_value)))
5793 : return NULL;
5794 121 : } else if (right) {
5795 3 : le = re;
5796 : }
5797 133 : exp_setname(sql, le, rname, name);
5798 133 : set_not_unique(le);
5799 133 : append(outexps, le);
5800 : } else {
5801 43 : if (l_nil)
5802 5 : set_has_nil(le);
5803 43 : set_not_unique(le);
5804 43 : append(outexps, le);
5805 : }
5806 : }
5807 57 : if (!found)
5808 2 : return sql_error(sql, 02, SQLSTATE(42000) "JOIN: no columns of tables '%s' and '%s' match", rel_name(t1)?rel_name(t1):"", rel_name(t2)?rel_name(t2):"");
5809 86 : for (node *n = r_exps->h; n; n = n->next) {
5810 31 : sql_exp *re = n->data;
5811 31 : if (r_nil)
5812 3 : set_has_nil(re);
5813 31 : set_not_unique(re);
5814 31 : append(outexps, re);
5815 : }
5816 55 : rel = rel_project(sql->sa, rel, outexps);
5817 55 : return rel;
5818 : }
5819 :
5820 : static sql_rel *
5821 374541 : rel_select_exp(sql_query *query, sql_rel *rel, SelectNode *sn, exp_kind ek)
5822 : {
5823 374541 : mvc *sql = query->sql;
5824 374541 : sql_rel *inner = NULL;
5825 374541 : int group_totals = 0;
5826 374541 : list *pexps = NULL;
5827 :
5828 374541 : assert(sn->s.token == SQL_SELECT);
5829 374541 : if (!sn->selection)
5830 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: the selection or from part is missing");
5831 :
5832 374541 : if (!rel)
5833 72672 : rel = rel_project_exp(sql, exp_atom_bool(sql->sa, 1));
5834 374556 : rel = rel_where_groupby_nodes(query, rel, sn, &group_totals);
5835 374542 : if (sql->session->status) /* rel might be NULL as input, so we have to check for the session status for errors */
5836 : return NULL;
5837 :
5838 374450 : inner = rel;
5839 374450 : pexps = sa_list(sql->sa);
5840 1755744 : for (dnode *n = sn->selection->h; n; n = n->next) {
5841 : /* Here we could get real column expressions
5842 : * (including single atoms) but also table results.
5843 : * Therefore we try both rel_column_exp
5844 : * and rel_table_exp.
5845 : */
5846 1382422 : list *te = NULL;
5847 2764785 : sql_exp *ce = rel_column_exp(query, &inner, n->data.sym, sql_sel | group_totals | (ek.aggr?sql_aggr:0));
5848 :
5849 1382449 : if (ce) {
5850 1324019 : if (inner && inner->flag && is_groupby(inner->op)) {
5851 62 : int found = 0;
5852 62 : list *gbe = inner->r;
5853 : /* flag == 2 just add to group by/ aggrs and ref-to pexps*/
5854 : /* flag == 1 find group by exp referencing this column nr */
5855 62 : if (inner->flag == 2) {
5856 25 : if (ce->card > CARD_AGGR) {
5857 9 : if (!gbe)
5858 8 : inner->r = gbe = sa_list(sql->sa);
5859 9 : append(gbe, ce);
5860 9 : ce = exp_ref(sql, ce);
5861 9 : ce->card = CARD_AGGR;
5862 9 : list_append(inner->exps, ce);
5863 9 : ce = exp_ref(sql, ce);
5864 9 : found = 1;
5865 : }
5866 : } else {
5867 81 : for(node *n = gbe->h; n && !found; n = n->next) {
5868 44 : sql_exp *e = n->data;
5869 44 : if (is_atom(e->type) && !e->alias.name) {
5870 29 : atom *a = e->l;
5871 29 : int nr = (int)atom_get_int(a);
5872 29 : if (nr == (list_length(pexps) + 1)) {
5873 27 : n->data = ce;
5874 27 : ce = exp_ref(sql, ce);
5875 27 : ce->card = CARD_AGGR;
5876 27 : list_append(inner->exps, ce);
5877 27 : ce = exp_ref(sql, ce);
5878 27 : found = 1;
5879 : }
5880 : }
5881 : }
5882 : }
5883 : }
5884 1324019 : pexps = append(pexps, ce);
5885 1323980 : rel = inner;
5886 1323980 : continue;
5887 : } else {
5888 62991 : te = rel_table_exp(query, &rel, n->data.sym, !list_length(pexps) && !n->next);
5889 : }
5890 58428 : if (!ce && !te) {
5891 1118 : if (sql->errstr[0])
5892 : return NULL;
5893 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery result missing");
5894 : }
5895 : /* here we should merge the column expressions we
5896 : * obtained so far with the table expression, ie
5897 : * t1.* or a subquery.
5898 : */
5899 57310 : pexps = list_merge(pexps, te, (fdup)NULL);
5900 : }
5901 373322 : if (rel && is_groupby(rel->op) && rel->flag) {
5902 34 : list *gbe = rel->r;
5903 34 : if (!list_empty(gbe)) {
5904 68 : for (node *n=gbe->h; n; n = n->next) {
5905 37 : sql_exp *e = n->data;
5906 37 : if (rel->flag == 1 && is_atom(e->type) && !e->alias.name) {
5907 1 : atom *a = e->l;
5908 1 : int nr = (int)atom_get_int(a);
5909 1 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: GROUP BY position %d is not in select list", nr);
5910 : }
5911 36 : if (exp_has_aggr(rel, e))
5912 2 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions are not allowed in GROUP BY");
5913 : }
5914 : }
5915 : }
5916 373319 : if (rel && is_groupby(rel->op) && (!sn->groupby || rel->flag) && !is_processed(rel)) {
5917 43218 : for (node *n=pexps->h; n; n = n->next) {
5918 22072 : sql_exp *ce = n->data;
5919 22072 : if (rel->card < ce->card && !exp_is_aggr(rel, ce)) {
5920 0 : if (exp_name(ce) && !has_label(ce))
5921 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(ce));
5922 0 : return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
5923 : }
5924 : }
5925 21146 : set_processed(rel);
5926 : }
5927 373319 : rel = rel_project(sql->sa, rel, pexps);
5928 :
5929 373344 : rel = rel_having_limits_nodes(query, rel, sn, ek, group_totals);
5930 373344 : return rel;
5931 : }
5932 :
5933 : static sql_rel*
5934 128780 : rel_unique_names(mvc *sql, sql_rel *rel)
5935 : {
5936 128780 : list *l;
5937 :
5938 128780 : if (!is_project(rel->op))
5939 : return rel;
5940 128780 : l = sa_list(sql->sa);
5941 969722 : for (node *n = rel->exps->h; n; n = n->next) {
5942 840942 : sql_exp *e = n->data;
5943 840942 : const char *name = exp_name(e);
5944 :
5945 : /* If there are two identical expression names, there will be ambiguity */
5946 840942 : if (!name || exps_bind_column(l, name, NULL, NULL, 0))
5947 58505 : exp_label(sql->sa, e, ++sql->label);
5948 840942 : append(l,e);
5949 : }
5950 128780 : rel->exps = l;
5951 128780 : return rel;
5952 : }
5953 :
5954 : static sql_rel *
5955 374841 : rel_query(sql_query *query, symbol *sq, exp_kind ek)
5956 : {
5957 374841 : mvc *sql = query->sql;
5958 374841 : sql_rel *res = NULL;
5959 374841 : SelectNode *sn = NULL;
5960 :
5961 374841 : if (sq->token != SQL_SELECT)
5962 22 : return table_ref(query, sq, 0, NULL);
5963 :
5964 : /* select ... into is currently not handled here ! */
5965 374819 : sn = (SelectNode *) sq;
5966 374819 : if (sn->into)
5967 : return NULL;
5968 :
5969 374819 : if (ek.card != card_relation && sn->orderby)
5970 0 : return sql_error(sql, 01, SQLSTATE(42000) "SELECT: ORDER BY only allowed on outermost SELECT");
5971 :
5972 374819 : if (sn->window) {
5973 20 : dlist *wl = sn->window->data.lval;
5974 51 : for (dnode *n = wl->h; n ; n = n->next) {
5975 32 : dlist *wd = n->data.sym->data.lval;
5976 32 : const char *name = wd->h->data.sval;
5977 32 : dlist *wdef = wd->h->next->data.lval;
5978 32 : if (frame_get_window_def(sql, name, NULL)) {
5979 1 : return sql_error(sql, 01, SQLSTATE(42000) "SELECT: Redefinition of window '%s'", name);
5980 31 : } else if (!frame_push_window_def(sql, name, wdef)) {
5981 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
5982 : }
5983 : }
5984 : }
5985 :
5986 374818 : if (sn->from) {
5987 302140 : dlist *fl = sn->from->data.lval;
5988 302140 : sql_rel *fnd = NULL;
5989 302140 : list *refs = new_exp_list(sql->sa); /* Keep list of relation names in order to test for duplicates */
5990 :
5991 751825 : for (dnode *n = fl->h; n ; n = n->next) {
5992 449950 : int lateral = check_is_lateral(n->data.sym);
5993 :
5994 : /* just used current expression */
5995 449955 : if (lateral && res)
5996 21 : query_push_outer(query, res, sql_from);
5997 449955 : fnd = table_ref(query, n->data.sym, lateral, refs);
5998 449963 : if (lateral && res)
5999 21 : res = query_pop_outer(query);
6000 449963 : if (!fnd)
6001 : break;
6002 449685 : if (res) {
6003 147796 : res = rel_crossproduct(sql->sa, res, fnd, op_join);
6004 147796 : if (lateral)
6005 21 : set_dependent(res);
6006 : } else {
6007 : res = fnd;
6008 : }
6009 : }
6010 302153 : if (!fnd) {
6011 278 : if (res)
6012 14 : rel_destroy(res);
6013 278 : return NULL;
6014 : }
6015 72678 : } else if (!query_has_outer(query) || !res) {/* only on top level query */
6016 72668 : return rel_select_exp(query, NULL, sn, ek);
6017 : }
6018 :
6019 301875 : sql_rel *rel = NULL;
6020 301875 : if (res)
6021 301875 : rel = rel_select_exp(query, res, sn, ek);
6022 301867 : if (!rel && res)
6023 1048 : rel_destroy(res);
6024 : return rel;
6025 : }
6026 :
6027 : /* NOTE: does NOT "set" query but instead generate set ops (union, except, intersect) */
6028 : static sql_rel *
6029 23 : rel_setquery_corresponding(sql_query *query, sql_rel *l, sql_rel *r, dlist *cols, int op, int outer, bool n_ary_op)
6030 : {
6031 23 : mvc *sql = query->sql;
6032 23 : const char *opname = op==SQL_EXCEPT?"EXCEPT":op==SQL_INTERSECT?"INTERSECT":outer?"OUTER UNION":"UNION";
6033 23 : list *lexps = sa_list(query->sql->sa), *rexps = sa_list(query->sql->sa);
6034 23 : if (!lexps || !rexps)
6035 : return NULL;
6036 23 : assert(cols);
6037 23 : if (dlist_length(cols)) {
6038 22 : for (dnode *dn = cols->h; dn; dn = dn ->next) {
6039 13 : char *nm = dn->data.sym->data.lval->h->data.sval;
6040 13 : sql_exp *ls, *rs;
6041 :
6042 13 : if (!(ls = rel_bind_column(sql, l, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
6043 : return NULL;
6044 13 : if (!(rs = rel_bind_column(sql, r, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
6045 : return NULL;
6046 13 : if ((!outer && (!ls || !rs)) || (outer && !ls && !rs))
6047 2 : return sql_error(sql, 02, SQLSTATE(42000) "%s: tables '%s' and '%s' do not have a matching column '%s'", opname, rel_name(l)?rel_name(l):"", rel_name(r)?rel_name(r):"", nm);
6048 11 : if (outer && !ls)
6049 4 : ls = exp_null(sql->sa, exp_subtype(rs));
6050 11 : if (outer && !rs)
6051 4 : rs = exp_null(sql->sa, exp_subtype(ls));
6052 11 : append(lexps, ls);
6053 11 : append(rexps, rs);
6054 : }
6055 : } else {
6056 12 : int found = 0;
6057 12 : list *exps = rel_projections(sql, l, NULL, 1, 0), *r_exps = rel_projections(sql, r, NULL, 1, 0);
6058 12 : if (!exps || !r_exps)
6059 : return NULL;
6060 : /* find cols which exist on both sides */
6061 35 : for (node *n = exps->h; n; n = n->next) {
6062 23 : sql_exp *le = n->data;
6063 23 : int multi = 0;
6064 23 : const char *rname = exp_relname(le), *name = exp_name(le);
6065 23 : sql_exp *re = exps_bind_column(r_exps, name, NULL, &multi, 0);
6066 23 : if (re) {
6067 13 : if (multi)
6068 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "%s: common column name '%s' appears more than once in right table", opname, rname);
6069 13 : multi = 0;
6070 13 : le = exps_bind_column(exps, name, NULL, &multi, 0);
6071 13 : if (multi)
6072 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "%s: common column name '%s' appears more than once in left table", opname, rname);
6073 :
6074 13 : found = 1;
6075 13 : append(lexps, le);
6076 13 : append(rexps, re);
6077 13 : list_remove_data(r_exps, NULL, re);
6078 10 : } else if (outer) {
6079 3 : append(lexps, le);
6080 3 : re = exp_null(sql->sa, exp_subtype(le));
6081 3 : append(rexps, re); /* nils */
6082 : }
6083 : }
6084 12 : if (!found)
6085 0 : return sql_error(sql, 02, SQLSTATE(42000) "%s: no columns of tables '%s' and '%s' match", opname, rel_name(l)?rel_name(l):"", rel_name(r)?rel_name(r):"");
6086 12 : if (outer) {
6087 7 : for (node *n = r_exps->h; n; n = n->next) {
6088 4 : sql_exp *re = n->data, *le;
6089 4 : append(rexps, re);
6090 4 : le = exp_null(sql->sa, exp_subtype(re));
6091 4 : append(lexps, le); /* nils */
6092 : }
6093 : }
6094 : }
6095 21 : return n_ary_op ?
6096 21 : rel_setop_n_ary_check_types(sql, l, r, lexps, rexps, (operator_type)op) :
6097 2 : rel_setop_check_types(sql, l, r, lexps, rexps, (operator_type)op);
6098 : }
6099 :
6100 : static sql_rel *
6101 2484 : rel_setquery_(sql_query *query, sql_rel *l, sql_rel *r, dlist *cols, int op, int outer)
6102 : {
6103 2484 : mvc *sql = query->sql;
6104 2484 : sql_rel *rel;
6105 :
6106 2484 : if (outer && !cols)
6107 0 : return sql_error(sql, 02, SQLSTATE(42000) "UNION: OUTER needs to be combined with CORRESPONDING [ BY ( column list ) ]");
6108 2484 : if (!cols) {
6109 2482 : list *ls, *rs;
6110 :
6111 2482 : l = rel_unique_names(sql, l);
6112 2482 : r = rel_unique_names(sql, r);
6113 2482 : ls = rel_projections(sql, l, NULL, 0, 1);
6114 2482 : rs = rel_projections(sql, r, NULL, 0, 1);
6115 2482 : rel = rel_setop_check_types(sql, l, r, ls, rs, (operator_type)op);
6116 : } else {
6117 2 : rel = rel_setquery_corresponding(query, l, r, cols, op, outer, false);
6118 : }
6119 2484 : if (rel) {
6120 2481 : rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 0, 1), false);
6121 2481 : set_processed(rel);
6122 : }
6123 : return rel;
6124 : }
6125 :
6126 : /* Generate n-ary set operator */
6127 : static sql_rel *
6128 61929 : rel_setquery_n_ary_(sql_query *query, sql_rel *l, sql_rel *r, dlist *cols, int op, int outer)
6129 : {
6130 : /* even though this is for a general n-ary operators in this phase of the query
6131 : * processing we gonna have only two operands (so technically it's binary). In
6132 : * general this op supports arbitrary number of operands.
6133 : */
6134 : // TODO: for now we support only multi-union
6135 61929 : assert(op == op_munion);
6136 :
6137 61929 : mvc *sql = query->sql;
6138 61929 : sql_rel *rel;
6139 :
6140 61929 : if (outer && !cols)
6141 0 : return sql_error(sql, 02, SQLSTATE(42000) "UNION: OUTER needs to be combined with CORRESPONDING [ BY ( column list ) ]");
6142 61929 : if (!cols) {
6143 : // TODO: make rel_setop_n_ary_check_types to accept a list of rels
6144 : // and a list of lists of exps
6145 61908 : list *ls, *rs;
6146 :
6147 61908 : l = rel_unique_names(sql, l);
6148 61908 : r = rel_unique_names(sql, r);
6149 61908 : ls = rel_projections(sql, l, NULL, 0, 1);
6150 61908 : rs = rel_projections(sql, r, NULL, 0, 1);
6151 61908 : rel = rel_setop_n_ary_check_types(sql, l, r, ls, rs, (operator_type)op);
6152 : } else {
6153 21 : rel = rel_setquery_corresponding(query, l, r, cols, op, outer, true);
6154 : }
6155 :
6156 61929 : if (rel) {
6157 61923 : rel_setop_n_ary_set_exps(sql, rel, rel_projections(sql, rel, NULL, 0, 1), false);
6158 61923 : set_processed(rel);
6159 : }
6160 :
6161 : return rel;
6162 :
6163 : }
6164 :
6165 : static sql_rel *
6166 64424 : rel_setquery(sql_query *query, symbol *q)
6167 : {
6168 64424 : mvc *sql = query->sql;
6169 64424 : sql_rel *res = NULL;
6170 64424 : dnode *n = q->data.lval->h;
6171 64424 : symbol *tab_ref1 = n->data.sym;
6172 64424 : int distinct = n->next->data.i_val;
6173 64424 : dlist *corresponding = n->next->next->data.lval;
6174 64424 : symbol *tab_ref2 = n->next->next->next->data.sym;
6175 64424 : sql_rel *t1, *t2;
6176 :
6177 64424 : assert(n->next->type == type_int);
6178 64424 : t1 = table_ref(query, tab_ref1, 0, NULL);
6179 64424 : if (!t1)
6180 : return NULL;
6181 64420 : t2 = table_ref(query, tab_ref2, 0, NULL);
6182 64420 : if (!t2)
6183 : return NULL;
6184 :
6185 64414 : rel_remove_internal_exp(t1);
6186 64414 : rel_remove_internal_exp(t2);
6187 64414 : if (!corresponding && list_length(t1->exps) != list_length(t2->exps)) {
6188 1 : int t1nrcols = list_length(t1->exps);
6189 1 : int t2nrcols = list_length(t2->exps);
6190 1 : const char *op = "UNION";
6191 1 : if (q->token == SQL_EXCEPT)
6192 : op = "EXCEPT";
6193 0 : else if (q->token == SQL_INTERSECT)
6194 0 : op = "INTERSECT";
6195 1 : rel_destroy(t1);
6196 1 : rel_destroy(t2);
6197 1 : return sql_error(sql, 02, SQLSTATE(42000) "%s: column counts (%d and %d) do not match", op, t1nrcols, t2nrcols);
6198 : }
6199 64413 : if ( q->token == SQL_UNION) {
6200 61929 : int outer = n->next->next->next->next->data.i_val;
6201 : /* For EXCEPT/INTERSECT the group by is always done within the implementation */
6202 : /* TODO add those later in an optimizer ! */
6203 61929 : if (t1 && distinct)
6204 3481 : t1 = rel_distinct(t1);
6205 61929 : if (t2 && distinct)
6206 3481 : t2 = rel_distinct(t2);
6207 : // TODO: this has to be fixed
6208 : /*res = rel_setquery_(query, t1, t2, corresponding, op_union, outer);*/
6209 61929 : res = rel_setquery_n_ary_(query, t1, t2, corresponding, op_munion, outer);
6210 2484 : } else if ( q->token == SQL_EXCEPT)
6211 2026 : res = rel_setquery_(query, t1, t2, corresponding, op_except, 0);
6212 458 : else if ( q->token == SQL_INTERSECT)
6213 458 : res = rel_setquery_(query, t1, t2, corresponding, op_inter, 0);
6214 64413 : if (res) {
6215 64404 : set_processed(res);
6216 64404 : if (distinct)
6217 5839 : res = rel_distinct(res);
6218 : }
6219 : return res;
6220 : }
6221 :
6222 : static sql_rel *
6223 59371 : rel_joinquery_(sql_query *query, symbol *tab1, int natural, jt jointype, symbol *tab2, symbol *js, list *refs)
6224 : {
6225 59371 : mvc *sql = query->sql;
6226 59371 : operator_type op = op_join;
6227 59371 : sql_rel *t1 = NULL, *t2 = NULL, *inner, *rel = NULL;
6228 59371 : int l_nil = 0, r_nil = 0, lateral = 0;
6229 :
6230 59371 : switch(jointype) {
6231 : case jt_inner:
6232 : case jt_cross: op = op_join;
6233 : break;
6234 : case jt_left: op = op_left;
6235 : r_nil = 1;
6236 : break;
6237 : case jt_right: op = op_right;
6238 : l_nil = 1;
6239 : break;
6240 : case jt_full: op = op_full;
6241 : l_nil = 1;
6242 : r_nil = 1;
6243 : break;
6244 : }
6245 :
6246 : /* a dependent join cannot depend on the right side, so disable lateral check for right and full joins */
6247 59371 : lateral = (op == op_join || op == op_left) && check_is_lateral(tab2);
6248 59371 : t1 = table_ref(query, tab1, 0, refs);
6249 59371 : if (t1) {
6250 59366 : if (!lateral) {
6251 59331 : t2 = table_ref(query, tab2, 0, refs);
6252 : } else {
6253 35 : query_processed(query);
6254 35 : query_push_outer(query, t1, sql_from);
6255 35 : t2 = table_ref(query, tab2, 0, refs);
6256 35 : t1 = query_pop_outer(query);
6257 : }
6258 : }
6259 59371 : if (!t1 || !t2)
6260 : return NULL;
6261 :
6262 59348 : query_processed(query);
6263 59348 : if (strcmp(rel_name(t1), rel_name(t2)) == 0) {
6264 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: ERROR: table name '%s' specified more than once", rel_name(t1));
6265 : }
6266 59348 : inner = rel = rel_crossproduct(sql->sa, t1, t2, op);
6267 59348 : if (!rel)
6268 : return NULL;
6269 59348 : if (lateral)
6270 34 : set_dependent(rel);
6271 :
6272 59348 : assert(jointype != jt_cross || (!natural && !js)); /* there are no natural cross joins, or cross joins with conditions */
6273 59348 : if (js && natural)
6274 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: cannot have a NATURAL JOIN with a join specification (ON or USING)");
6275 59348 : if (jointype != jt_cross && !js && !natural)
6276 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: must have NATURAL JOIN or a JOIN with a join specification (ON or USING)");
6277 :
6278 59348 : if (js && js->token != SQL_USING) { /* On sql_logical_exp */
6279 59173 : rel = rel_logical_exp(query, rel, js, sql_where | sql_join);
6280 175 : } else if (js) { /* using */
6281 24 : char rname[16], *rnme;
6282 24 : dnode *n = js->data.lval->h;
6283 24 : list *outexps = new_exp_list(sql->sa), *exps;
6284 24 : node *m;
6285 :
6286 24 : rnme = sa_strdup(sql->sa, number2name(rname, sizeof(rname), ++sql->label));
6287 54 : for (; n; n = n->next) {
6288 30 : char *nm = n->data.sval;
6289 30 : sql_exp *cond, *ls, *rs;
6290 :
6291 30 : if (!(ls = rel_bind_column(sql, t1, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
6292 0 : return NULL;
6293 30 : if (!(rs = rel_bind_column(sql, t2, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
6294 : return NULL;
6295 30 : if (!ls || !rs)
6296 0 : return sql_error(sql, 02, SQLSTATE(42000) "JOIN: tables '%s' and '%s' do not have a matching column '%s'", rel_name(t1)?rel_name(t1):"", rel_name(t2)?rel_name(t2):"", nm);
6297 30 : if (!(rel = rel_compare_exp(query, rel, ls, rs, "=", TRUE, 0, 0, 0, 0)))
6298 : return NULL;
6299 30 : if (op != op_join) {
6300 12 : if (!(cond = rel_unop_(sql, rel, ls, "sys", "isnull", card_value)))
6301 : return NULL;
6302 12 : set_has_no_nil(cond);
6303 12 : if (rel_convert_types(sql, t1, t2, &ls, &rs, 1, type_equal) < 0)
6304 : return NULL;
6305 12 : if (!(ls = rel_nop_(sql, rel, cond, rs, ls, NULL, "sys", "ifthenelse", card_value)))
6306 : return NULL;
6307 : }
6308 30 : exp_setname(sql, ls, rnme, nm);
6309 30 : append(outexps, ls);
6310 30 : if (!rel)
6311 : return NULL;
6312 : }
6313 24 : exps = rel_projections(sql, t1, NULL, 1, 1);
6314 207 : for (m = exps->h; m; m = m->next) {
6315 183 : const char *nm = exp_name(m->data);
6316 183 : int fnd = 0;
6317 :
6318 433 : for (n = js->data.lval->h; n; n = n->next) {
6319 280 : if (strcmp(nm, n->data.sval) == 0) {
6320 : fnd = 1;
6321 : break;
6322 : }
6323 : }
6324 183 : if (!fnd) {
6325 153 : sql_exp *ls = m->data;
6326 153 : if (l_nil)
6327 18 : set_has_nil(ls);
6328 153 : set_not_unique(ls);
6329 153 : append(outexps, ls);
6330 : }
6331 : }
6332 24 : exps = rel_projections(sql, t2, NULL, 1, 1);
6333 108 : for (m = exps->h; m; m = m->next) {
6334 84 : const char *nm = exp_name(m->data);
6335 84 : int fnd = 0;
6336 :
6337 234 : for (n = js->data.lval->h; n; n = n->next) {
6338 180 : if (strcmp(nm, n->data.sval) == 0) {
6339 : fnd = 1;
6340 : break;
6341 : }
6342 : }
6343 84 : if (!fnd) {
6344 54 : sql_exp *rs = m->data;
6345 54 : if (r_nil)
6346 14 : set_has_nil(rs);
6347 54 : set_not_unique(rs);
6348 54 : append(outexps, rs);
6349 : }
6350 : }
6351 24 : rel = rel_project(sql->sa, rel, outexps);
6352 151 : } else if (jointype != jt_cross) { /* ! js -> natural join */
6353 60 : rel = join_on_column_name(query, rel, t1, t2, op, l_nil, r_nil);
6354 : }
6355 59348 : if (!rel)
6356 : return NULL;
6357 59330 : if (inner && is_outerjoin(inner->op))
6358 20877 : set_processed(inner);
6359 59330 : set_processed(rel);
6360 59330 : query_processed(query);
6361 59330 : return rel;
6362 : }
6363 :
6364 : static sql_rel *
6365 59371 : rel_joinquery(sql_query *query, symbol *q, list *refs)
6366 : {
6367 59371 : dnode *n = q->data.lval->h;
6368 59371 : symbol *tab_ref1 = n->data.sym;
6369 59371 : int natural = n->next->data.i_val;
6370 59371 : jt jointype = (jt) n->next->next->data.i_val;
6371 59371 : symbol *tab_ref2 = n->next->next->next->data.sym;
6372 59371 : symbol *joinspec = n->next->next->next->next->data.sym;
6373 :
6374 59371 : assert(n->next->type == type_int);
6375 59371 : assert(n->next->next->type == type_int);
6376 59371 : return rel_joinquery_(query, tab_ref1, natural, jointype, tab_ref2, joinspec, refs);
6377 : }
6378 :
6379 : sql_rel *
6380 374790 : rel_subquery(sql_query *query, symbol *sq, exp_kind ek)
6381 : {
6382 374790 : mvc *sql = query->sql;
6383 :
6384 374790 : query_processed(query);
6385 374783 : if (!stack_push_frame(sql, NULL))
6386 0 : return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6387 374871 : sql_rel *rel = rel_query(query, sq, ek);
6388 374791 : stack_pop_frame(sql);
6389 374888 : if (!query_has_outer(query))
6390 336090 : query_processed(query);
6391 374877 : if (rel && ek.type == type_relation && ek.card < card_set && rel->card >= CARD_AGGR)
6392 15 : return rel_zero_or_one(sql, rel, ek);
6393 : return rel;
6394 : }
6395 :
6396 : sql_rel *
6397 236817 : rel_selects(sql_query *query, symbol *s)
6398 : {
6399 236817 : mvc *sql = query->sql;
6400 236817 : sql_rel *ret = NULL;
6401 :
6402 236817 : switch (s->token) {
6403 4469 : case SQL_WITH:
6404 4469 : ret = rel_with_query(query, s);
6405 4469 : sql->type = Q_TABLE;
6406 4469 : break;
6407 2230 : case SQL_VALUES:
6408 2230 : ret = rel_values(query, s, NULL);
6409 2230 : sql->type = Q_TABLE;
6410 2230 : break;
6411 209190 : case SQL_SELECT: {
6412 209190 : exp_kind ek = {type_value, card_relation, TRUE};
6413 209190 : SelectNode *sn = (SelectNode *) s;
6414 :
6415 209190 : if (sn->into) {
6416 1 : sql->type = Q_SCHEMA;
6417 1 : ret = rel_select_with_into(query, s);
6418 : } else {
6419 209189 : ret = rel_subquery(query, s, ek);
6420 209266 : sql->type = Q_TABLE;
6421 : }
6422 209268 : } break;
6423 0 : case SQL_JOIN:
6424 0 : ret = rel_joinquery(query, s, NULL);
6425 0 : sql->type = Q_TABLE;
6426 0 : break;
6427 20928 : case SQL_UNION:
6428 : case SQL_EXCEPT:
6429 : case SQL_INTERSECT:
6430 20928 : ret = rel_setquery(query, s);
6431 20928 : sql->type = Q_TABLE;
6432 20928 : break;
6433 : default:
6434 : return NULL;
6435 : }
6436 236895 : if (!ret && sql->errstr[0] == 0)
6437 0 : (void) sql_error(sql, 02, SQLSTATE(42000) "relational query without result");
6438 : return ret;
6439 : }
6440 :
6441 : sql_rel *
6442 77650 : schema_selects(sql_query *query, sql_schema *schema, symbol *s)
6443 : {
6444 77650 : mvc *sql = query->sql;
6445 77650 : sql_rel *res;
6446 77650 : sql_schema *os = cur_schema(sql);
6447 :
6448 77650 : sql->session->schema = schema;
6449 77650 : res = rel_selects(query, s);
6450 77650 : sql->session->schema = os;
6451 77650 : return res;
6452 : }
6453 :
6454 : sql_rel *
6455 26 : rel_loader_function(sql_query *query, symbol* fcall, list *fexps, sql_subfunc **loader_function)
6456 : {
6457 26 : mvc *sql = query->sql;
6458 26 : sql_rel *sq = NULL;
6459 26 : dnode *l = fcall->data.lval->h;
6460 26 : char *sname = qname_schema(l->data.lval);
6461 26 : char *fname = qname_schema_object(l->data.lval);
6462 :
6463 26 : list *tl = sa_list(sql->sa);
6464 26 : list *exps = sa_list(sql->sa);
6465 26 : if (l->next)
6466 26 : l = l->next; /* skip distinct */
6467 26 : if (l->next) { /* table call with subquery */
6468 22 : if (l->next->type == type_symbol || l->next->type == type_list) {
6469 22 : int count = 0;
6470 22 : symbol *subquery = NULL;
6471 22 : dnode *n = NULL;
6472 :
6473 22 : if (l->next->type == type_symbol)
6474 : n = l->next;
6475 : else
6476 1 : n = l->next->data.lval->h;
6477 :
6478 66 : for (dnode *m = n; m; m = m->next) {
6479 44 : if (m->type == type_symbol && m->data.sym->token == SQL_SELECT)
6480 44 : subquery = m->data.sym;
6481 44 : count++;
6482 : }
6483 22 : if (subquery && count > 1)
6484 0 : return sql_error(sql, 02, SQLSTATE(42000) "SELECT: The input for the loader function '%s' must be either a single sub query, or a list of values", fname);
6485 :
6486 22 : if (subquery) {
6487 0 : exp_kind ek = { type_value, card_relation, TRUE };
6488 0 : if (!(sq = rel_subquery(query, subquery, ek)))
6489 0 : return NULL;
6490 : } else {
6491 22 : exp_kind ek = { type_value, card_column, TRUE };
6492 22 : list *exps = sa_list(sql->sa);
6493 88 : for ( ; n; n = n->next) {
6494 44 : sql_exp *e = rel_value_exp(query, NULL, n->data.sym, sql_sel | sql_from, ek);
6495 :
6496 44 : if (!e)
6497 0 : return NULL;
6498 44 : append(exps, e);
6499 : }
6500 22 : sq = rel_project(sql->sa, NULL, exps);
6501 : }
6502 : }
6503 22 : if (!sq)
6504 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such loader function %s%s%s'%s'", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
6505 66 : for (node *en = sq->exps->h; en; en = en->next) {
6506 44 : sql_exp *e = en->data;
6507 :
6508 44 : append(exps, e = exp_ref(sql, e));
6509 44 : append(tl, exp_subtype(e));
6510 : }
6511 : }
6512 :
6513 26 : sql_exp *e = NULL;
6514 26 : if (!(e = find_table_function(sql, sname, fname, exps, tl, F_LOADER)))
6515 : return NULL;
6516 25 : sql_subfunc *sf = e->f;
6517 25 : if (sq) {
6518 66 : for (node *n = sq->exps->h, *m = sf->func->ops->h ; n && m ; n = n->next, m = m->next) {
6519 44 : sql_exp *e = (sql_exp*) n->data;
6520 44 : sql_arg *a = (sql_arg*) m->data;
6521 44 : if (!exp_subtype(e) && rel_set_type_param(sql, &(a->type), sq, e, 0) < 0)
6522 : return NULL;
6523 : }
6524 : }
6525 :
6526 25 : if (loader_function)
6527 25 : *loader_function = sf;
6528 :
6529 28 : return rel_table_func(sql->sa, sq, e, fexps, (sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
6530 : }
|