Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024, 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "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 : #include "rel_exp.h"
28 :
29 : /*
30 : * For debugging purposes we need to be able to convert sql-tokens to
31 : * a string representation.
32 : *
33 : * !SQL ERROR <sqlerrno> : <details>
34 : * !SQL DEBUG <details>
35 : * !SQL WARNING <details>
36 : * !SQL <informative message, reserved for ...rows affected>
37 : */
38 :
39 : void
40 390847 : sql_add_param(mvc *sql, const char *name, sql_subtype *st)
41 : {
42 390847 : sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
43 :
44 390847 : if (name)
45 389232 : a->name = sa_strdup(sql->sa, name);
46 390847 : if (st && st->type)
47 389221 : a->type = *st;
48 390847 : a->inout = ARG_IN;
49 390847 : if (name && strcmp(name, "*") == 0)
50 4 : a->type = *sql_bind_localtype("int");
51 390847 : if (!sql->params)
52 230771 : sql->params = sa_list(sql->sa);
53 390847 : list_append(sql->params, a);
54 390847 : }
55 :
56 : int
57 100686 : sql_bind_param(mvc *sql, const char *name)
58 : {
59 100686 : node *n;
60 100686 : int nr = 0;
61 :
62 100686 : if (sql->params) {
63 212134 : for (n = sql->params->h; n; n = n->next, nr++) {
64 207719 : sql_arg *a = n->data;
65 :
66 207719 : if (a->name && strcmp(a->name, name) == 0)
67 90113 : return nr;
68 : }
69 : }
70 : return -1;
71 : }
72 :
73 : sql_arg *
74 93288 : sql_bind_paramnr(mvc *sql, int nr)
75 : {
76 93288 : int i=0;
77 93288 : node *n;
78 :
79 93288 : if (sql->params && nr < list_length(sql->params)) {
80 684012 : for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
81 : ;
82 :
83 93288 : if (n)
84 93288 : return n->data;
85 : }
86 : return NULL;
87 : }
88 :
89 : sql_arg *
90 6 : sql_find_param(mvc *sql, char *name)
91 : {
92 9 : for (node *n = sql->params->h; n; n = n->next) {
93 8 : sql_arg *a = n->data;
94 8 : if (strcmp(a->name, name) == 0)
95 5 : return a;
96 : }
97 : return NULL;
98 : }
99 :
100 : void
101 787809 : sql_destroy_params(mvc *sql)
102 : {
103 787809 : sql->params = NULL;
104 787809 : }
105 :
106 : sql_schema *
107 1729161 : cur_schema(mvc *sql)
108 : {
109 1729161 : return sql->session->schema;
110 : }
111 :
112 : sql_schema *
113 568202 : tmp_schema(mvc *sql)
114 : {
115 568202 : return mvc_bind_schema(sql, "tmp");
116 : }
117 :
118 : #define DO_NOTHING(x) ;
119 :
120 : /* as we don't have OOP in C, I prefer a single macro with the search path algorithm to passing function pointers */
121 : #define search_object_on_path(CALL, EXTRA_CONDITION, EXTRA, ERROR_CODE, show_error) \
122 : do { \
123 : sql_schema *next = NULL; \
124 : \
125 : if (sname) { /* user has explicitly typed the schema, so either the object is there or we return error */ \
126 : if (!(next = mvc_bind_schema(sql, sname))) \
127 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s: no such schema '%s'", error, sname); \
128 : EXTRA_CONDITION(EXTRA); /* for functions without schema, 'sys' is a valid schema to bind them */ \
129 : if (!res) { \
130 : CALL; \
131 : } \
132 : } else { \
133 : sql_schema *cur = cur_schema(sql); \
134 : char *session_schema = cur->base.name; \
135 : \
136 : EXTRA; \
137 : 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 */ \
138 : next = tmp_schema(sql); \
139 : CALL; \
140 : } \
141 : if (!res) { /* then current session's schema */ \
142 : next = cur; \
143 : CALL; \
144 : } \
145 : if (!res) { \
146 : /* object not found yet, look inside search path */ \
147 : for (node *n = sql->schema_path->h ; n && !res ; n = n->next) { \
148 : str p = (str) n->data; \
149 : if (strcmp(session_schema, p) != 0 && (next = mvc_bind_schema(sql, p))) \
150 : CALL; \
151 : } \
152 : } \
153 : if (!res && !sql->schema_path_has_sys && strcmp(session_schema, "sys") != 0) { /* if 'sys' is not in the current path search it next */ \
154 : next = mvc_bind_schema(sql, "sys"); \
155 : CALL; \
156 : } \
157 : } \
158 : if (!res && show_error) \
159 : return sql_error(sql, ERR_NOTFOUND, ERROR_CODE "%s: no such %s %s%s%s'%s'", error, objstr, sname ? "'":"", sname ? sname : "", sname ? "'.":"", name); \
160 : } while (0)
161 :
162 : #define table_extra \
163 : do { \
164 : if (s) { \
165 : next = s; /* there's a default schema to search before all others, e.g. bind a child table from a merge table */ \
166 : res = mvc_bind_table(sql, next, name); \
167 : } \
168 : if (!res && strcmp(objstr, "table") == 0 && (res = stack_find_table(sql, name))) /* for tables, first try a declared table from the stack */ \
169 : return res; \
170 : } while (0)
171 :
172 : sql_table *
173 692716 : find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *name, const char *error, bool isView)
174 : {
175 692716 : const char *objstr = isView ? "view" : "table";
176 692716 : sql_table *res = NULL;
177 :
178 693283 : search_object_on_path(res = mvc_bind_table(sql, next, name), DO_NOTHING, table_extra, SQLSTATE(42S02), true);
179 : return res;
180 : }
181 :
182 : sql_sequence *
183 1481 : find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
184 : {
185 1481 : const char objstr[] = "sequence";
186 1481 : sql_sequence *res = NULL;
187 :
188 1483 : search_object_on_path(res = find_sql_sequence(sql->session->tr, next, name), DO_NOTHING, ;, SQLSTATE(42000), true);
189 : return res;
190 : }
191 :
192 : sql_idx *
193 218 : find_idx_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
194 : {
195 218 : const char objstr[] = "index";
196 218 : sql_idx *res = NULL;
197 :
198 292 : search_object_on_path(res = mvc_bind_idx(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S12), true);
199 : return res;
200 : }
201 :
202 : sql_type *
203 37 : find_type_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
204 : {
205 37 : const char objstr[] = "type";
206 37 : sql_type *res = NULL;
207 :
208 39 : search_object_on_path(res = schema_bind_type(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S01), true);
209 : return res;
210 : }
211 :
212 : sql_trigger *
213 96 : find_trigger_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
214 : {
215 96 : const char objstr[] = "trigger";
216 96 : sql_trigger *res = NULL;
217 :
218 118 : search_object_on_path(res = mvc_bind_trigger(sql, next, name), DO_NOTHING, ;, SQLSTATE(3F000), true);
219 : return res;
220 : }
221 :
222 : /* A variable can be any of the following, from the innermost to the outermost:
223 : - 'parameter of the function' (ie in the param list)
224 : - local variable, declared earlier
225 : - global variable, also declared earlier
226 : */
227 : #define variable_extra \
228 : do { \
229 : if (!res) { \
230 : if ((*var = stack_find_var_frame(sql, name, level))) { /* check if variable is known from the stack */ \
231 : *tpe = &((*var)->var.tpe); \
232 : res = true; \
233 : } else if ((nr = sql_bind_param(sql, name)) >= 0) { /* then if it is a parameter */ \
234 : *a = sql_bind_paramnr(sql, nr); \
235 : *tpe = &((*a)->type); \
236 : *level = 1; \
237 : res = true; \
238 : } \
239 : } \
240 : } while (0)
241 :
242 : #define var_find_on_global \
243 : do { \
244 : if ((*var = find_global_var(sql, next, name))) { /* then if it is a global var */ \
245 : *tpe = &((*var)->var.tpe); \
246 : *level = 0; \
247 : res = true; \
248 : } \
249 : } while (0)
250 :
251 : bool
252 210647 : 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)
253 : {
254 210647 : const char objstr[] = "variable";
255 210647 : bool res = false;
256 210647 : int nr = 0;
257 :
258 210647 : (void)nr;
259 219612 : search_object_on_path(var_find_on_global, DO_NOTHING, variable_extra, SQLSTATE(42000), false);
260 : return res;
261 : }
262 :
263 : static sql_subfunc *
264 999904 : _dup_subaggr(allocator *sa, sql_func *a, sql_subtype *member)
265 : {
266 999904 : node *tn;
267 999904 : unsigned int scale = 0, digits = 0;
268 999904 : sql_subfunc *ares = SA_ZNEW(sa, sql_subfunc);
269 :
270 :
271 1000110 : ares->func = a;
272 1000110 : if (IS_FILT(a)) {
273 5293 : ares->res = sa_list(sa);
274 5293 : list_append(ares->res, sql_bind_localtype("bit"));
275 994817 : } else if (IS_FUNC(a) || IS_UNION(a) || IS_ANALYTIC(a) || IS_AGGR(a)) { /* not needed for PROC */
276 957254 : if (a->res) {
277 957254 : ares->res = sa_list(sa);
278 2000219 : for(tn = a->res->h; tn; tn = tn->next) {
279 1042920 : sql_arg *rarg = tn->data;
280 1042920 : sql_subtype *res, *r = &rarg->type;
281 :
282 1042920 : if (a->fix_scale == SCALE_EQ && !IS_AGGR(a)) {
283 : res = r;
284 : } else {
285 865230 : digits = r->digits;
286 865230 : scale = r->scale;
287 : /* same scale as the input */
288 865230 : if (member && (member->scale != scale ||
289 179636 : (digits != member->digits && !EC_NUMBER(member->type->eclass)))) {
290 92319 : if (member->digits > digits)
291 : digits = member->digits;
292 : scale = member->scale;
293 : }
294 : /* same type as the input */
295 865230 : if (r->type->eclass == EC_ANY && member) {
296 13302 : r = member;
297 13302 : digits = member->digits;
298 : }
299 865230 : if (!EC_SCALE(r->type->eclass))
300 865230 : scale = 0;
301 865230 : res = sql_create_subtype(sa, r->type, digits, scale);
302 : }
303 1042907 : list_append(ares->res, res);
304 : }
305 : }
306 : }
307 1000155 : return ares;
308 : }
309 :
310 :
311 :
312 : static sql_subfunc *
313 135090 : func_cmp(allocator *sa, sql_func *f, const char *name, int nrargs)
314 : {
315 135090 : if (strcmp(f->base.name, name) == 0) {
316 135090 : if (f->vararg)
317 : //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
318 2 : return _dup_subaggr(sa, f, NULL);
319 135088 : if (nrargs < 0 || list_length(f->ops) == nrargs)
320 : //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
321 134298 : return _dup_subaggr(sa, f, NULL);
322 : }
323 : return NULL;
324 : }
325 :
326 : static sql_subfunc *
327 694322 : sql_find_func_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
328 : {
329 694322 : int key = hash_key(fname);
330 694322 : sql_subfunc *res = NULL;
331 694322 : int found = 0;
332 694322 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
333 :
334 694322 : if (ff) {
335 694322 : if (ff->ht) {
336 694322 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
337 694322 : if (prev) {
338 10 : for (; he && !found; he = he->chain)
339 0 : if (he->value == prev->func)
340 0 : found = 1;
341 : }
342 7889720 : for (; he; he = he->chain) {
343 7319969 : sql_func *f = he->value;
344 :
345 7319969 : if ((f->type != type && f->type != filt) || (f->private && !private))
346 7195379 : continue;
347 124590 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
348 124575 : return res;
349 : }
350 : } else {
351 0 : node *n = ff->h;
352 0 : if (prev) {
353 0 : for (; n && !found; n = n->next)
354 0 : if (n->data == prev->func)
355 0 : found = 1;
356 : }
357 0 : for (; n; n = n->next) {
358 0 : sql_func *f = n->data;
359 :
360 0 : if ((f->type != type && f->type != filt) || (f->private && !private))
361 0 : continue;
362 0 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
363 0 : return res;
364 : }
365 : }
366 : }
367 : return res;
368 : }
369 :
370 : static sql_subfunc *
371 820880 : os_find_func_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
372 : {
373 820880 : sql_subfunc *res = NULL;
374 820880 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
375 :
376 820880 : if (ff) {
377 820880 : struct os_iter oi;
378 820880 : os_iterator(&oi, ff, sql->session->tr, fname);
379 984582 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
380 173400 : sql_func *f = (sql_func*)b;
381 173400 : if (prev && prev->func != f) {
382 0 : continue;
383 173400 : } else if (prev) {
384 0 : prev = NULL;
385 0 : continue;
386 : }
387 :
388 173400 : if ((f->type != type && f->type != filt) || (f->private && !private))
389 162900 : continue;
390 10500 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
391 9725 : return res;
392 : }
393 : }
394 : return res;
395 : }
396 :
397 : #define functions_without_schema(X) if (strcmp(sname, "sys") == 0) X
398 :
399 : #define find_func_extra \
400 : do { \
401 : if (!res && (res = sql_find_func_internal(sql, funcs, name, nrargs, type, private, prev))) /* search system wide functions first */ \
402 : return res; \
403 : } while (0)
404 :
405 : sql_subfunc *
406 694976 : sql_find_func(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
407 : {
408 694976 : char *F = NULL, *objstr = NULL;
409 694976 : const char error[] = "CATALOG";
410 694976 : sql_subfunc *res = NULL;
411 :
412 694976 : FUNC_TYPE_STR(type, F, objstr);
413 694976 : (void) F; /* not used */
414 :
415 694976 : assert(nrargs >= -1);
416 :
417 929168 : search_object_on_path(res = os_find_func_internal(sql, next->funcs, name, nrargs, type, private, prev), functions_without_schema, find_func_extra, "", false);
418 : return res;
419 : }
420 :
421 : sql_subfunc *
422 387708 : sql_bind_func(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_ftype type, bool private, bool exact)
423 : {
424 387708 : list *l = sa_list(sql->sa);
425 :
426 387808 : if (tp1)
427 377490 : list_append(l, tp1);
428 387866 : if (tp2)
429 228316 : list_append(l, tp2);
430 387866 : return sql_bind_func_(sql, sname, fname, l, type, private, exact, true);
431 : }
432 :
433 : sql_subfunc *
434 175 : 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)
435 : {
436 175 : list *l = sa_list(sql->sa);
437 :
438 175 : if (tp1)
439 175 : list_append(l, tp1);
440 175 : if (tp2)
441 175 : list_append(l, tp2);
442 175 : if (tp3)
443 175 : list_append(l, tp3);
444 175 : return sql_bind_func_(sql, sname, fname, l, type, private, false, true);
445 : }
446 :
447 : static int /* bind the function version with more identical type matches */
448 784428 : next_cand_points(list *args, list *ops)
449 : {
450 784428 : int res = 0;
451 :
452 784428 : if (!list_empty(args) && !list_empty(ops))
453 2083516 : for (node *n = args->h, *m = ops->h; n && m ; n = n->next, m = m->next) {
454 1320108 : sql_arg *a = n->data;
455 1320108 : sql_subtype *t = m->data;
456 :
457 1320108 : if (a->type.type->eclass == EC_ANY)
458 681443 : res += 100;
459 638665 : else if (t)
460 638665 : res += a->type.type->base.id == t->type->base.id;
461 : }
462 784829 : res += (list_empty(args) && list_empty(ops));
463 784845 : return res;
464 : }
465 :
466 : static int
467 8204486 : score_func( sql_func *f, list *tl, bool exact, bool *downcast)
468 : {
469 8204486 : int score = 0;
470 8204486 : node *n, *m;
471 :
472 8204486 : if (exact)
473 743601 : return next_cand_points(f->ops, tl);
474 7460885 : if (!tl)
475 : return 1;
476 7460885 : if (f->vararg)
477 : return 1;
478 7460502 : unsigned int digits = 0, scale = 0;
479 7460502 : if (f->fix_scale == SCALE_FIX) {
480 3168508 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
481 2110782 : sql_subtype *t = m->data;
482 :
483 2110782 : if (!t)
484 51 : continue;
485 2110731 : if (t->type->eclass == EC_DEC) {
486 8142 : if (digits < t->digits)
487 : digits = t->digits;
488 8142 : if (scale < t->scale)
489 : scale = t->scale;
490 : }
491 : }
492 3168508 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
493 2110782 : sql_arg *a = n->data;
494 2110782 : sql_subtype *t = m->data;
495 :
496 2110782 : if (!t)
497 51 : continue;
498 2110731 : if (a->type.type->eclass == EC_DEC && t->type->eclass == EC_NUM) {
499 1158705 : if (digits < scale + bits2digits(t->digits))
500 816895 : digits = scale + bits2digits(t->digits);
501 : }
502 : }
503 : }
504 7460502 : int nr_strconverts = 0;
505 16475786 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
506 11824058 : sql_arg *a = n->data;
507 11824058 : sql_subtype *t = m->data;
508 :
509 11824058 : if (!t) { /* parameters */
510 499 : int ec = a->type.type->eclass;
511 499 : score++;
512 499 : if (ec == EC_DEC)
513 : return 0;
514 325 : if (a && EC_NUMBER(ec) && !EC_INTERVAL(ec))
515 218 : score += a->type.type->localtype * 10; /* premium on larger types */
516 107 : else if (a) /* all other types */
517 107 : score += 99;
518 325 : continue;
519 : }
520 :
521 11823559 : int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
522 : /* EX_EXTERNAL can only convert between equal implementation types */
523 11823517 : if (nscore == 0 &&
524 2605697 : t->type->eclass == a->type.type->eclass &&
525 573 : t->type->eclass == EC_EXTERNAL &&
526 573 : t->type->localtype == a->type.type->localtype)
527 : nscore = 10;
528 9218384 : if (nscore &&
529 9218384 : t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC &&
530 3441559 : t->type->localtype > a->type.type->localtype)
531 714013 : *downcast = true;
532 9218384 : if (nscore == 0)
533 : return 0;
534 9218384 : nscore *= 100; /* first based on preferred conversions */
535 9218384 : if (nscore < 0) {
536 291318 : *downcast = true;
537 291318 : nscore = -nscore;
538 : }
539 9218384 : score += nscore;
540 9218384 : if (EC_VARCHAR(t->type->eclass) && EC_NUMBER(a->type.type->eclass))
541 1233 : nr_strconverts++;
542 9218384 : if (nr_strconverts > 1)
543 : return 0;
544 :
545 9218348 : if (f->fix_scale == SCALE_FIX && a->type.type->eclass == EC_DEC && digits > a->type.type->digits) /* doesn't fit */
546 : return 0;
547 : /* sql types equal but implementation differences */
548 9014959 : 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 */
549 146 : score += (11 + t->type->localtype - a->type.type->localtype) * 8;
550 : /* sql types close but digits/scale diffs */
551 9014813 : 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)
552 : //score += (10 + t->type->localtype - a->type.type->localtype) * 8;
553 2520416 : score += (38 + bits2digits(t->digits) - a->type.type->digits);
554 : /* same class over converting to other class */
555 6494397 : else if (t->type->eclass == a->type.type->eclass && t->type->localtype <= a->type.type->localtype) {
556 3480784 : score += (11 + t->type->localtype - a->type.type->localtype) * 4;
557 : /* handle intervals (day, hour, minutes, second) mapped
558 : * within same eclass and implementation type. */
559 3480784 : if (t->type->eclass == a->type.type->eclass && t->type->eclass == EC_SEC)
560 3116 : score += ((t->type->digits > 4 && a->type.type->digits > 4) ||
561 3498 : (t->type->digits <= 4 && a->type.type->digits <= 4)) * 4;
562 : }
563 : /* conversion matrix needs check if conversion is possible */
564 3013613 : else if (t->type->eclass == a->type.type->eclass) {
565 1110421 : if (t->type->localtype <= a->type.type->localtype) {
566 0 : int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
567 0 : score += (10 + t->type->localtype - a->type.type->localtype) * nscore;
568 1110421 : } else if (t->type->eclass == EC_NUM || t->type->eclass == EC_FLT) { /* down casting */
569 1095514 : *downcast = true;
570 1095514 : score += 10 * (10 - t->type->localtype - a->type.type->localtype);
571 : }
572 : }
573 : }
574 4651728 : score += (list_empty(tl) && list_empty(f->ops));
575 4651752 : return score;
576 : }
577 :
578 :
579 : static sql_subfunc *
580 1644772 : sql_bind_func__(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
581 : {
582 1644772 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
583 1644772 : sql_subtype *input_type = NULL;
584 1644772 : sql_func *cand = NULL, *dcand = NULL;
585 1644772 : int points = 0, dpoints = 0;
586 :
587 1644772 : if (ops && ops->h)
588 1604821 : input_type = ops->h->data;
589 :
590 1644772 : assert(ff==funcs);
591 1644772 : if (ff) {
592 1644830 : if (ff->ht) {
593 1644830 : int key = hash_key(fname);
594 1644830 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
595 9947516 : for (; he; he = he->chain) {
596 8302752 : sql_func *f = he->value;
597 8302752 : bool downcast = false;
598 :
599 8302752 : if ((f->type != type && f->type != filt) || (f->private && !private))
600 340721 : continue;
601 7962031 : 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))) {
602 7832268 : int npoints = score_func(f, ops, exact, &downcast);
603 7832040 : if (downcast) {
604 1860316 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
605 7961965 : dcand = f;
606 7961965 : dpoints = npoints;
607 : }
608 : } else {
609 5971724 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
610 7961965 : cand = f;
611 7961965 : points = npoints;
612 : }
613 : }
614 : }
615 : }
616 : } else {
617 0 : node *n;
618 0 : sql_base_loop(ff, n) {
619 0 : sql_func *f = n->data;
620 0 : bool downcast = false;
621 :
622 0 : if ((f->type != type && f->type != filt) || (f->private && !private))
623 0 : continue;
624 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))) {
625 0 : int npoints = score_func(f, ops, exact, &downcast);
626 0 : if (downcast) {
627 0 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
628 0 : dcand = f;
629 0 : dpoints = npoints;
630 : }
631 : } else {
632 0 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
633 0 : cand = f;
634 0 : points = npoints;
635 : }
636 : }
637 : }
638 : }
639 : }
640 : }
641 1644706 : if (!cand && dcand)
642 20305 : cand = dcand;
643 1644706 : if (cand && exact && type != F_AGGR)
644 419054 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
645 1225652 : if (cand)
646 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
647 1227191 : return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
648 : return NULL;
649 : }
650 :
651 : static sql_subfunc *
652 681874 : os_bind_func__(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
653 : {
654 681874 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
655 681874 : sql_subtype *input_type = NULL;
656 681874 : sql_func *cand = NULL, *dcand = NULL;
657 681874 : int points = 0, dpoints = 0;
658 :
659 681874 : if (ops && ops->h)
660 648730 : input_type = ops->h->data;
661 :
662 681874 : if (ff) {
663 681890 : struct os_iter oi;
664 681890 : os_iterator(&oi, ff, sql->session->tr, fname);
665 2270055 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
666 1588196 : sql_func *f = (sql_func*)b;
667 1588196 : bool downcast = false;
668 :
669 1588196 : if ((f->type != type && f->type != filt) || (f->private && !private))
670 481494 : continue;
671 1106702 : 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))) {
672 372506 : int npoints = score_func(f, ops, exact, &downcast);
673 372469 : if (downcast) {
674 2576 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
675 1106653 : dcand = f;
676 1106653 : dpoints = npoints;
677 : }
678 : } else {
679 369893 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
680 1106653 : cand = f;
681 1106653 : points = npoints;
682 : }
683 : }
684 : }
685 : }
686 : }
687 681897 : if (!cand && dcand)
688 301 : cand = dcand;
689 681897 : if (cand && exact && type != F_AGGR)
690 170738 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
691 511159 : if (cand)
692 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
693 323911 : return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
694 : return NULL;
695 : }
696 :
697 : #define sql_bind_func__extra \
698 : do { \
699 : if (!res && (res = sql_bind_func__(sql, funcs, name, ops, type, private, exact))) /* search system wide functions first */ \
700 : return res; \
701 : } while (0)
702 :
703 : sql_subfunc *
704 1670349 : sql_bind_func_(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private, bool exact, bool rerr)
705 : {
706 1670349 : char *F = NULL, *objstr = NULL;
707 1670349 : const char error[] = "CATALOG";
708 1670349 : sql_subfunc *res = NULL;
709 :
710 1670349 : FUNC_TYPE_STR(type, F, objstr);
711 1670349 : (void) F; /* not used */
712 :
713 1671901 : 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), rerr);
714 : return res;
715 : }
716 :
717 : static sql_subfunc *
718 40837 : sql_bind_func_result_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
719 : {
720 40837 : sql_subtype *tp = sql_bind_localtype("bit");
721 40823 : sql_func *cand = NULL;
722 40823 : int points = 0, npoints = 0;
723 :
724 40823 : if (ff) {
725 40823 : if (ff->ht) {
726 40823 : int key = hash_key(fname);
727 40823 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
728 144124 : for (; he; he = he->chain) {
729 103274 : sql_func *f = he->value;
730 103274 : sql_arg *firstres = NULL;
731 :
732 103274 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
733 0 : continue;
734 103274 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
735 103274 : 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) {
736 40838 : npoints = next_cand_points(f->ops, ops);
737 :
738 40852 : if (!cand || npoints > points) {
739 103301 : cand = f;
740 103301 : points = npoints;
741 : }
742 : }
743 : }
744 : } else {
745 0 : node *n;
746 0 : sql_base_loop( ff, n) {
747 0 : sql_func *f = n->data;
748 0 : sql_arg *firstres = NULL;
749 :
750 0 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
751 0 : continue;
752 0 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
753 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) {
754 0 : npoints = next_cand_points(f->ops, ops);
755 :
756 0 : if (!cand || npoints > points) {
757 0 : cand = f;
758 0 : points = npoints;
759 : }
760 : }
761 : }
762 : }
763 : }
764 40850 : if (cand)
765 40849 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
766 : return NULL;
767 : }
768 :
769 : static sql_subfunc *
770 1 : os_bind_func_result_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
771 : {
772 1 : sql_subtype *tp = sql_bind_localtype("bit");
773 1 : sql_func *cand = NULL;
774 1 : int points = 0, npoints = 0;
775 :
776 1 : if (ff) {
777 1 : struct os_iter oi;
778 1 : os_iterator(&oi, ff, sql->session->tr, fname);
779 2 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
780 1 : sql_func *f = (sql_func*)b;
781 1 : sql_arg *firstres = NULL;
782 :
783 1 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
784 0 : continue;
785 1 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
786 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) {
787 1 : npoints = next_cand_points(f->ops, ops);
788 :
789 1 : if (!cand || npoints > points) {
790 1 : cand = f;
791 1 : points = npoints;
792 : }
793 : }
794 : }
795 : }
796 1 : if (cand)
797 1 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
798 : return NULL;
799 : }
800 :
801 : #define sql_bind_func_result_extra \
802 : do { \
803 : if (!res) \
804 : res = sql_bind_func_result_internal(sql, funcs, name, type, private, ops, r_res); /* search system wide functions first */ \
805 : } while (0)
806 :
807 :
808 : sql_subfunc *
809 40839 : sql_bind_func_result(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private, sql_subtype *r_res, int nargs, ...)
810 : {
811 40839 : char *F = NULL, *objstr = NULL;
812 40839 : const char error[] = "CATALOG";
813 40839 : sql_subfunc *res = NULL;
814 40839 : list *ops = sa_list(sql->sa);
815 40835 : va_list valist;
816 :
817 40835 : FUNC_TYPE_STR(type, F, objstr);
818 40835 : (void) F; /* not used */
819 :
820 40835 : va_start(valist, nargs);
821 124006 : for (int i = 0; i < nargs; i++) {
822 83159 : sql_type *tpe = va_arg(valist, sql_type*);
823 83160 : list_append(ops, tpe);
824 : }
825 40847 : va_end(valist);
826 :
827 40847 : 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), true);
828 40852 : if (res) /* make sure we have the correct result type */
829 40852 : res->res->h->data = r_res;
830 40852 : return res;
831 : }
832 :
833 : static list *
834 5336 : sql_find_funcs_by_name_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private)
835 : {
836 5336 : int key = hash_key(fname);
837 5336 : list *res = NULL;
838 :
839 5336 : if (ff) {
840 5336 : if (ff->ht) {
841 5337 : for (sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)]; he; he = he->chain) {
842 1 : sql_func *f = he->value;
843 :
844 1 : if (f->type != type || (f->private && !private))
845 1 : continue;
846 0 : if (strcmp(f->base.name, fname) == 0) {
847 0 : if (!res)
848 0 : res = sa_list(sql->sa);
849 0 : list_append(res, f);
850 : }
851 : }
852 : } else {
853 0 : node *n;
854 0 : sql_base_loop( ff, n) {
855 0 : sql_func *f = n->data;
856 :
857 0 : if (f->type != type || (f->private && !private))
858 0 : continue;
859 0 : if (strcmp(f->base.name, fname) == 0) {
860 0 : if (!res)
861 0 : res = sa_list(sql->sa);
862 0 : list_append(res, f);
863 : }
864 : }
865 : }
866 : }
867 5336 : return res;
868 : }
869 :
870 : static list *
871 9212 : os_find_funcs_by_name_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private)
872 : {
873 9212 : list *res = NULL;
874 :
875 9212 : if (ff) {
876 9212 : struct os_iter oi;
877 9212 : os_iterator(&oi, ff, sql->session->tr, fname);
878 15054 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
879 5842 : sql_func *f = (sql_func*)b;
880 :
881 5842 : if (f->type != type || (f->private && !private))
882 1346 : continue;
883 4496 : if (strcmp(f->base.name, fname) == 0) {
884 4496 : if (!res)
885 4468 : res = sa_list(sql->sa);
886 4496 : list_append(res, f);
887 : }
888 : }
889 : }
890 9212 : return res;
891 : }
892 :
893 : #define sql_find_funcs_by_name_extra \
894 : do { \
895 : if (!res && (res = sql_find_funcs_by_name_internal(sql, funcs, name, type, private))) /* search system wide functions first */ \
896 : return res; \
897 : } while (0)
898 :
899 : list *
900 5817 : sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private)
901 : {
902 5817 : char *F = NULL, *objstr = NULL;
903 5817 : const char error[] = "CATALOG";
904 5817 : list *res = NULL;
905 :
906 5817 : FUNC_TYPE_STR(type, F, objstr);
907 5817 : (void) F; /* not used */
908 :
909 6168 : 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, "", false);
910 : return res;
911 : }
912 :
913 : sql_alias *
914 622764 : qname2alias(allocator *sa, dlist *qname)
915 : {
916 622764 : sql_alias *a = NULL;
917 1691081 : for(dnode *dn = qname->h; dn; dn = dn->next) {
918 1068276 : sql_alias *p = a_create(sa, dn->data.sval);
919 1068317 : p->parent = a;
920 1068317 : a = p;
921 : }
922 622805 : return a;
923 : }
924 :
925 : char *
926 2033428 : qname_schema(dlist *qname)
927 : {
928 2033428 : assert(qname && qname->h);
929 :
930 2033428 : if (dlist_length(qname) == 2) {
931 1211624 : return qname->h->data.sval;
932 821868 : } else if (dlist_length(qname) == 3) {
933 4 : return qname->h->next->data.sval;
934 : }
935 : return NULL;
936 : }
937 :
938 : char *
939 1547029 : qname_schema_object(dlist *qname)
940 : {
941 1547029 : assert(qname && qname->h);
942 :
943 1547029 : if (dlist_length(qname) == 1) {
944 711950 : return qname->h->data.sval;
945 835238 : } else if (dlist_length(qname) == 2) {
946 835271 : return qname->h->next->data.sval;
947 0 : } else if (dlist_length(qname) == 3) {
948 0 : return qname->h->next->next->data.sval;
949 : }
950 : return "unknown";
951 : }
952 :
953 : char *
954 0 : qname_catalog(dlist *qname)
955 : {
956 0 : assert(qname && qname->h);
957 :
958 0 : if (dlist_length(qname) == 3) {
959 0 : return qname->h->data.sval;
960 : }
961 : return NULL;
962 : }
963 :
964 : int
965 1558 : set_type_param(mvc *sql, sql_subtype *type, int nr)
966 : {
967 1558 : sql_arg *a = sql_bind_paramnr(sql, nr);
968 :
969 1558 : if (!a)
970 : return -1;
971 1558 : a->type = *type;
972 1558 : return 0;
973 : }
974 :
975 : /*
976 : * Find the result_datatype for certain combinations of values
977 : * (like case expressions or columns in a result of a query expression).
978 : * See standaard pages 505-507 Result of data type combinations */
979 : sql_subtype *
980 210072 : result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
981 : {
982 210072 : int lclass = l->type->eclass, rclass = r->type->eclass;
983 :
984 : /* case a strings */
985 293295 : if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
986 83223 : const char *tpe = "varchar";
987 83223 : unsigned int digits = 0;
988 83223 : if (!EC_VARCHAR(lclass)) {
989 498 : tpe = r->type->base.name;
990 498 : digits = (!l->digits)?0:r->digits;
991 82725 : } else if (!EC_VARCHAR(rclass)) {
992 5246 : tpe = l->type->base.name;
993 5246 : digits = (!r->digits)?0:l->digits;
994 : } else { /* both */
995 77479 : tpe = !strcmp(l->type->base.name, "varchar")?l->type->base.name:!strcmp(r->type->base.name, "varchar")?r->type->base.name:
996 7 : (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
997 77479 : digits = (!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
998 : }
999 83223 : sql_find_subtype(super, tpe, digits, 0);
1000 : /* case b blob */
1001 126849 : } else if (lclass == EC_BLOB || rclass == EC_BLOB) {
1002 14 : *super = (lclass == EC_BLOB) ? *l : *r;
1003 : /* case c all exact numeric */
1004 225900 : } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
1005 99065 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1006 99065 : unsigned int digits = sql_max(l->digits, r->digits);
1007 99065 : unsigned int scale = sql_max(l->scale, r->scale);
1008 :
1009 99065 : if (l->type->radix == 10 && r->type->radix == 10) {
1010 90 : digits = scale + (sql_max(l->digits - l->scale, r->digits - r->scale));
1011 : #ifdef HAVE_HGE
1012 90 : if (digits > 38) {
1013 0 : digits = 38;
1014 : #else
1015 : if (digits > 18) {
1016 : digits = 18;
1017 : #endif
1018 0 : scale = MIN(scale, digits - 1);
1019 : }
1020 98975 : } else if (l->type->radix == 2 && r->type->radix == 10) { /* change to radix 10 */
1021 47 : digits = bits2digits(l->type->digits);
1022 47 : digits = sql_max(r->digits, digits);
1023 47 : scale = r->scale;
1024 98928 : } else if (l->type->radix == 10 && r->type->radix == 2) { /* change to radix 10 */
1025 121 : digits = bits2digits(r->type->digits);
1026 121 : digits = sql_max(l->digits, digits);
1027 121 : scale = l->scale;
1028 : }
1029 99065 : sql_find_subtype(super, tpe, digits, scale);
1030 : /* case d approximate numeric */
1031 27770 : } else if (EC_APPNUM(lclass) || EC_APPNUM(rclass)) {
1032 155 : if (!EC_APPNUM(lclass)) {
1033 45 : *super = *r;
1034 110 : } else if (!EC_APPNUM(rclass)) {
1035 89 : *super = *l;
1036 : } else { /* both */
1037 21 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1038 21 : unsigned int digits = sql_max(l->digits, r->digits); /* bits precision */
1039 21 : sql_find_subtype(super, tpe, digits, 0);
1040 : }
1041 : /* now its getting serious, ie e any 'case e' datetime data type */
1042 : /* 'case f' interval types */
1043 : /* 'case g' boolean */
1044 : /* 'case h-l' compounds like row (tuple), etc */
1045 : } else {
1046 27615 : return supertype(super, l, r);
1047 : }
1048 : return super;
1049 : }
1050 :
1051 : char *
1052 80 : toUpperCopy(char *dest, const char *src)
1053 : {
1054 80 : size_t i, len;
1055 :
1056 80 : if (src == NULL) {
1057 0 : *dest = '\0';
1058 0 : return(dest);
1059 : }
1060 :
1061 80 : len = _strlen(src);
1062 433 : for (i = 0; i < len; i++)
1063 353 : dest[i] = (char)toupper((int)src[i]);
1064 :
1065 80 : dest[i] = '\0';
1066 80 : return(dest);
1067 : }
1068 :
1069 : static char * _symbol2string(mvc *sql, symbol *se, int expression, char **err);
1070 :
1071 : static char *
1072 1 : dlist2string(mvc *sql, dlist *l, int expression, char **err)
1073 : {
1074 1 : char *b = NULL;
1075 1 : dnode *n;
1076 :
1077 3 : for (n=l->h; n; n = n->next) {
1078 2 : char *s = NULL;
1079 :
1080 2 : if (n->type == type_string && n->data.sval)
1081 2 : s = sa_strdup(sql->ta, n->data.sval);
1082 0 : else if (n->type == type_symbol)
1083 0 : s = _symbol2string(sql, n->data.sym, expression, err);
1084 :
1085 2 : if (!s)
1086 0 : return NULL;
1087 2 : if (b) {
1088 1 : char *o = SA_NEW_ARRAY(sql->ta, char, strlen(b) + strlen(s) + 2);
1089 1 : if (o)
1090 1 : stpcpy(stpcpy(stpcpy(o, b), "."), s);
1091 0 : b = o;
1092 1 : if (b == NULL)
1093 : return NULL;
1094 : } else {
1095 : b = s;
1096 : }
1097 : }
1098 : return b;
1099 : }
1100 :
1101 : static const char *
1102 882 : symbol_escape_ident(allocator *sa, const char *s)
1103 : {
1104 882 : char *res = NULL;
1105 882 : if (s) {
1106 830 : size_t l = strlen(s);
1107 830 : char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
1108 :
1109 830 : res = r;
1110 6114 : while (*s) {
1111 5284 : if (*s == '"')
1112 0 : *r++ = '"';
1113 5284 : *r++ = *s++;
1114 : }
1115 830 : *r = '\0';
1116 : }
1117 882 : return res;
1118 : }
1119 :
1120 : char *
1121 1593 : _symbol2string(mvc *sql, symbol *se, int expression, char **err)
1122 : {
1123 : /* inner symbol2string uses the temporary allocator */
1124 1593 : switch (se->token) {
1125 153 : case SQL_NOP: {
1126 153 : dnode *lst = se->data.lval->h, *ops = NULL, *aux;
1127 153 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1128 153 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1129 153 : int i = 0, nargs = 0;
1130 153 : char** inputs = NULL, *res;
1131 153 : size_t inputs_length = 0, extra = sname ? strlen(sname) + 3 : 0;
1132 :
1133 153 : if (lst->next->next->data.lval)
1134 113 : ops = lst->next->next->data.lval->h;
1135 :
1136 294 : for (aux = ops; aux; aux = aux->next)
1137 141 : nargs++;
1138 153 : if (!(inputs = SA_ZNEW_ARRAY(sql->ta, char*, nargs)))
1139 : return NULL;
1140 :
1141 289 : for (aux = ops; aux; aux = aux->next) {
1142 139 : if (!(inputs[i] = _symbol2string(sql, aux->data.sym, expression, err))) {
1143 : return NULL;
1144 : }
1145 136 : inputs_length += strlen(inputs[i]);
1146 136 : i++;
1147 : }
1148 :
1149 300 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + inputs_length + 3 + (nargs - 1 /* commas */) + 2))) {
1150 150 : char *concat = res;
1151 150 : if (sname)
1152 100 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1153 150 : concat = stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"(");
1154 150 : i = 0;
1155 286 : for (aux = ops; aux; aux = aux->next) {
1156 136 : concat = stpcpy(concat, inputs[i]);
1157 136 : if (aux->next)
1158 26 : concat = stpcpy(concat, ",");
1159 136 : i++;
1160 : }
1161 150 : concat = stpcpy(concat, ")");
1162 : }
1163 : return res;
1164 : }
1165 0 : case SQL_PARAMETER:
1166 0 : return sa_strdup(sql->ta, "?");
1167 193 : case SQL_NULL:
1168 193 : return sa_strdup(sql->ta, "NULL");
1169 : case SQL_ATOM:{
1170 935 : AtomNode *an = (AtomNode *) se;
1171 935 : if (an && an->a)
1172 935 : return atom2sql(sql->ta, an->a, sql->timezone);
1173 : else
1174 0 : return sa_strdup(sql->ta, "NULL");
1175 : }
1176 272 : case SQL_NEXT: {
1177 272 : const char *seq = symbol_escape_ident(sql->ta, qname_schema_object(se->data.lval)),
1178 272 : *sname = qname_schema(se->data.lval);
1179 272 : char *res;
1180 :
1181 272 : if (!sname)
1182 218 : sname = sql->session->schema->base.name;
1183 272 : sname = symbol_escape_ident(sql->ta, sname);
1184 :
1185 544 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen("next value for \"") + strlen(sname) + strlen(seq) + 5)))
1186 272 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for \""), sname), "\".\""), seq), "\"");
1187 : return res;
1188 33 : } break;
1189 33 : case SQL_IDENT:
1190 : case SQL_COLUMN: {
1191 : /* can only be variables */
1192 33 : dlist *l = se->data.lval;
1193 33 : assert(l->h->type != type_lng);
1194 33 : if (expression && dlist_length(l) == 1 && l->h->type == type_string) {
1195 : /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */
1196 32 : const char *op = symbol_escape_ident(sql->ta, l->h->data.sval);
1197 32 : char *res;
1198 :
1199 64 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3)))
1200 32 : stpcpy(stpcpy(stpcpy(res, "\""), op), "\"");
1201 32 : return res;
1202 0 : } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) {
1203 0 : const char *first = symbol_escape_ident(sql->ta, l->h->data.sval),
1204 0 : *second = symbol_escape_ident(sql->ta, l->h->next->data.sval);
1205 0 : char *res;
1206 :
1207 0 : if (!first || !second)
1208 : return NULL;
1209 0 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(first) + strlen(second) + 6)))
1210 0 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), first), "\".\""), second), "\"");
1211 0 : return res;
1212 : } else {
1213 1 : char *e = dlist2string(sql, l, expression, err);
1214 1 : if (e)
1215 1 : *err = e;
1216 1 : return NULL;
1217 : }
1218 : }
1219 6 : case SQL_CAST: {
1220 6 : dlist *dl = se->data.lval;
1221 6 : char *val = NULL, *tpe = NULL, *res;
1222 :
1223 6 : if (!(val = _symbol2string(sql, dl->h->data.sym, expression, err)) || !(tpe = subtype2string2(sql->ta, &dl->h->next->data.typeval)))
1224 0 : return NULL;
1225 12 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(val) + strlen(tpe) + 11)))
1226 6 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "cast("), val), " as "), tpe), ")");
1227 : return res;
1228 : }
1229 1 : default: {
1230 1 : const char msg[] = "SQL feature not yet available for expressions and default values: ";
1231 1 : char *tok_str = token2string(se->token);
1232 2 : if ((*err = SA_NEW_ARRAY(sql->ta, char, strlen(msg) + strlen(tok_str) + 1)))
1233 1 : stpcpy(stpcpy(*err, msg), tok_str);
1234 : }
1235 : }
1236 1 : return NULL;
1237 : }
1238 :
1239 : char *
1240 1448 : symbol2string(mvc *sql, symbol *se, int expression, char **err)
1241 : {
1242 1448 : char *res = _symbol2string(sql, se, expression, err);
1243 :
1244 1448 : if (res)
1245 1446 : res = sa_strdup(sql->sa, res);
1246 1448 : if (*err)
1247 2 : *err = sa_strdup(sql->sa, *err);
1248 1448 : sa_reset(sql->ta);
1249 1448 : return res;
1250 : }
|