LCOV - code coverage report
Current view: top level - sql/server - sql_semantic.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 552 613 90.0 %
Date: 2021-10-13 02:24:04 Functions: 49 51 96.1 %

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

Generated by: LCOV version 1.14