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 369137 : sql_add_param(mvc *sql, const char *name, sql_subtype *st)
40 : {
41 369137 : sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
42 :
43 369137 : if (name)
44 367523 : a->name = sa_strdup(sql->sa, name);
45 369137 : if (st && st->type)
46 367513 : a->type = *st;
47 369137 : a->inout = ARG_IN;
48 369137 : if (name && strcmp(name, "*") == 0)
49 3 : a->type = *sql_bind_localtype("int");
50 369137 : if (!sql->params)
51 218666 : sql->params = sa_list(sql->sa);
52 369137 : list_append(sql->params, a);
53 369137 : }
54 :
55 : int
56 95245 : sql_bind_param(mvc *sql, const char *name)
57 : {
58 95245 : node *n;
59 95245 : int nr = 0;
60 :
61 95245 : if (sql->params) {
62 208008 : for (n = sql->params->h; n; n = n->next, nr++) {
63 203695 : sql_arg *a = n->data;
64 :
65 203695 : if (a->name && strcmp(a->name, name) == 0)
66 87428 : return nr;
67 : }
68 : }
69 : return -1;
70 : }
71 :
72 : sql_arg *
73 90603 : sql_bind_paramnr(mvc *sql, int nr)
74 : {
75 90603 : int i=0;
76 90603 : node *n;
77 :
78 90603 : if (sql->params && nr < list_length(sql->params)) {
79 680278 : for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
80 : ;
81 :
82 90603 : if (n)
83 90603 : 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 725453 : sql_destroy_params(mvc *sql)
101 : {
102 725453 : sql->params = NULL;
103 725453 : }
104 :
105 : sql_schema *
106 1658952 : cur_schema(mvc *sql)
107 : {
108 1658952 : return sql->session->schema;
109 : }
110 :
111 : sql_schema *
112 541099 : tmp_schema(mvc *sql)
113 : {
114 541099 : 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 : assert(objstr); \
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) \
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 650499 : find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *name, const char *error, bool isView)
174 : {
175 650499 : const char *objstr = isView ? "view" : "table";
176 1300504 : sql_table *res = NULL;
177 :
178 650995 : search_object_on_path(res = mvc_bind_table(sql, next, name), DO_NOTHING, table_extra, SQLSTATE(42S02));
179 : return res;
180 : }
181 :
182 : sql_sequence *
183 1468 : find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
184 : {
185 1468 : const char *objstr = "sequence";
186 1468 : sql_sequence *res = NULL;
187 :
188 1472 : search_object_on_path(res = find_sql_sequence(sql->session->tr, next, name), DO_NOTHING, ;, SQLSTATE(42000));
189 : return res;
190 : }
191 :
192 : sql_idx *
193 215 : find_idx_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
194 : {
195 215 : const char *objstr = "index";
196 215 : sql_idx *res = NULL;
197 :
198 289 : search_object_on_path(res = mvc_bind_idx(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S12));
199 : return res;
200 : }
201 :
202 : sql_type *
203 5 : find_type_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
204 : {
205 5 : const char *objstr = "type";
206 5 : sql_type *res = NULL;
207 :
208 7 : search_object_on_path(res = schema_bind_type(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S01));
209 : return res;
210 : }
211 :
212 : sql_trigger *
213 91 : find_trigger_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
214 : {
215 91 : const char *objstr = "trigger";
216 91 : sql_trigger *res = NULL;
217 :
218 113 : search_object_on_path(res = mvc_bind_trigger(sql, next, name), DO_NOTHING, ;, SQLSTATE(3F000));
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 200241 : 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 200241 : const char *objstr = "variable";
255 200241 : bool res = false;
256 200241 : int nr = 0;
257 :
258 200241 : (void)nr;
259 204916 : search_object_on_path(var_find_on_global, DO_NOTHING, variable_extra, SQLSTATE(42000));
260 : return res;
261 : }
262 :
263 : static sql_subfunc *
264 923146 : _dup_subaggr(allocator *sa, sql_func *a, sql_subtype *member)
265 : {
266 923146 : node *tn;
267 923146 : unsigned int scale = 0, digits = 0;
268 923146 : sql_subfunc *ares = SA_ZNEW(sa, sql_subfunc);
269 :
270 :
271 923304 : ares->func = a;
272 923304 : if (IS_FILT(a)) {
273 4591 : ares->res = sa_list(sa);
274 4591 : list_append(ares->res, sql_bind_localtype("bit"));
275 918713 : } else if (IS_FUNC(a) || IS_UNION(a) || IS_ANALYTIC(a) || IS_AGGR(a)) { /* not needed for PROC */
276 915382 : if (a->res) {
277 915382 : ares->res = sa_list(sa);
278 1908668 : for(tn = a->res->h; tn; tn = tn->next) {
279 993191 : sql_arg *rarg = tn->data;
280 993191 : sql_subtype *res, *r = &rarg->type;
281 :
282 993191 : if (a->fix_scale == SCALE_EQ && !IS_AGGR(a)) {
283 : res = r;
284 : } else {
285 824683 : digits = r->digits;
286 824683 : scale = r->scale;
287 : /* same scale as the input */
288 824683 : if (member && (member->scale != scale ||
289 170452 : (digits != member->digits && !EC_NUMBER(member->type->eclass)))) {
290 88768 : if (member->digits > digits)
291 : digits = member->digits;
292 : scale = member->scale;
293 : }
294 : /* same type as the input */
295 824683 : if (r->type->eclass == EC_ANY && member) {
296 14292 : r = member;
297 14292 : digits = member->digits;
298 : }
299 824683 : if (!EC_SCALE(r->type->eclass))
300 824683 : scale = 0;
301 824683 : res = sql_create_subtype(sa, r->type, digits, scale);
302 : }
303 993143 : list_append(ares->res, res);
304 : }
305 : }
306 : }
307 923399 : return ares;
308 : }
309 :
310 :
311 :
312 : static sql_subfunc *
313 126873 : func_cmp(allocator *sa, sql_func *f, const char *name, int nrargs)
314 : {
315 126873 : if (strcmp(f->base.name, name) == 0) {
316 126873 : if (f->vararg)
317 : //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
318 1 : return _dup_subaggr(sa, f, NULL);
319 126872 : 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 126107 : return _dup_subaggr(sa, f, NULL);
322 : }
323 : return NULL;
324 : }
325 :
326 : static sql_subfunc *
327 633497 : sql_find_func_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
328 : {
329 633497 : int key = hash_key(fname);
330 633497 : sql_subfunc *res = NULL;
331 633497 : int found = 0;
332 633497 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
333 :
334 633497 : if (ff) {
335 633497 : if (ff->ht) {
336 633497 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
337 633497 : if (prev) {
338 1 : for (; he && !found; he = he->chain)
339 0 : if (he->value == prev->func)
340 0 : found = 1;
341 : }
342 7584866 : for (; he; he = he->chain) {
343 7072361 : sql_func *f = he->value;
344 :
345 7072361 : if ((f->type != type && f->type != filt) || (f->private && !private))
346 6951354 : continue;
347 121007 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
348 120992 : 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 749692 : os_find_func_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
372 : {
373 749692 : sql_subfunc *res = NULL;
374 749692 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
375 :
376 749692 : if (ff) {
377 749692 : struct os_iter oi;
378 749692 : os_iterator(&oi, ff, sql->session->tr, fname);
379 849725 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
380 105148 : sql_func *f = (sql_func*)b;
381 105148 : if (prev && prev->func != f) {
382 0 : continue;
383 105148 : } else if (prev) {
384 0 : prev = NULL;
385 0 : continue;
386 : }
387 :
388 105148 : if ((f->type != type && f->type != filt) || (f->private && !private))
389 99282 : continue;
390 5866 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
391 5116 : 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 634188 : sql_find_func(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
407 : {
408 634188 : char *F = NULL, *objstr = NULL;
409 634188 : const char *error = "CATALOG";
410 634188 : sql_subfunc *res = NULL;
411 :
412 634188 : FUNC_TYPE_STR(type, F, objstr);
413 634188 : (void) F; /* not used */
414 :
415 634188 : assert(nrargs >= -1);
416 :
417 1084077 : 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));
418 : return res;
419 : }
420 :
421 : sql_subfunc *
422 376897 : 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 376897 : list *l = sa_list(sql->sa);
425 :
426 377016 : if (tp1)
427 366838 : list_append(l, tp1);
428 377072 : if (tp2)
429 207539 : list_append(l, tp2);
430 377072 : return sql_bind_func_(sql, sname, fname, l, type, private, exact);
431 : }
432 :
433 : sql_subfunc *
434 280 : 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 280 : list *l = sa_list(sql->sa);
437 :
438 280 : if (tp1)
439 280 : list_append(l, tp1);
440 280 : if (tp2)
441 280 : list_append(l, tp2);
442 280 : if (tp3)
443 280 : list_append(l, tp3);
444 280 : return sql_bind_func_(sql, sname, fname, l, type, private, false);
445 : }
446 :
447 : static int /* bind the function version with more identical type matches */
448 739860 : next_cand_points(list *args, list *ops)
449 : {
450 739860 : int res = 0;
451 :
452 739860 : if (!list_empty(args) && !list_empty(ops))
453 1941813 : for (node *n = args->h, *m = ops->h; n && m ; n = n->next, m = m->next) {
454 1223827 : sql_arg *a = n->data;
455 1223827 : sql_subtype *t = m->data;
456 :
457 1223827 : if (a->type.type->eclass == EC_ANY)
458 644664 : res += 100;
459 579163 : else if (t)
460 579163 : res += a->type.type->base.id == t->type->base.id;
461 : }
462 740171 : res += (list_empty(args) && list_empty(ops));
463 740237 : return res;
464 : }
465 :
466 : static int
467 7868543 : score_func( sql_func *f, list *tl, bool exact, bool *downcast)
468 : {
469 7868543 : int score = 0;
470 7868543 : node *n, *m;
471 :
472 7868543 : if (exact)
473 702608 : return next_cand_points(f->ops, tl);
474 7165935 : if (!tl)
475 : return 1;
476 7165935 : if (f->vararg)
477 : return 1;
478 7165922 : unsigned int digits = 0, scale = 0;
479 7165922 : if (f->fix_scale == SCALE_FIX) {
480 3041206 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
481 2025567 : sql_subtype *t = m->data;
482 :
483 2025567 : if (!t)
484 52 : continue;
485 2025515 : if (t->type->eclass == EC_DEC) {
486 7542 : if (digits < t->digits)
487 : digits = t->digits;
488 7542 : if (scale < t->scale)
489 : scale = t->scale;
490 : }
491 : }
492 3041216 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
493 2025576 : sql_arg *a = n->data;
494 2025576 : sql_subtype *t = m->data;
495 :
496 2025576 : if (!t)
497 52 : continue;
498 2025524 : if (a->type.type->eclass == EC_DEC && t->type->eclass == EC_NUM) {
499 1116559 : if (digits < scale + bits2digits(t->digits))
500 774689 : digits = scale + bits2digits(t->digits);
501 : }
502 : }
503 : }
504 7165923 : int nr_strconverts = 0;
505 15830853 : for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
506 11377238 : sql_arg *a = n->data;
507 11377238 : sql_subtype *t = m->data;
508 :
509 11377238 : if (!t) { /* parameters */
510 403 : int ec = a->type.type->eclass;
511 403 : score++;
512 403 : if (ec == EC_DEC)
513 : return 0;
514 280 : if (a && EC_NUMBER(ec) && !EC_INTERVAL(ec))
515 171 : score += a->type.type->localtype * 10; /* premium on larger types */
516 109 : else if (a) /* all other types */
517 109 : score += 99;
518 280 : continue;
519 : }
520 :
521 11376835 : int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
522 : /* EX_EXTERNAL can only convert between equal implementation types */
523 11376854 : if (nscore == 0 &&
524 2515886 : t->type->eclass == a->type.type->eclass &&
525 545 : t->type->eclass == EC_EXTERNAL &&
526 545 : t->type->localtype == a->type.type->localtype)
527 : nscore = 10;
528 8861510 : if (nscore &&
529 8861510 : t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC &&
530 3351763 : t->type->localtype > a->type.type->localtype)
531 687382 : *downcast = true;
532 8861510 : if (nscore == 0)
533 : return 0;
534 8861510 : nscore *= 100; /* first based on prefered conversions */
535 8861510 : if (nscore < 0) {
536 259761 : *downcast = true;
537 259761 : nscore = -nscore;
538 : }
539 8861510 : score += nscore;
540 8861510 : if (EC_VARCHAR(t->type->eclass) && EC_NUMBER(a->type.type->eclass))
541 1185 : nr_strconverts++;
542 8861510 : if (nr_strconverts > 1)
543 : return 0;
544 :
545 8861476 : 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 8664650 : 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 140 : score += (11 + t->type->localtype - a->type.type->localtype) * 8;
550 : /* sql types close but digits/scale diffs */
551 8664510 : 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 2466696 : score += (38 + bits2digits(t->digits) - a->type.type->digits);
554 : /* same class over converting to other class */
555 6197814 : else if (t->type->eclass == a->type.type->eclass && t->type->localtype <= a->type.type->localtype) {
556 3324960 : 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 3324960 : if (t->type->eclass == a->type.type->eclass && t->type->eclass == EC_SEC)
560 2914 : score += ((t->type->digits > 4 && a->type.type->digits > 4) ||
561 3276 : (t->type->digits <= 4 && a->type.type->digits <= 4)) * 4;
562 : }
563 : /* conversion matrix needs check if conversion is possible */
564 2872854 : else if (t->type->eclass == a->type.type->eclass) {
565 1081126 : 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 1081126 : } else if (t->type->eclass == EC_NUM || t->type->eclass == EC_FLT) { /* down casting */
569 1066344 : *downcast = true;
570 1066344 : score += 10 * (10 - t->type->localtype - a->type.type->localtype);
571 : }
572 : }
573 : }
574 4453615 : score += (list_empty(tl) && list_empty(f->ops));
575 4453613 : return score;
576 : }
577 :
578 :
579 : static sql_subfunc *
580 1527037 : sql_bind_func__(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
581 : {
582 1527037 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
583 1527037 : sql_subtype *input_type = NULL;
584 1527037 : sql_func *cand = NULL, *dcand = NULL;
585 1527037 : int points = 0, dpoints = 0;
586 :
587 1527037 : if (ops && ops->h)
588 1489599 : input_type = ops->h->data;
589 :
590 1527037 : assert(ff==funcs);
591 1527037 : if (ff) {
592 1527230 : if (ff->ht) {
593 1527230 : int key = hash_key(fname);
594 1527230 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
595 9544097 : for (; he; he = he->chain) {
596 8016900 : sql_func *f = he->value;
597 8016900 : bool downcast = false;
598 :
599 8016900 : if ((f->type != type && f->type != filt) || (f->private && !private))
600 328002 : continue;
601 7688898 : 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 7550899 : int npoints = score_func(f, ops, exact, &downcast);
603 7550701 : if (downcast) {
604 1786574 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
605 7688865 : dcand = f;
606 7688865 : dpoints = npoints;
607 : }
608 : } else {
609 5764127 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
610 7688865 : cand = f;
611 7688865 : 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 1527004 : if (!cand && dcand)
642 20077 : cand = dcand;
643 1527004 : if (cand && exact && type != F_AGGR)
644 395799 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
645 1131205 : if (cand)
646 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
647 1175231 : return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
648 : return NULL;
649 : }
650 :
651 : static sql_subfunc *
652 609527 : os_bind_func__(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
653 : {
654 609527 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
655 609527 : sql_subtype *input_type = NULL;
656 609527 : sql_func *cand = NULL, *dcand = NULL;
657 609527 : int points = 0, dpoints = 0;
658 :
659 609527 : if (ops && ops->h)
660 578506 : input_type = ops->h->data;
661 :
662 609527 : if (ff) {
663 609527 : struct os_iter oi;
664 609527 : os_iterator(&oi, ff, sql->session->tr, fname);
665 1990812 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
666 1381286 : sql_func *f = (sql_func*)b;
667 1381286 : bool downcast = false;
668 :
669 1381286 : if ((f->type != type && f->type != filt) || (f->private && !private))
670 430448 : continue;
671 950838 : 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 317890 : int npoints = score_func(f, ops, exact, &downcast);
673 317889 : if (downcast) {
674 2306 : if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
675 950838 : dcand = f;
676 950838 : dpoints = npoints;
677 : }
678 : } else {
679 315583 : if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
680 950838 : cand = f;
681 950838 : points = npoints;
682 : }
683 : }
684 : }
685 : }
686 : }
687 609526 : if (!cand && dcand)
688 252 : cand = dcand;
689 609526 : if (cand && exact && type != F_AGGR)
690 158300 : return sql_dup_subfunc(sql->sa, cand, ops, NULL);
691 451226 : if (cand)
692 : //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
693 247709 : 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 1552049 : sql_bind_func_(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private, bool exact)
705 : {
706 1552049 : char *F = NULL, *objstr = NULL;
707 1552049 : const char *error = "CATALOG";
708 1552049 : sql_subfunc *res = NULL;
709 :
710 1552049 : FUNC_TYPE_STR(type, F, objstr);
711 409997 : (void) F; /* not used */
712 :
713 1553530 : 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));
714 : return res;
715 : }
716 :
717 : static sql_subfunc *
718 37275 : sql_bind_func_result_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
719 : {
720 37275 : sql_subtype *tp = sql_bind_localtype("bit");
721 37262 : sql_func *cand = NULL;
722 37262 : int points = 0, npoints = 0;
723 :
724 37262 : if (ff) {
725 37262 : if (ff->ht) {
726 37262 : int key = hash_key(fname);
727 37262 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
728 136032 : for (; he; he = he->chain) {
729 98764 : sql_func *f = he->value;
730 98764 : sql_arg *firstres = NULL;
731 :
732 98764 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
733 0 : continue;
734 98764 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
735 98764 : 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 37274 : npoints = next_cand_points(f->ops, ops);
737 :
738 37274 : if (!cand || npoints > points) {
739 98770 : cand = f;
740 98770 : 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 37268 : if (cand)
765 37267 : 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 37269 : 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 37269 : char *F = NULL, *objstr = NULL;
812 37269 : const char *error = "CATALOG";
813 37269 : sql_subfunc *res = NULL;
814 37269 : list *ops = sa_list(sql->sa);
815 37275 : va_list valist;
816 :
817 37275 : FUNC_TYPE_STR(type, F, objstr);
818 37275 : (void) F; /* not used */
819 :
820 37275 : va_start(valist, nargs);
821 112907 : for (int i = 0; i < nargs; i++) {
822 75631 : sql_type *tpe = va_arg(valist, sql_type*);
823 75630 : list_append(ops, tpe);
824 : }
825 37276 : va_end(valist);
826 :
827 37276 : 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));
828 37276 : if (res) /* make sure we have the correct result type */
829 37276 : res->res->h->data = r_res;
830 37276 : return res;
831 : }
832 :
833 : static list *
834 4924 : sql_find_funcs_by_name_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private)
835 : {
836 4924 : int key = hash_key(fname);
837 4924 : list *res = NULL;
838 :
839 4924 : if (ff) {
840 4924 : if (ff->ht) {
841 4924 : for (sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)]; he; he = he->chain) {
842 0 : sql_func *f = he->value;
843 :
844 0 : if (f->type != type || (f->private && !private))
845 0 : 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 4924 : return res;
868 : }
869 :
870 : static list *
871 8676 : os_find_funcs_by_name_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private)
872 : {
873 8676 : list *res = NULL;
874 :
875 8676 : if (ff) {
876 8676 : struct os_iter oi;
877 8676 : os_iterator(&oi, ff, sql->session->tr, fname);
878 14095 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
879 5419 : sql_func *f = (sql_func*)b;
880 :
881 5419 : if (f->type != type || (f->private && !private))
882 1306 : continue;
883 4113 : if (strcmp(f->base.name, fname) == 0) {
884 4113 : if (!res)
885 4085 : res = sa_list(sql->sa);
886 4113 : list_append(res, f);
887 : }
888 : }
889 : }
890 8676 : 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 5389 : sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private)
901 : {
902 5389 : char *F = NULL, *objstr = NULL;
903 5389 : const char *error = "CATALOG";
904 5389 : list *res = NULL;
905 :
906 5389 : FUNC_TYPE_STR(type, F, objstr);
907 1294 : (void) F; /* not used */
908 :
909 6063 : 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));
910 : return res;
911 : }
912 :
913 : char *
914 1929477 : qname_schema(dlist *qname)
915 : {
916 1929477 : assert(qname && qname->h);
917 :
918 1929477 : if (dlist_length(qname) == 2) {
919 1103847 : return qname->h->data.sval;
920 825628 : } else if (dlist_length(qname) == 3) {
921 4 : return qname->h->next->data.sval;
922 : }
923 : return NULL;
924 : }
925 :
926 : char *
927 1942655 : qname_schema_object(dlist *qname)
928 : {
929 1942655 : assert(qname && qname->h);
930 :
931 1942655 : if (dlist_length(qname) == 1) {
932 838839 : return qname->h->data.sval;
933 1104025 : } else if (dlist_length(qname) == 2) {
934 1104021 : return qname->h->next->data.sval;
935 4 : } else if (dlist_length(qname) == 3) {
936 4 : return qname->h->next->next->data.sval;
937 : }
938 : return "unknown";
939 : }
940 :
941 : char *
942 0 : qname_catalog(dlist *qname)
943 : {
944 0 : assert(qname && qname->h);
945 :
946 0 : if (dlist_length(qname) == 3) {
947 0 : return qname->h->data.sval;
948 : }
949 : return NULL;
950 : }
951 :
952 : int
953 1558 : set_type_param(mvc *sql, sql_subtype *type, int nr)
954 : {
955 1558 : sql_arg *a = sql_bind_paramnr(sql, nr);
956 :
957 1558 : if (!a)
958 : return -1;
959 1558 : a->type = *type;
960 1558 : return 0;
961 : }
962 :
963 : /*
964 : * Find the result_datatype for certain combinations of values
965 : * (like case expressions or columns in a result of a query expression).
966 : * See standaard pages 505-507 Result of data type combinations */
967 : sql_subtype *
968 202590 : result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
969 : {
970 202590 : int lclass = l->type->eclass, rclass = r->type->eclass;
971 :
972 : /* case a strings */
973 284081 : if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
974 81491 : char *tpe = "varchar";
975 81491 : unsigned int digits = 0;
976 81491 : if (!EC_VARCHAR(lclass)) {
977 497 : tpe = r->type->base.name;
978 497 : digits = (!l->digits)?0:r->digits;
979 80994 : } else if (!EC_VARCHAR(rclass)) {
980 4705 : tpe = l->type->base.name;
981 4705 : digits = (!r->digits)?0:l->digits;
982 : } else { /* both */
983 76289 : tpe = !strcmp(l->type->base.name, "varchar")?l->type->base.name:!strcmp(r->type->base.name, "varchar")?r->type->base.name:
984 6 : (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
985 76289 : digits = (!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
986 : }
987 81491 : sql_find_subtype(super, tpe, digits, 0);
988 : /* case b blob */
989 121099 : } else if (lclass == EC_BLOB || rclass == EC_BLOB) {
990 14 : *super = (lclass == EC_BLOB) ? *l : *r;
991 : /* case c all exact numeric */
992 215245 : } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
993 94160 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
994 94160 : unsigned int digits = sql_max(l->digits, r->digits);
995 94160 : unsigned int scale = sql_max(l->scale, r->scale);
996 :
997 94160 : if (l->type->radix == 10 && r->type->radix == 10) {
998 96 : digits = scale + (sql_max(l->digits - l->scale, r->digits - r->scale));
999 : #ifdef HAVE_HGE
1000 96 : if (digits > 38) {
1001 0 : digits = 38;
1002 : #else
1003 : if (digits > 18) {
1004 : digits = 18;
1005 : #endif
1006 0 : scale = MIN(scale, digits - 1);
1007 : }
1008 94064 : } else if (l->type->radix == 2 && r->type->radix == 10) { /* change to radix 10 */
1009 47 : digits = bits2digits(l->type->digits);
1010 47 : digits = sql_max(r->digits, digits);
1011 47 : scale = r->scale;
1012 94017 : } else if (l->type->radix == 10 && r->type->radix == 2) { /* change to radix 10 */
1013 115 : digits = bits2digits(r->type->digits);
1014 115 : digits = sql_max(l->digits, digits);
1015 115 : scale = l->scale;
1016 : }
1017 94160 : sql_find_subtype(super, tpe, digits, scale);
1018 : /* case d approximate numeric */
1019 26925 : } else if (EC_APPNUM(lclass) || EC_APPNUM(rclass)) {
1020 154 : if (!EC_APPNUM(lclass)) {
1021 44 : *super = *r;
1022 110 : } else if (!EC_APPNUM(rclass)) {
1023 91 : *super = *l;
1024 : } else { /* both */
1025 19 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1026 19 : unsigned int digits = sql_max(l->digits, r->digits); /* bits precision */
1027 19 : sql_find_subtype(super, tpe, digits, 0);
1028 : }
1029 : /* now its getting serious, ie e any 'case e' datetime data type */
1030 : /* 'case f' interval types */
1031 : /* 'case g' boolean */
1032 : /* 'case h-l' compounds like row (tuple), etc */
1033 : } else {
1034 26771 : return supertype(super, l, r);
1035 : }
1036 : return super;
1037 : }
1038 :
1039 : char *
1040 76 : toUpperCopy(char *dest, const char *src)
1041 : {
1042 76 : size_t i, len;
1043 :
1044 76 : if (src == NULL) {
1045 0 : *dest = '\0';
1046 0 : return(dest);
1047 : }
1048 :
1049 76 : len = _strlen(src);
1050 388 : for (i = 0; i < len; i++)
1051 312 : dest[i] = (char)toupper((int)src[i]);
1052 :
1053 76 : dest[i] = '\0';
1054 76 : return(dest);
1055 : }
1056 :
1057 : static char * _symbol2string(mvc *sql, symbol *se, int expression, char **err);
1058 :
1059 : static char *
1060 1 : dlist2string(mvc *sql, dlist *l, int expression, char **err)
1061 : {
1062 1 : char *b = NULL;
1063 1 : dnode *n;
1064 :
1065 3 : for (n=l->h; n; n = n->next) {
1066 2 : char *s = NULL;
1067 :
1068 2 : if (n->type == type_string && n->data.sval)
1069 2 : s = sa_strdup(sql->ta, n->data.sval);
1070 0 : else if (n->type == type_symbol)
1071 0 : s = _symbol2string(sql, n->data.sym, expression, err);
1072 :
1073 2 : if (!s)
1074 0 : return NULL;
1075 2 : if (b) {
1076 1 : char *o = SA_NEW_ARRAY(sql->ta, char, strlen(b) + strlen(s) + 2);
1077 1 : if (o)
1078 1 : stpcpy(stpcpy(stpcpy(o, b), "."), s);
1079 0 : b = o;
1080 1 : if (b == NULL)
1081 : return NULL;
1082 : } else {
1083 : b = s;
1084 : }
1085 : }
1086 : return b;
1087 : }
1088 :
1089 : static const char *
1090 843 : symbol_escape_ident(allocator *sa, const char *s)
1091 : {
1092 843 : char *res = NULL;
1093 843 : if (s) {
1094 795 : size_t l = strlen(s);
1095 795 : char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
1096 :
1097 795 : res = r;
1098 5921 : while (*s) {
1099 5126 : if (*s == '"')
1100 1 : *r++ = '"';
1101 5126 : *r++ = *s++;
1102 : }
1103 795 : *r = '\0';
1104 : }
1105 843 : return res;
1106 : }
1107 :
1108 : char *
1109 1541 : _symbol2string(mvc *sql, symbol *se, int expression, char **err)
1110 : {
1111 : /* inner symbol2string uses the temporary allocator */
1112 1541 : switch (se->token) {
1113 3 : case SQL_NOP: {
1114 3 : dnode *lst = se->data.lval->h, *ops = lst->next->next->data.lval->h, *aux;
1115 3 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1116 3 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1117 3 : int i = 0, nargs = 0;
1118 3 : char** inputs = NULL, *res;
1119 3 : size_t inputs_length = 0, extra = sname ? strlen(sname) + 3 : 0;
1120 :
1121 12 : for (aux = ops; aux; aux = aux->next)
1122 9 : nargs++;
1123 3 : if (!(inputs = SA_ZNEW_ARRAY(sql->ta, char*, nargs)))
1124 : return NULL;
1125 :
1126 12 : for (aux = ops; aux; aux = aux->next) {
1127 9 : if (!(inputs[i] = _symbol2string(sql, aux->data.sym, expression, err))) {
1128 : return NULL;
1129 : }
1130 9 : inputs_length += strlen(inputs[i]);
1131 9 : i++;
1132 : }
1133 :
1134 6 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + inputs_length + 3 + (nargs - 1 /* commas */) + 2))) {
1135 3 : char *concat = res;
1136 3 : if (sname)
1137 3 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1138 3 : concat = stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"(");
1139 3 : i = 0;
1140 12 : for (aux = ops; aux; aux = aux->next) {
1141 9 : concat = stpcpy(concat, inputs[i]);
1142 9 : if (aux->next)
1143 6 : concat = stpcpy(concat, ",");
1144 9 : i++;
1145 : }
1146 3 : concat = stpcpy(concat, ")");
1147 : }
1148 : return res;
1149 : }
1150 22 : case SQL_BINOP: {
1151 22 : dnode *lst = se->data.lval->h;
1152 22 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1153 22 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1154 22 : char *l = NULL, *r = NULL, *res;
1155 22 : size_t extra = sname ? strlen(sname) + 3 : 0;
1156 :
1157 22 : if (!(l = _symbol2string(sql, lst->next->next->data.sym, expression, err)) || !(r = _symbol2string(sql, lst->next->next->next->data.sym, expression, err)))
1158 2 : return NULL;
1159 :
1160 40 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + strlen(r) + 6))) {
1161 20 : char *concat = res;
1162 20 : if (sname)
1163 18 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1164 20 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("), l), ","), r), ")");
1165 : }
1166 : return res;
1167 : }
1168 36 : case SQL_OP: {
1169 36 : dnode *lst = se->data.lval->h;
1170 36 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1171 36 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1172 36 : char *res;
1173 36 : size_t extra = sname ? strlen(sname) + 3 : 0;
1174 :
1175 72 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + 5))) {
1176 36 : char *concat = res;
1177 36 : if (sname)
1178 0 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1179 36 : stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"()");
1180 : }
1181 : return res;
1182 : }
1183 83 : case SQL_UNOP: {
1184 83 : dnode *lst = se->data.lval->h;
1185 83 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1186 83 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1187 83 : char *l = _symbol2string(sql, lst->next->next->data.sym, expression, err), *res;
1188 83 : size_t extra = sname ? strlen(sname) + 3 : 0;
1189 :
1190 83 : if (!l)
1191 : return NULL;
1192 :
1193 164 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + 5))) {
1194 82 : char *concat = res;
1195 82 : if (sname)
1196 74 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1197 82 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("), l), ")");
1198 : }
1199 : return res;
1200 : }
1201 0 : case SQL_PARAMETER:
1202 0 : return sa_strdup(sql->ta, "?");
1203 188 : case SQL_NULL:
1204 188 : return sa_strdup(sql->ta, "NULL");
1205 : case SQL_ATOM:{
1206 909 : AtomNode *an = (AtomNode *) se;
1207 909 : if (an && an->a)
1208 909 : return atom2sql(sql->ta, an->a, sql->timezone);
1209 : else
1210 0 : return sa_strdup(sql->ta, "NULL");
1211 : }
1212 264 : case SQL_NEXT: {
1213 264 : const char *seq = symbol_escape_ident(sql->ta, qname_schema_object(se->data.lval)),
1214 264 : *sname = qname_schema(se->data.lval);
1215 264 : char *res;
1216 :
1217 264 : if (!sname)
1218 198 : sname = sql->session->schema->base.name;
1219 264 : sname = symbol_escape_ident(sql->ta, sname);
1220 :
1221 528 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen("next value for \"") + strlen(sname) + strlen(seq) + 5)))
1222 264 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for \""), sname), "\".\""), seq), "\"");
1223 : return res;
1224 28 : } break;
1225 28 : case SQL_IDENT:
1226 : case SQL_COLUMN: {
1227 : /* can only be variables */
1228 28 : dlist *l = se->data.lval;
1229 28 : assert(l->h->type != type_lng);
1230 28 : if (expression && dlist_length(l) == 1 && l->h->type == type_string) {
1231 : /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */
1232 27 : const char *op = symbol_escape_ident(sql->ta, l->h->data.sval);
1233 27 : char *res;
1234 :
1235 54 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3)))
1236 27 : stpcpy(stpcpy(stpcpy(res, "\""), op), "\"");
1237 27 : return res;
1238 0 : } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) {
1239 0 : const char *first = symbol_escape_ident(sql->ta, l->h->data.sval),
1240 0 : *second = symbol_escape_ident(sql->ta, l->h->next->data.sval);
1241 0 : char *res;
1242 :
1243 0 : if (!first || !second)
1244 : return NULL;
1245 0 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(first) + strlen(second) + 6)))
1246 0 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), first), "\".\""), second), "\"");
1247 0 : return res;
1248 : } else {
1249 1 : char *e = dlist2string(sql, l, expression, err);
1250 1 : if (e)
1251 1 : *err = e;
1252 1 : return NULL;
1253 : }
1254 : }
1255 6 : case SQL_CAST: {
1256 6 : dlist *dl = se->data.lval;
1257 6 : char *val = NULL, *tpe = NULL, *res;
1258 :
1259 6 : if (!(val = _symbol2string(sql, dl->h->data.sym, expression, err)) || !(tpe = subtype2string2(sql->ta, &dl->h->next->data.typeval)))
1260 0 : return NULL;
1261 12 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(val) + strlen(tpe) + 11)))
1262 6 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "cast("), val), " as "), tpe), ")");
1263 : return res;
1264 : }
1265 2 : default: {
1266 2 : const char *msg = "SQL feature not yet available for expressions and default values: ";
1267 2 : char *tok_str = token2string(se->token);
1268 4 : if ((*err = SA_NEW_ARRAY(sql->ta, char, strlen(msg) + strlen(tok_str) + 1)))
1269 2 : stpcpy(stpcpy(*err, msg), tok_str);
1270 : }
1271 : }
1272 : return NULL;
1273 : }
1274 :
1275 : char *
1276 1401 : symbol2string(mvc *sql, symbol *se, int expression, char **err)
1277 : {
1278 1401 : char *res = _symbol2string(sql, se, expression, err);
1279 :
1280 1401 : if (res)
1281 1398 : res = sa_strdup(sql->sa, res);
1282 1401 : if (*err)
1283 3 : *err = sa_strdup(sql->sa, *err);
1284 1401 : sa_reset(sql->ta);
1285 1401 : return res;
1286 : }
|