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

Generated by: LCOV version 1.14