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 359361 : sql_add_param(mvc *sql, const char *name, sql_subtype *st)
40 : {
41 359361 : sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
42 :
43 359361 : if (name)
44 357747 : a->name = sa_strdup(sql->sa, name);
45 359361 : if (st && st->type)
46 357737 : a->type = *st;
47 359361 : a->inout = ARG_IN;
48 359361 : if (name && strcmp(name, "*") == 0)
49 3 : a->type = *sql_bind_localtype("int");
50 359361 : if (!sql->params)
51 212155 : sql->params = sa_list(sql->sa);
52 359361 : list_append(sql->params, a);
53 359361 : }
54 :
55 : int
56 123300 : sql_bind_param(mvc *sql, const char *name)
57 : {
58 123300 : node *n;
59 123300 : int nr = 0;
60 :
61 123300 : if (sql->params) {
62 273365 : for (n = sql->params->h; n; n = n->next, nr++) {
63 269063 : sql_arg *a = n->data;
64 :
65 269063 : if (a->name && strcmp(a->name, name) == 0)
66 115443 : return nr;
67 : }
68 : }
69 : return -1;
70 : }
71 :
72 : sql_arg *
73 118618 : sql_bind_paramnr(mvc *sql, int nr)
74 : {
75 118618 : int i=0;
76 118618 : node *n;
77 :
78 118618 : if (sql->params && nr < list_length(sql->params)) {
79 745680 : for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
80 : ;
81 :
82 118618 : if (n)
83 118618 : 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 716370 : sql_destroy_params(mvc *sql)
101 : {
102 716370 : sql->params = NULL;
103 716370 : }
104 :
105 : sql_schema *
106 1798824 : cur_schema(mvc *sql)
107 : {
108 1798824 : return sql->session->schema;
109 : }
110 :
111 : sql_schema *
112 621547 : tmp_schema(mvc *sql)
113 : {
114 621547 : 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 : CALL; \
130 : } else { \
131 : sql_schema *cur = cur_schema(sql); \
132 : char *session_schema = cur->base.name; \
133 : \
134 : EXTRA; \
135 : 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 */ \
136 : next = tmp_schema(sql); \
137 : CALL; \
138 : } \
139 : if (!res) { /* then current session's schema */ \
140 : next = cur; \
141 : CALL; \
142 : } \
143 : if (!res) { \
144 : /* object not found yet, look inside search path */ \
145 : for (node *n = sql->schema_path->h ; n && !res ; n = n->next) { \
146 : str p = (str) n->data; \
147 : if (strcmp(session_schema, p) != 0 && (next = mvc_bind_schema(sql, p))) \
148 : CALL; \
149 : } \
150 : } \
151 : if (!res && !sql->schema_path_has_sys && strcmp(session_schema, "sys") != 0) { /* if 'sys' is not in the current path search it next */ \
152 : next = mvc_bind_schema(sql, "sys"); \
153 : CALL; \
154 : } \
155 : } \
156 : if (!res) \
157 : return sql_error(sql, ERR_NOTFOUND, ERROR_CODE "%s: no such %s %s%s%s'%s'", error, objstr, sname ? "'":"", sname ? sname : "", sname ? "'.":"", name); \
158 : } while (0)
159 :
160 : #define table_extra \
161 : do { \
162 : if (s) { \
163 : next = s; /* there's a default schema to search before all others, e.g. bind a child table from a merge table */ \
164 : res = mvc_bind_table(sql, next, name); \
165 : } \
166 : if (!res && strcmp(objstr, "table") == 0 && (res = stack_find_table(sql, name))) /* for tables, first try a declared table from the stack */ \
167 : return res; \
168 : } while (0)
169 :
170 : sql_table *
171 643703 : find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *name, const char *error, bool isView)
172 : {
173 643703 : const char *objstr = isView ? "view" : "table";
174 1287143 : sql_table *res = NULL;
175 :
176 644150 : search_object_on_path(res = mvc_bind_table(sql, next, name), DO_NOTHING, table_extra, SQLSTATE(42S02));
177 : return res;
178 : }
179 :
180 : sql_sequence *
181 1454 : find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
182 : {
183 1454 : const char *objstr = "sequence";
184 1454 : sql_sequence *res = NULL;
185 :
186 1458 : search_object_on_path(res = find_sql_sequence(sql->session->tr, next, name), DO_NOTHING, ;, SQLSTATE(42000));
187 : return res;
188 : }
189 :
190 : sql_idx *
191 213 : find_idx_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
192 : {
193 213 : const char *objstr = "index";
194 213 : sql_idx *res = NULL;
195 :
196 287 : search_object_on_path(res = mvc_bind_idx(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S12));
197 : return res;
198 : }
199 :
200 : sql_type *
201 5 : find_type_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
202 : {
203 5 : const char *objstr = "type";
204 5 : sql_type *res = NULL;
205 :
206 7 : search_object_on_path(res = schema_bind_type(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S01));
207 : return res;
208 : }
209 :
210 : sql_trigger *
211 93 : find_trigger_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
212 : {
213 93 : const char *objstr = "trigger";
214 93 : sql_trigger *res = NULL;
215 :
216 115 : search_object_on_path(res = mvc_bind_trigger(sql, next, name), DO_NOTHING, ;, SQLSTATE(3F000));
217 : return res;
218 : }
219 :
220 : /* A variable can be any of the following, from the innermost to the outermost:
221 : - 'parameter of the function' (ie in the param list)
222 : - local variable, declared earlier
223 : - global variable, also declared earlier
224 : */
225 : #define variable_extra \
226 : do { \
227 : if (!res) { \
228 : if ((*var = stack_find_var_frame(sql, name, level))) { /* check if variable is known from the stack */ \
229 : *tpe = &((*var)->var.tpe); \
230 : res = true; \
231 : } else if ((nr = sql_bind_param(sql, name)) >= 0) { /* then if it is a parameter */ \
232 : *a = sql_bind_paramnr(sql, nr); \
233 : *tpe = &((*a)->type); \
234 : *level = 1; \
235 : res = true; \
236 : } \
237 : } \
238 : } while (0)
239 :
240 : #define var_find_on_global \
241 : do { \
242 : if ((*var = find_global_var(sql, next, name))) { /* then if it is a global var */ \
243 : *tpe = &((*var)->var.tpe); \
244 : *level = 0; \
245 : res = true; \
246 : } \
247 : } while (0)
248 :
249 : bool
250 228464 : 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)
251 : {
252 228464 : const char *objstr = "variable";
253 228464 : bool res = false;
254 228464 : int nr = 0;
255 :
256 228464 : (void)nr;
257 233243 : search_object_on_path(var_find_on_global, DO_NOTHING, variable_extra, SQLSTATE(42000));
258 : return res;
259 : }
260 :
261 : static sql_subfunc *
262 186804 : _dup_subaggr(sql_allocator *sa, sql_func *a, sql_subtype *member)
263 : {
264 186804 : node *tn;
265 186804 : unsigned int scale = 0, digits = 0;
266 186804 : sql_subfunc *ares = SA_ZNEW(sa, sql_subfunc);
267 :
268 186804 : assert (a->res);
269 :
270 186804 : ares->func = a;
271 186804 : ares->res = sa_list(sa);
272 373608 : for(tn = a->res->h; tn; tn = tn->next) {
273 186803 : sql_arg *rarg = tn->data;
274 186803 : sql_subtype *res, *r = &rarg->type;
275 :
276 186803 : digits = r->digits;
277 186803 : scale = r->scale;
278 : /* same scale as the input */
279 186803 : if (member && (member->scale != scale ||
280 162174 : (digits != member->digits && !EC_NUMBER(member->type->eclass)))) {
281 89557 : if (member->digits > digits)
282 : digits = member->digits;
283 : scale = member->scale;
284 : }
285 : /* same type as the input */
286 186803 : if (r->type->eclass == EC_ANY && member) {
287 14412 : r = member;
288 14412 : digits = member->digits;
289 : }
290 186803 : if (!EC_SCALE(r->type->eclass))
291 186803 : scale = 0;
292 186803 : res = sql_create_subtype(sa, r->type, digits, scale);
293 186805 : list_append(ares->res, res);
294 : }
295 186805 : return ares;
296 : }
297 :
298 : static sql_subfunc *
299 219830 : func_cmp(sql_allocator *sa, sql_func *f, const char *name, int nrargs)
300 : {
301 219830 : if (strcmp(f->base.name, name) == 0) {
302 218948 : if (f->vararg)
303 14 : return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
304 218934 : if (nrargs < 0 || list_length(f->ops) == nrargs)
305 205183 : return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
306 : }
307 : return NULL;
308 : }
309 :
310 : static sql_subfunc *
311 677554 : sql_find_func_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
312 : {
313 677554 : int key = hash_key(fname);
314 677554 : sql_subfunc *res = NULL;
315 677554 : int found = 0;
316 677554 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
317 :
318 677554 : if (ff) {
319 677554 : if (ff->ht) {
320 677554 : sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
321 677554 : if (prev) {
322 272 : for (; he && !found; he = he->chain)
323 170 : if (he->value == prev->func)
324 76 : found = 1;
325 : }
326 9253466 : for (; he; he = he->chain) {
327 8708266 : sql_func *f = he->value;
328 :
329 8708266 : if ((f->type != type && f->type != filt) || (f->private && !private))
330 8575038 : continue;
331 133228 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
332 132354 : return res;
333 : }
334 : } else {
335 0 : node *n = ff->h;
336 0 : if (prev) {
337 0 : for (; n && !found; n = n->next)
338 0 : if (n->data == prev->func)
339 0 : found = 1;
340 : }
341 0 : for (; n; n = n->next) {
342 0 : sql_func *f = n->data;
343 :
344 0 : if ((f->type != type && f->type != filt) || (f->private && !private))
345 0 : continue;
346 0 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
347 0 : return res;
348 : }
349 : }
350 : }
351 : return res;
352 : }
353 :
354 : static sql_subfunc *
355 812332 : os_find_func_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
356 : {
357 812332 : sql_subfunc *res = NULL;
358 812332 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
359 :
360 812332 : if (ff) {
361 812332 : struct os_iter oi;
362 812332 : os_iterator(&oi, ff, sql->session->tr, fname);
363 904563 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
364 100175 : sql_func *f = (sql_func*)b;
365 100175 : if (prev && prev->func != f) {
366 13 : continue;
367 100162 : } else if (prev) {
368 26 : prev = NULL;
369 26 : continue;
370 : }
371 :
372 100136 : if ((f->type != type && f->type != filt) || (f->private && !private))
373 88193 : continue;
374 11943 : if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
375 7944 : return res;
376 : }
377 : }
378 : return res;
379 : }
380 :
381 : #define functions_without_schema(X) if (strcmp(sname, "sys") == 0) X
382 :
383 : #define find_func_extra \
384 : do { \
385 : if (!res && (res = sql_find_func_internal(sql, funcs, name, nrargs, type, private, prev))) /* search system wide functions first */ \
386 : return res; \
387 : } while (0)
388 :
389 : sql_subfunc *
390 678271 : sql_find_func(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
391 : {
392 678271 : char *F = NULL, *objstr = NULL;
393 678271 : const char *error = "CATALOG";
394 678271 : sql_subfunc *res = NULL;
395 :
396 678271 : FUNC_TYPE_STR(type, F, objstr);
397 678271 : (void) F; /* not used */
398 :
399 678271 : assert(nrargs >= -1);
400 :
401 1187186 : 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));
402 : return res;
403 : }
404 :
405 : static int
406 95283 : is_subtypeof(sql_subtype *sub, sql_subtype *super)
407 : /* returns true if sub is a sub type of super */
408 : {
409 95283 : if (!sub || !super)
410 : return 0;
411 95283 : if (super->digits > 0 && sub->digits > super->digits)
412 : return 0;
413 : /* while binding a function, 'char' types match each other */
414 94387 : if (super->digits == 0 &&
415 90212 : ((super->type->eclass == EC_STRING && EC_VARCHAR(sub->type->eclass)) ||
416 29651 : (super->type->eclass == EC_CHAR && sub->type->eclass == EC_CHAR)))
417 : return 1;
418 6376 : if (super->type->eclass == sub->type->eclass)
419 : return 1;
420 : /* subtypes are only equal iff
421 : they map onto the same systemtype */
422 5330 : return (type_cmp(sub->type, super->type) == 0);
423 : }
424 :
425 : /* find function based on first argument */
426 : static sql_subfunc *
427 32819 : sql_bind_member_internal(mvc *sql, list *ff, const char *fname, sql_subtype *tp, sql_ftype type, int nrargs, bool private, sql_subfunc *prev)
428 : {
429 32819 : sql_func *cand = NULL;
430 32819 : int points = 0, npoints = 0, found = 1;
431 :
432 32819 : assert(nrargs);
433 32819 : if (ff) {
434 32819 : node *n = ff->h;
435 32819 : if (prev) {
436 : found = 0;
437 64886 : for(; n && !found; n = n->next)
438 64805 : if (n->data == prev->func)
439 81 : found = 1;
440 : }
441 34682296 : for (; n; n = n->next) {
442 34649477 : sql_func *f = n->data;
443 :
444 34649477 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
445 7562883 : continue;
446 27086594 : if (strcmp(f->base.name, fname) == 0 && f->type == type && list_length(f->ops) == nrargs) {
447 101113 : sql_subtype *ft = &((sql_arg *) f->ops->h->data)->type;
448 101113 : if ((f->fix_scale == INOUT && type_cmp(tp->type, ft->type) == 0) || (f->fix_scale != INOUT && is_subtypeof(tp, ft))) {
449 90302 : if (!cand) {
450 31737 : cand = f;
451 31737 : points = tp->type->eclass == ft->type->eclass;
452 58565 : } else if ((npoints = tp->type->eclass == ft->type->eclass) > points) {
453 34649477 : cand = f;
454 34649477 : points = npoints;
455 : }
456 : }
457 : }
458 : }
459 : }
460 32819 : if (cand)
461 31737 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, NULL, tp);
462 : return NULL;
463 : }
464 :
465 : static sql_subfunc *
466 2127 : os_bind_member_internal(mvc *sql, struct objectset *ff, const char *fname, sql_subtype *tp, sql_ftype type, int nrargs, bool private, sql_subfunc *prev)
467 : {
468 2127 : sql_func *cand = NULL;
469 2127 : int points = 0, npoints = 0;
470 :
471 2127 : assert(nrargs);
472 2127 : if (ff) {
473 2127 : struct os_iter oi;
474 2127 : os_iterator(&oi, ff, sql->session->tr, fname);
475 4341 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
476 2214 : sql_func *f = (sql_func*)b;
477 2214 : if (prev && prev->func != f)
478 0 : continue;
479 2214 : else if (prev) {
480 0 : prev = NULL;
481 0 : continue;
482 : }
483 :
484 2214 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
485 18 : continue;
486 2196 : if (strcmp(f->base.name, fname) == 0 && f->type == type && list_length(f->ops) == nrargs) {
487 1508 : sql_subtype *ft = &((sql_arg *) f->ops->h->data)->type;
488 1508 : if ((f->fix_scale == INOUT && type_cmp(tp->type, ft->type) == 0) || (f->fix_scale != INOUT && is_subtypeof(tp, ft))) {
489 536 : if (!cand) {
490 361 : cand = f;
491 361 : points = tp->type->eclass == ft->type->eclass;
492 175 : } else if ((npoints = tp->type->eclass == ft->type->eclass) > points) {
493 0 : cand = f;
494 0 : points = npoints;
495 : }
496 : }
497 : }
498 : }
499 : }
500 2127 : if (cand)
501 361 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, tp) : sql_dup_subfunc(sql->sa, cand, NULL, tp);
502 : return NULL;
503 : }
504 :
505 :
506 : #define sql_bind_member_extra \
507 : do { \
508 : if (!res && (res = sql_bind_member_internal(sql, funcs, name, tp, type, nrargs, private, prev))) /* search system wide functions first */ \
509 : return res; \
510 : } while (0)
511 :
512 : sql_subfunc *
513 32844 : sql_bind_member(mvc *sql, const char *sname, const char *name, sql_subtype *tp, sql_ftype type, int nrargs, bool private, sql_subfunc *prev)
514 : {
515 32844 : char *F = NULL, *objstr = NULL;
516 32844 : const char *error = "CATALOG";
517 32844 : sql_subfunc *res = NULL;
518 :
519 32844 : FUNC_TYPE_STR(type, F, objstr);
520 121 : (void) F; /* not used */
521 :
522 34090 : search_object_on_path(res = os_bind_member_internal(sql, next->funcs, name, tp, type, nrargs, private, prev), functions_without_schema, sql_bind_member_extra, SQLSTATE(42000));
523 : return res;
524 : }
525 :
526 : sql_subfunc *
527 1239201 : sql_bind_func(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_ftype type, bool private)
528 : {
529 1239201 : list *l = sa_list(sql->sa);
530 :
531 1239201 : if (tp1)
532 1229592 : list_append(l, tp1);
533 1239200 : if (tp2)
534 976813 : list_append(l, tp2);
535 1239201 : return sql_bind_func_(sql, sname, fname, l, type, private);
536 : }
537 :
538 : sql_subfunc *
539 273 : 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)
540 : {
541 273 : list *l = sa_list(sql->sa);
542 :
543 273 : if (tp1)
544 273 : list_append(l, tp1);
545 273 : if (tp2)
546 273 : list_append(l, tp2);
547 273 : if (tp3)
548 273 : list_append(l, tp3);
549 273 : return sql_bind_func_(sql, sname, fname, l, type, private);
550 : }
551 :
552 : static int /* bind the function version with more identical type matches */
553 1644016 : next_cand_points(list *args, list *ops)
554 : {
555 1644016 : int res = 0;
556 :
557 1644016 : if (!list_empty(args) && !list_empty(ops))
558 4599489 : for (node *n = args->h, *m = ops->h; n && m ; n = n->next, m = m->next) {
559 2986352 : sql_arg *a = n->data;
560 2986352 : sql_subtype *t = m->data;
561 :
562 2986352 : if (t)
563 2986163 : res += a->type.type->base.id == t->type->base.id;
564 : }
565 1644015 : return res;
566 : }
567 :
568 : static sql_subfunc *
569 1758244 : sql_bind_func__(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private)
570 : {
571 1758244 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
572 1758244 : sql_subtype *input_type = NULL;
573 1758244 : sql_func *cand = NULL;
574 1758244 : int points = 0, npoints = 0;
575 :
576 1758244 : if (ops && ops->h)
577 1721272 : input_type = ops->h->data;
578 :
579 1758244 : if (ff) {
580 1758244 : node *n;
581 1861141845 : sql_base_loop(ff, n) {
582 1859383609 : sql_func *f = n->data;
583 :
584 1859383609 : if ((f->type != type && f->type != filt) || (f->private && !private))
585 798856357 : continue;
586 1060527252 : if (strcmp(f->base.name, fname) == 0 && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
587 1312822 : if (!cand) {
588 1056190 : cand = f;
589 1056190 : points = next_cand_points(f->ops, ops);
590 256632 : } else if ((npoints = next_cand_points(f->ops, ops)) > points) {
591 1859383601 : cand = f;
592 1859383601 : points = npoints;
593 : }
594 : }
595 : }
596 : }
597 1758236 : if (cand)
598 1056184 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
599 : return NULL;
600 : }
601 :
602 : static sql_subfunc *
603 925997 : os_bind_func__(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private)
604 : {
605 925997 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
606 925997 : sql_subtype *input_type = NULL;
607 925997 : sql_func *cand = NULL;
608 925997 : int points = 0, npoints = 0;
609 :
610 925997 : if (ops && ops->h)
611 895110 : input_type = ops->h->data;
612 :
613 925997 : if (ff) {
614 925997 : struct os_iter oi;
615 925997 : os_iterator(&oi, ff, sql->session->tr, fname);
616 2112023 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
617 1186026 : sql_func *f = (sql_func*)b;
618 :
619 1186026 : if ((f->type != type && f->type != filt) || (f->private && !private))
620 384497 : continue;
621 801529 : if (strcmp(f->base.name, fname) == 0 && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
622 295322 : if (!cand) {
623 294331 : cand = f;
624 294331 : points = next_cand_points(f->ops, ops);
625 991 : } else if ((npoints = next_cand_points(f->ops, ops)) > points) {
626 1186026 : cand = f;
627 1186026 : points = npoints;
628 : }
629 : }
630 : }
631 : }
632 925997 : if (cand)
633 294331 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
634 : return NULL;
635 : }
636 :
637 : #define sql_bind_func__extra \
638 : do { \
639 : if (!res && (res = sql_bind_func__(sql, funcs, name, ops, type, private))) /* search system wide functions first */ \
640 : return res; \
641 : } while (0)
642 :
643 : sql_subfunc *
644 1783395 : sql_bind_func_(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private)
645 : {
646 1783395 : char *F = NULL, *objstr = NULL;
647 1783395 : const char *error = "CATALOG";
648 1783395 : sql_subfunc *res = NULL;
649 :
650 1783395 : FUNC_TYPE_STR(type, F, objstr);
651 398264 : (void) F; /* not used */
652 :
653 1886914 : search_object_on_path(res = os_bind_func__(sql, next->funcs, name, ops, type, private), functions_without_schema, sql_bind_func__extra, SQLSTATE(42000));
654 : return res;
655 : }
656 :
657 : static sql_subfunc *
658 35709 : sql_bind_func_result_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
659 : {
660 35709 : sql_subtype *tp = sql_bind_localtype("bit");
661 35709 : sql_func *cand = NULL;
662 35709 : int points = 0, npoints = 0;
663 :
664 35709 : if (ff) {
665 35709 : node *n;
666 37795902 : sql_base_loop( ff, n) {
667 37760193 : sql_func *f = n->data;
668 37760193 : sql_arg *firstres = NULL;
669 :
670 37760193 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
671 71418 : continue;
672 37688775 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
673 37688775 : 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) {
674 35708 : if (!cand) {
675 35708 : cand = f;
676 35708 : points = next_cand_points(f->ops, ops);
677 0 : } else if ((npoints = next_cand_points(f->ops, ops)) > points) {
678 37760193 : cand = f;
679 37760193 : points = npoints;
680 : }
681 : }
682 : }
683 : }
684 35709 : if (cand)
685 35708 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
686 : return NULL;
687 : }
688 :
689 : static sql_subfunc *
690 1 : os_bind_func_result_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
691 : {
692 1 : sql_subtype *tp = sql_bind_localtype("bit");
693 1 : sql_func *cand = NULL;
694 1 : int points = 0, npoints = 0;
695 :
696 1 : if (ff) {
697 1 : struct os_iter oi;
698 1 : os_iterator(&oi, ff, sql->session->tr, fname);
699 2 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
700 1 : sql_func *f = (sql_func*)b;
701 1 : sql_arg *firstres = NULL;
702 :
703 1 : if ((!f->res && !IS_FILT(f)) || (f->private && !private))
704 0 : continue;
705 1 : firstres = IS_FILT(f)?tp->type:f->res->h->data;
706 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) {
707 1 : if (!cand) {
708 1 : cand = f;
709 1 : points = next_cand_points(f->ops, ops);
710 0 : } else if ((npoints = next_cand_points(f->ops, ops)) > points) {
711 1 : cand = f;
712 1 : points = npoints;
713 : }
714 : }
715 : }
716 : }
717 1 : if (cand)
718 1 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
719 : return NULL;
720 : }
721 :
722 : #define sql_bind_func_result_extra \
723 : do { \
724 : if (!res && (res = sql_bind_func_result_internal(sql, funcs, name, type, private, ops, r_res))) /* search system wide functions first */ \
725 : return res; \
726 : } while (0)
727 :
728 : sql_subfunc *
729 35709 : sql_bind_func_result(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private, sql_subtype *r_res, int nargs, ...)
730 : {
731 35709 : char *F = NULL, *objstr = NULL;
732 35709 : const char *error = "CATALOG";
733 35709 : sql_subfunc *res = NULL;
734 35709 : list *ops = sa_list(sql->sa);
735 35709 : va_list valist;
736 :
737 35709 : FUNC_TYPE_STR(type, F, objstr);
738 35709 : (void) F; /* not used */
739 :
740 35709 : va_start(valist, nargs);
741 108356 : for (int i = 0; i < nargs; i++) {
742 72647 : sql_type *tpe = va_arg(valist, sql_type*);
743 72647 : list_append(ops, tpe);
744 : }
745 35709 : va_end(valist);
746 :
747 35709 : 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));
748 : return res;
749 : }
750 :
751 : static int
752 713 : arg_subtype_cmp_null(sql_arg *a, sql_subtype *t)
753 : {
754 713 : if (a->type.type->eclass == EC_ANY)
755 : return 0;
756 709 : if (!t)
757 : return 0;
758 397 : return (is_subtypeof(t, &a->type )?0:-1);
759 : }
760 :
761 : static sql_subfunc *
762 16 : sql_resolve_function_with_undefined_parameters_internal(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private)
763 : {
764 16 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
765 16 : sql_func *cand = NULL;
766 16 : int points = 0, npoints = 0;
767 :
768 16 : if (ff) {
769 16 : node *n;
770 16944 : sql_base_loop( ff, n) {
771 16928 : sql_func *f = n->data;
772 :
773 16928 : if ((f->type != type && f->type != filt) || (f->private && !private))
774 5648 : continue;
775 11280 : if (strcmp(f->base.name, fname) == 0 && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp_null) == 0) {
776 151 : if (!cand) {
777 13 : cand = f;
778 13 : points = next_cand_points(f->ops, ops);
779 138 : } else if ((npoints = next_cand_points(f->ops, ops)) > points) {
780 16928 : cand = f;
781 16928 : points = npoints;
782 : }
783 : }
784 : }
785 : }
786 16 : if (cand)
787 13 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
788 : return NULL;
789 : }
790 :
791 : static sql_subfunc *
792 7 : os_resolve_function_with_undefined_parameters_internal(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private)
793 : {
794 7 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
795 7 : sql_func *cand = NULL;
796 7 : int points = 0, npoints = 0;
797 :
798 7 : if (ff) {
799 7 : struct os_iter oi;
800 7 : os_iterator(&oi, ff, sql->session->tr, fname);
801 20 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
802 13 : sql_func *f = (sql_func*)b;
803 :
804 13 : if ((f->type != type && f->type != filt) || (f->private && !private))
805 0 : continue;
806 13 : if (strcmp(f->base.name, fname) == 0 && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp_null) == 0) {
807 12 : if (!cand) {
808 4 : cand = f;
809 4 : points = next_cand_points(f->ops, ops);
810 8 : } else if ((npoints = next_cand_points(f->ops, ops)) > points) {
811 13 : cand = f;
812 13 : points = npoints;
813 : }
814 : }
815 : }
816 : }
817 7 : if (cand)
818 4 : return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
819 : return NULL;
820 : }
821 :
822 : #define sql_resolve_function_with_undefined_parameters_extra \
823 : do { \
824 : if (!res && (res = sql_resolve_function_with_undefined_parameters_internal(sql, funcs, name, ops, type, private))) /* search system wide functions first */ \
825 : return res; \
826 : } while (0)
827 :
828 : sql_subfunc *
829 18 : sql_resolve_function_with_undefined_parameters(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private)
830 : {
831 18 : char *F = NULL, *objstr = NULL;
832 18 : const char *error = "CATALOG";
833 18 : sql_subfunc *res = NULL;
834 :
835 18 : FUNC_TYPE_STR(type, F, objstr);
836 0 : (void) F; /* not used */
837 :
838 18 : search_object_on_path(res = os_resolve_function_with_undefined_parameters_internal(sql, next->funcs, name, ops, type, private), functions_without_schema, sql_resolve_function_with_undefined_parameters_extra, SQLSTATE(42000));
839 : return res;
840 : }
841 :
842 : static list *
843 59192 : sql_find_funcs_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private)
844 : {
845 59192 : sql_subfunc *fres;
846 59192 : int key = hash_key(fname);
847 59192 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
848 59192 : list *res = NULL;
849 :
850 59192 : if (ff) {
851 59192 : if (ff->ht) {
852 236551 : for (sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)]; he; he = he->chain) {
853 177359 : sql_func *f = he->value;
854 :
855 177359 : if ((f->type != type && f->type != filt) || (f->private && !private))
856 108706 : continue;
857 68653 : if ((fres = func_cmp(sql->sa, f, fname, nrargs )) != NULL) {
858 60854 : if (!res)
859 55544 : res = sa_list(sql->sa);
860 60854 : list_append(res, fres);
861 : }
862 : }
863 : } else {
864 0 : node *n;
865 0 : sql_base_loop( ff, n) {
866 0 : sql_func *f = n->data;
867 :
868 0 : if ((f->type != type && f->type != filt) || (f->private && !private))
869 0 : continue;
870 0 : if ((fres = func_cmp(sql->sa, f, fname, nrargs )) != NULL) {
871 0 : if (!res)
872 0 : res = sa_list(sql->sa);
873 0 : list_append(res, fres);
874 : }
875 : }
876 : }
877 : }
878 59192 : return res;
879 : }
880 :
881 : static list *
882 3963 : os_find_funcs_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private)
883 : {
884 3963 : sql_subfunc *fres;
885 3963 : sql_ftype filt = (type == F_FUNC)?F_FILT:type;
886 3963 : list *res = NULL;
887 :
888 3963 : if (ff) {
889 3963 : struct os_iter oi;
890 3963 : os_iterator(&oi, ff, sql->session->tr, fname);
891 10016 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
892 6053 : sql_func *f = (sql_func*)b;
893 :
894 6053 : if ((f->type != type && f->type != filt) || (f->private && !private))
895 47 : continue;
896 6006 : if ((fres = func_cmp(sql->sa, f, fname, nrargs )) != NULL) {
897 4045 : if (!res)
898 3630 : res = sa_list(sql->sa);
899 4045 : list_append(res, fres);
900 : }
901 : }
902 : }
903 3963 : return res;
904 : }
905 :
906 : #define sql_find_funcs_extra \
907 : do { \
908 : if (!res && (res = sql_find_funcs_internal(sql, funcs, name, nrargs, type, private))) /* search system wide functions first */ \
909 : return res; \
910 : } while (0)
911 :
912 : list *
913 59194 : sql_find_funcs(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private)
914 : {
915 59194 : char *F = NULL, *objstr = NULL;
916 59194 : const char *error = "CATALOG";
917 59194 : list *res = NULL;
918 :
919 59194 : FUNC_TYPE_STR(type, F, objstr);
920 679 : (void) F; /* not used */
921 :
922 59224 : search_object_on_path(res = os_find_funcs_internal(sql, next->funcs, name, nrargs, type, private), functions_without_schema, sql_find_funcs_extra, SQLSTATE(42000));
923 : return res;
924 : }
925 :
926 : static list *
927 5217 : sql_find_funcs_by_name_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private)
928 : {
929 5217 : int key = hash_key(fname);
930 5217 : list *res = NULL;
931 :
932 5217 : if (ff) {
933 5217 : if (ff->ht) {
934 26434 : for (sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)]; he; he = he->chain) {
935 21217 : sql_func *f = he->value;
936 :
937 21217 : if (f->type != type || (f->private && !private))
938 15565 : continue;
939 5652 : if (strcmp(f->base.name, fname) == 0) {
940 0 : if (!res)
941 0 : res = sa_list(sql->sa);
942 0 : list_append(res, f);
943 : }
944 : }
945 : } else {
946 0 : node *n;
947 0 : sql_base_loop( ff, n) {
948 0 : sql_func *f = n->data;
949 :
950 0 : if (f->type != type || (f->private && !private))
951 0 : continue;
952 0 : if (strcmp(f->base.name, fname) == 0) {
953 0 : if (!res)
954 0 : res = sa_list(sql->sa);
955 0 : list_append(res, f);
956 : }
957 : }
958 : }
959 : }
960 5217 : return res;
961 : }
962 :
963 : static list *
964 9219 : os_find_funcs_by_name_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private)
965 : {
966 9219 : list *res = NULL;
967 :
968 9219 : if (ff) {
969 9219 : struct os_iter oi;
970 9219 : os_iterator(&oi, ff, sql->session->tr, fname);
971 14935 : for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
972 5716 : sql_func *f = (sql_func*)b;
973 :
974 5716 : if (f->type != type || (f->private && !private))
975 1346 : continue;
976 4370 : if (strcmp(f->base.name, fname) == 0) {
977 4370 : if (!res)
978 4342 : res = sa_list(sql->sa);
979 4370 : list_append(res, f);
980 : }
981 : }
982 : }
983 9219 : return res;
984 : }
985 :
986 : #define sql_find_funcs_by_name_extra \
987 : do { \
988 : if (!res && (res = sql_find_funcs_by_name_internal(sql, funcs, name, type, private))) /* search system wide functions first */ \
989 : return res; \
990 : } while (0)
991 :
992 : list *
993 5686 : sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private)
994 : {
995 5686 : char *F = NULL, *objstr = NULL;
996 5686 : const char *error = "CATALOG";
997 5686 : list *res = NULL;
998 :
999 5686 : FUNC_TYPE_STR(type, F, objstr);
1000 1303 : (void) F; /* not used */
1001 :
1002 6362 : 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));
1003 : return res;
1004 : }
1005 :
1006 : char *
1007 1935196 : qname_schema(dlist *qname)
1008 : {
1009 1935196 : assert(qname && qname->h);
1010 :
1011 1935196 : if (dlist_length(qname) == 2) {
1012 1088187 : return qname->h->data.sval;
1013 847008 : } else if (dlist_length(qname) == 3) {
1014 4 : return qname->h->next->data.sval;
1015 : }
1016 : return NULL;
1017 : }
1018 :
1019 : char *
1020 1947768 : qname_schema_object(dlist *qname)
1021 : {
1022 1947768 : assert(qname && qname->h);
1023 :
1024 1947768 : if (dlist_length(qname) == 1) {
1025 859440 : return qname->h->data.sval;
1026 1088328 : } else if (dlist_length(qname) == 2) {
1027 1088324 : return qname->h->next->data.sval;
1028 4 : } else if (dlist_length(qname) == 3) {
1029 4 : return qname->h->next->next->data.sval;
1030 : }
1031 : return "unknown";
1032 : }
1033 :
1034 : char *
1035 0 : qname_catalog(dlist *qname)
1036 : {
1037 0 : assert(qname && qname->h);
1038 :
1039 0 : if (dlist_length(qname) == 3) {
1040 0 : return qname->h->data.sval;
1041 : }
1042 : return NULL;
1043 : }
1044 :
1045 : int
1046 1558 : set_type_param(mvc *sql, sql_subtype *type, int nr)
1047 : {
1048 1558 : sql_arg *a = sql_bind_paramnr(sql, nr);
1049 :
1050 1558 : if (!a)
1051 : return -1;
1052 1558 : a->type = *type;
1053 1558 : return 0;
1054 : }
1055 :
1056 : /*
1057 : * Find the result_datatype for certain combinations of values
1058 : * (like case expressions or coumns in a result of a query expression).
1059 : * See standaard pages 505-507 Result of data type combinations */
1060 : sql_subtype *
1061 317790 : result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
1062 : {
1063 317790 : int lclass = l->type->eclass, rclass = r->type->eclass;
1064 :
1065 : /* case a strings */
1066 480139 : if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
1067 162349 : char *tpe = "varchar";
1068 162349 : unsigned int digits = 0;
1069 162349 : if (!EC_VARCHAR(lclass)) {
1070 3803 : tpe = r->type->base.name;
1071 3803 : digits = (!l->digits)?0:r->digits;
1072 158546 : } else if (!EC_VARCHAR(rclass)) {
1073 6130 : tpe = l->type->base.name;
1074 6130 : digits = (!r->digits)?0:l->digits;
1075 : } else { /* both */
1076 152416 : tpe = !strcmp(l->type->base.name, "clob")?l->type->base.name:!strcmp(r->type->base.name, "clob")?r->type->base.name:
1077 122527 : (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1078 152416 : digits = (!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
1079 : }
1080 162349 : sql_find_subtype(super, tpe, digits, 0);
1081 : /* case b blob */
1082 155441 : } else if (lclass == EC_BLOB || rclass == EC_BLOB) {
1083 15 : *super = (lclass == EC_BLOB) ? *l : *r;
1084 : /* case c all exact numeric */
1085 273016 : } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
1086 117590 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1087 117590 : unsigned int digits = sql_max(l->digits, r->digits);
1088 117590 : unsigned int scale = sql_max(l->scale, r->scale);
1089 :
1090 117590 : if (l->type->radix == 10 && r->type->radix == 10) {
1091 97 : digits = scale + (sql_max(l->digits - l->scale, r->digits - r->scale));
1092 : #ifdef HAVE_HGE
1093 97 : if (digits > 38) {
1094 0 : digits = 38;
1095 : #else
1096 : if (digits > 18) {
1097 : digits = 18;
1098 : #endif
1099 0 : scale = MIN(scale, digits - 1);
1100 : }
1101 117493 : } else if (l->type->radix == 2 && r->type->radix == 10) { /* change to radix 10 */
1102 47 : digits = bits2digits(l->type->digits);
1103 47 : digits = sql_max(r->digits, digits);
1104 47 : scale = r->scale;
1105 117446 : } else if (l->type->radix == 10 && r->type->radix == 2) { /* change to radix 10 */
1106 119 : digits = bits2digits(r->type->digits);
1107 119 : digits = sql_max(l->digits, digits);
1108 119 : scale = l->scale;
1109 : }
1110 117590 : sql_find_subtype(super, tpe, digits, scale);
1111 : /* case d approximate numeric */
1112 37836 : } else if (EC_APPNUM(lclass) || EC_APPNUM(rclass)) {
1113 152 : if (!EC_APPNUM(lclass)) {
1114 45 : *super = *r;
1115 107 : } else if (!EC_APPNUM(rclass)) {
1116 86 : *super = *l;
1117 : } else { /* both */
1118 21 : char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
1119 21 : unsigned int digits = sql_max(l->digits, r->digits); /* bits precision */
1120 21 : sql_find_subtype(super, tpe, digits, 0);
1121 : }
1122 : /* now its getting serious, ie e any 'case e' datetime data type */
1123 : /* 'case f' interval types */
1124 : /* 'case g' boolean */
1125 : /* 'case h-l' compounds like row (tuple), etc */
1126 : } else {
1127 37684 : return supertype(super, l, r);
1128 : }
1129 : return super;
1130 : }
1131 :
1132 : sql_subtype *
1133 829673 : supertype(sql_subtype *super, sql_subtype *r, sql_subtype *i)
1134 : {
1135 : /* first find super type */
1136 829673 : char *tpe = r->type->base.name;
1137 829673 : unsigned int radix = (unsigned int) r->type->radix;
1138 829673 : unsigned int digits = 0;
1139 829673 : unsigned int idigits = i->digits;
1140 829673 : unsigned int rdigits = r->digits;
1141 829673 : unsigned int scale = sql_max(i->scale, r->scale);
1142 829673 : sql_class eclass = r->type->eclass;
1143 829673 : sql_subtype lsuper;
1144 :
1145 829673 : lsuper = *r;
1146 : /* EC_STRING class is superior to EC_CHAR */
1147 829673 : if (EC_VARCHAR(i->type->eclass) && EC_VARCHAR(r->type->eclass)) {
1148 294470 : if (!strcmp(i->type->base.name, "clob") || !strcmp(r->type->base.name, "clob")) {
1149 9977 : lsuper = !strcmp(i->type->base.name, "clob") ? *i : *r;
1150 9977 : radix = lsuper.type->radix;
1151 9977 : tpe = lsuper.type->base.name;
1152 9977 : eclass = lsuper.type->eclass;
1153 : } else {
1154 284493 : lsuper = i->type->base.id > r->type->base.id ? *i : *r;
1155 284493 : radix = lsuper.type->radix;
1156 284493 : tpe = lsuper.type->base.name;
1157 284493 : eclass = lsuper.type->eclass;
1158 : }
1159 535203 : } else if (i->type->base.id > r->type->base.id || (EC_VARCHAR(i->type->eclass) && !EC_VARCHAR(r->type->eclass))) {
1160 320870 : lsuper = *i;
1161 320870 : radix = i->type->radix;
1162 320870 : tpe = i->type->base.name;
1163 320870 : eclass = i->type->eclass;
1164 : }
1165 829673 : if (!EC_SCALE(lsuper.type->eclass))
1166 829673 : scale = 0; /* reset scale for types without it */
1167 829673 : if (!lsuper.type->localtype) {
1168 60 : tpe = "smallint";
1169 60 : eclass = EC_NUM;
1170 : }
1171 : /*
1172 : * In case of different radix we should change one.
1173 : */
1174 829673 : if (i->type->radix != r->type->radix) {
1175 27159 : if (radix == 10 || radix == 0 /* strings */) {
1176 : /* change to radix 10 */
1177 6665 : if (i->type->radix == 2)
1178 1268 : idigits = bits2digits(idigits);
1179 6665 : if (r->type->radix == 2)
1180 4793 : rdigits = bits2digits(rdigits);
1181 20494 : } else if (radix == 2) { /* change to radix 2 */
1182 20494 : if (i->type->radix == 10)
1183 190 : idigits = digits2bits(idigits);
1184 20494 : if (r->type->radix == 10)
1185 822 : rdigits = digits2bits(rdigits);
1186 : }
1187 : }
1188 : /* handle OID horror */
1189 829673 : if (i->type->radix == r->type->radix && i->type->base.id < r->type->base.id && strcmp(i->type->base.name, "oid") == 0) {
1190 829673 : tpe = i->type->base.name;
1191 829673 : eclass = EC_POS;
1192 : }
1193 829673 : if (scale == 0 && (idigits == 0 || rdigits == 0)) {
1194 30920 : sql_find_subtype(&lsuper, tpe, 0, 0);
1195 : } else {
1196 : /* for strings use the max of both */
1197 798753 : if (EC_VARCHAR(eclass))
1198 287126 : digits = sql_max(type_digits_to_char_digits(i), type_digits_to_char_digits(r));
1199 : else
1200 511627 : digits = sql_max(idigits - i->scale, rdigits - r->scale);
1201 798753 : sql_find_subtype(&lsuper, tpe, digits+scale, scale);
1202 : }
1203 829673 : *super = lsuper;
1204 829673 : return super;
1205 : }
1206 :
1207 : char *
1208 78 : toUpperCopy(char *dest, const char *src)
1209 : {
1210 78 : size_t i, len;
1211 :
1212 78 : if (src == NULL) {
1213 0 : *dest = '\0';
1214 0 : return(dest);
1215 : }
1216 :
1217 78 : len = _strlen(src);
1218 410 : for (i = 0; i < len; i++)
1219 332 : dest[i] = (char)toupper((int)src[i]);
1220 :
1221 78 : dest[i] = '\0';
1222 78 : return(dest);
1223 : }
1224 :
1225 : static char * _symbol2string(mvc *sql, symbol *se, int expression, char **err);
1226 :
1227 : static char *
1228 1 : dlist2string(mvc *sql, dlist *l, int expression, char **err)
1229 : {
1230 1 : char *b = NULL;
1231 1 : dnode *n;
1232 :
1233 3 : for (n=l->h; n; n = n->next) {
1234 2 : char *s = NULL;
1235 :
1236 2 : if (n->type == type_string && n->data.sval)
1237 2 : s = sa_strdup(sql->ta, n->data.sval);
1238 0 : else if (n->type == type_symbol)
1239 0 : s = _symbol2string(sql, n->data.sym, expression, err);
1240 :
1241 2 : if (!s)
1242 0 : return NULL;
1243 2 : if (b) {
1244 1 : char *o = SA_NEW_ARRAY(sql->ta, char, strlen(b) + strlen(s) + 2);
1245 1 : if (o)
1246 1 : stpcpy(stpcpy(stpcpy(o, b), "."), s);
1247 0 : b = o;
1248 1 : if (b == NULL)
1249 : return NULL;
1250 : } else {
1251 : b = s;
1252 : }
1253 : }
1254 : return b;
1255 : }
1256 :
1257 : static const char *
1258 853 : symbol_escape_ident(sql_allocator *sa, const char *s)
1259 : {
1260 853 : char *res = NULL;
1261 853 : if (s) {
1262 801 : size_t l = strlen(s);
1263 801 : char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
1264 :
1265 801 : res = r;
1266 5960 : while (*s) {
1267 5159 : if (*s == '"')
1268 1 : *r++ = '"';
1269 5159 : *r++ = *s++;
1270 : }
1271 801 : *r = '\0';
1272 : }
1273 853 : return res;
1274 : }
1275 :
1276 : char *
1277 1563 : _symbol2string(mvc *sql, symbol *se, int expression, char **err)
1278 : {
1279 : /* inner symbol2string uses the temporary allocator */
1280 1563 : switch (se->token) {
1281 3 : case SQL_NOP: {
1282 3 : dnode *lst = se->data.lval->h, *ops = lst->next->next->data.lval->h, *aux;
1283 3 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1284 3 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1285 3 : int i = 0, nargs = 0;
1286 3 : char** inputs = NULL, *res;
1287 3 : size_t inputs_length = 0, extra = sname ? strlen(sname) + 3 : 0;
1288 :
1289 12 : for (aux = ops; aux; aux = aux->next)
1290 9 : nargs++;
1291 3 : if (!(inputs = SA_ZNEW_ARRAY(sql->ta, char*, nargs)))
1292 : return NULL;
1293 :
1294 12 : for (aux = ops; aux; aux = aux->next) {
1295 9 : if (!(inputs[i] = _symbol2string(sql, aux->data.sym, expression, err))) {
1296 : return NULL;
1297 : }
1298 9 : inputs_length += strlen(inputs[i]);
1299 9 : i++;
1300 : }
1301 :
1302 6 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + inputs_length + 3 + (nargs - 1 /* commas */) + 2))) {
1303 3 : char *concat = res;
1304 3 : if (sname)
1305 3 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1306 3 : concat = stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"(");
1307 3 : i = 0;
1308 12 : for (aux = ops; aux; aux = aux->next) {
1309 9 : concat = stpcpy(concat, inputs[i]);
1310 9 : if (aux->next)
1311 6 : concat = stpcpy(concat, ",");
1312 9 : i++;
1313 : }
1314 3 : concat = stpcpy(concat, ")");
1315 : }
1316 : return res;
1317 : }
1318 22 : case SQL_BINOP: {
1319 22 : dnode *lst = se->data.lval->h;
1320 22 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1321 22 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1322 22 : char *l = NULL, *r = NULL, *res;
1323 22 : size_t extra = sname ? strlen(sname) + 3 : 0;
1324 :
1325 22 : if (!(l = _symbol2string(sql, lst->next->next->data.sym, expression, err)) || !(r = _symbol2string(sql, lst->next->next->next->data.sym, expression, err)))
1326 2 : return NULL;
1327 :
1328 40 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + strlen(r) + 6))) {
1329 20 : char *concat = res;
1330 20 : if (sname)
1331 18 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1332 20 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("), l), ","), r), ")");
1333 : }
1334 : return res;
1335 : }
1336 40 : case SQL_OP: {
1337 40 : dnode *lst = se->data.lval->h;
1338 40 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1339 40 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1340 40 : char *res;
1341 40 : size_t extra = sname ? strlen(sname) + 3 : 0;
1342 :
1343 80 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + 5))) {
1344 40 : char *concat = res;
1345 40 : if (sname)
1346 0 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1347 40 : stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"()");
1348 : }
1349 : return res;
1350 : }
1351 83 : case SQL_UNOP: {
1352 83 : dnode *lst = se->data.lval->h;
1353 83 : const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
1354 83 : *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
1355 83 : char *l = _symbol2string(sql, lst->next->next->data.sym, expression, err), *res;
1356 83 : size_t extra = sname ? strlen(sname) + 3 : 0;
1357 :
1358 83 : if (!l)
1359 : return NULL;
1360 :
1361 164 : if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + strlen(l) + 5))) {
1362 82 : char *concat = res;
1363 82 : if (sname)
1364 74 : concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
1365 82 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("), l), ")");
1366 : }
1367 : return res;
1368 : }
1369 0 : case SQL_PARAMETER:
1370 0 : return sa_strdup(sql->ta, "?");
1371 193 : case SQL_NULL:
1372 193 : return sa_strdup(sql->ta, "NULL");
1373 : case SQL_ATOM:{
1374 921 : AtomNode *an = (AtomNode *) se;
1375 921 : if (an && an->a)
1376 921 : return atom2sql(sql->ta, an->a, sql->timezone);
1377 : else
1378 0 : return sa_strdup(sql->ta, "NULL");
1379 : }
1380 265 : case SQL_NEXT: {
1381 265 : const char *seq = symbol_escape_ident(sql->ta, qname_schema_object(se->data.lval)),
1382 265 : *sname = qname_schema(se->data.lval);
1383 265 : char *res;
1384 :
1385 265 : if (!sname)
1386 200 : sname = sql->session->schema->base.name;
1387 265 : sname = symbol_escape_ident(sql->ta, sname);
1388 :
1389 530 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen("next value for \"") + strlen(sname) + strlen(seq) + 5)))
1390 265 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for \""), sname), "\".\""), seq), "\"");
1391 : return res;
1392 28 : } break;
1393 28 : case SQL_IDENT:
1394 : case SQL_COLUMN: {
1395 : /* can only be variables */
1396 28 : dlist *l = se->data.lval;
1397 28 : assert(l->h->type != type_lng);
1398 28 : if (expression && dlist_length(l) == 1 && l->h->type == type_string) {
1399 : /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */
1400 27 : const char *op = symbol_escape_ident(sql->ta, l->h->data.sval);
1401 27 : char *res;
1402 :
1403 54 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3)))
1404 27 : stpcpy(stpcpy(stpcpy(res, "\""), op), "\"");
1405 27 : return res;
1406 0 : } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) {
1407 0 : const char *first = symbol_escape_ident(sql->ta, l->h->data.sval),
1408 0 : *second = symbol_escape_ident(sql->ta, l->h->next->data.sval);
1409 0 : char *res;
1410 :
1411 0 : if (!first || !second)
1412 : return NULL;
1413 0 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(first) + strlen(second) + 6)))
1414 0 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), first), "\".\""), second), "\"");
1415 0 : return res;
1416 : } else {
1417 1 : char *e = dlist2string(sql, l, expression, err);
1418 1 : if (e)
1419 1 : *err = e;
1420 1 : return NULL;
1421 : }
1422 : }
1423 6 : case SQL_CAST: {
1424 6 : dlist *dl = se->data.lval;
1425 6 : char *val = NULL, *tpe = NULL, *res;
1426 :
1427 6 : if (!(val = _symbol2string(sql, dl->h->data.sym, expression, err)) || !(tpe = subtype2string2(sql->ta, &dl->h->next->data.typeval)))
1428 0 : return NULL;
1429 12 : if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(val) + strlen(tpe) + 11)))
1430 6 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "cast("), val), " as "), tpe), ")");
1431 : return res;
1432 : }
1433 2 : default: {
1434 2 : const char *msg = "SQL feature not yet available for expressions and default values: ";
1435 2 : char *tok_str = token2string(se->token);
1436 4 : if ((*err = SA_NEW_ARRAY(sql->ta, char, strlen(msg) + strlen(tok_str) + 1)))
1437 2 : stpcpy(stpcpy(*err, msg), tok_str);
1438 : }
1439 : }
1440 : return NULL;
1441 : }
1442 :
1443 : char *
1444 1423 : symbol2string(mvc *sql, symbol *se, int expression, char **err)
1445 : {
1446 1423 : char *res = _symbol2string(sql, se, expression, err);
1447 :
1448 1423 : if (res)
1449 1420 : res = sa_strdup(sql->sa, res);
1450 1423 : if (*err)
1451 3 : *err = sa_strdup(sql->sa, *err);
1452 1423 : sa_reset(sql->ta);
1453 1423 : return res;
1454 : }
|