LCOV - code coverage report
Current view: top level - sql/server - sql_semantic.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 562 650 86.5 %
Date: 2024-12-20 21:24:02 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      384850 : sql_add_param(mvc *sql, const char *name, sql_subtype *st)
      40             : {
      41      384850 :         sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
      42             : 
      43      384850 :         if (name)
      44      383234 :                 a->name = sa_strdup(sql->sa, name);
      45      384850 :         if (st && st->type)
      46      383223 :                 a->type = *st;
      47      384850 :         a->inout = ARG_IN;
      48      384850 :         if (name && strcmp(name, "*") == 0)
      49           4 :                 a->type = *sql_bind_localtype("int");
      50      384850 :         if (!sql->params)
      51      226844 :                 sql->params = sa_list(sql->sa);
      52      384850 :         list_append(sql->params, a);
      53      384850 : }
      54             : 
      55             : int
      56       97095 : sql_bind_param(mvc *sql, const char *name)
      57             : {
      58       97095 :         node *n;
      59       97095 :         int nr = 0;
      60             : 
      61       97095 :         if (sql->params) {
      62      209614 :                 for (n = sql->params->h; n; n = n->next, nr++) {
      63      205231 :                         sql_arg *a = n->data;
      64             : 
      65      205231 :                         if (a->name && strcmp(a->name, name) == 0)
      66       89013 :                                 return nr;
      67             :                 }
      68             :         }
      69             :         return -1;
      70             : }
      71             : 
      72             : sql_arg *
      73       92190 : sql_bind_paramnr(mvc *sql, int nr)
      74             : {
      75       92190 :         int i=0;
      76       92190 :         node *n;
      77             : 
      78       92190 :         if (sql->params && nr < list_length(sql->params)) {
      79      681616 :                 for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
      80             :                         ;
      81             : 
      82       92190 :                 if (n)
      83       92190 :                         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      747501 : sql_destroy_params(mvc *sql)
     101             : {
     102      747501 :         sql->params = NULL;
     103      747501 : }
     104             : 
     105             : sql_schema *
     106     1706033 : cur_schema(mvc *sql)
     107             : {
     108     1706033 :         return sql->session->schema;
     109             : }
     110             : 
     111             : sql_schema *
     112      560866 : tmp_schema(mvc *sql)
     113             : {
     114      560866 :         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, show_error) \
     121             :         do { \
     122             :                 sql_schema *next = NULL; \
     123             :  \
     124             :                 if (sname) { /* user has explicitly typed the schema, so either the object is there or we return error */ \
     125             :                         if (!(next = mvc_bind_schema(sql, sname))) \
     126             :                                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s: no such schema '%s'", error, sname); \
     127             :                         EXTRA_CONDITION(EXTRA); /* for functions without schema, 'sys' is a valid schema to bind them */ \
     128             :                         if (!res) { \
     129             :                                 CALL; \
     130             :                         } \
     131             :                 } else { \
     132             :                         sql_schema *cur = cur_schema(sql); \
     133             :                         char *session_schema = cur->base.name; \
     134             :  \
     135             :                         EXTRA; \
     136             :                         if (!res && !sql->schema_path_has_tmp && strcmp(session_schema, "tmp") != 0) { /* if 'tmp' is not in the search path, search it before all others */ \
     137             :                                 next = tmp_schema(sql); \
     138             :                                 CALL; \
     139             :                         } \
     140             :                         if (!res) { /* then current session's schema */ \
     141             :                                 next = cur; \
     142             :                                 CALL; \
     143             :                         } \
     144             :                         if (!res) { \
     145             :                                 /* object not found yet, look inside search path */ \
     146             :                                 for (node *n = sql->schema_path->h ; n && !res ; n = n->next) { \
     147             :                                         str p = (str) n->data; \
     148             :                                         if (strcmp(session_schema, p) != 0 && (next = mvc_bind_schema(sql, p))) \
     149             :                                                 CALL; \
     150             :                                 } \
     151             :                         } \
     152             :                         if (!res && !sql->schema_path_has_sys && strcmp(session_schema, "sys") != 0) { /* if 'sys' is not in the current path search it next */ \
     153             :                                 next = mvc_bind_schema(sql, "sys"); \
     154             :                                 CALL; \
     155             :                         } \
     156             :                 } \
     157             :                 if (!res && show_error) \
     158             :                         return sql_error(sql, ERR_NOTFOUND, ERROR_CODE "%s: no such %s %s%s%s'%s'", error, objstr, sname ? "'":"", sname ? sname : "", sname ? "'.":"", name); \
     159             :         } while (0)
     160             : 
     161             : #define table_extra \
     162             :         do { \
     163             :                 if (s) { \
     164             :                         next = s; /* there's a default schema to search before all others, e.g. bind a child table from a merge table */ \
     165             :                         res = mvc_bind_table(sql, next, name); \
     166             :                 } \
     167             :                 if (!res && strcmp(objstr, "table") == 0 && (res = stack_find_table(sql, name))) /* for tables, first try a declared table from the stack */ \
     168             :                         return res; \
     169             :         } while (0)
     170             : 
     171             : sql_table *
     172      684804 : find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *name, const char *error, bool isView)
     173             : {
     174      684804 :         const char *objstr = isView ? "view" : "table";
     175      684804 :         sql_table *res = NULL;
     176             : 
     177      685369 :         search_object_on_path(res = mvc_bind_table(sql, next, name), DO_NOTHING, table_extra, SQLSTATE(42S02), true);
     178             :         return res;
     179             : }
     180             : 
     181             : sql_sequence *
     182        1480 : find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
     183             : {
     184        1480 :         const char objstr[] = "sequence";
     185        1480 :         sql_sequence *res = NULL;
     186             : 
     187        1482 :         search_object_on_path(res = find_sql_sequence(sql->session->tr, next, name), DO_NOTHING, ;, SQLSTATE(42000), true);
     188             :         return res;
     189             : }
     190             : 
     191             : sql_idx *
     192         218 : find_idx_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
     193             : {
     194         218 :         const char objstr[] = "index";
     195         218 :         sql_idx *res = NULL;
     196             : 
     197         292 :         search_object_on_path(res = mvc_bind_idx(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S12), true);
     198             :         return res;
     199             : }
     200             : 
     201             : sql_type *
     202           5 : find_type_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
     203             : {
     204           5 :         const char objstr[] = "type";
     205           5 :         sql_type *res = NULL;
     206             : 
     207           7 :         search_object_on_path(res = schema_bind_type(sql, next, name), DO_NOTHING, ;, SQLSTATE(42S01), true);
     208             :         return res;
     209             : }
     210             : 
     211             : sql_trigger *
     212          96 : find_trigger_on_scope(mvc *sql, const char *sname, const char *name, const char *error)
     213             : {
     214          96 :         const char objstr[] = "trigger";
     215          96 :         sql_trigger *res = NULL;
     216             : 
     217         118 :         search_object_on_path(res = mvc_bind_trigger(sql, next, name), DO_NOTHING, ;, SQLSTATE(3F000), true);
     218             :         return res;
     219             : }
     220             : 
     221             : /* A variable can be any of the following, from the innermost to the outermost:
     222             :         - 'parameter of the function' (ie in the param list)
     223             :         - local variable, declared earlier
     224             :         - global variable, also declared earlier
     225             : */
     226             : #define variable_extra \
     227             :         do { \
     228             :                 if (!res) { \
     229             :                         if ((*var = stack_find_var_frame(sql, name, level))) { /* check if variable is known from the stack */ \
     230             :                                 *tpe = &((*var)->var.tpe); \
     231             :                                 res = true; \
     232             :                         } else if ((nr = sql_bind_param(sql, name)) >= 0) { /* then if it is a parameter */ \
     233             :                                 *a = sql_bind_paramnr(sql, nr); \
     234             :                                 *tpe = &((*a)->type); \
     235             :                                 *level = 1; \
     236             :                                 res = true; \
     237             :                         } \
     238             :                 } \
     239             :         } while (0)
     240             : 
     241             : #define var_find_on_global \
     242             :         do { \
     243             :                 if ((*var = find_global_var(sql, next, name))) { /* then if it is a global var */ \
     244             :                         *tpe = &((*var)->var.tpe); \
     245             :                         *level = 0; \
     246             :                         res = true; \
     247             :                 } \
     248             :         } while (0)
     249             : 
     250             : bool
     251      205693 : find_variable_on_scope(mvc *sql, const char *sname, const char *name, sql_var **var, sql_arg **a, sql_subtype **tpe, int *level, const char *error)
     252             : {
     253      205693 :         const char objstr[] = "variable";
     254      205693 :         bool res = false;
     255      205693 :         int nr = 0;
     256             : 
     257      205693 :         (void)nr;
     258      210740 :         search_object_on_path(var_find_on_global, DO_NOTHING, variable_extra, SQLSTATE(42000), true);
     259             :         return res;
     260             : }
     261             : 
     262             : static sql_subfunc *
     263      949490 : _dup_subaggr(allocator *sa, sql_func *a, sql_subtype *member)
     264             : {
     265      949490 :         node *tn;
     266      949490 :         unsigned int scale = 0, digits = 0;
     267      949490 :         sql_subfunc *ares = SA_ZNEW(sa, sql_subfunc);
     268             : 
     269             : 
     270      949651 :         ares->func = a;
     271      949651 :         if (IS_FILT(a)) {
     272        4779 :                 ares->res = sa_list(sa);
     273        4779 :         list_append(ares->res, sql_bind_localtype("bit"));
     274      944872 :         } else if (IS_FUNC(a) || IS_UNION(a) || IS_ANALYTIC(a) || IS_AGGR(a)) { /* not needed for PROC */
     275      940013 :                 if (a->res) {
     276      940013 :                         ares->res = sa_list(sa);
     277     1964569 :                         for(tn = a->res->h; tn; tn = tn->next) {
     278     1024524 :                                 sql_arg *rarg = tn->data;
     279     1024524 :                                 sql_subtype *res, *r = &rarg->type;
     280             : 
     281     1024524 :                                 if (a->fix_scale == SCALE_EQ && !IS_AGGR(a)) {
     282             :                                         res = r;
     283             :                                 } else {
     284      849043 :                                         digits = r->digits;
     285      849043 :                                         scale = r->scale;
     286             :                                         /* same scale as the input */
     287      849043 :                                         if (member && (member->scale != scale ||
     288      177909 :                                                                 (digits != member->digits && !EC_NUMBER(member->type->eclass)))) {
     289       91690 :                                                 if (member->digits > digits)
     290             :                                                         digits = member->digits;
     291             :                                                 scale = member->scale;
     292             :                                         }
     293             :                                         /* same type as the input */
     294      849043 :                                         if (r->type->eclass == EC_ANY && member) {
     295       13155 :                                                 r = member;
     296       13155 :                                                 digits = member->digits;
     297             :                                         }
     298      849043 :                                         if (!EC_SCALE(r->type->eclass))
     299      849043 :                                                 scale = 0;
     300      849043 :                                         res = sql_create_subtype(sa, r->type, digits, scale);
     301             :                                 }
     302     1024596 :                                 list_append(ares->res, res);
     303             :                         }
     304             :                 }
     305             :         }
     306      949683 :         return ares;
     307             : }
     308             : 
     309             : 
     310             : 
     311             : static sql_subfunc *
     312      133592 : func_cmp(allocator *sa, sql_func *f, const char *name, int nrargs)
     313             : {
     314      133592 :         if (strcmp(f->base.name, name) == 0) {
     315      133592 :                 if (f->vararg)
     316             :                         //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
     317           2 :                         return _dup_subaggr(sa, f, NULL);
     318      133590 :                 if (nrargs < 0 || list_length(f->ops) == nrargs)
     319             :                         //return (f->type == F_AGGR) ? _dup_subaggr(sa, f, NULL) : sql_dup_subfunc(sa, f, NULL, NULL);
     320      132809 :                         return _dup_subaggr(sa, f, NULL);
     321             :         }
     322             :         return NULL;
     323             : }
     324             : 
     325             : static sql_subfunc *
     326      654389 : sql_find_func_internal(mvc *sql, list *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
     327             : {
     328      654389 :         int key = hash_key(fname);
     329      654389 :         sql_subfunc *res = NULL;
     330      654389 :         int found = 0;
     331      654389 :         sql_ftype filt = (type == F_FUNC)?F_FILT:type;
     332             : 
     333      654389 :         if (ff) {
     334      654389 :                 if (ff->ht) {
     335      654389 :                         sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
     336      654389 :                         if (prev) {
     337           0 :                                 for (; he && !found; he = he->chain)
     338           0 :                                         if (he->value == prev->func)
     339           0 :                                                 found = 1;
     340             :                         }
     341     7803351 :                         for (; he; he = he->chain) {
     342     7272164 :                                 sql_func *f = he->value;
     343             : 
     344     7272164 :                                 if ((f->type != type && f->type != filt) || (f->private && !private))
     345     7148947 :                                         continue;
     346      123217 :                                 if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
     347      123202 :                                         return res;
     348             :                         }
     349             :                 } else {
     350           0 :                         node *n = ff->h;
     351           0 :                         if (prev) {
     352           0 :                                 for (; n && !found; n = n->next)
     353           0 :                                         if (n->data == prev->func)
     354           0 :                                                 found = 1;
     355             :                         }
     356           0 :                         for (; n; n = n->next) {
     357           0 :                                 sql_func *f = n->data;
     358             : 
     359           0 :                                 if ((f->type != type && f->type != filt) || (f->private && !private))
     360           0 :                                         continue;
     361           0 :                                 if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
     362           0 :                                         return res;
     363             :                         }
     364             :                 }
     365             :         }
     366             :         return res;
     367             : }
     368             : 
     369             : static sql_subfunc *
     370      779363 : os_find_func_internal(mvc *sql, struct objectset *ff, const char *fname, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
     371             : {
     372      779363 :         sql_subfunc *res = NULL;
     373      779363 :         sql_ftype filt = (type == F_FUNC)?F_FILT:type;
     374             : 
     375      779363 :         if (ff) {
     376      779363 :                 struct os_iter oi;
     377      779363 :                 os_iterator(&oi, ff, sql->session->tr, fname);
     378      876417 :                 for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     379      106663 :                         sql_func *f = (sql_func*)b;
     380      106663 :                         if (prev && prev->func != f) {
     381           0 :                                 continue;
     382      106663 :                         } else if (prev) {
     383           0 :                                 prev = NULL;
     384           0 :                                 continue;
     385             :                         }
     386             : 
     387      106663 :                         if ((f->type != type && f->type != filt) || (f->private && !private))
     388       96288 :                                 continue;
     389       10375 :                         if ((res = func_cmp(sql->sa, f, fname, nrargs)) != NULL)
     390        9609 :                                 return res;
     391             :                 }
     392             :         }
     393             :         return res;
     394             : }
     395             : 
     396             : #define functions_without_schema(X) if (strcmp(sname, "sys") == 0) X
     397             : 
     398             : #define find_func_extra \
     399             :         do { \
     400             :                 if (!res && (res = sql_find_func_internal(sql, funcs, name, nrargs, type, private, prev))) /* search system wide functions first */ \
     401             :                         return res; \
     402             :         } while (0)
     403             : 
     404             : sql_subfunc *
     405      655088 : sql_find_func(mvc *sql, const char *sname, const char *name, int nrargs, sql_ftype type, bool private, sql_subfunc *prev)
     406             : {
     407      655088 :         char *F = NULL, *objstr = NULL;
     408      655088 :         const char error[] = "CATALOG";
     409      655088 :         sql_subfunc *res = NULL;
     410             : 
     411      655088 :         FUNC_TYPE_STR(type, F, objstr);
     412      655088 :         (void) F; /* not used */
     413             : 
     414      655088 :         assert(nrargs >= -1);
     415             : 
     416      886483 :         search_object_on_path(res = os_find_func_internal(sql, next->funcs, name, nrargs, type, private, prev), functions_without_schema, find_func_extra, "", false); //SQLSTATE(42000), true);
     417             :         return res;
     418             : }
     419             : 
     420             : sql_subfunc *
     421      375141 : sql_bind_func(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_ftype type, bool private, bool exact)
     422             : {
     423      375141 :         list *l = sa_list(sql->sa);
     424             : 
     425      375286 :         if (tp1)
     426      365088 :                 list_append(l, tp1);
     427      375324 :         if (tp2)
     428      216982 :                 list_append(l, tp2);
     429      375324 :         return sql_bind_func_(sql, sname, fname, l, type, private, exact);
     430             : }
     431             : 
     432             : sql_subfunc *
     433         175 : sql_bind_func3(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_subtype *tp3, sql_ftype type, bool private)
     434             : {
     435         175 :         list *l = sa_list(sql->sa);
     436             : 
     437         175 :         if (tp1)
     438         175 :                 list_append(l, tp1);
     439         175 :         if (tp2)
     440         175 :                 list_append(l, tp2);
     441         175 :         if (tp3)
     442         175 :                 list_append(l, tp3);
     443         175 :         return sql_bind_func_(sql, sname, fname, l, type, private, false);
     444             : }
     445             : 
     446             : static int /* bind the function version with more identical type matches */
     447      747433 : next_cand_points(list *args, list *ops)
     448             : {
     449      747433 :         int res = 0;
     450             : 
     451      747433 :         if (!list_empty(args) && !list_empty(ops))
     452     1975932 :         for (node *n = args->h, *m = ops->h; n && m ; n = n->next, m = m->next) {
     453     1249229 :                 sql_arg *a = n->data;
     454     1249229 :                 sql_subtype *t = m->data;
     455             : 
     456     1249229 :                 if (a->type.type->eclass == EC_ANY)
     457      636164 :                         res += 100;
     458      613065 :                 else if (t)
     459      613065 :                         res += a->type.type->base.id == t->type->base.id;
     460             :         }
     461      747866 :         res += (list_empty(args) && list_empty(ops));
     462      747873 :         return res;
     463             : }
     464             : 
     465             : static int
     466     8078693 : score_func( sql_func *f, list *tl, bool exact, bool *downcast)
     467             : {
     468     8078693 :         int score = 0;
     469     8078693 :         node *n, *m;
     470             : 
     471     8078693 :         if (exact)
     472      706856 :                 return next_cand_points(f->ops, tl);
     473     7371837 :         if (!tl)
     474             :                 return 1;
     475     7371837 :         if (f->vararg)
     476             :                 return 1;
     477     7371455 :         unsigned int digits = 0, scale = 0;
     478     7371455 :         if (f->fix_scale == SCALE_FIX) {
     479     3121906 :                 for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
     480     2079667 :                         sql_subtype *t = m->data;
     481             : 
     482     2079667 :                         if (!t)
     483          51 :                                 continue;
     484     2079616 :                         if (t->type->eclass == EC_DEC) {
     485        8142 :                                 if (digits < t->digits)
     486             :                                         digits = t->digits;
     487        8142 :                                 if (scale < t->scale)
     488             :                                         scale = t->scale;
     489             :                         }
     490             :                 }
     491     3121906 :                 for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
     492     2079667 :                         sql_arg *a = n->data;
     493     2079667 :                         sql_subtype *t = m->data;
     494             : 
     495     2079667 :                         if (!t)
     496          51 :                                 continue;
     497     2079616 :                         if (a->type.type->eclass == EC_DEC && t->type->eclass == EC_NUM) {
     498     1149405 :                                 if (digits < scale + bits2digits(t->digits))
     499      809940 :                                         digits = scale + bits2digits(t->digits);
     500             :                         }
     501             :                 }
     502             :         }
     503     7371455 :         int nr_strconverts = 0;
     504    16283046 :         for (n = f->ops->h, m = tl->h; n && m; n = n->next, m = m->next) {
     505    11701396 :                 sql_arg *a = n->data;
     506    11701396 :                 sql_subtype *t = m->data;
     507             : 
     508    11701396 :                 if (!t) { /* parameters */
     509         502 :                         int ec = a->type.type->eclass;
     510         502 :                         score++;
     511         502 :                         if (ec == EC_DEC)
     512             :                                 return 0;
     513         326 :                         if (a && EC_NUMBER(ec) && !EC_INTERVAL(ec))
     514         218 :                                 score += a->type.type->localtype * 10; /* premium on larger types */
     515         108 :                         else if (a) /* all other types */
     516         108 :                                 score += 99;
     517         326 :                         continue;
     518             :                 }
     519             : 
     520    11700894 :                 int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
     521             :                 /* EX_EXTERNAL can only convert between equal implementation types */
     522    11700894 :                 if (nscore == 0 &&
     523     2588178 :                         t->type->eclass == a->type.type->eclass &&
     524         571 :                         t->type->eclass == EC_EXTERNAL &&
     525         571 :                         t->type->localtype == a->type.type->localtype)
     526             :                                 nscore = 10;
     527     9113278 :                 if (nscore &&
     528     9113278 :                         t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC &&
     529     3420640 :                         t->type->localtype > a->type.type->localtype)
     530      708628 :                         *downcast = true;
     531     9113278 :                 if (nscore == 0)
     532             :                         return 0;
     533     9113278 :                 nscore *= 100; /* first based on preferred conversions */
     534     9113278 :                 if (nscore < 0) {
     535      292511 :                         *downcast = true;
     536      292511 :                         nscore = -nscore;
     537             :                 }
     538     9113278 :                 score += nscore;
     539     9113278 :                 if (EC_VARCHAR(t->type->eclass) && EC_NUMBER(a->type.type->eclass))
     540        1227 :                         nr_strconverts++;
     541     9113278 :                 if (nr_strconverts > 1)
     542             :                         return 0;
     543             : 
     544     9113242 :                 if (f->fix_scale == SCALE_FIX && a->type.type->eclass == EC_DEC && digits > a->type.type->digits) /* doesn't fit */
     545             :                         return 0;
     546             :                 /* sql types equal but implementation differences */
     547     8911265 :                 else if (t->type->eclass == EC_BIT && a->type.type->eclass == EC_NUM && t->type->localtype <= a->type.type->localtype) /* convert bits into smallest number */
     548         146 :                         score += (11 + t->type->localtype - a->type.type->localtype) * 8;
     549             :                 /* sql types close but digits/scale diffs */
     550     8911119 :                 else if (t->type->eclass == EC_NUM && a->type.type->eclass == EC_DEC && /*t->type->localtype <= a->type.type->localtype*/ bits2digits(t->digits) < a->type.type->digits)
     551             :                         //score += (10 + t->type->localtype - a->type.type->localtype) * 8;
     552     2507282 :                         score += (38 + bits2digits(t->digits) - a->type.type->digits);
     553             :                 /* same class over converting to other class */
     554     6403837 :                 else if (t->type->eclass == a->type.type->eclass && t->type->localtype <= a->type.type->localtype) {
     555     3406227 :                         score += (11 + t->type->localtype - a->type.type->localtype) * 4;
     556             :                         /* handle intervals (day, hour, minutes, second) mapped
     557             :                          * within same eclass and implementation type. */
     558     3406227 :                         if (t->type->eclass == a->type.type->eclass && t->type->eclass == EC_SEC)
     559        3088 :                                 score += ((t->type->digits > 4 && a->type.type->digits > 4) ||
     560        3467 :                                           (t->type->digits <= 4 && a->type.type->digits <= 4)) * 4;
     561             :                 }
     562             :                 /* conversion matrix needs check if conversion is possible */
     563     2997610 :                 else if (t->type->eclass == a->type.type->eclass) {
     564     1103267 :                                 if (t->type->localtype <= a->type.type->localtype) {
     565           0 :                                         int nscore = sql_type_convert_preference(t->type->eclass, a->type.type->eclass);
     566           0 :                                         score += (10 + t->type->localtype - a->type.type->localtype) * nscore;
     567     1103267 :                                 } else if (t->type->eclass == EC_NUM || t->type->eclass == EC_FLT) { /* down casting */
     568     1088365 :                                         *downcast = true;
     569     1088365 :                                         score += 10 * (10 - t->type->localtype - a->type.type->localtype);
     570             :                                 }
     571             :                 }
     572             :         }
     573     4581650 :         score += (list_empty(tl) && list_empty(f->ops));
     574     4581651 :         return score;
     575             : }
     576             : 
     577             : 
     578             : static sql_subfunc *
     579     1557107 : sql_bind_func__(mvc *sql, list *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
     580             : {
     581     1557107 :         sql_ftype filt = (type == F_FUNC)?F_FILT:type;
     582     1557107 :         sql_subtype *input_type = NULL;
     583     1557107 :         sql_func *cand = NULL, *dcand = NULL;
     584     1557107 :         int points = 0, dpoints = 0;
     585             : 
     586     1557107 :         if (ops && ops->h)
     587     1517865 :                 input_type = ops->h->data;
     588             : 
     589     1557107 :         assert(ff==funcs);
     590     1557107 :         if (ff) {
     591     1557324 :                 if (ff->ht) {
     592     1557324 :                         int key = hash_key(fname);
     593     1557324 :                         sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
     594     9767994 :                         for (; he; he = he->chain) {
     595     8210651 :                                 sql_func *f = he->value;
     596     8210651 :                                 bool downcast = false;
     597             : 
     598     8210651 :                                 if ((f->type != type && f->type != filt) || (f->private && !private))
     599      338483 :                                         continue;
     600     7872168 :                                 if (strcmp(f->base.name, fname) == 0 && ((!exact && (list_length(f->ops) == list_length(ops) || (list_length(f->ops) <= list_length(ops) && f->vararg))) || (exact && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0))) {
     601     7744315 :                                         int npoints = score_func(f, ops, exact, &downcast);
     602     7744033 :                                         if (downcast) {
     603     1849685 :                                                 if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
     604     7872187 :                                                         dcand = f;
     605     7872187 :                                                         dpoints = npoints;
     606             :                                                 }
     607             :                                         } else {
     608     5894348 :                                                 if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
     609     7872187 :                                                         cand = f;
     610     7872187 :                                                         points = npoints;
     611             :                                                 }
     612             :                                         }
     613             :                                 }
     614             :                         }
     615             :                 } else {
     616           0 :                         node *n;
     617           0 :                         sql_base_loop(ff, n) {
     618           0 :                                 sql_func *f = n->data;
     619           0 :                                 bool downcast = false;
     620             : 
     621           0 :                                 if ((f->type != type && f->type != filt) || (f->private && !private))
     622           0 :                                         continue;
     623           0 :                                 if (strcmp(f->base.name, fname) == 0 && ((!exact && (list_length(f->ops) == list_length(ops) || (list_length(f->ops) <= list_length(ops) && f->vararg))) || (exact && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0))) {
     624           0 :                                         int npoints = score_func(f, ops, exact, &downcast);
     625           0 :                                         if (downcast) {
     626           0 :                                                 if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
     627           0 :                                                         dcand = f;
     628           0 :                                                         dpoints = npoints;
     629             :                                                 }
     630             :                                         } else {
     631           0 :                                                 if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
     632           0 :                                                         cand = f;
     633           0 :                                                         points = npoints;
     634             :                                                 }
     635             :                                         }
     636             :                                 }
     637             :                         }
     638             :                 }
     639             :         }
     640     1557126 :         if (!cand && dcand)
     641       20050 :                 cand = dcand;
     642     1557126 :         if (cand && exact && type != F_AGGR)
     643      386730 :                         return sql_dup_subfunc(sql->sa, cand, ops, NULL);
     644     1170396 :         if (cand)
     645             :                 //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
     646     1199435 :                 return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
     647             :         return NULL;
     648             : }
     649             : 
     650             : static sql_subfunc *
     651      639364 : os_bind_func__(mvc *sql, struct objectset *ff, const char *fname, list *ops, sql_ftype type, bool private, bool exact)
     652             : {
     653      639364 :         sql_ftype filt = (type == F_FUNC)?F_FILT:type;
     654      639364 :         sql_subtype *input_type = NULL;
     655      639364 :         sql_func *cand = NULL, *dcand = NULL;
     656      639364 :         int points = 0, dpoints = 0;
     657             : 
     658      639364 :         if (ops && ops->h)
     659      606707 :                 input_type = ops->h->data;
     660             : 
     661      639364 :         if (ff) {
     662      639364 :                 struct os_iter oi;
     663      639364 :                 os_iterator(&oi, ff, sql->session->tr, fname);
     664     2141985 :                 for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
     665     1502621 :                         sql_func *f = (sql_func*)b;
     666     1502621 :                         bool downcast = false;
     667             : 
     668     1502621 :                         if ((f->type != type && f->type != filt) || (f->private && !private))
     669      475399 :                                 continue;
     670     1027222 :                         if (strcmp(f->base.name, fname) == 0 && ((!exact && (list_length(f->ops) == list_length(ops) || (list_length(f->ops) <= list_length(ops) && f->vararg))) || (exact && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0))) {
     671      334699 :                                 int npoints = score_func(f, ops, exact, &downcast);
     672      334699 :                                 if (downcast) {
     673        2563 :                                         if ((!dcand && (npoints || exact)) || (dcand && npoints > dpoints)) {
     674     1027222 :                                                 dcand = f;
     675     1027222 :                                                 dpoints = npoints;
     676             :                                         }
     677             :                                 } else {
     678      332136 :                                         if ((!cand && (npoints || exact)) || (cand && npoints > points)) {
     679     1027222 :                                                 cand = f;
     680     1027222 :                                                 points = npoints;
     681             :                                         }
     682             :                                 }
     683             :                         }
     684             :                 }
     685             :         }
     686      639364 :         if (!cand && dcand)
     687         302 :                 cand = dcand;
     688      639364 :         if (cand && exact && type != F_AGGR)
     689      167696 :                         return sql_dup_subfunc(sql->sa, cand, ops, NULL);
     690      471668 :         if (cand)
     691             :                 //return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, input_type) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
     692      255345 :                 return _dup_subaggr(sql->sa, cand, (type == F_AGGR) ?input_type: NULL);
     693             :         return NULL;
     694             : }
     695             : 
     696             : #define sql_bind_func__extra \
     697             :         do { \
     698             :                 if (!res && (res = sql_bind_func__(sql, funcs, name, ops, type, private, exact))) /* search system wide functions first */ \
     699             :                         return res; \
     700             :         } while (0)
     701             : 
     702             : sql_subfunc *
     703     1582497 : sql_bind_func_(mvc *sql, const char *sname, const char *name, list *ops, sql_ftype type, bool private, bool exact)
     704             : {
     705     1582497 :         char *F = NULL, *objstr = NULL;
     706     1582497 :         const char error[] = "CATALOG";
     707     1582497 :         sql_subfunc *res = NULL;
     708             : 
     709     1582497 :         FUNC_TYPE_STR(type, F, objstr);
     710     1582497 :         (void) F; /* not used */
     711             : 
     712     1584037 :         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), true);
     713             :         return res;
     714             : }
     715             : 
     716             : static sql_subfunc *
     717       40572 : sql_bind_func_result_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
     718             : {
     719       40572 :         sql_subtype *tp = sql_bind_localtype("bit");
     720       40561 :         sql_func *cand = NULL;
     721       40561 :         int points = 0, npoints = 0;
     722             : 
     723       40561 :         if (ff) {
     724       40561 :                 if (ff->ht) {
     725       40561 :                         int key = hash_key(fname);
     726       40561 :                         sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)];
     727      143589 :                         for (; he; he = he->chain) {
     728      102991 :                                 sql_func *f = he->value;
     729      102991 :                                 sql_arg *firstres = NULL;
     730             : 
     731      102991 :                                 if ((!f->res && !IS_FILT(f)) || (f->private && !private))
     732           0 :                                         continue;
     733      102991 :                                 firstres = IS_FILT(f)?tp->type:f->res->h->data;
     734      102991 :                                 if (strcmp(f->base.name, fname) == 0 && f->type == type && (is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
     735       40595 :                                         npoints = next_cand_points(f->ops, ops);
     736             : 
     737       40594 :                                         if (!cand || npoints > points) {
     738      103028 :                                                 cand = f;
     739      103028 :                                                 points = npoints;
     740             :                                         }
     741             :                                 }
     742             :                         }
     743             :                 } else {
     744           0 :                         node *n;
     745           0 :                         sql_base_loop( ff, n) {
     746           0 :                                 sql_func *f = n->data;
     747           0 :                                 sql_arg *firstres = NULL;
     748             : 
     749           0 :                                 if ((!f->res && !IS_FILT(f)) || (f->private && !private))
     750           0 :                                         continue;
     751           0 :                                 firstres = IS_FILT(f)?tp->type:f->res->h->data;
     752           0 :                                 if (strcmp(f->base.name, fname) == 0 && f->type == type && (is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
     753           0 :                                         npoints = next_cand_points(f->ops, ops);
     754             : 
     755           0 :                                         if (!cand || npoints > points) {
     756           0 :                                                 cand = f;
     757           0 :                                                 points = npoints;
     758             :                                         }
     759             :                                 }
     760             :                         }
     761             :                 }
     762             :         }
     763       40598 :         if (cand)
     764       40597 :                 return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
     765             :         return NULL;
     766             : }
     767             : 
     768             : static sql_subfunc *
     769           1 : os_bind_func_result_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private, list *ops, sql_subtype *res)
     770             : {
     771           1 :         sql_subtype *tp = sql_bind_localtype("bit");
     772           1 :         sql_func *cand = NULL;
     773           1 :         int points = 0, npoints = 0;
     774             : 
     775           1 :         if (ff) {
     776           1 :                 struct os_iter oi;
     777           1 :                 os_iterator(&oi, ff, sql->session->tr, fname);
     778           2 :                 for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
     779           1 :                         sql_func *f = (sql_func*)b;
     780           1 :                         sql_arg *firstres = NULL;
     781             : 
     782           1 :                         if ((!f->res && !IS_FILT(f)) || (f->private && !private))
     783           0 :                                 continue;
     784           1 :                         firstres = IS_FILT(f)?tp->type:f->res->h->data;
     785           1 :                         if (strcmp(f->base.name, fname) == 0 && f->type == type && (is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) && list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0) {
     786           1 :                                 npoints = next_cand_points(f->ops, ops);
     787             : 
     788           1 :                                 if (!cand || npoints > points) {
     789           1 :                                         cand = f;
     790           1 :                                         points = npoints;
     791             :                                 }
     792             :                         }
     793             :                 }
     794             :         }
     795           1 :         if (cand)
     796           1 :                 return (type == F_AGGR) ? _dup_subaggr(sql->sa, cand, NULL) : sql_dup_subfunc(sql->sa, cand, ops, NULL);
     797             :         return NULL;
     798             : }
     799             : 
     800             : #define sql_bind_func_result_extra \
     801             :         do { \
     802             :                 if (!res) \
     803             :                         res = sql_bind_func_result_internal(sql, funcs, name, type, private, ops, r_res); /* search system wide functions first */ \
     804             :         } while (0)
     805             : 
     806             : 
     807             : sql_subfunc *
     808       40565 : sql_bind_func_result(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private, sql_subtype *r_res, int nargs, ...)
     809             : {
     810       40565 :         char *F = NULL, *objstr = NULL;
     811       40565 :         const char error[] = "CATALOG";
     812       40565 :         sql_subfunc *res = NULL;
     813       40565 :         list *ops = sa_list(sql->sa);
     814       40585 :         va_list valist;
     815             : 
     816       40585 :         FUNC_TYPE_STR(type, F, objstr);
     817       40585 :         (void) F; /* not used */
     818             : 
     819       40585 :         va_start(valist, nargs);
     820      123239 :         for (int i = 0; i < nargs; i++) {
     821       82642 :                 sql_type *tpe = va_arg(valist, sql_type*);
     822       82651 :                 list_append(ops, tpe);
     823             :         }
     824       40597 :         va_end(valist);
     825             : 
     826       40597 :         search_object_on_path(res = os_bind_func_result_internal(sql, next->funcs, name, type, private, ops, r_res), functions_without_schema, sql_bind_func_result_extra, SQLSTATE(42000), true);
     827       40599 :         if (res) /* make sure we have the correct result type */
     828       40599 :                 res->res->h->data = r_res;
     829       40599 :         return res;
     830             : }
     831             : 
     832             : static list *
     833        5273 : sql_find_funcs_by_name_internal(mvc *sql, list *ff, const char *fname, sql_ftype type, bool private)
     834             : {
     835        5273 :         int key = hash_key(fname);
     836        5273 :         list *res = NULL;
     837             : 
     838        5273 :         if (ff) {
     839        5273 :                 if (ff->ht) {
     840        5273 :                         for (sql_hash_e *he = ff->ht->buckets[key&(ff->ht->size-1)]; he; he = he->chain) {
     841           0 :                                 sql_func *f = he->value;
     842             : 
     843           0 :                                 if (f->type != type || (f->private && !private))
     844           0 :                                         continue;
     845           0 :                                 if (strcmp(f->base.name, fname) == 0) {
     846           0 :                                         if (!res)
     847           0 :                                                 res = sa_list(sql->sa);
     848           0 :                                         list_append(res, f);
     849             :                                 }
     850             :                         }
     851             :                 } else {
     852           0 :                         node *n;
     853           0 :                         sql_base_loop( ff, n) {
     854           0 :                                 sql_func *f = n->data;
     855             : 
     856           0 :                                 if (f->type != type || (f->private && !private))
     857           0 :                                         continue;
     858           0 :                                 if (strcmp(f->base.name, fname) == 0) {
     859           0 :                                         if (!res)
     860           0 :                                                 res = sa_list(sql->sa);
     861           0 :                                         list_append(res, f);
     862             :                                 }
     863             :                         }
     864             :                 }
     865             :         }
     866        5273 :         return res;
     867             : }
     868             : 
     869             : static list *
     870        9107 : os_find_funcs_by_name_internal(mvc *sql, struct objectset *ff, const char *fname, sql_ftype type, bool private)
     871             : {
     872        9107 :         list *res = NULL;
     873             : 
     874        9107 :         if (ff) {
     875        9107 :                 struct os_iter oi;
     876        9107 :                 os_iterator(&oi, ff, sql->session->tr, fname);
     877       14881 :                 for (sql_base *b = oi_next(&oi); b; b=oi_next(&oi)) {
     878        5774 :                         sql_func *f = (sql_func*)b;
     879             : 
     880        5774 :                         if (f->type != type || (f->private && !private))
     881        1333 :                                 continue;
     882        4441 :                         if (strcmp(f->base.name, fname) == 0) {
     883        4441 :                                 if (!res)
     884        4413 :                                         res = sa_list(sql->sa);
     885        4441 :                                 list_append(res, f);
     886             :                         }
     887             :                 }
     888             :         }
     889        9107 :         return res;
     890             : }
     891             : 
     892             : #define sql_find_funcs_by_name_extra \
     893             :         do { \
     894             :                 if (!res && (res = sql_find_funcs_by_name_internal(sql, funcs, name, type, private))) /* search system wide functions first */ \
     895             :                         return res; \
     896             :         } while (0)
     897             : 
     898             : list *
     899        5748 : sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type, bool private)
     900             : {
     901        5748 :         char *F = NULL, *objstr = NULL;
     902        5748 :         const char error[] = "CATALOG";
     903        5748 :         list *res = NULL;
     904             : 
     905        5748 :         FUNC_TYPE_STR(type, F, objstr);
     906        5748 :         (void) F; /* not used */
     907             : 
     908        6096 :         search_object_on_path(res = os_find_funcs_by_name_internal(sql, next->funcs, name, type, private), functions_without_schema, sql_find_funcs_by_name_extra, "", false);
     909             :         return res;
     910             : }
     911             : 
     912             : char *
     913     1974857 : qname_schema(dlist *qname)
     914             : {
     915     1974857 :         assert(qname && qname->h);
     916             : 
     917     1974857 :         if (dlist_length(qname) == 2) {
     918     1161314 :                 return qname->h->data.sval;
     919      813634 :         } else if (dlist_length(qname) == 3) {
     920           4 :                 return qname->h->next->data.sval;
     921             :         }
     922             :         return NULL;
     923             : }
     924             : 
     925             : char *
     926     1985452 : qname_schema_object(dlist *qname)
     927             : {
     928     1985452 :         assert(qname && qname->h);
     929             : 
     930     1985452 :         if (dlist_length(qname) == 1) {
     931      823766 :                 return qname->h->data.sval;
     932     1161616 :         } else if (dlist_length(qname) == 2) {
     933     1161612 :                 return qname->h->next->data.sval;
     934           4 :         } else if (dlist_length(qname) == 3) {
     935           4 :                 return qname->h->next->next->data.sval;
     936             :         }
     937             :         return "unknown";
     938             : }
     939             : 
     940             : char *
     941           0 : qname_catalog(dlist *qname)
     942             : {
     943           0 :         assert(qname && qname->h);
     944             : 
     945           0 :         if (dlist_length(qname) == 3) {
     946           0 :                 return qname->h->data.sval;
     947             :         }
     948             :         return NULL;
     949             : }
     950             : 
     951             : int
     952        1559 : set_type_param(mvc *sql, sql_subtype *type, int nr)
     953             : {
     954        1559 :         sql_arg *a = sql_bind_paramnr(sql, nr);
     955             : 
     956        1559 :         if (!a)
     957             :                 return -1;
     958        1559 :         a->type = *type;
     959        1559 :         return 0;
     960             : }
     961             : 
     962             : /*
     963             :  * Find the result_datatype for certain combinations of values
     964             :  * (like case expressions or columns in a result of a query expression).
     965             :  * See standaard pages 505-507 Result of data type combinations */
     966             : sql_subtype *
     967      207826 : result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
     968             : {
     969      207826 :         int lclass = l->type->eclass, rclass = r->type->eclass;
     970             : 
     971             :         /* case a strings */
     972      290064 :         if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
     973       82238 :                 const char *tpe = "varchar";
     974       82238 :                 unsigned int digits = 0;
     975       82238 :                 if (!EC_VARCHAR(lclass)) {
     976         492 :                         tpe = r->type->base.name;
     977         492 :                         digits = (!l->digits)?0:r->digits;
     978       81746 :                 } else if (!EC_VARCHAR(rclass)) {
     979        5184 :                         tpe = l->type->base.name;
     980        5184 :                         digits = (!r->digits)?0:l->digits;
     981             :                 } else { /* both */
     982       76562 :                         tpe = !strcmp(l->type->base.name, "varchar")?l->type->base.name:!strcmp(r->type->base.name, "varchar")?r->type->base.name:
     983           7 :                         (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
     984       76562 :                         digits = (!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
     985             :                 }
     986       82238 :                 sql_find_subtype(super, tpe, digits, 0);
     987             :         /* case b blob */
     988      125588 :         } else if (lclass == EC_BLOB || rclass == EC_BLOB) {
     989          14 :                 *super = (lclass == EC_BLOB) ? *l : *r;
     990             :         /* case c all exact numeric */
     991      223679 :         } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
     992       98105 :                 char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
     993       98105 :                 unsigned int digits = sql_max(l->digits, r->digits);
     994       98105 :                 unsigned int scale = sql_max(l->scale, r->scale);
     995             : 
     996       98105 :                 if (l->type->radix == 10 && r->type->radix == 10) {
     997          90 :                         digits = scale + (sql_max(l->digits - l->scale, r->digits - r->scale));
     998             : #ifdef HAVE_HGE
     999          90 :                         if (digits > 38) {
    1000           0 :                                 digits = 38;
    1001             : #else
    1002             :                         if (digits > 18) {
    1003             :                                 digits = 18;
    1004             : #endif
    1005           0 :                                 scale = MIN(scale, digits - 1);
    1006             :                         }
    1007       98015 :                 } else if (l->type->radix == 2 && r->type->radix == 10) { /* change to radix 10 */
    1008          47 :                         digits = bits2digits(l->type->digits);
    1009          47 :                         digits = sql_max(r->digits, digits);
    1010          47 :                         scale = r->scale;
    1011       97968 :                 } else if (l->type->radix == 10 && r->type->radix == 2) { /* change to radix 10 */
    1012         121 :                         digits = bits2digits(r->type->digits);
    1013         121 :                         digits = sql_max(l->digits, digits);
    1014         121 :                         scale = l->scale;
    1015             :                 }
    1016       98105 :                 sql_find_subtype(super, tpe, digits, scale);
    1017             :         /* case d approximate numeric */
    1018       27469 :         } else if (EC_APPNUM(lclass) || EC_APPNUM(rclass)) {
    1019         157 :                 if (!EC_APPNUM(lclass)) {
    1020          45 :                         *super = *r;
    1021         112 :                 } else if (!EC_APPNUM(rclass)) {
    1022          91 :                         *super = *l;
    1023             :                 } else { /* both */
    1024          21 :                         char *tpe = (l->type->base.id > r->type->base.id)?l->type->base.name:r->type->base.name;
    1025          21 :                         unsigned int digits = sql_max(l->digits, r->digits); /* bits precision */
    1026          21 :                         sql_find_subtype(super, tpe, digits, 0);
    1027             :                 }
    1028             :         /* now its getting serious, ie e any 'case e' datetime data type */
    1029             :         /* 'case f' interval types */
    1030             :         /* 'case g' boolean */
    1031             :         /* 'case h-l' compounds like row (tuple), etc */
    1032             :         } else {
    1033       27312 :                 return supertype(super, l, r);
    1034             :         }
    1035             :         return super;
    1036             : }
    1037             : 
    1038             : char *
    1039          80 : toUpperCopy(char *dest, const char *src)
    1040             : {
    1041          80 :         size_t i, len;
    1042             : 
    1043          80 :         if (src == NULL) {
    1044           0 :                 *dest = '\0';
    1045           0 :                 return(dest);
    1046             :         }
    1047             : 
    1048          80 :         len = _strlen(src);
    1049         433 :         for (i = 0; i < len; i++)
    1050         353 :                 dest[i] = (char)toupper((int)src[i]);
    1051             : 
    1052          80 :         dest[i] = '\0';
    1053          80 :         return(dest);
    1054             : }
    1055             : 
    1056             : static char * _symbol2string(mvc *sql, symbol *se, int expression, char **err);
    1057             : 
    1058             : static char *
    1059           1 : dlist2string(mvc *sql, dlist *l, int expression, char **err)
    1060             : {
    1061           1 :         char *b = NULL;
    1062           1 :         dnode *n;
    1063             : 
    1064           3 :         for (n=l->h; n; n = n->next) {
    1065           2 :                 char *s = NULL;
    1066             : 
    1067           2 :                 if (n->type == type_string && n->data.sval)
    1068           2 :                         s = sa_strdup(sql->ta, n->data.sval);
    1069           0 :                 else if (n->type == type_symbol)
    1070           0 :                         s = _symbol2string(sql, n->data.sym, expression, err);
    1071             : 
    1072           2 :                 if (!s)
    1073           0 :                         return NULL;
    1074           2 :                 if (b) {
    1075           1 :                         char *o = SA_NEW_ARRAY(sql->ta, char, strlen(b) + strlen(s) + 2);
    1076           1 :                         if (o)
    1077           1 :                                 stpcpy(stpcpy(stpcpy(o, b), "."), s);
    1078           0 :                         b = o;
    1079           1 :                         if (b == NULL)
    1080             :                                 return NULL;
    1081             :                 } else {
    1082             :                         b = s;
    1083             :                 }
    1084             :         }
    1085             :         return b;
    1086             : }
    1087             : 
    1088             : static const char *
    1089         876 : symbol_escape_ident(allocator *sa, const char *s)
    1090             : {
    1091         876 :         char *res = NULL;
    1092         876 :         if (s) {
    1093         824 :                 size_t l = strlen(s);
    1094         824 :                 char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
    1095             : 
    1096         824 :                 res = r;
    1097        6094 :                 while (*s) {
    1098        5270 :                         if (*s == '"')
    1099           1 :                                 *r++ = '"';
    1100        5270 :                         *r++ = *s++;
    1101             :                 }
    1102         824 :                 *r = '\0';
    1103             :         }
    1104         876 :         return res;
    1105             : }
    1106             : 
    1107             : char *
    1108        1584 : _symbol2string(mvc *sql, symbol *se, int expression, char **err)
    1109             : {
    1110             :         /* inner symbol2string uses the temporary allocator */
    1111        1584 :         switch (se->token) {
    1112         153 :         case SQL_NOP: {
    1113         153 :                 dnode *lst = se->data.lval->h, *ops = NULL, *aux;
    1114         153 :                 const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)),
    1115         153 :                                    *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval));
    1116         153 :                 int i = 0, nargs = 0;
    1117         153 :                 char** inputs = NULL, *res;
    1118         153 :                 size_t inputs_length = 0, extra = sname ? strlen(sname) + 3 : 0;
    1119             : 
    1120         153 :                 if (lst->next->next->data.lval)
    1121         113 :                         ops = lst->next->next->data.lval->h;
    1122             : 
    1123         294 :                 for (aux = ops; aux; aux = aux->next)
    1124         141 :                         nargs++;
    1125         153 :                 if (!(inputs = SA_ZNEW_ARRAY(sql->ta, char*, nargs)))
    1126             :                         return NULL;
    1127             : 
    1128         289 :                 for (aux = ops; aux; aux = aux->next) {
    1129         139 :                         if (!(inputs[i] = _symbol2string(sql, aux->data.sym, expression, err))) {
    1130             :                                 return NULL;
    1131             :                         }
    1132         136 :                         inputs_length += strlen(inputs[i]);
    1133         136 :                         i++;
    1134             :                 }
    1135             : 
    1136         300 :                 if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + inputs_length + 3 + (nargs - 1 /* commas */) + 2))) {
    1137         150 :                         char *concat = res;
    1138         150 :                         if (sname)
    1139         100 :                                 concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\".");
    1140         150 :                         concat = stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"(");
    1141         150 :                         i = 0;
    1142         286 :                         for (aux = ops; aux; aux = aux->next) {
    1143         136 :                                 concat = stpcpy(concat, inputs[i]);
    1144         136 :                                 if (aux->next)
    1145          26 :                                         concat = stpcpy(concat, ",");
    1146         136 :                                 i++;
    1147             :                         }
    1148         150 :                         concat = stpcpy(concat, ")");
    1149             :                 }
    1150             :                 return res;
    1151             :         }
    1152           0 :         case SQL_PARAMETER:
    1153           0 :                 return sa_strdup(sql->ta, "?");
    1154         193 :         case SQL_NULL:
    1155         193 :                 return sa_strdup(sql->ta, "NULL");
    1156             :         case SQL_ATOM:{
    1157         929 :                 AtomNode *an = (AtomNode *) se;
    1158         929 :                 if (an && an->a)
    1159         929 :                         return atom2sql(sql->ta, an->a, sql->timezone);
    1160             :                 else
    1161           0 :                         return sa_strdup(sql->ta, "NULL");
    1162             :         }
    1163         269 :         case SQL_NEXT: {
    1164         269 :                 const char *seq = symbol_escape_ident(sql->ta, qname_schema_object(se->data.lval)),
    1165         269 :                                    *sname = qname_schema(se->data.lval);
    1166         269 :                 char *res;
    1167             : 
    1168         269 :                 if (!sname)
    1169         200 :                         sname = sql->session->schema->base.name;
    1170         269 :                 sname = symbol_escape_ident(sql->ta, sname);
    1171             : 
    1172         538 :                 if ((res = SA_NEW_ARRAY(sql->ta, char, strlen("next value for \"") + strlen(sname) + strlen(seq) + 5)))
    1173         269 :                         stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for \""), sname), "\".\""), seq), "\"");
    1174             :                 return res;
    1175          33 :         }       break;
    1176          33 :         case SQL_IDENT:
    1177             :         case SQL_COLUMN: {
    1178             :                 /* can only be variables */
    1179          33 :                 dlist *l = se->data.lval;
    1180          33 :                 assert(l->h->type != type_lng);
    1181          33 :                 if (expression && dlist_length(l) == 1 && l->h->type == type_string) {
    1182             :                         /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */
    1183          32 :                         const char *op = symbol_escape_ident(sql->ta, l->h->data.sval);
    1184          32 :                         char *res;
    1185             : 
    1186          64 :                         if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3)))
    1187          32 :                                 stpcpy(stpcpy(stpcpy(res, "\""), op), "\"");
    1188          32 :                         return res;
    1189           0 :                 } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) {
    1190           0 :                         const char *first = symbol_escape_ident(sql->ta, l->h->data.sval),
    1191           0 :                                            *second = symbol_escape_ident(sql->ta, l->h->next->data.sval);
    1192           0 :                         char *res;
    1193             : 
    1194           0 :                         if (!first || !second)
    1195             :                                 return NULL;
    1196           0 :                         if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(first) + strlen(second) + 6)))
    1197           0 :                                 stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), first), "\".\""), second), "\"");
    1198           0 :                         return res;
    1199             :                 } else {
    1200           1 :                         char *e = dlist2string(sql, l, expression, err);
    1201           1 :                         if (e)
    1202           1 :                                 *err = e;
    1203           1 :                         return NULL;
    1204             :                 }
    1205             :         }
    1206           6 :         case SQL_CAST: {
    1207           6 :                 dlist *dl = se->data.lval;
    1208           6 :                 char *val = NULL, *tpe = NULL, *res;
    1209             : 
    1210           6 :                 if (!(val = _symbol2string(sql, dl->h->data.sym, expression, err)) || !(tpe = subtype2string2(sql->ta, &dl->h->next->data.typeval)))
    1211           0 :                         return NULL;
    1212          12 :                 if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(val) + strlen(tpe) + 11)))
    1213           6 :                         stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "cast("), val), " as "), tpe), ")");
    1214             :                 return res;
    1215             :         }
    1216           1 :         default: {
    1217           1 :                 const char msg[] = "SQL feature not yet available for expressions and default values: ";
    1218           1 :                 char *tok_str = token2string(se->token);
    1219           2 :                 if ((*err = SA_NEW_ARRAY(sql->ta, char, strlen(msg) + strlen(tok_str) + 1)))
    1220           1 :                         stpcpy(stpcpy(*err, msg), tok_str);
    1221             :         }
    1222             :         }
    1223           1 :         return NULL;
    1224             : }
    1225             : 
    1226             : char *
    1227        1439 : symbol2string(mvc *sql, symbol *se, int expression, char **err)
    1228             : {
    1229        1439 :         char *res = _symbol2string(sql, se, expression, err);
    1230             : 
    1231        1439 :         if (res)
    1232        1437 :                 res = sa_strdup(sql->sa, res);
    1233        1439 :         if (*err)
    1234           2 :                 *err = sa_strdup(sql->sa, *err);
    1235        1439 :         sa_reset(sql->ta);
    1236        1439 :         return res;
    1237             : }

Generated by: LCOV version 1.14