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 "sql_parser.h"
15 : #include "sql_symbol.h"
16 : #include "sql_semantic.h"
17 : #include "sql_env.h"
18 : #include "sql_privileges.h"
19 : #include "sql_string.h"
20 : #include "sql_atom.h"
21 :
22 : #include <unistd.h>
23 : #include <string.h>
24 : #include <ctype.h>
25 :
26 : #include "rel_semantic.h"
27 :
28 : /*
29 : * For debugging purposes we need to be able to convert sql-tokens to
30 : * a string representation.
31 : *
32 : * !SQL ERROR <sqlerrno> : <details>
33 : * !SQL DEBUG <details>
34 : * !SQL WARNING <details>
35 : * !SQL <informative message, reserved for ...rows affected>
36 : */
37 :
38 : void
39 382616 : sql_add_param(mvc *sql, const char *name, sql_subtype *st)
40 : {
41 382616 : sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
42 :
43 382616 : if (name)
44 381000 : a->name = sa_strdup(sql->sa, name);
45 382616 : if (st && st->type)
46 380989 : a->type = *st;
47 382616 : a->inout = ARG_IN;
48 382616 : if (name && strcmp(name, "*") == 0)
49 4 : a->type = *sql_bind_localtype("int");
50 382616 : if (!sql->params)
51 225296 : sql->params = sa_list(sql->sa);
52 382616 : list_append(sql->params, a);
53 382616 : }
54 :
55 : int
56 95693 : sql_bind_param(mvc *sql, const char *name)
57 : {
58 95693 : node *n;
59 95693 : int nr = 0;
60 :
61 95693 : if (sql->params) {
62 207742 : for (n = sql->params->h; n; n = n->next, nr++) {
63 203373 : sql_arg *a = n->data;
64 :
65 203373 : if (a->name && strcmp(a->name, name) == 0)
66 87637 : return nr;
67 : }
68 : }
69 : return -1;
70 : }
71 :
72 : sql_arg *
73 90814 : sql_bind_paramnr(mvc *sql, int nr)
74 : {
75 90814 : int i=0;
76 90814 : node *n;
77 :
78 90814 : if (sql->params && nr < list_length(sql->params)) {
79 679798 : for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
80 : ;
81 :
82 90814 : if (n)
83 90814 : return n->data;
84 : }
85 : return NULL;
86 : }
87 :
88 : sql_arg *
89 6 : sql_find_param(mvc *sql, char *name)
90 : {
91 9 : for (node *n = sql->params->h; n; n = n->next) {
92 8 : sql_arg *a = n->data;
93 8 : if (strcmp(a->name, name) == 0)
94 5 : return a;
95 : }
96 : return NULL;
97 : }
98 :
99 : void
100 744583 : sql_destroy_params(mvc *sql)
101 : {
102 744583 : sql->params = NULL;
103 744583 : }
104 :
105 : sql_schema *
106 1687548 : cur_schema(mvc *sql)
107 : {
108 1687548 : return sql->session->schema;
109 : }
110 :
111 : sql_schema *
112 547516 : tmp_schema(mvc *sql)
113 : {
114 547516 : return mvc_bind_schema(sql, "tmp");
115 : }
116 :
117 : #define DO_NOTHING(x) ;
118 :
119 : /* as we don't have OOP in C, I prefer a single macro with the search path algorithm to passing function pointers */
120 : #define search_object_on_path(CALL, EXTRA_CONDITION, EXTRA, ERROR_CODE) \
121 : do { \
122 : sql_schema *next = NULL; \
123 : \
124 : if (sname) { /* user has explicitly typed the schema, so either the object is there or we return error */ \
125 : if (!(next = mvc_bind_schema(sql, sname))) \
126 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s: no such schema '%s'", error, sname); \
127 : EXTRA_CONDITION(EXTRA); /* for functions without schema, 'sys' is a valid schema to bind them */ \
128 : if (!res) { \
129 : CALL; \
130 : } \
131 : } else { \
132 : sql_schema *cur = cur_schema(sql); \
133 : char *session_schema = cur->base.name; \
134 : \
135 : EXTRA; \
136 : if (!res && !sql->schema_path_has_tmp && strcmp(session_schema, "tmp") != 0) { /* if 'tmp' is not in the search path, search it before all others */ \
137 : next = tmp_schema(sql); \
138 : CALL; \
139 : } \
140 : if (!res) { /* then current session's schema */ \
141 : next = cur; \
142 : CALL; \
143 : } \
144 : if (!res) { \
145 : /* object not found yet, look inside search path */ \
146 : for (node *n = sql->schema_path->h ; n && !res ; n = n->next) { \
147 : str p = (str) n->data; \
148 : if (strcmp(session_schema, p) != 0 && (next = mvc_bind_schema(sql, p))) \
149 : CALL; \
150 : } \
151 : } \
152 : if (!res && !sql->schema_path_has_sys && strcmp(session_schema, "sys") != 0) { /* if 'sys' is not in the current path search it next */ \
153 : next = mvc_bind_schema(sql, "sys"); \
154 : CALL; \
155 : } \
156 : } \
157 : if (!res) \
158 : return sql_error(sql, ERR_NOTFOUND, ERROR_CODE "%s: no such %s %s%s%s'%s'", error, objstr, sname ? "'":"", sname ? sname : "", sname ? "'.":"", name); \
159 : } while (0)
160 :
161 : #define table_extra \
162 : do { \
163 : if (s) { \
164 : next = s; /* there's a default schema to search before all others, e.g. bind a child table from a merge table */ \
165 : res = mvc_bind_table(sql, next, name); \
166 : } \
167 : if (!res && strcmp(objstr, "table") == 0 && (res = stack_find_table(sql, name))) /* for tables, first try a declared table from the stack */ \
168 : return res; \
169 : } while (0)
170 :
171 : sql_table *
172 669319 : find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *name, const char *error, bool isView)
173 : {
174 669319 : const char *objstr = isView ? "view" : "table";
175 669319 : sql_table *res = NULL;
176 :
177 669818 : search_object_on_path(res = mvc_bind_table(sql, next, name), DO_NOTHING, table_extra, SQLSTATE(42S02));
178 : return res;
179 : }
180 :
181 : sql_sequence *
182 1480 : find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
183 : {
184 1480 : const char objstr[] = "sequence";
185 1480 : sql_sequence *res = NULL;
186 :
187 1484 : search_object_on_path(res = find_sql_sequence(sql->session->tr, next, name), DO_NOTHING, ;, SQLSTATE(42000));
188 : return res;
189 : }
190 :
191 : sql_idx *
192 218 : find_idx_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
193 : {
194 218 : const char objstr[] = "index";
195 218 : sql_idx *res = NULL;
196 :
197 292 : search_object_on_path(res = mvc_bind_idx(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S12));
198 : return res;
199 : }
200 :
201 : sql_type *
202 5 : find_type_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
203 : {
204 5 : const char objstr[] = "type";
205 5 : sql_type *res = NULL;
206 :
207 7 : search_object_on_path(res = schema_bind_type(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S01));
208 : return res;
209 : }
210 :
211 : sql_trigger *
212 96 : find_trigger_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
213 : {
214 96 : const char objstr[] = "trigger";
215 96 : sql_trigger *res = NULL;
216 :
217 118 : search_object_on_path(res = mvc_bind_trigger(sql, next, name), DO_NOTHING, ;, SQLSTATE(3F000));
218 : return res;
219 : }
220 :
221 : /* A variable can be any of the following, from the innermost to the outermost:
222 : - 'parameter of the function' (ie in the param list)
223 : - local variable, declared earlier
224 : - global variable, also declared earlier
225 : */
226 : #define variable_extra \
227 : do { \
228 : if (!res) { \
229 : if ((*var = stack_find_var_frame(sql, name, level))) { /* check if variable is known from the stack */ \
230 : *tpe = &((*var)->var.tpe); \
231 : res = true; \
232 : } else if ((nr = sql_bind_param(sql, name)) >= 0) { /* then if it is a parameter */ \
233 : *a = sql_bind_paramnr(sql, nr); \
234 : *tpe = &((*a)->type); \
235 : *level = 1; \
236 : res = true; \
237 : } \
238 : } \
239 : } while (0)
240 :
241 : #define var_find_on_global \
242 : do { \
243 : if ((*var = find_global_var(sql, next, name))) { /* then if it is a global var */ \
244 : *tpe = &((*var)->var.tpe); \
245 : *level = 0; \
246 : res = true; \
247 : } \
248 : } while (0)
249 :
250 : bool
251 203349 : find_variable_on_scope(mvc *sql, const char *sname, const char *name, sql_var **var, sql_arg **a, sql_subtype **tpe, int *level, const char *error)
252 : {
253 203349 : const char objstr[] = "variable";
254 203349 : bool res = false;
255 203349 : int nr = 0;
256 :
257 203349 : (void)nr;
258 208382 : search_object_on_path(var_find_on_global, DO_NOTHING, variable_extra, SQLSTATE(42000));
259 : return res;
260 : }
261 :
262 : static sql_subfunc *
263 932148 : _dup_subaggr(allocator *sa, sql_func *a, sql_subtype *member)
264 : {
265 932148 : node *tn;
266 932148 : unsigned int scale = 0, digits = 0;
267 932148 : sql_subfunc *ares = SA_ZNEW(sa, sql_subfunc);
268 :
269 :
270 932148 : ares->func = a;
271 932148 : if (IS_FILT(a)) {
272 4416 : ares->res = sa_list(sa);
273 4416 : list_append(ares->res, sql_bind_localtype("bit"));
274 927732 : } else if (IS_FUNC(a) || IS_UNION(a) || IS_ANALYTIC(a) || IS_AGGR(a)) { /* not needed for PROC */
275 924009 : if (a->res) {
276 924009 : ares->res = sa_list(sa);
277 1932379 : for(tn = a->res->h; tn; tn = tn->next) {
278 1008371 : sql_arg *rarg = tn->data;
279 1008371 : sql_subtype *res, *r = &rarg->type;
280 :
281 1008371 : if (a->fix_scale == SCALE_EQ && !IS_AGGR(a)) {
282 : res = r;
283 : } else {
284 832671 : digits = r->digits;
285 832671 : scale = r->scale;
286 : /* same scale as the input */
287 832671 : if (member && (member->scale != scale ||
288 173482 : (digits != member->digits && !EC_NUMBER(member->type->eclass)))) {
289 90830 : if (member->digits > digits)
290 : digits = member->digits;
291 : scale = member->scale;
292 : }
293 : /* same type as the input */
294 832671 : if (r->type->eclass == EC_ANY && member) {
295 14455 : r = member;
296 14455 : digits = member->digits;
297 : }
298 832671 : if (!EC_SCALE(r->type->eclass))
299 832671 : scale = 0;
300 832671 : res = sql_create_subtype(sa, r->type, digits, scale);
301 : }
302 1008371 : list_append(ares->res, res);
303 : }
304 : }
305 : }
306 932147 : return ares;
307 : }
308 :
309 :
310 :
311 : static sql_subfunc *
312 129678 : func_cmp(allocator *sa, sql_func *f, const char *name, int nrargs)
313 : {
314 129678 : if (strcmp(f->base.name, name) == 0) {
315 129678 : if (f->vararg)
316 : //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
317 2 : return _dup_subaggr(sa, f, NULL);
318 129676 : if (nrargs < 0 || list_length(f->ops) == nrargs)
319 : //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
320 128914 : return _dup_subaggr(sa, f, NULL);
321 : }
322 : return NULL;
323 : }
324 :
325 : static sql_subfunc *
326 638326 : sql_find_func_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
327 : {
328 638326 : int key = hash_key(fname);
329 638326 : sql_subfunc *res = NULL;
330 638326 : int found = 0;
331 638326 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
332 :
333 638326 : if (ff) {
334 638326 : if (ff->ht) {
335 638326 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
336 638326 : if (prev) {
337 0 : for (; he && !found; he = he->chain)
338 0 : if (he->value == prev->func)
339 0 : found = 1;
340 : }
341 7719462 : for (; he; he = he->chain) {
342 7204969 : sql_func *f = he->value;
343 :
344 7204969 : if ((f->type != type && f->type != filt) || (f->private && !private))
345 7081121 : continue;
346 123848 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
347 123833 : return res;
348 : }
349 : } else {
350 0 : node *n = ff->h;
351 0 : if (prev) {
352 0 : for (; n && !found; n = n->next)
353 0 : if (n->data == prev->func)
354 0 : found = 1;
355 : }
356 0 : for (; n; n = n->next) {
357 0 : sql_func *f = n->data;
358 :
359 0 : if ((f->type != type && f->type != filt) || (f->private && !private))
360 0 : continue;
361 0 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
362 0 : return res;
363 : }
364 : }
365 : }
366 : return res;
367 : }
368 :
369 : static sql_subfunc *
370 751290 : os_find_func_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
371 : {
372 751290 : sql_subfunc *res = NULL;
373 751290 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
374 :
375 751290 : if (ff) {
376 751290 : struct os_iter oi;
377 751290 : os_iterator(&oi, ff, sql->session->tr, fname);
378 852480 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
379 106273 : sql_func *f = (sql_func*)b;
380 106273 : if (prev && prev->func != f) {
381 0 : continue;
382 106273 : } else if (prev) {
383 0 : prev = NULL;
384 0 : continue;
385 : }
386 :
387 106273 : if ((f->type != type && f->type != filt) || (f->private && !private))
388 100443 : continue;
389 5830 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
390 5083 : return res;
391 : }
392 : }
393 : return res;
394 : }
395 :
396 : #define functions_without_schema(X) if (strcmp(sname, "sys") == 0) X
397 :
398 : #define find_func_extra \
399 : do { \
400 : if (!res && (res = sql_find_func_internal(sql, funcs, name, nrargs, type, private, prev))) /* search system wide functions first */ \
401 : return res; \
402 : } while (0)
403 :
404 : sql_subfunc *
405 639025 : sql_find_func(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
406 : {
407 639025 : char *F = NULL, *objstr = NULL;
408 639025 : const char error[] = "CATALOG";
409 639025 : sql_subfunc *res = NULL;
410 :
411 639025 : FUNC_TYPE_STR(type, F, objstr);
412 639025 : (void) F; /* not used */
413 :
414 639025 : assert(nrargs >= -1);
415 :
416 1088328 : search_object_on_path(res = os_find_func_internal(sql, next->funcs, name, nrargs, type, private, prev), functions_without_schema, find_func_extra, SQLSTATE(42000));
417 : return res;
418 : }
419 :
420 : sql_subfunc *
421 379584 : sql_bind_func(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_ftype type, bool private, bool exact)
422 : {
423 379584 : list *l = sa_list(sql->sa);
424 :
425 379584 : if (tp1)
426 370073 : list_append(l, tp1);
427 379584 : if (tp2)
428 211677 : list_append(l, tp2);
429 379584 : return sql_bind_func_(sql, sname, fname, l, type, private, exact);
430 : }
431 :
432 : sql_subfunc *
433 174 : sql_bind_func3(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_subtype *tp3, sql_ftype type, bool private)
434 : {
435 174 : list *l = sa_list(sql->sa);
436 :
437 174 : if (tp1)
438 174 : list_append(l, tp1);
439 174 : if (tp2)
440 174 : list_append(l, tp2);
441 174 : if (tp3)
442 174 : list_append(l, tp3);
443 174 : return sql_bind_func_(sql, sname, fname, l, type, private, false);
444 : }
445 :
446 : static int /* bind the function version with more identical type matches */
447 749809 : next_cand_points(list *args, list *ops)
448 : {
449 749809 : int res = 0;
450 :
451 749809 : if (!list_empty(args) && !list_empty(ops))
452 1969316 : for (node *n = args->h, *m = ops->h; n && m ; n = n->next, m = m->next) {
453 1241752 : sql_arg *a = n->data;
454 1241752 : sql_subtype *t = m->data;
455 :
456 1241752 : if (a->type.type->eclass == EC_ANY)
457 634856 : res += 100;
458 606896 : else if (t)
459 606896 : res += a->type.type->base.id == t->type->base.id;
460 : }
461 749808 : res += (list_empty(args) && list_empty(ops));
462 749808 : return res;
463 : }
464 :
465 : static int
466 8007983 : score_func( sql_func *f, list *tl, bool exact, bool *downcast)
467 : {
468 8007983 : int score = 0;
469 8007983 : node *n, *m;
470 :
471 8007983 : if (exact)
472 709386 : return next_cand_points(f->ops, tl);
473 7298597 : if (!tl)
474 : return 1;
475 7298597 : if (f->vararg)
476 : return 1;
477 7298583 : unsigned int digits = 0, scale = 0;
478 7298583 : if (f->fix_scale == SCALE_FIX) {
479 3078096 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
480 2049880 : sql_subtype *t = m->data;
481 :
482 2049880 : if (!t)
483 52 : continue;
484 2049828 : if (t->type->eclass == EC_DEC) {
485 8219 : if (digits < t->digits)
486 : digits = t->digits;
487 8219 : if (scale < t->scale)
488 : scale = t->scale;
489 : }
490 : }
491 3078096 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
492 2049880 : sql_arg *a = n->data;
493 2049880 : sql_subtype *t = m->data;
494 :
495 2049880 : if (!t)
496 52 : continue;
497 2049828 : if (a->type.type->eclass == EC_DEC && t->type->eclass == EC_NUM) {
498 1130930 : if (digits < scale + bits2digits(t->digits))
499 784575 : digits = scale + bits2digits(t->digits);
500 : }
501 : }
502 : }
503 7298583 : int nr_strconverts = 0;
504 16134337 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
505 11591763 : sql_arg *a = n->data;
506 11591763 : sql_subtype *t = m->data;
507 :
508 11591763 : if (!t) { /* parameters */
509 503 : int ec = a->type.type->eclass;
510 503 : score++;
511 503 : if (ec == EC_DEC)
512 : return 0;
513 327 : if (a && EC_NUMBER(ec) && !EC_INTERVAL(ec))
514 218 : score += a->type.type->localtype * 10; /* premium on larger types */
515 109 : else if (a) /* all other types */
516 109 : score += 99;
517 327 : continue;
518 : }
519 :
520 11591260 : int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
521 : /* EX_EXTERNAL can only convert between equal implementation types */
522 11591260 : if (nscore == 0 &&
523 2558698 : t->type->eclass == a->type.type->eclass &&
524 573 : t->type->eclass == EC_EXTERNAL &&
525 573 : t->type->localtype == a->type.type->localtype)
526 : nscore = 10;
527 9033126 : if (nscore &&
528 9033126 : t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC &&
529 3397770 : t->type->localtype > a->type.type->localtype)
530 696463 : *downcast = true;
531 9033126 : if (nscore == 0)
532 : return 0;
533 9033126 : nscore *= 100; /* first based on preferred conversions */
534 9033126 : if (nscore < 0) {
535 291844 : *downcast = true;
536 291844 : nscore = -nscore;
537 : }
538 9033126 : score += nscore;
539 9033126 : if (EC_VARCHAR(t->type->eclass) && EC_NUMBER(a->type.type->eclass))
540 1227 : nr_strconverts++;
541 9033126 : if (nr_strconverts > 1)
542 : return 0;
543 :
544 9033090 : if (f->fix_scale == SCALE_FIX && a->type.type->eclass == EC_DEC && digits > a->type.type->digits) /* doesn't fit */
545 : return 0;
546 : /* sql types equal but implementation differences */
547 8835427 : else if (t->type->eclass == EC_BIT && a->type.type->eclass == EC_NUM && t->type->localtype <= a->type.type->localtype) /* convert bits into smallest number */
548 146 : score += (11 + t->type->localtype - a->type.type->localtype) * 8;
549 : /* sql types close but digits/scale diffs */
550 8835281 : else if (t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC && /*t->type->localtype <= a->type.type->localtype*/ bits2digits(t->digits) < a->type.type->digits)
551 : //score += (10 + t->type->localtype - a->type.type->localtype) * 8;
552 2500187 : score += (38 + bits2digits(t->digits) - a->type.type->digits);
553 : /* same class over converting to other class */
554 6335094 : else if (t->type->eclass == a->type.type->eclass && t->type->localtype <= a->type.type->localtype) {
555 3362989 : score += (11 + t->type->localtype - a->type.type->localtype) * 4;
556 : /* handle intervals (day, hour, minutes, second) mapped
557 : * within same eclass and implementation type. */
558 3362989 : if (t->type->eclass == a->type.type->eclass && t->type->eclass == EC_SEC)
559 3088 : score += ((t->type->digits > 4 && a->type.type->digits > 4) ||
560 3467 : (t->type->digits <= 4 && a->type.type->digits <= 4)) * 4;
561 : }
562 : /* conversion matrix needs check if conversion is possible */
563 2972105 : else if (t->type->eclass == a->type.type->eclass) {
564 1094884 : if (t->type->localtype <= a->type.type->localtype) {
565 0 : int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
566 0 : score += (10 + t->type->localtype - a->type.type->localtype) * nscore;
567 1094884 : } else if (t->type->eclass == EC_NUM || t->type->eclass == EC_FLT) { /* down casting */
568 1080094 : *downcast = true;
569 1080094 : score += 10 * (10 - t->type->localtype - a->type.type->localtype);
570 : }
571 : }
572 : }
573 4542574 : score += (list_empty(tl) && list_empty(f->ops));
574 4542574 : return score;
575 : }
576 :
577 :
578 : static sql_subfunc *
579 1545612 : sql_bind_func__(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
580 : {
581 1545612 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
582 1545612 : sql_subtype *input_type = NULL;
583 1545612 : sql_func *cand = NULL, *dcand = NULL;
584 1545612 : int points = 0, dpoints = 0;
585 :
586 1545612 : if (ops && ops->h)
587 1507107 : input_type = ops->h->data;
588 :
589 1545612 : assert(ff==funcs);
590 1545612 : if (ff) {
591 1545613 : if (ff->ht) {
592 1545613 : int key = hash_key(fname);
593 1545613 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
594 9705471 : for (; he; he = he->chain) {
595 8159859 : sql_func *f = he->value;
596 8159859 : bool downcast = false;
597 :
598 8159859 : if ((f->type != type && f->type != filt) || (f->private && !private))
599 339535 : continue;
600 7820324 : if (strcmp(f->base.name, fname) == 0 && ((!exact && (list_length(f->ops) == list_length(ops) || (list_length(f->ops) <= list_length(ops) && f->vararg))) || (exact && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0))) {
601 7679542 : int npoints = score_func(f, ops, exact, &downcast);
602 7679541 : if (downcast) {
603 1830555 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
604 7820323 : dcand = f;
605 7820323 : dpoints = npoints;
606 : }
607 : } else {
608 5848986 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
609 7820323 : cand = f;
610 7820323 : points = npoints;
611 : }
612 : }
613 : }
614 : }
615 : } else {
616 0 : node *n;
617 0 : sql_base_loop(ff, n) {
618 0 : sql_func *f = n->data;
619 0 : bool downcast = false;
620 :
621 0 : if ((f->type != type && f->type != filt) || (f->private && !private))
622 0 : continue;
623 0 : if (strcmp(f->base.name, fname) == 0 && ((!exact && (list_length(f->ops) == list_length(ops) || (list_length(f->ops) <= list_length(ops) && f->vararg))) || (exact && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0))) {
624 0 : int npoints = score_func(f, ops, exact, &downcast);
625 0 : if (downcast) {
626 0 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
627 0 : dcand = f;
628 0 : dpoints = npoints;
629 : }
630 : } else {
631 0 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
632 0 : cand = f;
633 0 : points = npoints;
634 : }
635 : }
636 : }
637 : }
638 : }
639 : }
640 1545611 : if (!cand && dcand)
641 19853 : cand = dcand;
642 1545611 : if (cand && exact && type != F_AGGR)
643 391241 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
644 1154370 : if (cand)
645 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
646 1182048 : return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
647 : return NULL;
648 : }
649 :
650 : static sql_subfunc *
651 629461 : os_bind_func__(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
652 : {
653 629461 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
654 629461 : sql_subtype *input_type = NULL;
655 629461 : sql_func *cand = NULL, *dcand = NULL;
656 629461 : int points = 0, dpoints = 0;
657 :
658 629461 : if (ops && ops->h)
659 596985 : input_type = ops->h->data;
660 :
661 629461 : if (ff) {
662 629461 : struct os_iter oi;
663 629461 : os_iterator(&oi, ff, sql->session->tr, fname);
664 2117426 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
665 1487965 : sql_func *f = (sql_func*)b;
666 1487965 : bool downcast = false;
667 :
668 1487965 : if ((f->type != type && f->type != filt) || (f->private && !private))
669 471498 : continue;
670 1016467 : if (strcmp(f->base.name, fname) == 0 && ((!exact && (list_length(f->ops) == list_length(ops) || (list_length(f->ops) <= list_length(ops) && f->vararg))) || (exact && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0))) {
671 328441 : int npoints = score_func(f, ops, exact, &downcast);
672 328441 : if (downcast) {
673 2556 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
674 1016467 : dcand = f;
675 1016467 : dpoints = npoints;
676 : }
677 : } else {
678 325885 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
679 1016467 : cand = f;
680 1016467 : points = npoints;
681 : }
682 : }
683 : }
684 : }
685 : }
686 629461 : if (!cand && dcand)
687 301 : cand = dcand;
688 629461 : if (cand && exact && type != F_AGGR)
689 166776 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
690 462685 : if (cand)
691 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
692 249922 : return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
693 : return NULL;
694 : }
695 :
696 : #define sql_bind_func__extra \
697 : do { \
698 : if (!res && (res = sql_bind_func__(sql, funcs, name, ops, type, private, exact))) /* search system wide functions first */ \
699 : return res; \
700 : } while (0)
701 :
702 : sql_subfunc *
703 1570991 : sql_bind_func_(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private, bool exact)
704 : {
705 1570991 : char *F = NULL, *objstr = NULL;
706 1570991 : const char error[] = "CATALOG";
707 1570991 : sql_subfunc *res = NULL;
708 :
709 1570991 : FUNC_TYPE_STR(type, F, objstr);
710 1570991 : (void) F; /* not used */
711 :
712 1572527 : search_object_on_path(res = os_bind_func__(sql, next->funcs, name, ops, type, private, exact), functions_without_schema, sql_bind_func__extra, SQLSTATE(42000));
713 : return res;
714 : }
715 :
716 : static sql_subfunc *
717 40423 : sql_bind_func_result_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
718 : {
719 40423 : sql_subtype *tp = sql_bind_localtype("bit");
720 40423 : sql_func *cand = NULL;
721 40423 : int points = 0, npoints = 0;
722 :
723 40423 : if (ff) {
724 40423 : if (ff->ht) {
725 40423 : int key = hash_key(fname);
726 40423 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
727 143266 : for (; he; he = he->chain) {
728 102843 : sql_func *f = he->value;
729 102843 : sql_arg *firstres = NULL;
730 :
731 102843 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
732 0 : continue;
733 102843 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
734 102843 : if (strcmp(f->base.name, fname) == 0 && f->type == type && (is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
735 40422 : npoints = next_cand_points(f->ops, ops);
736 :
737 40422 : if (!cand || npoints > points) {
738 102843 : cand = f;
739 102843 : points = npoints;
740 : }
741 : }
742 : }
743 : } else {
744 0 : node *n;
745 0 : sql_base_loop( ff, n) {
746 0 : sql_func *f = n->data;
747 0 : sql_arg *firstres = NULL;
748 :
749 0 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
750 0 : continue;
751 0 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
752 0 : if (strcmp(f->base.name, fname) == 0 && f->type == type && (is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
753 0 : npoints = next_cand_points(f->ops, ops);
754 :
755 0 : if (!cand || npoints > points) {
756 0 : cand = f;
757 0 : points = npoints;
758 : }
759 : }
760 : }
761 : }
762 : }
763 40423 : if (cand)
764 40422 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
765 : return NULL;
766 : }
767 :
768 : static sql_subfunc *
769 1 : os_bind_func_result_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
770 : {
771 1 : sql_subtype *tp = sql_bind_localtype("bit");
772 1 : sql_func *cand = NULL;
773 1 : int points = 0, npoints = 0;
774 :
775 1 : if (ff) {
776 1 : struct os_iter oi;
777 1 : os_iterator(&oi, ff, sql->session->tr, fname);
778 2 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
779 1 : sql_func *f = (sql_func*)b;
780 1 : sql_arg *firstres = NULL;
781 :
782 1 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
783 0 : continue;
784 1 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
785 1 : if (strcmp(f->base.name, fname) == 0 && f->type == type && (is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
786 1 : npoints = next_cand_points(f->ops, ops);
787 :
788 1 : if (!cand || npoints > points) {
789 1 : cand = f;
790 1 : points = npoints;
791 : }
792 : }
793 : }
794 : }
795 1 : if (cand)
796 1 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
797 : return NULL;
798 : }
799 :
800 : #define sql_bind_func_result_extra \
801 : do { \
802 : if (!res) \
803 : res = sql_bind_func_result_internal(sql, funcs, name, type, private, ops, r_res); /* search system wide functions first */ \
804 : } while (0)
805 :
806 :
807 : sql_subfunc *
808 40423 : sql_bind_func_result(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private, sql_subtype *r_res, int nargs, ...)
809 : {
810 40423 : char *F = NULL, *objstr = NULL;
811 40423 : const char error[] = "CATALOG";
812 40423 : sql_subfunc *res = NULL;
813 40423 : list *ops = sa_list(sql->sa);
814 40423 : va_list valist;
815 :
816 40423 : FUNC_TYPE_STR(type, F, objstr);
817 40423 : (void) F; /* not used */
818 :
819 40423 : va_start(valist, nargs);
820 122682 : for (int i = 0; i < nargs; i++) {
821 82259 : sql_type *tpe = va_arg(valist, sql_type*);
822 82259 : list_append(ops, tpe);
823 : }
824 40423 : va_end(valist);
825 :
826 40423 : search_object_on_path(res = os_bind_func_result_internal(sql, next->funcs, name, type, private, ops, r_res), functions_without_schema, sql_bind_func_result_extra, SQLSTATE(42000));
827 40423 : if (res) /* make sure we have the correct result type */
828 40423 : res->res->h->data = r_res;
829 40423 : return res;
830 : }
831 :
832 : static list *
833 5253 : sql_find_funcs_by_name_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private)
834 : {
835 5253 : int key = hash_key(fname);
836 5253 : list *res = NULL;
837 :
838 5253 : if (ff) {
839 5253 : if (ff->ht) {
840 5253 : for (sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)]; he; he = he->chain) {
841 0 : sql_func *f = he->value;
842 :
843 0 : if (f->type != type || (f->private && !private))
844 0 : continue;
845 0 : if (strcmp(f->base.name, fname) == 0) {
846 0 : if (!res)
847 0 : res = sa_list(sql->sa);
848 0 : list_append(res, f);
849 : }
850 : }
851 : } else {
852 0 : node *n;
853 0 : sql_base_loop( ff, n) {
854 0 : sql_func *f = n->data;
855 :
856 0 : if (f->type != type || (f->private && !private))
857 0 : continue;
858 0 : if (strcmp(f->base.name, fname) == 0) {
859 0 : if (!res)
860 0 : res = sa_list(sql->sa);
861 0 : list_append(res, f);
862 : }
863 : }
864 : }
865 : }
866 5253 : return res;
867 : }
868 :
869 : static list *
870 9073 : os_find_funcs_by_name_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private)
871 : {
872 9073 : list *res = NULL;
873 :
874 9073 : if (ff) {
875 9073 : struct os_iter oi;
876 9073 : os_iterator(&oi, ff, sql->session->tr, fname);
877 14825 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
878 5752 : sql_func *f = (sql_func*)b;
879 :
880 5752 : if (f->type != type || (f->private && !private))
881 1328 : continue;
882 4424 : if (strcmp(f->base.name, fname) == 0) {
883 4424 : if (!res)
884 4396 : res = sa_list(sql->sa);
885 4424 : list_append(res, f);
886 : }
887 : }
888 : }
889 9073 : return res;
890 : }
891 :
892 : #define sql_find_funcs_by_name_extra \
893 : do { \
894 : if (!res && (res = sql_find_funcs_by_name_internal(sql, funcs, name, type, private))) /* search system wide functions first */ \
895 : return res; \
896 : } while (0)
897 :
898 : list *
899 5726 : sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private)
900 : {
901 5726 : char *F = NULL, *objstr = NULL;
902 5726 : const char error[] = "CATALOG";
903 5726 : list *res = NULL;
904 :
905 5726 : FUNC_TYPE_STR(type, F, objstr);
906 5726 : (void) F; /* not used */
907 :
908 6420 : search_object_on_path(res = os_find_funcs_by_name_internal(sql, next->funcs, name, type, private), functions_without_schema, sql_find_funcs_by_name_extra, SQLSTATE(42000));
909 : return res;
910 : }
911 :
912 : char *
913 1974494 : qname_schema(dlist *qname)
914 : {
915 1974494 : assert(qname && qname->h);
916 :
917 1974494 : if (dlist_length(qname) == 2) {
918 1137924 : return qname->h->data.sval;
919 836569 : } else if (dlist_length(qname) == 3) {
920 4 : return qname->h->next->data.sval;
921 : }
922 : return NULL;
923 : }
924 :
925 : char *
926 1987387 : qname_schema_object(dlist *qname)
927 : {
928 1987387 : assert(qname && qname->h);
929 :
930 1987387 : if (dlist_length(qname) == 1) {
931 849305 : return qname->h->data.sval;
932 1138082 : } else if (dlist_length(qname) == 2) {
933 1138078 : return qname->h->next->data.sval;
934 4 : } else if (dlist_length(qname) == 3) {
935 4 : return qname->h->next->next->data.sval;
936 : }
937 : return "unknown";
938 : }
939 :
940 : char *
941 0 : qname_catalog(dlist *qname)
942 : {
943 0 : assert(qname && qname->h);
944 :
945 0 : if (dlist_length(qname) == 3) {
946 0 : return qname->h->data.sval;
947 : }
948 : return NULL;
949 : }
950 :
951 : int
952 1559 : set_type_param(mvc *sql, sql_subtype *type, int nr)
953 : {
954 1559 : sql_arg *a = sql_bind_paramnr(sql, nr);
955 :
956 1559 : if (!a)
957 : return -1;
958 1559 : a->type = *type;
959 1559 : return 0;
960 : }
961 :
962 : /*
963 : * Find the result_datatype for certain combinations of values
964 : * (like case expressions or columns in a result of a query expression).
965 : * See standaard pages 505-507 Result of data type combinations */
966 : sql_subtype *
967 206094 : result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
968 : {
969 206094 : int lclass = l->type->eclass, rclass = r->type->eclass;
970 :
971 : /* case a strings */
972 288309 : if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
973 82215 : const char *tpe = "varchar";
974 82215 : unsigned int digits = 0;
975 82215 : if (!EC_VARCHAR(lclass)) {
976 490 : tpe = r->type->base.name;
977 490 : digits = (!l->digits)?0:r->digits;
978 81725 : } else if (!EC_VARCHAR(rclass)) {
979 5116 : tpe = l->type->base.name;
980 5116 : digits = (!r->digits)?0:l->digits;
981 : } else { /* both */
982 76609 : tpe = !strcmp(l->type->base.name, "varchar")?l->type->base.name:!strcmp(r->type->base.name, "varchar")?r->type->base.name:
983 7 : (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
984 76609 : digits = (!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
985 : }
986 82215 : sql_find_subtype(super, tpe, digits, 0);
987 : /* case b blob */
988 123879 : } else if (lclass == EC_BLOB || rclass == EC_BLOB) {
989 14 : *super = (lclass == EC_BLOB) ? *l : *r;
990 : /* case c all exact numeric */
991 220911 : } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
992 97046 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
993 97046 : unsigned int digits = sql_max(l->digits, r->digits);
994 97046 : unsigned int scale = sql_max(l->scale, r->scale);
995 :
996 97046 : if (l->type->radix == 10 && r->type->radix == 10) {
997 90 : digits = scale + (sql_max(l->digits - l->scale, r->digits - r->scale));
998 : #ifdef HAVE_HGE
999 90 : if (digits > 38) {
1000 0 : digits = 38;
1001 : #else
1002 : if (digits > 18) {
1003 : digits = 18;
1004 : #endif
1005 0 : scale = MIN(scale, digits - 1);
1006 : }
1007 96956 : } else if (l->type->radix == 2 && r->type->radix == 10) { /* change to radix 10 */
1008 47 : digits = bits2digits(l->type->digits);
1009 47 : digits = sql_max(r->digits, digits);
1010 47 : scale = r->scale;
1011 96909 : } else if (l->type->radix == 10 && r->type->radix == 2) { /* change to radix 10 */
1012 121 : digits = bits2digits(r->type->digits);
1013 121 : digits = sql_max(l->digits, digits);
1014 121 : scale = l->scale;
1015 : }
1016 97046 : sql_find_subtype(super, tpe, digits, scale);
1017 : /* case d approximate numeric */
1018 26819 : } else if (EC_APPNUM(lclass) || EC_APPNUM(rclass)) {
1019 157 : if (!EC_APPNUM(lclass)) {
1020 45 : *super = *r;
1021 112 : } else if (!EC_APPNUM(rclass)) {
1022 91 : *super = *l;
1023 : } else { /* both */
1024 21 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1025 21 : unsigned int digits = sql_max(l->digits, r->digits); /* bits precision */
1026 21 : sql_find_subtype(super, tpe, digits, 0);
1027 : }
1028 : /* now its getting serious, ie e any 'case e' datetime data type */
1029 : /* 'case f' interval types */
1030 : /* 'case g' boolean */
1031 : /* 'case h-l' compounds like row (tuple), etc */
1032 : } else {
1033 26662 : return supertype(super, l, r);
1034 : }
1035 : return super;
1036 : }
1037 :
1038 : char *
1039 79 : toUpperCopy(char *dest, const char *src)
1040 : {
1041 79 : size_t i, len;
1042 :
1043 79 : if (src == NULL) {
1044 0 : *dest = '\0';
1045 0 : return(dest);
1046 : }
1047 :
1048 79 : len = _strlen(src);
1049 422 : for (i = 0; i < len; i++)
1050 343 : dest[i] = (char)toupper((int)src[i]);
1051 :
1052 79 : dest[i] = '\0';
1053 79 : return(dest);
1054 : }
1055 :
1056 : static char * _symbol2string(mvc *sql, symbol *se, int expression, char **err);
1057 :
1058 : static char *
1059 1 : dlist2string(mvc *sql, dlist *l, int expression, char **err)
1060 : {
1061 1 : char *b = NULL;
1062 1 : dnode *n;
1063 :
1064 3 : for (n=l->h; n; n = n->next) {
1065 2 : char *s = NULL;
1066 :
1067 2 : if (n->type == type_string && n->data.sval)
1068 2 : s = sa_strdup(sql->ta, n->data.sval);
1069 0 : else if (n->type == type_symbol)
1070 0 : s = _symbol2string(sql, n->data.sym, expression, err);
1071 :
1072 2 : if (!s)
1073 0 : return NULL;
1074 2 : if (b) {
1075 1 : char *o = SA_NEW_ARRAY(sql->ta, char, strlen(b) + strlen(s) + 2);
1076 1 : if (o)
1077 1 : stpcpy(stpcpy(stpcpy(o, b), "."), s);
1078 0 : b = o;
1079 1 : if (b == NULL)
1080 : return NULL;
1081 : } else {
1082 : b = s;
1083 : }
1084 : }
1085 : return b;
1086 : }
1087 :
1088 : static const char *
1089 876 : symbol_escape_ident(allocator *sa, const char *s)
1090 : {
1091 876 : char *res = NULL;
1092 876 : if (s) {
1093 824 : size_t l = strlen(s);
1094 824 : char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
1095 :
1096 824 : res = r;
1097 6094 : while (*s) {
1098 5270 : if (*s == '"')
1099 1 : *r++ = '"';
1100 5270 : *r++ = *s++;
1101 : }
1102 824 : *r = '\0';
1103 : }
1104 876 : return res;
1105 : }
1106 :
1107 : char *
1108 1583 : _symbol2string(mvc *sql, symbol *se, int expression, char **err)
1109 : {
1110 : /* inner symbol2string uses the temporary allocator */
1111 1583 : switch (se->token) {
1112 3 : case SQL_NOP: {
1113 3 : dnode *lst = se->data.lval->h, *ops = lst->next->next->data.lval->h, *aux;
1114 3 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1115 3 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1116 3 : int i = 0, nargs = 0;
1117 3 : char** inputs = NULL, *res;
1118 3 : size_t inputs_length = 0, extra = sname ? strlen(sname) + 3 : 0;
1119 :
1120 12 : for (aux = ops; aux; aux = aux->next)
1121 9 : nargs++;
1122 3 : if (!(inputs = SA_ZNEW_ARRAY(sql->ta, char*, nargs)))
1123 : return NULL;
1124 :
1125 12 : for (aux = ops; aux; aux = aux->next) {
1126 9 : if (!(inputs[i] = _symbol2string(sql, aux->data.sym, expression, err))) {
1127 : return NULL;
1128 : }
1129 9 : inputs_length += strlen(inputs[i]);
1130 9 : i++;
1131 : }
1132 :
1133 6 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + inputs_length + 3 + (nargs - 1 /* commas */) + 2))) {
1134 3 : char *concat = res;
1135 3 : if (sname)
1136 3 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1137 3 : concat = stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"(");
1138 3 : i = 0;
1139 12 : for (aux = ops; aux; aux = aux->next) {
1140 9 : concat = stpcpy(concat, inputs[i]);
1141 9 : if (aux->next)
1142 6 : concat = stpcpy(concat, ",");
1143 9 : i++;
1144 : }
1145 3 : concat = stpcpy(concat, ")");
1146 : }
1147 : return res;
1148 : }
1149 22 : case SQL_BINOP: {
1150 22 : dnode *lst = se->data.lval->h;
1151 22 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1152 22 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1153 22 : char *l = NULL, *r = NULL, *res;
1154 22 : size_t extra = sname ? strlen(sname) + 3 : 0;
1155 :
1156 22 : if (!(l = _symbol2string(sql, lst->next->next->data.sym, expression, err)) || !(r = _symbol2string(sql, lst->next->next->next->data.sym, expression, err)))
1157 2 : return NULL;
1158 :
1159 40 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + strlen(r) + 6))) {
1160 20 : char *concat = res;
1161 20 : if (sname)
1162 18 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1163 20 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("), l), ","), r), ")");
1164 : }
1165 : return res;
1166 : }
1167 40 : case SQL_OP: {
1168 40 : dnode *lst = se->data.lval->h;
1169 40 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1170 40 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1171 40 : char *res;
1172 40 : size_t extra = sname ? strlen(sname) + 3 : 0;
1173 :
1174 80 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + 5))) {
1175 40 : char *concat = res;
1176 40 : if (sname)
1177 0 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1178 40 : stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"()");
1179 : }
1180 : return res;
1181 : }
1182 88 : case SQL_UNOP: {
1183 88 : dnode *lst = se->data.lval->h;
1184 88 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1185 88 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1186 88 : char *l = _symbol2string(sql, lst->next->next->data.sym, expression, err), *res;
1187 88 : size_t extra = sname ? strlen(sname) + 3 : 0;
1188 :
1189 88 : if (!l)
1190 : return NULL;
1191 :
1192 174 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + 5))) {
1193 87 : char *concat = res;
1194 87 : if (sname)
1195 79 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1196 87 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("), l), ")");
1197 : }
1198 : return res;
1199 : }
1200 0 : case SQL_PARAMETER:
1201 0 : return sa_strdup(sql->ta, "?");
1202 193 : case SQL_NULL:
1203 193 : return sa_strdup(sql->ta, "NULL");
1204 : case SQL_ATOM:{
1205 927 : AtomNode *an = (AtomNode *) se;
1206 927 : if (an && an->a)
1207 927 : return atom2sql(sql->ta, an->a, sql->timezone);
1208 : else
1209 0 : return sa_strdup(sql->ta, "NULL");
1210 : }
1211 269 : case SQL_NEXT: {
1212 269 : const char *seq = symbol_escape_ident(sql->ta, qname_schema_object(se->data.lval)),
1213 269 : *sname = qname_schema(se->data.lval);
1214 269 : char *res;
1215 :
1216 269 : if (!sname)
1217 200 : sname = sql->session->schema->base.name;
1218 269 : sname = symbol_escape_ident(sql->ta, sname);
1219 :
1220 538 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen("next value for \"") + strlen(sname) + strlen(seq) + 5)))
1221 269 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for \""), sname), "\".\""), seq), "\"");
1222 : return res;
1223 33 : } break;
1224 33 : case SQL_IDENT:
1225 : case SQL_COLUMN: {
1226 : /* can only be variables */
1227 33 : dlist *l = se->data.lval;
1228 33 : assert(l->h->type != type_lng);
1229 33 : if (expression && dlist_length(l) == 1 && l->h->type == type_string) {
1230 : /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */
1231 32 : const char *op = symbol_escape_ident(sql->ta, l->h->data.sval);
1232 32 : char *res;
1233 :
1234 64 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3)))
1235 32 : stpcpy(stpcpy(stpcpy(res, "\""), op), "\"");
1236 32 : return res;
1237 0 : } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) {
1238 0 : const char *first = symbol_escape_ident(sql->ta, l->h->data.sval),
1239 0 : *second = symbol_escape_ident(sql->ta, l->h->next->data.sval);
1240 0 : char *res;
1241 :
1242 0 : if (!first || !second)
1243 : return NULL;
1244 0 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(first) + strlen(second) + 6)))
1245 0 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), first), "\".\""), second), "\"");
1246 0 : return res;
1247 : } else {
1248 1 : char *e = dlist2string(sql, l, expression, err);
1249 1 : if (e)
1250 1 : *err = e;
1251 1 : return NULL;
1252 : }
1253 : }
1254 6 : case SQL_CAST: {
1255 6 : dlist *dl = se->data.lval;
1256 6 : char *val = NULL, *tpe = NULL, *res;
1257 :
1258 6 : if (!(val = _symbol2string(sql, dl->h->data.sym, expression, err)) || !(tpe = subtype2string2(sql->ta, &dl->h->next->data.typeval)))
1259 0 : return NULL;
1260 12 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(val) + strlen(tpe) + 11)))
1261 6 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "cast("), val), " as "), tpe), ")");
1262 : return res;
1263 : }
1264 2 : default: {
1265 2 : const char msg[] = "SQL feature not yet available for expressions and default values: ";
1266 2 : char *tok_str = token2string(se->token);
1267 4 : if ((*err = SA_NEW_ARRAY(sql->ta, char, strlen(msg) + strlen(tok_str) + 1)))
1268 2 : stpcpy(stpcpy(*err, msg), tok_str);
1269 : }
1270 : }
1271 2 : return NULL;
1272 : }
1273 :
1274 : char *
1275 1438 : symbol2string(mvc *sql, symbol *se, int expression, char **err)
1276 : {
1277 1438 : char *res = _symbol2string(sql, se, expression, err);
1278 :
1279 1438 : if (res)
1280 1435 : res = sa_strdup(sql->sa, res);
1281 1438 : if (*err)
1282 3 : *err = sa_strdup(sql->sa, *err);
1283 1438 : sa_reset(sql->ta);
1284 1438 : return res;
1285 : }
|