LCOV - code coverage report
Current view: top level - sql/server - sql_semantic.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 706 773 91.3 %
Date: 2024-04-25 20:03:45 Functions: 51 52 98.1 %

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

Generated by: LCOV version 1.14