LCOV - code coverage report
Current view: top level - sql/server - sql_semantic.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 595 683 87.1 %
Date: 2024-04-26 00:35:57 Functions: 40 41 97.6 %

          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             : }

Generated by: LCOV version 1.14