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 380909 : sql_add_param(mvc *sql, const char *name, sql_subtype *st)
40 : {
41 380909 : sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
42 :
43 380909 : if (name)
44 379293 : a->name = sa_strdup(sql->sa, name);
45 380909 : if (st && st->type)
46 379282 : a->type = *st;
47 380909 : a->inout = ARG_IN;
48 380909 : if (name && strcmp(name, "*") == 0)
49 4 : a->type = *sql_bind_localtype("int");
50 380909 : if (!sql->params)
51 224277 : sql->params = sa_list(sql->sa);
52 380909 : list_append(sql->params, a);
53 380909 : }
54 :
55 : int
56 95161 : sql_bind_param(mvc *sql, const char *name)
57 : {
58 95161 : node *n;
59 95161 : int nr = 0;
60 :
61 95161 : if (sql->params) {
62 206821 : for (n = sql->params->h; n; n = n->next, nr++) {
63 202471 : sql_arg *a = n->data;
64 :
65 202471 : if (a->name && strcmp(a->name, name) == 0)
66 87224 : return nr;
67 : }
68 : }
69 : return -1;
70 : }
71 :
72 : sql_arg *
73 90401 : sql_bind_paramnr(mvc *sql, int nr)
74 : {
75 90401 : int i=0;
76 90401 : node *n;
77 :
78 90401 : if (sql->params && nr < list_length(sql->params)) {
79 678941 : for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
80 : ;
81 :
82 90401 : if (n)
83 90401 : 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 741724 : sql_destroy_params(mvc *sql)
101 : {
102 741724 : sql->params = NULL;
103 741724 : }
104 :
105 : sql_schema *
106 1676681 : cur_schema(mvc *sql)
107 : {
108 1676681 : return sql->session->schema;
109 : }
110 :
111 : sql_schema *
112 543838 : tmp_schema(mvc *sql)
113 : {
114 543838 : 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 662992 : find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *name, const char *error, bool isView)
173 : {
174 662992 : const char *objstr = isView ? "view" : "table";
175 662992 : sql_table *res = NULL;
176 :
177 663479 : 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 1477 : find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
183 : {
184 1477 : const char objstr[] = "sequence";
185 1477 : sql_sequence *res = NULL;
186 :
187 1481 : 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 202314 : 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 202314 : const char objstr[] = "variable";
254 202314 : bool res = false;
255 202314 : int nr = 0;
256 :
257 202314 : (void)nr;
258 207128 : search_object_on_path(var_find_on_global, DO_NOTHING, variable_extra, SQLSTATE(42000));
259 : return res;
260 : }
261 :
262 : static sql_subfunc *
263 925900 : _dup_subaggr(allocator *sa, sql_func *a, sql_subtype *member)
264 : {
265 925900 : node *tn;
266 925900 : unsigned int scale = 0, digits = 0;
267 925900 : sql_subfunc *ares = SA_ZNEW(sa, sql_subfunc);
268 :
269 :
270 926095 : ares->func = a;
271 926095 : if (IS_FILT(a)) {
272 4400 : ares->res = sa_list(sa);
273 4400 : list_append(ares->res, sql_bind_localtype("bit"));
274 921695 : } else if (IS_FUNC(a) || IS_UNION(a) || IS_ANALYTIC(a) || IS_AGGR(a)) { /* not needed for PROC */
275 918029 : if (a->res) {
276 918029 : ares->res = sa_list(sa);
277 1921223 : for(tn = a->res->h; tn; tn = tn->next) {
278 1003181 : sql_arg *rarg = tn->data;
279 1003181 : sql_subtype *res, *r = &rarg->type;
280 :
281 1003181 : if (a->fix_scale == SCALE_EQ && !IS_AGGR(a)) {
282 : res = r;
283 : } else {
284 826972 : digits = r->digits;
285 826972 : scale = r->scale;
286 : /* same scale as the input */
287 826972 : if (member && (member->scale != scale ||
288 172278 : (digits != member->digits && !EC_NUMBER(member->type->eclass)))) {
289 90366 : if (member->digits > digits)
290 : digits = member->digits;
291 : scale = member->scale;
292 : }
293 : /* same type as the input */
294 826972 : if (r->type->eclass == EC_ANY && member) {
295 14246 : r = member;
296 14246 : digits = member->digits;
297 : }
298 826972 : if (!EC_SCALE(r->type->eclass))
299 826972 : scale = 0;
300 826972 : res = sql_create_subtype(sa, r->type, digits, scale);
301 : }
302 1003149 : list_append(ares->res, res);
303 : }
304 : }
305 : }
306 926108 : return ares;
307 : }
308 :
309 :
310 :
311 : static sql_subfunc *
312 128725 : func_cmp(allocator *sa, sql_func *f, const char *name, int nrargs)
313 : {
314 128725 : if (strcmp(f->base.name, name) == 0) {
315 128725 : 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 128723 : 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 127965 : return _dup_subaggr(sa, f, NULL);
321 : }
322 : return NULL;
323 : }
324 :
325 : static sql_subfunc *
326 634244 : sql_find_func_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
327 : {
328 634244 : int key = hash_key(fname);
329 634244 : sql_subfunc *res = NULL;
330 634244 : int found = 0;
331 634244 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
332 :
333 634244 : if (ff) {
334 634244 : if (ff->ht) {
335 634244 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
336 634244 : if (prev) {
337 2 : for (; he && !found; he = he->chain)
338 0 : if (he->value == prev->func)
339 0 : found = 1;
340 : }
341 7680952 : for (; he; he = he->chain) {
342 7169612 : sql_func *f = he->value;
343 :
344 7169612 : if ((f->type != type && f->type != filt) || (f->private && !private))
345 7046694 : continue;
346 122918 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
347 122903 : 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 746335 : os_find_func_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
371 : {
372 746335 : sql_subfunc *res = NULL;
373 746335 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
374 :
375 746335 : if (ff) {
376 746335 : struct os_iter oi;
377 746335 : os_iterator(&oi, ff, sql->session->tr, fname);
378 847015 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
379 105743 : sql_func *f = (sql_func*)b;
380 105743 : if (prev && prev->func != f) {
381 0 : continue;
382 105743 : } else if (prev) {
383 0 : prev = NULL;
384 0 : continue;
385 : }
386 :
387 105743 : if ((f->type != type && f->type != filt) || (f->private && !private))
388 99936 : continue;
389 5807 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
390 5063 : 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 634942 : sql_find_func(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
406 : {
407 634942 : char *F = NULL, *objstr = NULL;
408 634942 : const char error[] = "CATALOG";
409 634942 : sql_subfunc *res = NULL;
410 :
411 634942 : FUNC_TYPE_STR(type, F, objstr);
412 634942 : (void) F; /* not used */
413 :
414 634942 : assert(nrargs >= -1);
415 :
416 1080717 : 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 376867 : 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 376867 : list *l = sa_list(sql->sa);
424 :
425 376927 : if (tp1)
426 367473 : list_append(l, tp1);
427 376956 : if (tp2)
428 210101 : list_append(l, tp2);
429 376956 : return sql_bind_func_(sql, sname, fname, l, type, private, exact);
430 : }
431 :
432 : sql_subfunc *
433 81 : 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 81 : list *l = sa_list(sql->sa);
436 :
437 81 : if (tp1)
438 81 : list_append(l, tp1);
439 81 : if (tp2)
440 81 : list_append(l, tp2);
441 81 : if (tp3)
442 81 : list_append(l, tp3);
443 81 : 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 744552 : next_cand_points(list *args, list *ops)
448 : {
449 744552 : int res = 0;
450 :
451 744552 : if (!list_empty(args) && !list_empty(ops))
452 1955731 : for (node *n = args->h, *m = ops->h; n && m ; n = n->next, m = m->next) {
453 1232932 : sql_arg *a = n->data;
454 1232932 : sql_subtype *t = m->data;
455 :
456 1232932 : if (a->type.type->eclass == EC_ANY)
457 629225 : res += 100;
458 603707 : else if (t)
459 603707 : res += a->type.type->base.id == t->type->base.id;
460 : }
461 744914 : res += (list_empty(args) && list_empty(ops));
462 744931 : return res;
463 : }
464 :
465 : static int
466 7967721 : score_func( sql_func *f, list *tl, bool exact, bool *downcast)
467 : {
468 7967721 : int score = 0;
469 7967721 : node *n, *m;
470 :
471 7967721 : if (exact)
472 704592 : return next_cand_points(f->ops, tl);
473 7263129 : if (!tl)
474 : return 1;
475 7263129 : if (f->vararg)
476 : return 1;
477 7263115 : unsigned int digits = 0, scale = 0;
478 7263115 : if (f->fix_scale == SCALE_FIX) {
479 3060696 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
480 2038171 : sql_subtype *t = m->data;
481 :
482 2038171 : if (!t)
483 52 : continue;
484 2038119 : if (t->type->eclass == EC_DEC) {
485 8217 : if (digits < t->digits)
486 : digits = t->digits;
487 8217 : if (scale < t->scale)
488 : scale = t->scale;
489 : }
490 : }
491 3060705 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
492 2038182 : sql_arg *a = n->data;
493 2038182 : sql_subtype *t = m->data;
494 :
495 2038182 : if (!t)
496 52 : continue;
497 2038130 : if (a->type.type->eclass == EC_DEC && t->type->eclass == EC_NUM) {
498 1124980 : if (digits < scale + bits2digits(t->digits))
499 780492 : digits = scale + bits2digits(t->digits);
500 : }
501 : }
502 : }
503 7263113 : int nr_strconverts = 0;
504 16055645 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
505 11535395 : sql_arg *a = n->data;
506 11535395 : sql_subtype *t = m->data;
507 :
508 11535395 : if (!t) { /* parameters */
509 500 : int ec = a->type.type->eclass;
510 500 : score++;
511 500 : 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 11534895 : int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
521 : /* EX_EXTERNAL can only convert between equal implementation types */
522 11534905 : if (nscore == 0 &&
523 2546343 : 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 8989126 : if (nscore &&
528 8989126 : t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC &&
529 3383154 : t->type->localtype > a->type.type->localtype)
530 692618 : *downcast = true;
531 8989126 : if (nscore == 0)
532 : return 0;
533 8989126 : nscore *= 100; /* first based on preferred conversions */
534 8989126 : if (nscore < 0) {
535 290765 : *downcast = true;
536 290765 : nscore = -nscore;
537 : }
538 8989126 : score += nscore;
539 8989126 : if (EC_VARCHAR(t->type->eclass) && EC_NUMBER(a->type.type->eclass))
540 1227 : nr_strconverts++;
541 8989126 : if (nr_strconverts > 1)
542 : return 0;
543 :
544 8989090 : 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 8792205 : 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 8792059 : 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 2489443 : score += (38 + bits2digits(t->digits) - a->type.type->digits);
553 : /* same class over converting to other class */
554 6302616 : else if (t->type->eclass == a->type.type->eclass && t->type->localtype <= a->type.type->localtype) {
555 3346128 : 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 3346128 : 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 2956488 : else if (t->type->eclass == a->type.type->eclass) {
564 1089523 : 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 1089523 : } else if (t->type->eclass == EC_NUM || t->type->eclass == EC_FLT) { /* down casting */
568 1074733 : *downcast = true;
569 1074733 : score += 10 * (10 - t->type->localtype - a->type.type->localtype);
570 : }
571 : }
572 : }
573 4520250 : score += (list_empty(tl) && list_empty(f->ops));
574 4520253 : return score;
575 : }
576 :
577 :
578 : static sql_subfunc *
579 1535918 : sql_bind_func__(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
580 : {
581 1535918 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
582 1535918 : sql_subtype *input_type = NULL;
583 1535918 : sql_func *cand = NULL, *dcand = NULL;
584 1535918 : int points = 0, dpoints = 0;
585 :
586 1535918 : if (ops && ops->h)
587 1497492 : input_type = ops->h->data;
588 :
589 1535918 : assert(ff==funcs);
590 1535918 : if (ff) {
591 1536015 : if (ff->ht) {
592 1536015 : int key = hash_key(fname);
593 1536015 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
594 9651329 : for (; he; he = he->chain) {
595 8115450 : sql_func *f = he->value;
596 8115450 : bool downcast = false;
597 :
598 8115450 : if ((f->type != type && f->type != filt) || (f->private && !private))
599 334777 : continue;
600 7780673 : 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 7640946 : int npoints = score_func(f, ops, exact, &downcast);
602 7640736 : if (downcast) {
603 1821661 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
604 7780537 : dcand = f;
605 7780537 : dpoints = npoints;
606 : }
607 : } else {
608 5819075 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
609 7780537 : cand = f;
610 7780537 : 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 1535782 : if (!cand && dcand)
641 19768 : cand = dcand;
642 1535782 : if (cand && exact && type != F_AGGR)
643 388253 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
644 1147529 : if (cand)
645 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
646 1173884 : return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
647 : return NULL;
648 : }
649 :
650 : static sql_subfunc *
651 626642 : os_bind_func__(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
652 : {
653 626642 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
654 626642 : sql_subtype *input_type = NULL;
655 626642 : sql_func *cand = NULL, *dcand = NULL;
656 626642 : int points = 0, dpoints = 0;
657 :
658 626642 : if (ops && ops->h)
659 594218 : input_type = ops->h->data;
660 :
661 626642 : if (ff) {
662 626642 : struct os_iter oi;
663 626642 : os_iterator(&oi, ff, sql->session->tr, fname);
664 2108191 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
665 1481549 : sql_func *f = (sql_func*)b;
666 1481549 : bool downcast = false;
667 :
668 1481549 : if ((f->type != type && f->type != filt) || (f->private && !private))
669 469491 : continue;
670 1012058 : 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 327038 : int npoints = score_func(f, ops, exact, &downcast);
672 327038 : if (downcast) {
673 2534 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
674 1012058 : dcand = f;
675 1012058 : dpoints = npoints;
676 : }
677 : } else {
678 324504 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
679 1012058 : cand = f;
680 1012058 : points = npoints;
681 : }
682 : }
683 : }
684 : }
685 : }
686 626642 : if (!cand && dcand)
687 279 : cand = dcand;
688 626642 : if (cand && exact && type != F_AGGR)
689 166001 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
690 460641 : if (cand)
691 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
692 248925 : 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 1561167 : sql_bind_func_(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private, bool exact)
704 : {
705 1561167 : char *F = NULL, *objstr = NULL;
706 1561167 : const char error[] = "CATALOG";
707 1561167 : sql_subfunc *res = NULL;
708 :
709 1561167 : FUNC_TYPE_STR(type, F, objstr);
710 1561167 : (void) F; /* not used */
711 :
712 1562687 : 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 39962 : sql_bind_func_result_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
718 : {
719 39962 : sql_subtype *tp = sql_bind_localtype("bit");
720 39955 : sql_func *cand = NULL;
721 39955 : int points = 0, npoints = 0;
722 :
723 39955 : if (ff) {
724 39955 : if (ff->ht) {
725 39955 : int key = hash_key(fname);
726 39955 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
727 142060 : for (; he; he = he->chain) {
728 102100 : sql_func *f = he->value;
729 102100 : sql_arg *firstres = NULL;
730 :
731 102100 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
732 0 : continue;
733 102100 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
734 102100 : 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 39962 : npoints = next_cand_points(f->ops, ops);
736 :
737 39963 : if (!cand || npoints > points) {
738 102105 : cand = f;
739 102105 : 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 39960 : if (cand)
764 39959 : 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 39964 : 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 39964 : char *F = NULL, *objstr = NULL;
811 39964 : const char error[] = "CATALOG";
812 39964 : sql_subfunc *res = NULL;
813 39964 : list *ops = sa_list(sql->sa);
814 39967 : va_list valist;
815 :
816 39967 : FUNC_TYPE_STR(type, F, objstr);
817 39967 : (void) F; /* not used */
818 :
819 39967 : va_start(valist, nargs);
820 121250 : for (int i = 0; i < nargs; i++) {
821 81282 : sql_type *tpe = va_arg(valist, sql_type*);
822 81288 : list_append(ops, tpe);
823 : }
824 39968 : va_end(valist);
825 :
826 39968 : 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 39968 : if (res) /* make sure we have the correct result type */
828 39968 : res->res->h->data = r_res;
829 39968 : return res;
830 : }
831 :
832 : static list *
833 5238 : sql_find_funcs_by_name_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private)
834 : {
835 5238 : int key = hash_key(fname);
836 5238 : list *res = NULL;
837 :
838 5238 : if (ff) {
839 5238 : if (ff->ht) {
840 5238 : 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 5238 : return res;
867 : }
868 :
869 : static list *
870 9041 : os_find_funcs_by_name_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private)
871 : {
872 9041 : list *res = NULL;
873 :
874 9041 : if (ff) {
875 9041 : struct os_iter oi;
876 9041 : os_iterator(&oi, ff, sql->session->tr, fname);
877 14786 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
878 5745 : sql_func *f = (sql_func*)b;
879 :
880 5745 : if (f->type != type || (f->private && !private))
881 1343 : continue;
882 4402 : if (strcmp(f->base.name, fname) == 0) {
883 4402 : if (!res)
884 4374 : res = sa_list(sql->sa);
885 4402 : list_append(res, f);
886 : }
887 : }
888 : }
889 9041 : 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 5709 : sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private)
900 : {
901 5709 : char *F = NULL, *objstr = NULL;
902 5709 : const char error[] = "CATALOG";
903 5709 : list *res = NULL;
904 :
905 5709 : FUNC_TYPE_STR(type, F, objstr);
906 5709 : (void) F; /* not used */
907 :
908 6401 : 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 1961038 : qname_schema(dlist *qname)
914 : {
915 1961038 : assert(qname && qname->h);
916 :
917 1961038 : if (dlist_length(qname) == 2) {
918 1130161 : return qname->h->data.sval;
919 830969 : } else if (dlist_length(qname) == 3) {
920 4 : return qname->h->next->data.sval;
921 : }
922 : return NULL;
923 : }
924 :
925 : char *
926 1974101 : qname_schema_object(dlist *qname)
927 : {
928 1974101 : assert(qname && qname->h);
929 :
930 1974101 : if (dlist_length(qname) == 1) {
931 843744 : return qname->h->data.sval;
932 1130329 : } else if (dlist_length(qname) == 2) {
933 1130325 : 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 205157 : result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
968 : {
969 205157 : int lclass = l->type->eclass, rclass = r->type->eclass;
970 :
971 : /* case a strings */
972 287014 : if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
973 81857 : const char *tpe = "varchar";
974 81857 : unsigned int digits = 0;
975 81857 : if (!EC_VARCHAR(lclass)) {
976 488 : tpe = r->type->base.name;
977 488 : digits = (!l->digits)?0:r->digits;
978 81369 : } else if (!EC_VARCHAR(rclass)) {
979 5075 : tpe = l->type->base.name;
980 5075 : digits = (!r->digits)?0:l->digits;
981 : } else { /* both */
982 76294 : 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 76294 : digits = (!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
985 : }
986 81857 : sql_find_subtype(super, tpe, digits, 0);
987 : /* case b blob */
988 123300 : } else if (lclass == EC_BLOB || rclass == EC_BLOB) {
989 14 : *super = (lclass == EC_BLOB) ? *l : *r;
990 : /* case c all exact numeric */
991 219861 : } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
992 96575 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
993 96575 : unsigned int digits = sql_max(l->digits, r->digits);
994 96575 : unsigned int scale = sql_max(l->scale, r->scale);
995 :
996 96575 : 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 96485 : } 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 96438 : } 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 96575 : sql_find_subtype(super, tpe, digits, scale);
1017 : /* case d approximate numeric */
1018 26711 : } 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 26554 : return supertype(super, l, r);
1034 : }
1035 : return super;
1036 : }
1037 :
1038 : char *
1039 49 : toUpperCopy(char *dest, const char *src)
1040 : {
1041 49 : size_t i, len;
1042 :
1043 49 : if (src == NULL) {
1044 0 : *dest = '\0';
1045 0 : return(dest);
1046 : }
1047 :
1048 49 : len = _strlen(src);
1049 293 : for (i = 0; i < len; i++)
1050 244 : dest[i] = (char)toupper((int)src[i]);
1051 :
1052 49 : dest[i] = '\0';
1053 49 : 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 861 : symbol_escape_ident(allocator *sa, const char *s)
1090 : {
1091 861 : char *res = NULL;
1092 861 : if (s) {
1093 809 : size_t l = strlen(s);
1094 809 : char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
1095 :
1096 809 : res = r;
1097 6044 : while (*s) {
1098 5235 : if (*s == '"')
1099 1 : *r++ = '"';
1100 5235 : *r++ = *s++;
1101 : }
1102 809 : *r = '\0';
1103 : }
1104 861 : return res;
1105 : }
1106 :
1107 : char *
1108 1571 : _symbol2string(mvc *sql, symbol *se, int expression, char **err)
1109 : {
1110 : /* inner symbol2string uses the temporary allocator */
1111 1571 : 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 83 : case SQL_UNOP: {
1183 83 : dnode *lst = se->data.lval->h;
1184 83 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1185 83 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1186 83 : char *l = _symbol2string(sql, lst->next->next->data.sym, expression, err), *res;
1187 83 : size_t extra = sname ? strlen(sname) + 3 : 0;
1188 :
1189 83 : if (!l)
1190 : return NULL;
1191 :
1192 164 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + 5))) {
1193 82 : char *concat = res;
1194 82 : if (sname)
1195 74 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1196 82 : 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 925 : AtomNode *an = (AtomNode *) se;
1206 925 : if (an && an->a)
1207 925 : 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 28 : } break;
1224 28 : case SQL_IDENT:
1225 : case SQL_COLUMN: {
1226 : /* can only be variables */
1227 28 : dlist *l = se->data.lval;
1228 28 : assert(l->h->type != type_lng);
1229 28 : 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 27 : const char *op = symbol_escape_ident(sql->ta, l->h->data.sval);
1232 27 : char *res;
1233 :
1234 54 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3)))
1235 27 : stpcpy(stpcpy(stpcpy(res, "\""), op), "\"");
1236 27 : 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 1431 : symbol2string(mvc *sql, symbol *se, int expression, char **err)
1276 : {
1277 1431 : char *res = _symbol2string(sql, se, expression, err);
1278 :
1279 1431 : if (res)
1280 1428 : res = sa_strdup(sql->sa, res);
1281 1431 : if (*err)
1282 3 : *err = sa_strdup(sql->sa, *err);
1283 1431 : sa_reset(sql->ta);
1284 1431 : return res;
1285 : }
|