LCOV - code coverage report
Current view: top level - sql/server - rel_psm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 975 1079 90.4 %
Date: 2024-12-20 21:24:02 Functions: 36 36 100.0 %

          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 "rel_psm.h"
      15             : #include "rel_semantic.h"
      16             : #include "rel_schema.h"
      17             : #include "rel_select.h"
      18             : #include "rel_rel.h"
      19             : #include "rel_basetable.h"
      20             : #include "rel_exp.h"
      21             : #include "rel_updates.h"
      22             : #include "sql_privileges.h"
      23             : #include "sql_storage.h"
      24             : 
      25             : #define psm_zero_or_one(exp) \
      26             :         do { \
      27             :                 if (exp && exp->card > CARD_AGGR) { \
      28             :                         sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", exp_subtype(exp), NULL, F_AGGR, true, true); \
      29             :                         assert(zero_or_one); \
      30             :                         exp = exp_aggr1(sql->sa, exp, zero_or_one, 0, 0, CARD_ATOM, has_nil(exp)); \
      31             :                 } \
      32             :         } while(0)
      33             : 
      34             : static list *sequential_block(sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_name, int is_func);
      35             : 
      36             : sql_rel *
      37       23521 : rel_psm_block(allocator *sa, list *l)
      38             : {
      39       23521 :         if (l) {
      40       23519 :                 sql_rel *r = rel_create(sa);
      41       23521 :                 if(!r)
      42             :                         return NULL;
      43             : 
      44       23521 :                 r->op = op_ddl;
      45       23521 :                 r->flag = ddl_psm;
      46       23521 :                 r->exps = l;
      47       23521 :                 return r;
      48             :         }
      49             :         return NULL;
      50             : }
      51             : 
      52             : sql_rel *
      53        9466 : rel_psm_stmt(allocator *sa, sql_exp *e)
      54             : {
      55        9466 :         if (e) {
      56        9428 :                 list *l = sa_list(sa);
      57        9430 :                 if(!l)
      58             :                         return NULL;
      59             : 
      60        9430 :                 list_append(l, e);
      61        9430 :                 return rel_psm_block(sa, l);
      62             :         }
      63             :         return NULL;
      64             : }
      65             : 
      66             : /* SET [ schema '.' ] variable = value and set ( [ schema1 '.' ] variable1, .., [ schemaN '.' ] variableN) = (query) */
      67             : static sql_exp *
      68       14783 : psm_set_exp(sql_query *query, dnode *n)
      69             : {
      70       14783 :         mvc *sql = query->sql;
      71       14783 :         dlist *qname = n->data.lval;
      72       14783 :         symbol *val = n->next->data.sym;
      73       14783 :         sql_exp *res = NULL, *e = NULL;
      74       14783 :         int level = 0, single = (qname->h->type == type_string);
      75       14783 :         sql_rel *rel = NULL;
      76       14783 :         sql_subtype *tpe;
      77             : 
      78       14783 :         if (single) {
      79       14777 :                 exp_kind ek = {type_value, card_value, FALSE};
      80       14777 :                 const char *sname = qname_schema(qname);
      81       14777 :                 const char *vname = qname_schema_object(qname);
      82       14777 :                 sql_var *var = NULL;
      83       14777 :                 sql_arg *a = NULL;
      84             : 
      85       14777 :                 if (!find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SET"))
      86          29 :                         return NULL;
      87       14757 :                 if (!(e = rel_value_exp2(query, &rel, val, sql_sel | sql_psm, ek)))
      88             :                         return NULL;
      89       14749 :                 psm_zero_or_one(e);
      90             : 
      91       14749 :                 if (!(e = exp_check_type(sql, tpe, rel, e, type_cast)))
      92             :                         return NULL;
      93       15641 :                 res = exp_set(sql->sa, var && var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, vname), e, level);
      94             :         } else { /* multi assignment */
      95           6 :                 exp_kind ek = {type_relation, card_value, FALSE};
      96           6 :                 sql_rel *rel_val = rel_subquery(query, val, ek);
      97           6 :                 dlist *vars = n->data.lval;
      98           6 :                 dnode *m;
      99           6 :                 node *n;
     100           6 :                 list *b;
     101             : 
     102           6 :                 if (!rel_val)
     103           0 :                         return NULL;
     104           6 :                 if (!is_project(rel_val->op))
     105           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SET: The subquery is not a projection");
     106           6 :                 if (dlist_length(vars) != list_length(rel_val->exps))
     107           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SET: Number of variables not equal to number of supplied values");
     108           6 :                 rel_val = rel_return_zero_or_one(sql, rel_val, ek);
     109             : 
     110           6 :                 b = sa_list(sql->sa);
     111           6 :                 append(b, exp_rel(sql, rel_val));
     112             : 
     113          18 :                 for (m = vars->h, n = rel_val->exps->h; n && m; n = n->next, m = m->next) {
     114          12 :                         dlist *nqname = m->data.lval;
     115          12 :                         const char *sname = qname_schema(nqname);
     116          12 :                         const char *vname = qname_schema_object(nqname);
     117          12 :                         sql_exp *v = n->data;
     118          12 :                         sql_var *var = NULL;
     119          12 :                         sql_arg *a = NULL;
     120             : 
     121          12 :                         if (!find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SET"))
     122           0 :                                 return NULL;
     123             : 
     124          12 :                         v = exp_ref(sql, v);
     125          12 :                         if (!(v = exp_check_type(sql, tpe, rel_val, v, type_cast)))
     126             :                                 return NULL;
     127          12 :                         append(b, exp_set(sql->sa, var && var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, vname), v, level));
     128             :                 }
     129           6 :                 res = exp_rel(sql, rel_psm_block(sql->sa, b));
     130             :         }
     131             :         return res;
     132             : }
     133             : 
     134             : static sql_exp*
     135       10750 : rel_psm_call(sql_query * query, symbol *se)
     136             : {
     137       10750 :         mvc *sql = query->sql;
     138       10750 :         sql_subtype *t;
     139       10750 :         sql_exp *res = NULL;
     140       10750 :         exp_kind ek = {type_value, card_none, FALSE};
     141       10750 :         sql_rel *rel = NULL;
     142             : 
     143       10750 :         res = rel_value_exp(query, &rel, se, sql_sel | psm_call, ek);
     144       10750 :         if (!res || rel || ((t=exp_subtype(res)) && t->type))  /* only procedures */
     145          21 :                 return sql_error(sql, 01, SQLSTATE(42000) "Function calls are ignored");
     146             :         return res;
     147             : }
     148             : 
     149             : static list *
     150        8357 : rel_psm_declare(mvc *sql, dnode *n)
     151             : {
     152        8357 :         list *l = sa_list(sql->sa);
     153             : 
     154       17867 :         while (n) { /* list of 'identfiers with type' */
     155        9513 :                 dnode *ids = n->data.sym->data.lval->h->data.lval->h;
     156        9513 :                 sql_subtype *ctype = &n->data.sym->data.lval->h->next->data.typeval;
     157       19044 :                 while (ids) {
     158        9534 :                         dlist *qname = ids->data.lval;
     159        9534 :                         const char *sname = qname_schema(qname);
     160        9534 :                         const char *tname = qname_schema_object(qname);
     161        9534 :                         sql_exp *r = NULL;
     162             : 
     163        9534 :                         if (sname)
     164           1 :                                 return sql_error(sql, 01, SQLSTATE(42000) "DECLARE: Declared variables don't have a schema");
     165             :                         /* find if there's a parameter with the same name */
     166        9533 :                         if (sql->frame == 1 && sql_bind_param(sql, tname) >= 0)
     167           2 :                                 return sql_error(sql, 01, SQLSTATE(42000) "DECLARE: Variable '%s' declared as a parameter", tname);
     168             :                         /* check if we overwrite a scope local variable declare x; declare x; */
     169        9531 :                         if (frame_find_var(sql, tname))
     170           0 :                                 return sql_error(sql, 01, SQLSTATE(42000) "DECLARE: Variable '%s' already declared", tname);
     171             :                         /* variables are put on stack, globals on a separate list */
     172        9531 :                         if (!frame_push_var(sql, tname, ctype))
     173           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     174        9531 :                         r = exp_var(sql->sa, NULL, sa_strdup(sql->sa, tname), ctype, sql->frame);
     175        9531 :                         append(l, r);
     176        9531 :                         ids = ids->next;
     177             :                 }
     178        9510 :                 n = n->next;
     179             :         }
     180             :         return l;
     181             : }
     182             : 
     183             : static sql_exp *
     184         122 : rel_psm_declare_table(sql_query *query, dnode *n)
     185             : {
     186         122 :         mvc *sql = query->sql;
     187         122 :         sql_rel *rel = NULL, *baset = NULL;
     188         122 :         dlist *qname = n->next->data.lval;
     189         122 :         const char *sname = qname_schema(qname);
     190         122 :         const char *name = qname_schema_object(qname);
     191         122 :         sql_table *t;
     192             : 
     193         122 :         if (sname)
     194           1 :                 return sql_error(sql, 01, SQLSTATE(42000) "DECLARE TABLE: Declared tables don't have a schema");
     195             : 
     196         121 :         assert(n->next->next->next->type == type_int);
     197         242 :         rel = rel_create_table(query, SQL_DECLARED_TABLE, sname, name, false, n->next->next->data.sym,
     198             :                                                    n->next->next->next->data.i_val, NULL, NULL, NULL, false, NULL,
     199         121 :                                                    n->next->next->next->next->next->next->data.i_val);
     200             : 
     201         121 :         if (!rel)
     202             :                 return NULL;
     203         119 :         if (rel->op == op_ddl) {
     204             :                 baset = rel;
     205           3 :         } else if (rel->op == op_insert) {
     206           3 :                 baset = rel->l;
     207             :         } else {
     208           0 :                 assert(0);
     209             :         }
     210         119 :         assert(baset->flag == ddl_create_table);
     211         119 :         t = (sql_table*)((atom*)((sql_exp*)baset->exps->t->data)->l)->data.val.pval;
     212         119 :         if (!frame_push_table(sql, t))
     213           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     214         119 :         return exp_table(sql->sa, sa_strdup(sql->sa, name), t, sql->frame);
     215             : }
     216             : 
     217             : /* [ label: ]
     218             :    while (cond) do
     219             :         statement_list
     220             :    end [ label ]
     221             :    currently we only parse the labels, they cannot be used as there is no
     222             : 
     223             :    support for LEAVE and ITERATE (sql multi-level break and continue)
     224             :  */
     225             : static sql_exp *
     226        1023 : rel_psm_while_do( sql_query *query, sql_subtype *res, list *restypelist, dnode *w, int is_func )
     227             : {
     228        1023 :         mvc *sql = query->sql;
     229        1023 :         if (!w)
     230             :                 return NULL;
     231        1023 :         if (w->type == type_symbol) {
     232        1023 :                 sql_exp *cond;
     233        1023 :                 list *whilestmts;
     234        1023 :                 dnode *n = w;
     235        1023 :                 sql_rel *rel = NULL;
     236        1023 :                 exp_kind ek = {type_value, card_value, FALSE};
     237             : 
     238        1023 :                 if (!(cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek)))
     239             :                         return NULL;
     240        1023 :                 psm_zero_or_one(cond);
     241        1023 :                 n = n->next;
     242        1023 :                 if (!(whilestmts = sequential_block(query, res, restypelist, n->data.lval, n->next->data.sval, is_func)))
     243             :                         return NULL;
     244             : 
     245        1023 :                 return exp_while( sql->sa, cond, whilestmts );
     246             :         }
     247             :         return NULL;
     248             : }
     249             : 
     250             : /* if (cond) then statement_list
     251             :    [ elseif (cond) then statement_list ]*
     252             :    [ else statement_list ]
     253             :    end if
     254             :  */
     255             : static list *
     256       11643 : psm_if_then_else( sql_query *query, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
     257             : {
     258       11643 :         mvc *sql = query->sql;
     259       11643 :         if (!elseif)
     260             :                 return NULL;
     261       11643 :         assert(elseif->type == type_symbol);
     262       11643 :         if (elseif->data.sym && elseif->data.sym->token == SQL_IF) {
     263           7 :                 sql_exp *cond;
     264           7 :                 list *ifstmts, *elsestmts;
     265           7 :                 dnode *n = elseif->data.sym->data.lval->h;
     266           7 :                 sql_rel *rel = NULL;
     267           7 :                 exp_kind ek = {type_value, card_value, FALSE};
     268             : 
     269           7 :                 if (!(cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek)))
     270             :                         return NULL;
     271           7 :                 psm_zero_or_one(cond);
     272           7 :                 n = n->next;
     273           7 :                 if (!(ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func)))
     274             :                         return NULL;
     275           7 :                 n = n->next;
     276           7 :                 elsestmts = psm_if_then_else( query, res, restypelist, n, is_func);
     277           7 :                 if (sql->session->status)
     278             :                         return NULL;
     279             : 
     280           7 :                 return append(sa_list(sql->sa), exp_if( sql->sa, cond, ifstmts, elsestmts));
     281             :         } else { /* else */
     282       11636 :                 symbol *e = elseif->data.sym;
     283             : 
     284       11636 :                 if (e==NULL || (e->token != SQL_ELSE))
     285             :                         return NULL;
     286        1430 :                 return sequential_block(query, res, restypelist, e->data.lval, NULL, is_func);
     287             :         }
     288             : }
     289             : 
     290             : static sql_exp *
     291       11637 : rel_psm_if_then_else( sql_query *query, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
     292             : {
     293       11637 :         mvc *sql = query->sql;
     294       11637 :         if (!elseif)
     295             :                 return NULL;
     296       11637 :         if (elseif->next && elseif->type == type_symbol) { /* if or elseif */
     297       11637 :                 sql_exp *cond;
     298       11637 :                 list *ifstmts, *elsestmts;
     299       11637 :                 dnode *n = elseif;
     300       11637 :                 sql_rel *rel = NULL;
     301       11637 :                 exp_kind ek = {type_value, card_value, FALSE};
     302             : 
     303       11637 :                 if (!(cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek)))
     304             :                         return NULL;
     305       11637 :                 psm_zero_or_one(cond);
     306       11637 :                 n = n->next;
     307       11637 :                 if (!(ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func)))
     308             :                         return NULL;
     309       11636 :                 n = n->next;
     310       11636 :                 elsestmts = psm_if_then_else( query, res, restypelist, n, is_func);
     311       11636 :                 if (sql->session->status)
     312             :                         return NULL;
     313             : 
     314       11636 :                 return exp_if( sql->sa, cond, ifstmts, elsestmts);
     315             :         }
     316             :         return NULL;
     317             : }
     318             : 
     319             : /*      1
     320             :         CASE
     321             :         WHEN search_condition THEN statements
     322             :         [ WHEN search_condition THEN statements ]
     323             :         [ ELSE statements ]
     324             :         END CASE
     325             : 
     326             :         2
     327             :         CASE case_value
     328             :         WHEN when_value THEN statements
     329             :         [ WHEN when_value THEN statements ]
     330             :         [ ELSE statements ]
     331             :         END CASE
     332             :  */
     333             : static sql_exp *
     334          59 : rel_psm_case( sql_query *query, sql_subtype *res, list *restypelist, dnode *case_when, int is_func )
     335             : {
     336          59 :         mvc *sql = query->sql;
     337          59 :         sql_exp *case_stmt = NULL, *last_if = NULL, *ifst = NULL;
     338          59 :         list *else_stmt = NULL;
     339             : 
     340          59 :         if (!case_when)
     341             :                 return NULL;
     342             : 
     343             :         /* case 1 */
     344          59 :         if (case_when->type == type_symbol) {
     345          12 :                 dnode *n = case_when;
     346          12 :                 symbol *case_value = n->data.sym;
     347          12 :                 dlist *when_statements = n->next->data.lval;
     348          12 :                 dlist *else_statements = n->next->next->data.lval;
     349          12 :                 sql_rel *rel = NULL;
     350          12 :                 exp_kind ek = {type_value, card_value, FALSE};
     351          12 :                 sql_exp *v = rel_value_exp(query, &rel, case_value, sql_sel | sql_psm, ek);
     352             : 
     353          12 :                 psm_zero_or_one(v);
     354           0 :                 if (!v)
     355           0 :                         return NULL;
     356          12 :                 if (else_statements && !(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func)))
     357             :                         return NULL;
     358             : 
     359          12 :                 n = when_statements->h;
     360          60 :                 while(n) {
     361          48 :                         dnode *m = n->data.sym->data.lval->h;
     362          48 :                         sql_exp *cond=0, *when_value = rel_value_exp(query, &rel, m->data.sym, sql_sel | sql_psm, ek);
     363          48 :                         list *if_stmts = NULL;
     364             : 
     365          48 :                         psm_zero_or_one(when_value);
     366           0 :                         if (!when_value ||
     367          48 :                            (cond = rel_binop_(sql, rel, v, when_value, "sys", "=", card_value, false)) == NULL ||
     368          48 :                            (if_stmts = sequential_block(query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) {
     369           0 :                                 return NULL;
     370             :                         }
     371          48 :                         psm_zero_or_one(cond);
     372          48 :                         ifst = exp_if(sql->sa, cond, if_stmts, NULL);
     373          48 :                         if (last_if) { /* chain if statements for case, keep the last if */
     374          36 :                                 last_if->f = list_append(sa_list(sql->sa), ifst);
     375          36 :                                 last_if = ifst;
     376             :                         } else {
     377             :                                 case_stmt = last_if = ifst;
     378             :                         }
     379          48 :                         n = n->next;
     380             :                 }
     381             :         } else {
     382             :                 /* case 2 */
     383          47 :                 dnode *n = case_when;
     384          47 :                 dlist *whenlist = n->data.lval;
     385          47 :                 dlist *else_statements = n->next->data.lval;
     386             : 
     387          47 :                 if (else_statements && !(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func)))
     388             :                         return NULL;
     389             : 
     390          47 :                 n = whenlist->h;
     391          97 :                 while(n) {
     392          50 :                         dnode *m = n->data.sym->data.lval->h;
     393          50 :                         sql_rel *rel = NULL;
     394          50 :                         exp_kind ek = {type_value, card_value, FALSE};
     395          50 :                         sql_exp *cond = rel_logical_value_exp(query, &rel, m->data.sym, sql_sel | sql_psm, ek);
     396          50 :                         list *if_stmts = NULL;
     397             : 
     398          50 :                         psm_zero_or_one(cond);
     399           0 :                         if (!cond ||
     400          50 :                            (if_stmts = sequential_block(query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) {
     401           0 :                                 return NULL;
     402             :                         }
     403          50 :                         ifst = exp_if(sql->sa, cond, if_stmts, NULL);
     404          50 :                         if (last_if) { /* chain if statements for case, keep the last if */
     405           3 :                                 last_if->f = list_append(sa_list(sql->sa), ifst);
     406           3 :                                 last_if = ifst;
     407             :                         } else {
     408             :                                 case_stmt = last_if = ifst;
     409             :                         }
     410          50 :                         n = n->next;
     411             :                 }
     412             :         }
     413          59 :         if (else_stmt) {
     414          51 :                 assert(case_stmt && last_if && !last_if->f);
     415          51 :                 last_if->f = else_stmt;
     416             :         }
     417             :         return case_stmt;
     418             : }
     419             : 
     420             : /* return val;
     421             :  */
     422             : static sql_exp *
     423       24270 : rel_psm_return( sql_query *query, sql_subtype *restype, list *restypelist, symbol *return_sym )
     424             : {
     425       24270 :         mvc *sql = query->sql;
     426       24270 :         exp_kind ek = {type_value, card_value, FALSE};
     427       24270 :         sql_exp *res = NULL;
     428       24270 :         sql_rel *rel = NULL;
     429       24270 :         bool requires_proj = false;
     430             : 
     431       24270 :         if (restypelist)
     432             :                 ek.card = card_relation;
     433       21394 :         else if (return_sym->token == SQL_TABLE)
     434           2 :                 return sql_error(sql, 02, SQLSTATE(42000) "RETURN: TABLE return not allowed for non table returning functions");
     435       24268 :         if (return_sym->token == SQL_COLUMN && restypelist) { /* RETURN x; where x is a reference to a table */
     436         572 :                 dlist *l = return_sym->data.lval;
     437         572 :                 const char *sname = qname_schema(l);
     438         572 :                 const char *tname = qname_schema_object(l);
     439         572 :                 sql_table *t = NULL;
     440             : 
     441         572 :                 if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "RETURN", false)))
     442             :                         return NULL;
     443         571 :                 if (isDeclaredTable(t)) {
     444          60 :                         rel = rel_table(sql, ddl_create_table, "sys", t, SQL_DECLARED_TABLE);
     445             :                 } else {
     446         511 :                         rel = rel_basetable(sql, t, t->base.name);
     447         511 :                         rel = rel_base_add_columns(sql, rel);
     448             :                 }
     449             :         } else { /* other cases */
     450       23696 :                 res = rel_value_exp2(query, &rel, return_sym, sql_sel, ek);
     451       23696 :                 if (!res)
     452             :                         return NULL;
     453       23686 :                 if (!rel && exp_is_rel(res)) {
     454        6407 :                         rel = exp_rel_get_rel(sql->sa, res);
     455        6407 :                         if (rel && !restypelist && !is_groupby(rel->op)) { /* On regular functions return zero or 1 rows for every row */
     456        4321 :                                 rel->card = CARD_MULTI;
     457        4321 :                                 rel = rel_return_zero_or_one(sql, rel, ek);
     458        4321 :                                 if (list_length(rel->exps) != 1)
     459           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "RETURN: must return a single column");
     460        4321 :                                 res = exp_ref(sql, (sql_exp*) rel->exps->t->data);
     461        4321 :                                 requires_proj = true;
     462             :                         }
     463             :                 }
     464             :         }
     465             : 
     466       24257 :         if (ek.card != card_relation && (!restype || (res = exp_check_type(sql, restype, rel, res, type_equal)) == NULL))
     467           0 :                 return (!restype)?sql_error(sql, 02, SQLSTATE(42000) "RETURN: return type does not match"):NULL;
     468       24257 :         else if (ek.card == card_relation && !rel)
     469             :                 return NULL;
     470             : 
     471       24257 :         if (requires_proj) {
     472        4321 :                 rel = rel_project(sql->sa, rel, list_append(sa_list(sql->sa), res));
     473        4321 :                 res = exp_rel(sql, rel);
     474             :         }
     475             : 
     476       27066 :         if (rel && !is_ddl(rel->op) && ek.card == card_relation) {
     477        2810 :                 list *exps = sa_list(sql->sa), *oexps = rel->exps;
     478        2810 :                 node *n, *m;
     479        2810 :                 int isproject = (rel->op == op_project);
     480        2810 :                 sql_rel *l = rel->l, *oexps_rel = rel;
     481             : 
     482        2810 :                 if (is_topn(rel->op) || is_sample(rel->op)) {
     483          14 :                         oexps_rel = l;
     484          14 :                         oexps = l->exps;
     485             :                 }
     486        2810 :                 if (list_length(oexps) != list_length(restypelist))
     487           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "RETURN: number of columns do not match");
     488       14150 :                 for (n = oexps->h, m = restypelist->h; n && m; n = n->next, m = m->next) {
     489       11341 :                         sql_exp *e = n->data;
     490       11341 :                         sql_arg *ce = m->data;
     491       11341 :                         const char *cname = exp_name(e);
     492       11341 :                         char name[16];
     493             : 
     494       11341 :                         if (!cname)
     495         106 :                                 cname = sa_strdup(sql->sa, number2name(name, sizeof(name), ++sql->label));
     496       11341 :                         if (!isproject)
     497        1123 :                                 e = exp_ref(sql, e);
     498       11341 :                         e = exp_check_type(sql, &ce->type, oexps_rel, e, type_equal);
     499       11341 :                         if (!e)
     500           0 :                                 return NULL;
     501       11341 :                         append(exps, e);
     502             :                 }
     503        2809 :                 if (isproject)
     504        2239 :                         rel->exps = exps;
     505             :                 else
     506         570 :                         rel = rel_project(sql->sa, rel, exps);
     507        2809 :                 res = exp_rel(sql, rel);
     508       21447 :         } else if (rel && restypelist) { /* handle return table-var */
     509          60 :                 list *exps = sa_list(sql->sa);
     510          60 :                 sql_rel *bt = rel_ddl_basetable_get(rel);
     511          60 :                 sql_table *t = rel_ddl_table_get(rel);
     512          60 :                 node *n, *m;
     513          60 :                 const char *tname = t->base.name;
     514             : 
     515          60 :                 if (ol_length(t->columns) != list_length(restypelist))
     516           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "RETURN: number of columns do not match");
     517         188 :                 for (n = ol_first_node(t->columns), m = restypelist->h; n && m; n = n->next, m = m->next) {
     518         129 :                         sql_column *c = n->data;
     519         129 :                         sql_arg *ce = m->data;
     520         129 :                         sql_exp *e = exp_column(sql->sa, tname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     521         129 :                         e->nid = rel_base_nid(bt, c);
     522         129 :                         e->alias.label = e->nid;
     523             : 
     524         129 :                         e = exp_check_type(sql, &ce->type, rel, e, type_equal);
     525         129 :                         if (!e)
     526             :                                 return NULL;
     527         129 :                         append(exps, e);
     528             :                 }
     529          59 :                 rel = rel_project(sql->sa, rel, exps);
     530          59 :                 res = exp_rel(sql, rel);
     531             :         }
     532       24255 :         res = exp_return(sql->sa, res, stack_nr_of_declared_tables(sql));
     533       24255 :         if (ek.card != card_relation)
     534       21387 :                 res->card = CARD_ATOM;
     535             :         else
     536        2868 :                 res->card = CARD_MULTI;
     537             :         return res;
     538             : }
     539             : 
     540             : static list *
     541        1475 : rel_select_into( sql_query *query, symbol *sq, exp_kind ek)
     542             : {
     543        1475 :         mvc *sql = query->sql;
     544        1475 :         SelectNode *sn = (SelectNode*)sq;
     545        1475 :         dlist *into = sn->into;
     546        1475 :         node *m;
     547        1475 :         dnode *n;
     548        1475 :         sql_rel *r;
     549        1475 :         list *nl = NULL;
     550             : 
     551             :         /* SELECT ... INTO var_list */
     552        1475 :         sn->into = NULL;
     553        1475 :         r = rel_subquery(query, sq, ek);
     554        1475 :         if (!r)
     555             :                 return NULL;
     556        1475 :         if (!is_project(r->op))
     557           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT INTO: The subquery is not a projection");
     558        1475 :         if (list_length(r->exps) != dlist_length(into))
     559           2 :                 return sql_error(sql, 02, SQLSTATE(21S01) "SELECT INTO: number of values doesn't match number of variables to set");
     560        1473 :         r = rel_return_zero_or_one(sql, r, ek);
     561        1473 :         nl = sa_list(sql->sa);
     562        1473 :         append(nl, exp_rel(sql, r));
     563        2953 :         for (m = r->exps->h, n = into->h; m && n; m = m->next, n = n->next) {
     564        1480 :                 dlist *qname = n->data.lval;
     565        1480 :                 const char *sname = qname_schema(qname);
     566        1480 :                 const char *vname = qname_schema_object(qname);
     567        1480 :                 sql_exp *v = m->data;
     568        1480 :                 int level;
     569        1480 :                 sql_var *var;
     570        1480 :                 sql_subtype *tpe;
     571        1480 :                 sql_arg *a = NULL;
     572             : 
     573        1480 :                 if (!find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SELECT INTO"))
     574           0 :                         return NULL;
     575             : 
     576        1480 :                 v = exp_ref(sql, v);
     577        1480 :                 if (!(v = exp_check_type(sql, tpe, r, v, type_equal)))
     578             :                         return NULL;
     579        1480 :                 v = exp_set(sql->sa, var && var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, vname), v, level);
     580        1480 :                 list_append(nl, v);
     581             :         }
     582             :         return nl;
     583             : }
     584             : 
     585             : extern sql_rel *
     586           1 : rel_select_with_into(sql_query *query, symbol *sq)
     587             : {
     588           1 :         exp_kind ek = {type_relation, card_value, TRUE};
     589           1 :         list *reslist = rel_select_into(query, sq, ek);
     590           1 :         if (!reslist)
     591             :                 return NULL;
     592           0 :         return rel_psm_block(query->sql->sa, reslist);
     593             : }
     594             : 
     595             : static int has_return( list *l );
     596             : 
     597             : static int
     598       21481 : exp_has_return(sql_exp *e)
     599             : {
     600       21481 :         if (e->type == e_psm) {
     601       21003 :                 if (e->flag & PSM_RETURN)
     602             :                         return 1;
     603        4254 :                 if (e->flag & PSM_IF) /* for if, both sides must exist and both must have a return */
     604        5088 :                         return has_return(e->r) && e->f && has_return(e->f);
     605             :         }
     606             :         return 0;
     607             : }
     608             : 
     609             : static int
     610       21481 : has_return( list *l )
     611             : {
     612       21481 :         node *n = l->t;
     613             : 
     614             :         /* last statement of sequential block */
     615       21481 :         if (n && exp_has_return(n->data))
     616             :                 return 1;
     617             :         return 0;
     618             : }
     619             : 
     620             : static list *
     621          60 : psm_analyze(sql_query *query, dlist *qname, dlist *columns)
     622             : {
     623          60 :         mvc *sql = query->sql;
     624          60 :         const char *sname = qname_schema(qname), *tname = qname_schema_object(qname);
     625          60 :         list *tl = sa_list(sql->sa), *exps = sa_list(sql->sa), *analyze_calls = sa_list(sql->sa);
     626          60 :         sql_subfunc *f = NULL;
     627          60 :         sql_subtype tpe;
     628             : 
     629          60 :         if (!sql_find_subtype(&tpe, "varchar", 1024, 0))
     630           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) "varchar type missing?");
     631             : 
     632          60 :         if (sname && tname) {
     633          53 :                 sql_table *t = NULL;
     634             : 
     635          53 :                 if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "ANALYZE", false)))
     636             :                         return NULL;
     637          53 :                 if (isDeclaredTable(t))
     638           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "Cannot analyze a declared table");
     639          53 :                 sname = t->s->base.name;
     640             :         }
     641             :         /* call analyze( [schema, [ table ]] ) */
     642          60 :         if (sname) {
     643          53 :                 sql_exp *sname_exp = exp_atom_str(sql->sa, sname, &tpe);
     644             : 
     645          53 :                 list_append(exps, sname_exp);
     646          53 :                 list_append(tl, exp_subtype(sname_exp));
     647             :         }
     648          60 :         if (tname) {
     649          60 :                 sql_exp *tname_exp = exp_atom_str(sql->sa, tname, &tpe);
     650             : 
     651          60 :                 list_append(exps, tname_exp);
     652          60 :                 list_append(tl, exp_subtype(tname_exp));
     653             : 
     654          60 :                 if (columns)
     655           7 :                         list_append(tl, exp_subtype(tname_exp));
     656             :         }
     657          60 :         if (!(f = sql_bind_func_(sql, "sys", "analyze", tl, F_PROC, true, false)))
     658           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Analyze procedure missing");
     659          60 :         if (!execute_priv(sql, f->func))
     660           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "No privilege to call analyze procedure");
     661          60 :         if (!columns) {
     662          53 :                 list_append(analyze_calls, exp_op(sql->sa, exps, f));
     663             :         } else {
     664           7 :                 if (!sname || !tname)
     665           2 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Analyze schema or table name missing");
     666          17 :                 for(dnode *n = columns->h; n; n = n->next) {
     667          12 :                         const char *cname = n->data.sval;
     668          12 :                         list *nexps = list_dup(exps, NULL);
     669          12 :                         sql_exp *cname_exp = exp_atom_str(sql->sa, cname, &tpe);
     670             : 
     671          12 :                         list_append(nexps, cname_exp);
     672             :                         /* call analyze(sname, tname, cname) */
     673          12 :                         list_append(analyze_calls, exp_op(sql->sa, nexps, f));
     674             :                 }
     675             :         }
     676             :         return analyze_calls;
     677             : }
     678             : 
     679             : static list *
     680       36388 : sequential_block(sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_label, int is_func)
     681             : {
     682       36388 :         mvc *sql = query->sql;
     683       36388 :         list *l=0;
     684       36388 :         dnode *n;
     685             : 
     686       36388 :         assert(!restype || !restypelist);
     687             : 
     688       36388 :         if (mvc_highwater(sql))
     689           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     690             : 
     691       36388 :         if (blk->h)
     692       36388 :                 l = sa_list(sql->sa);
     693       36388 :         if (!stack_push_frame(sql, opt_label))
     694           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     695      118605 :         for (n = blk->h; n; n = n->next ) {
     696       82260 :                 sql_exp *res = NULL;
     697       82260 :                 list *reslist = NULL;
     698       82260 :                 symbol *s = n->data.sym;
     699             : 
     700       82260 :                 switch (s->token) {
     701       14390 :                 case SQL_SET:
     702       14390 :                         res = psm_set_exp(query, s->data.lval->h);
     703       14390 :                         break;
     704        8357 :                 case SQL_DECLARE:
     705        8357 :                         reslist = rel_psm_declare(sql, s->data.lval->h);
     706        8357 :                         break;
     707         122 :                 case SQL_DECLARE_TABLE:
     708             :                 case SQL_CREATE_TABLE:
     709         122 :                         res = rel_psm_declare_table(query, s->data.lval->h);
     710         122 :                         break;
     711        1023 :                 case SQL_WHILE:
     712        1023 :                         res = rel_psm_while_do(query, restype, restypelist, s->data.lval->h, is_func);
     713        1023 :                         break;
     714       11637 :                 case SQL_IF:
     715       11637 :                         res = rel_psm_if_then_else(query, restype, restypelist, s->data.lval->h, is_func);
     716       11637 :                         break;
     717          59 :                 case SQL_CASE:
     718          59 :                         res = rel_psm_case(query, restype, restypelist, s->data.lval->h, is_func);
     719          59 :                         break;
     720          20 :                 case SQL_ANALYZE: {
     721          20 :                         dlist *l = s->data.lval;
     722             : 
     723          20 :                         reslist = psm_analyze(query, l->h->data.lval /* qualified table name */, l->h->next->data.lval /* opt list of column */);
     724          20 :                 }       break;
     725        1881 :                 case SQL_CALL:
     726        1881 :                         assert(s->type == type_symbol);
     727        1881 :                         res = rel_psm_call(query, s->data.sym);
     728        1881 :                         break;
     729       24270 :                 case SQL_RETURN:
     730             :                         /*If it is not a function it cannot have a return statement*/
     731       24270 :                         if (!is_func)
     732           0 :                                 res = sql_error(sql, 01, SQLSTATE(42000) "Return statement in the procedure body");
     733       24270 :                         else if (n->next) /* should be last statement of a sequential_block */
     734           0 :                                 res = sql_error(sql, 01, SQLSTATE(42000) "Statement after return");
     735             :                         else
     736       24270 :                                 res = rel_psm_return(query, restype, restypelist, s->data.sym);
     737             :                         break;
     738        1474 :                 case SQL_SELECT: { /* row selections (into variables) */
     739        1474 :                         exp_kind ek = {type_value, card_row, TRUE};
     740        1474 :                         reslist = rel_select_into(query, s, ek);
     741        1474 :                 }       break;
     742       19027 :                 case SQL_COPYFROM:
     743             :                 case SQL_BINCOPYFROM:
     744             :                 case SQL_INSERT:
     745             :                 case SQL_UPDATE:
     746             :                 case SQL_DELETE:
     747             :                 case SQL_TRUNCATE:
     748             :                 case SQL_MERGE: {
     749       19027 :                         sql_rel *r = rel_updates(query, s);
     750       19027 :                         if (!r) {
     751           8 :                                 stack_pop_frame(sql);
     752           8 :                                 return NULL;
     753             :                         }
     754       19019 :                         res = exp_rel(sql, r);
     755       19019 :                 }       break;
     756           0 :                 default:
     757           0 :                         res = sql_error(sql, 01, SQLSTATE(42000) "Statement '%s' is not a valid flow control statement",
     758             :                          token2string(s->token));
     759             :                 }
     760       82252 :                 if (!res && !reslist) {
     761             :                         l = NULL;
     762             :                         break;
     763             :                 }
     764       82217 :                 if (res)
     765       72370 :                         list_append(l, res);
     766             :                 else
     767        9847 :                         list_merge(l, reslist, NULL);
     768             :         }
     769       36380 :         stack_pop_frame(sql);
     770       36380 :         return l;
     771             : }
     772             : 
     773             : static int
     774      633494 : arg_cmp(void *A, void *N)
     775             : {
     776      633494 :         sql_arg *a = A;
     777      633494 :         char *name = N;
     778      633494 :         return strcmp(a->name, name);
     779             : }
     780             : 
     781             : static list *
     782      206279 : result_type(mvc *sql, symbol *res)
     783             : {
     784      206279 :         if (res->token == SQL_TYPE) {
     785      181161 :                 sql_subtype *st = &res->data.lval->h->data.typeval;
     786      181161 :                 sql_arg *a = sql_create_arg(sql->sa, "result", st, ARG_OUT);
     787             : 
     788      181161 :                 return list_append(sa_list(sql->sa), a);
     789       25118 :         } else if (res->token == SQL_TABLE) {
     790       25118 :                 sql_arg *a;
     791       25118 :                 dnode *n = res->data.lval->h;
     792       25118 :                 list *types = sa_list(sql->sa);
     793             : 
     794      186412 :                 for(;n; n = n->next->next) {
     795      136177 :                         sql_subtype *ct = &n->next->data.typeval;
     796             : 
     797      136177 :                         if (list_find(types, n->data.sval, &arg_cmp) != NULL)
     798           1 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "CREATE FUNC: identifier '%s' ambiguous", n->data.sval);
     799             : 
     800      136176 :                         a = sql_create_arg(sql->sa, n->data.sval, ct, ARG_OUT);
     801      136176 :                         list_append(types, a);
     802             :                 }
     803             :                 return types;
     804             :         }
     805             :         return NULL;
     806             : }
     807             : 
     808             : static list *
     809      340829 : create_type_list(mvc *sql, dlist *params, int param)
     810             : {
     811      340829 :         sql_subtype *par_subtype;
     812      340829 :         list * type_list = sa_list(sql->sa);
     813      340829 :         dnode * n = NULL;
     814             : 
     815      340829 :         if (params) {
     816      863458 :                 for (n = params->h; n; n = n->next) {
     817      540575 :                         dnode *an = n;
     818             : 
     819      540575 :                         if (param) {
     820      383235 :                                 an = n->data.lval->h;
     821      383235 :                                 par_subtype = &an->next->data.typeval;
     822      383235 :                                 if (par_subtype && !par_subtype->type) /* var arg */
     823             :                                         return type_list;
     824      383231 :                                 list_append(type_list, par_subtype);
     825             :                         } else {
     826      157340 :                                 par_subtype = &an->data.typeval;
     827      157340 :                                 list_prepend(type_list, par_subtype);
     828             :                         }
     829             :                 }
     830             :         }
     831             :         return type_list;
     832             : }
     833             : 
     834             : static sql_rel*
     835      235776 : rel_create_function(allocator *sa, const char *sname, sql_func *f, int replace)
     836             : {
     837      235776 :         sql_rel *rel = rel_create(sa);
     838      235776 :         list *exps = new_exp_list(sa);
     839      235776 :         if(!rel || !exps)
     840             :                 return NULL;
     841             : 
     842      235776 :         append(exps, exp_atom_clob(sa, sname));
     843      235776 :         if (f)
     844      235776 :                 append(exps, exp_atom_clob(sa, f->base.name));
     845      235776 :         append(exps, exp_atom_ptr(sa, f));
     846      235776 :         append(exps, exp_atom_int(sa, replace));
     847      235776 :         rel->l = NULL;
     848      235776 :         rel->r = NULL;
     849      235776 :         rel->op = op_ddl;
     850      235776 :         rel->flag = ddl_create_function;
     851      235776 :         rel->exps = exps;
     852      235776 :         rel->card = 0;
     853      235776 :         rel->nrcols = 0;
     854      235776 :         return rel;
     855             : }
     856             : 
     857             : static bool
     858         234 : has_generic_decimal(list *types)
     859             : {
     860         234 :         if (!list_empty(types)) {
     861         439 :                 for(node *n = types->h; n; n = n->next) {
     862         269 :                         sql_subtype *st = n->data;
     863             : 
     864         269 :                         if (st->type->eclass == EC_DEC && !st->digits && !st->scale)
     865             :                                 return true;
     866             :                 }
     867             :         }
     868             :         return false;
     869             : }
     870             : 
     871             : static bool
     872         232 : has_generic_decimal_result(list *types)
     873             : {
     874         232 :         if (!list_empty(types)) {
     875         508 :                 for(node *n = types->h; n; n = n->next) {
     876         289 :                         sql_arg *a = n->data;
     877             : 
     878         289 :                         if (a->type.type->eclass == EC_DEC && !a->type.digits && !a->type.scale)
     879             :                                 return true;
     880             :                 }
     881             :         }
     882             :         return false;
     883             : }
     884             : 
     885             : 
     886             : static sql_rel *
     887      244520 : rel_create_func(sql_query *query, dlist *qname, dlist *params, symbol *res, dlist *ext_name, dlist *body, sql_ftype type, sql_flang lang, int replace, int order_spec)
     888             : {
     889      244520 :         mvc *sql = query->sql;
     890      244520 :         const char *fname = qname_schema_object(qname);
     891      244520 :         const char *sname = qname_schema(qname);
     892      244520 :         sql_schema *s = cur_schema(sql);
     893      244520 :         sql_func *f = NULL;
     894      244520 :         sql_subfunc *sf = NULL;
     895      244520 :         dnode *n;
     896      244520 :         list *type_list = NULL, *restype = NULL, *l = NULL;
     897      244520 :         int instantiate = (sql->emode == m_instantiate);
     898      244520 :         int deps = (sql->emode == m_deps);
     899      244520 :         int create = (!instantiate && !deps);
     900      244520 :         bit vararg = FALSE, union_err = 0;
     901      244520 :         char *F = NULL, *fn = NULL, is_func, *q = QUERY(sql->scanner);
     902      244520 :         bit order_required = (order_spec == 2);
     903      244520 :         bit opt_order = (order_spec == 1);
     904             : 
     905      244520 :         if (res && res->token == SQL_TABLE) {
     906       25120 :                 if (type == F_FUNC)
     907             :                         type = F_UNION;
     908             :                 else
     909             :                         union_err = 1;
     910             :         }
     911             : 
     912      219401 :         FUNC_TYPE_STR(type, F, fn)
     913             : 
     914      244520 :         is_func = (type != F_PROC && type != F_LOADER);
     915      244520 :         assert(lang != FUNC_LANG_INT);
     916             : 
     917      244520 :         if (create && store_readonly(sql->session->tr->store))
     918           0 :                 return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
     919             : 
     920      244520 :         if (union_err)
     921           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %ss cannot return tables", F, fn);
     922      244519 :         else if (res && type == F_PROC)
     923           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: procedures cannot have return parameters", F);
     924      244519 :         else if (res && (type == F_FILT || type == F_LOADER))
     925           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %s functions don't have to specify a return type", F, fn);
     926       38228 :         else if (!res && !(type == F_PROC || type == F_FILT || type == F_LOADER))
     927           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %ss require a return type", F, fn);
     928      244519 :         else if (lang == FUNC_LANG_MAL && type == F_LOADER)
     929           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %s functions creation via MAL not supported", F, fn);
     930      244519 :         else if (lang == FUNC_LANG_SQL && !(type == F_FUNC || type == F_PROC || type == F_UNION))
     931           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %s functions creation via SQL not supported", F, fn);
     932      244519 :         else if (LANG_EXT(lang) && !(type == F_FUNC || type == F_AGGR || type == F_UNION || type == F_LOADER))
     933           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: %ss creation via external programming languages not supported", F, fn);
     934             : 
     935      244519 :         if (sname && !(s = mvc_bind_schema(sql, sname)))
     936           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "CREATE %s: no such schema '%s'", F, sname);
     937      244519 :         if (create && !mvc_schema_privs(sql, s))
     938           5 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: insufficient privileges for user '%s' in schema '%s'", F,
     939             :                                                  get_string_global_var(sql, "current_user"), s->base.name);
     940             : 
     941      244514 :         type_list = create_type_list(sql, params, 1);
     942             : 
     943      244514 :         if ((sf = sql_bind_func_(sql, s->base.name, fname, type_list, type, true, true)) != NULL && create) {
     944          31 :                 if (sf->func->private) { /* cannot create a function using a private name or replace a existing one */
     945           2 :                         list_destroy(type_list);
     946           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' cannot be used", F, fname);
     947             :                 }
     948          29 :                 if (!replace && params) {
     949           0 :                         char *arg_list = NULL;
     950           0 :                         node *n;
     951             : 
     952           0 :                         for (n = type_list->h; n; n = n->next) {
     953           0 :                                 char *tpe =  sql_subtype_string(sql->ta, (sql_subtype *) n->data);
     954             : 
     955           0 :                                 if (arg_list) {
     956           0 :                                         arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe);
     957             :                                 } else {
     958             :                                         arg_list = tpe;
     959             :                                 }
     960             :                         }
     961           0 :                         (void)sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' (%s) already in use", F, fname, arg_list ? arg_list : "");
     962           0 :                         list_destroy(type_list);
     963           0 :                         return NULL;
     964          29 :                 } else if (!replace) {
     965           2 :                         list_destroy(type_list);
     966           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' already in use", F, fname);
     967          27 :                 } else if (replace && !sf->func->s) {
     968           0 :                         list_destroy(type_list);
     969           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: cannot replace system function '%s'", F, fname);
     970             :                 }
     971             :         } else {
     972      244483 :                 sql->session->status = 0; /* if the function was not found clean the error */
     973      244483 :                 sql->errstr[0] = '\0';
     974             :         }
     975             : 
     976      244510 :         if (create && (type == F_FUNC || type == F_AGGR || type == F_FILT)) {
     977       82340 :                 sql_subfunc *found = NULL;
     978      108848 :                 if ((found = sql_bind_func_(sql, s->base.name, fname, type_list, (type == F_FUNC || type == F_FILT) ? F_AGGR : F_FUNC, true, true))) {
     979           2 :                         list_destroy(type_list);
     980           2 :                         if (found->func->private) /* cannot create a function using a private name or replace a existing one */
     981           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: name '%s' cannot be used", F, fname);
     982           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: there's %s with the name '%s' and the same parameters, which causes ambiguous calls", F,
     983           2 :                                                          IS_AGGR(found->func) ? "an aggregate" : IS_FILT(found->func) ? "a filter function" : "a function", fname);
     984             :                 }
     985       82338 :                 sql->session->status = 0; /* if the function was not found clean the error */
     986       82338 :                 sql->errstr[0] = '\0';
     987             :         }
     988      244508 :         if (lang > FUNC_LANG_SQL && has_generic_decimal(type_list))
     989           2 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: the function '%s' uses a generic DECIMAL type, UDFs require precision and scale", F, fname);
     990             : 
     991      244506 :         list_destroy(type_list);
     992             : 
     993      244506 :         if (params) {
     994      609793 :                 for (n = params->h; n; n = n->next) {
     995      383227 :                         dnode *an = n->data.lval->h;
     996      383227 :                         sql_add_param(sql, an->data.sval, &an->next->data.typeval);
     997             :                 }
     998      226566 :                 l = sql->params;
     999      226566 :                 if (l && list_length(l) == 1) {
    1000      108522 :                         sql_arg *a = l->h->data;
    1001             : 
    1002      108522 :                         if (strcmp(a->name, "*") == 0) {
    1003             :                                 l = NULL;
    1004             :                                 vararg = TRUE;
    1005             :                         }
    1006             :                 }
    1007             :         }
    1008             :         if (!l)
    1009       17944 :                 l = sa_list(sql->sa);
    1010      244506 :         if (res && !(restype = result_type(sql, res)))
    1011           1 :                 return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: failed to get restype", F);
    1012             : 
    1013      244505 :         if (lang > FUNC_LANG_SQL && has_generic_decimal_result(restype))
    1014           2 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s: the function '%s' returns a generic DECIMAL type, UDFs require precision and scale", F, fname);
    1015      244503 :         if (body && LANG_EXT(lang)) {
    1016         230 :                 const char *lang_body = body->h->data.sval, *mod = "unknown", *slang = "Unknown", *imp = "Unknown";
    1017         230 :                 switch (lang) {
    1018             :                 case FUNC_LANG_R:
    1019             :                         mod = "rapi";
    1020             :                         slang = "R";
    1021             :                         break;
    1022          43 :                 case FUNC_LANG_C:
    1023          43 :                         mod = "capi";
    1024          43 :                         slang = "C";
    1025          43 :                         break;
    1026           1 :                 case FUNC_LANG_CPP:
    1027           1 :                         mod = "capi";
    1028           1 :                         slang = "CPP";
    1029           1 :                         break;
    1030           0 :                 case FUNC_LANG_J:
    1031           0 :                         mod = "japi";
    1032           0 :                         slang = "Javascript";
    1033           0 :                         break;
    1034         149 :                 case FUNC_LANG_PY:
    1035             :                 case FUNC_LANG_PY3:
    1036         149 :                         mod = "pyapi3";
    1037         149 :                         slang = "Python";
    1038         149 :                         break;
    1039           0 :                 default:
    1040           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "Function language without a MAL backend");
    1041             :                 }
    1042         230 :                 switch(type) {
    1043             :                 case F_AGGR:
    1044             :                         imp = "eval_aggr";
    1045             :                         break;
    1046             :                 case F_LOADER:
    1047          11 :                         imp = "eval_loader";
    1048          11 :                         break;
    1049             :                 default: /* for every other function type at the moment */
    1050         187 :                         imp = "eval";
    1051             :                 }
    1052             : 
    1053         198 :                 if (type == F_LOADER && !(lang == FUNC_LANG_PY || lang == FUNC_LANG_PY3))
    1054           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: Language name \"Python[3]\" expected", F);
    1055             : 
    1056         230 :                 sql->params = NULL;
    1057         230 :                 if (create) {
    1058         230 :                         bit side_effect = (list_empty(restype) || (!vararg && list_empty(l))); /* TODO make this more precise? */
    1059         230 :                         switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, mod, imp, lang_body, (type == F_LOADER)?TRUE:FALSE, vararg, FALSE, side_effect, order_required, opt_order)) {
    1060           0 :                                 case -1:
    1061           0 :                                         return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1062           0 :                                 case -2:
    1063             :                                 case -3:
    1064           0 :                                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: transaction conflict detected", F);
    1065             :                                 default:
    1066             :                                         break;
    1067             :                         }
    1068           0 :                 } else if (!sf) {
    1069           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: %s function %s.%s not bound", F, slang, s->base.name, fname);
    1070             :                 }
    1071      244273 :         } else if (body) { /* SQL implementation */
    1072       16863 :                 sql_arg *ra = (restype && type != F_UNION)?restype->h->data:NULL;
    1073       16863 :                 list *b = NULL;
    1074       16863 :                 sql_schema *os = cur_schema(sql);
    1075             : 
    1076       16863 :                 if (create) { /* needed for recursive functions */
    1077        8178 :                         bit side_effect = list_empty(restype) == 1; /* TODO make this more precise? */
    1078        8178 :                         q = query_cleaned(sql->ta, q);
    1079        8178 :                         switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, sql_shared_module_name, NULL, q, FALSE, vararg, FALSE, side_effect, order_required, opt_order)) {
    1080           0 :                                 case -1:
    1081           0 :                                         return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1082           0 :                                 case -2:
    1083             :                                 case -3:
    1084           0 :                                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: transaction conflict detected", F);
    1085             :                                 default:
    1086        8178 :                                         break;
    1087             :                         }
    1088        8178 :                         sql->forward = f;
    1089        8685 :                 } else if (!sf) {
    1090           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: SQL function %s.%s not bound", F, s->base.name, fname);
    1091             :                 }
    1092       16863 :                 sql->session->schema = s;
    1093       16863 :                 b = sequential_block(query, (ra)?&ra->type:NULL, ra?NULL:restype, body, NULL, is_func);
    1094       16863 :                 sql->forward = NULL;
    1095       16863 :                 sql->session->schema = os;
    1096       16863 :                 sql->params = NULL;
    1097       16863 :                 if (!b)
    1098             :                         return NULL;
    1099             : 
    1100             :                 /* check if we have a return statement */
    1101       16827 :                 if (is_func && restype && !has_return(b))
    1102           4 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: missing return statement", F);
    1103       16823 :                 if (!is_func && !restype && has_return(b))
    1104           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: %ss cannot have return statements", F, fn);
    1105             :                 /* in execute mode we instantiate the function */
    1106       16823 :                 if (instantiate || deps)
    1107        8683 :                         return rel_psm_block(sql->sa, b);
    1108             :         } else { /* MAL implementation */
    1109      227410 :                 int clientid = sql->clientid;
    1110      227410 :                 char *fmod = qname_module(ext_name);
    1111      227410 :                 char *fnme = qname_schema_object(ext_name);
    1112             : 
    1113      227410 :                 if (!fmod || !fnme)
    1114           4 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: MAL module or function name missing", F);
    1115      227410 :                 if (strlen(fmod) >= IDLENGTH)
    1116           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: MAL module name '%s' too large for the backend", F, fmod);
    1117      227410 :                 if (strlen(fnme) >= IDLENGTH)
    1118           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: MAL function name '%s' too large for the backend", F, fnme);
    1119      227410 :                 sql->params = NULL;
    1120      227410 :                 if (create) {
    1121      113707 :                         q = query_cleaned(sql->ta, q);
    1122      113707 :                         switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, fmod, fnme, q, FALSE, vararg, FALSE, FALSE, order_required, opt_order)) {
    1123           0 :                                 case -1:
    1124           4 :                                         return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1125           0 :                                 case -2:
    1126             :                                 case -3:
    1127           0 :                                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: transaction conflict detected", F);
    1128             :                                 default:
    1129      113707 :                                         break;
    1130             :                         }
    1131             : 
    1132             :                         /* instantiate MAL functions while being created. This also sets the side-effects flag */
    1133      113707 :                         bool se = f->side_effect;
    1134      113707 :                         if (!backend_resolve_function(&clientid, f, fnme, &se))
    1135           4 :                                 return sql_error(sql, 02, SQLSTATE(3F000) "CREATE %s: external name %s.%s not bound (%s.%s)", F, fmod, fnme, s->base.name, fname );
    1136      113703 :                         f->side_effect = se;
    1137      113703 :                         f->instantiated = TRUE;
    1138      113703 :                 } else if (!sf) {
    1139           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s: external name %s.%s not bound (%s.%s)", F, fmod, fnme, s->base.name, fname );
    1140             :                 }
    1141      227406 :                 if (!f)
    1142      113703 :                         f = sf->func;
    1143      227406 :                 assert(f);
    1144             :         }
    1145      235776 :         return rel_create_function(sql->sa, s->base.name, f, replace);
    1146             : }
    1147             : 
    1148             : static sql_rel*
    1149         686 : rel_drop_function(allocator *sa, const char *sname, const char *name, int nr, sql_ftype type, int action)
    1150             : {
    1151         686 :         sql_rel *rel = rel_create(sa);
    1152         686 :         list *exps = new_exp_list(sa);
    1153         686 :         if(!rel || !exps)
    1154             :                 return NULL;
    1155             : 
    1156         686 :         append(exps, exp_atom_clob(sa, sname));
    1157         686 :         append(exps, exp_atom_clob(sa, name));
    1158         686 :         append(exps, exp_atom_int(sa, nr));
    1159         686 :         append(exps, exp_atom_int(sa, (int) type));
    1160         686 :         append(exps, exp_atom_int(sa, action));
    1161         686 :         rel->l = NULL;
    1162         686 :         rel->r = NULL;
    1163         686 :         rel->op = op_ddl;
    1164         686 :         rel->flag = ddl_drop_function;
    1165         686 :         rel->exps = exps;
    1166         686 :         rel->card = 0;
    1167         686 :         rel->nrcols = 0;
    1168         686 :         return rel;
    1169             : }
    1170             : 
    1171             : sql_func *
    1172      100671 : resolve_func(mvc *sql, const char *sname, const char *name, dlist *typelist, sql_ftype type, const char *op, int if_exists)
    1173             : {
    1174      100671 :         sql_func *func = NULL;
    1175      100671 :         list *list_func = NULL, *type_list = NULL;
    1176      100671 :         char is_func = (type != F_PROC && type != F_LOADER), *F = NULL, *fn = NULL;
    1177             : 
    1178      100671 :         FUNC_TYPE_STR(type, F, fn)
    1179             : 
    1180      100671 :         if (typelist) {
    1181       96315 :                 sql_subfunc *sub_func;
    1182             : 
    1183       96315 :                 type_list = create_type_list(sql, typelist, 0);
    1184       96315 :                 sub_func = sql_bind_func_(sql, sname, name, type_list, type, false, true);
    1185       96315 :                 if (!sub_func && type == F_FUNC) {
    1186        6079 :                         sql->session->status = 0; /* if the function was not found clean the error */
    1187        6079 :                         sql->errstr[0] = '\0';
    1188        6079 :                         sub_func = sql_bind_func_(sql, sname, name, type_list, F_UNION, false, true);
    1189        6079 :                         type = sub_func?F_UNION:F_FUNC;
    1190             :                 }
    1191       96296 :                 if ( sub_func && sub_func->func->type == type)
    1192       96292 :                         func = sub_func->func;
    1193             :         } else {
    1194        4356 :                 list_func = sql_find_funcs_by_name(sql, sname, name, type, false);
    1195        4356 :                 if (!list_func && type == F_FUNC) {
    1196        1250 :                         sql->session->status = 0; /* if the function was not found clean the error */
    1197        1250 :                         sql->errstr[0] = '\0';
    1198        1250 :                         list_func = sql_find_funcs_by_name(sql, sname, name, F_UNION, false);
    1199             :                 }
    1200        4356 :                 if (list_func && list_func->cnt > 1) {
    1201           3 :                         list_destroy(list_func);
    1202           3 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: there are more than one %s called '%s', please use the full signature", op, F, fn, name);
    1203             :                 }
    1204        4346 :                 if (list_func && list_func->cnt == 1)
    1205        4346 :                         func = (sql_func*) list_func->h->data;
    1206             :         }
    1207             : 
    1208      100668 :         if (!func) {
    1209          30 :                 void *e = NULL;
    1210          30 :                 if (typelist) {
    1211          23 :                         char *arg_list = NULL;
    1212          23 :                         node *n;
    1213             : 
    1214          23 :                         if (type_list->cnt > 0) {
    1215          49 :                                 for (n = type_list->h; n; n = n->next) {
    1216          30 :                                         char *tpe =  sql_subtype_string(sql->ta, (sql_subtype *) n->data);
    1217             : 
    1218          30 :                                         if (arg_list) {
    1219          11 :                                                 arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe);
    1220             :                                         } else {
    1221             :                                                 arg_list = tpe;
    1222             :                                         }
    1223             :                                 }
    1224          19 :                                 list_destroy(list_func);
    1225          19 :                                 list_destroy(type_list);
    1226          19 :                                 if (!if_exists)
    1227          16 :                                         e = sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: no such %s '%s' (%s)", op, F, fn, name, arg_list);
    1228          19 :                                 return e;
    1229             :                         }
    1230           4 :                         list_destroy(list_func);
    1231           4 :                         list_destroy(type_list);
    1232           4 :                         if (!if_exists)
    1233           2 :                                 e = sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: no such %s '%s' ()", op, F, fn, name);
    1234           4 :                         return e;
    1235             :                 } else {
    1236           7 :                         if (!if_exists)
    1237           5 :                                 e = sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: no such %s '%s'", op, F, fn, name);
    1238           7 :                         return e;
    1239             :                 }
    1240      100638 :         } else if (((is_func && type != F_FILT) && !func->res) || (!is_func && func->res)) {
    1241           0 :                 list_destroy(list_func);
    1242           0 :                 list_destroy(type_list);
    1243           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s: cannot drop %s '%s'", op, F, fn, name);
    1244             :         }
    1245             : 
    1246      100638 :         list_destroy(list_func);
    1247      100638 :         list_destroy(type_list);
    1248      100638 :         return func;
    1249             : }
    1250             : 
    1251             : static sql_rel*
    1252         686 : rel_drop_func(mvc *sql, dlist *qname, dlist *typelist, int drop_action, sql_ftype type, int if_exists)
    1253             : {
    1254         686 :         const char *name = qname_schema_object(qname);
    1255         686 :         const char *sname = qname_schema(qname);
    1256         686 :         sql_func *func = NULL;
    1257         686 :         char *F = NULL, *fn = NULL;
    1258             : 
    1259         686 :         FUNC_TYPE_STR(type, F, fn)
    1260             : 
    1261         686 :         if (!(func = resolve_func(sql, sname, name, typelist, type, "DROP", if_exists))) {
    1262          32 :                 if (if_exists) {
    1263           7 :                         sql->errstr[0] = '\0'; /* reset function not found error */
    1264           7 :                         sql->session->status = 0;
    1265           7 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1266             :                 }
    1267             :                 return NULL;
    1268             :         }
    1269         654 :         if (!func->s) /* attempting to drop a system function */
    1270           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DROP %s: cannot drop system %s '%s'", F, fn, name);
    1271         654 :         if (!mvc_schema_privs(sql, func->s))
    1272           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DROP %s: insufficient privileges for user '%s' in schema '%s'", F, get_string_global_var(sql, "current_user"), func->s->base.name);
    1273         654 :         return rel_drop_function(sql->sa, func->s->base.name, name, func->base.id, type, drop_action);
    1274             : }
    1275             : 
    1276             : static sql_rel*
    1277         110 : rel_drop_all_func(mvc *sql, dlist *qname, int drop_action, sql_ftype type)
    1278             : {
    1279         110 :         const char *name = qname_schema_object(qname);
    1280         110 :         const char *sname = qname_schema(qname);
    1281         110 :         sql_schema *s = cur_schema(sql);
    1282         110 :         list *list_func = NULL;
    1283         110 :         char *F = NULL, *fn = NULL;
    1284             : 
    1285         110 :         FUNC_TYPE_STR(type, F, fn)
    1286             : 
    1287         110 :         if (sname && !(s = mvc_bind_schema(sql, sname)))
    1288           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "DROP ALL %s: no such schema '%s'", F, sname);
    1289         110 :         if (!mvc_schema_privs(sql, s))
    1290           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DROP ALL %s: insufficient privileges for user '%s' in schema '%s'", F, get_string_global_var(sql, "current_user"), s->base.name);
    1291             : 
    1292         110 :         if (!(list_func = sql_find_funcs_by_name(sql, s->base.name, name, type, false)) || list_empty(list_func)) {
    1293          78 :                 list_destroy(list_func);
    1294          78 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "DROP ALL %s: no such %s '%s'", F, fn, name);
    1295             :         }
    1296          32 :         list_destroy(list_func);
    1297          32 :         return rel_drop_function(sql->sa, s->base.name, name, -1, type, drop_action);
    1298             : }
    1299             : 
    1300             : static sql_rel *
    1301         346 : rel_create_trigger(mvc *sql, const char *sname, const char *tname, const char *triggername, int time, int orientation, int event, const char *old_name, const char *new_name, symbol *condition, const char *query, int replace)
    1302             : {
    1303         346 :         sql_rel *rel = rel_create(sql->sa);
    1304         346 :         list *exps = new_exp_list(sql->sa);
    1305         346 :         if(!rel || !exps)
    1306             :                 return NULL;
    1307             : 
    1308         346 :         append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
    1309         346 :         append(exps, exp_atom_str(sql->sa, tname, sql_bind_localtype("str") ));
    1310         346 :         append(exps, exp_atom_str(sql->sa, triggername, sql_bind_localtype("str") ));
    1311         346 :         append(exps, exp_atom_int(sql->sa, time));
    1312         346 :         append(exps, exp_atom_int(sql->sa, orientation));
    1313         346 :         append(exps, exp_atom_int(sql->sa, event));
    1314         346 :         append(exps, exp_atom_str(sql->sa, old_name, sql_bind_localtype("str") ));
    1315         346 :         append(exps, exp_atom_str(sql->sa, new_name, sql_bind_localtype("str") ));
    1316         346 :         (void)condition;
    1317         346 :         append(exps, exp_atom_str(sql->sa, NULL, sql_bind_localtype("str") ));
    1318         346 :         append(exps, exp_atom_str(sql->sa, query, sql_bind_localtype("str") ));
    1319         346 :         append(exps, exp_atom_int(sql->sa, replace));
    1320         346 :         rel->l = NULL;
    1321         346 :         rel->r = NULL;
    1322         346 :         rel->op = op_ddl;
    1323         346 :         rel->flag = ddl_create_trigger;
    1324         346 :         rel->exps = exps;
    1325         346 :         rel->card = CARD_MULTI;
    1326         346 :         rel->nrcols = 0;
    1327         346 :         return rel;
    1328             : }
    1329             : 
    1330             : static sql_rel_view*
    1331          67 : _stack_push_table(mvc *sql, const char *tname, sql_table *t)
    1332             : {
    1333          67 :         sql_rel *r = rel_basetable(sql, t, tname );
    1334          67 :         rel_base_use_all(sql, r);
    1335          67 :         r = rewrite_basetable(sql, r);
    1336          67 :         return stack_push_rel_view(sql, tname, r);
    1337             : }
    1338             : 
    1339             : static sql_rel *
    1340        5636 : create_trigger(sql_query *query, dlist *qname, int time, symbol *trigger_event, dlist *tqname, dlist *opt_ref, dlist *triggered_action, int replace)
    1341             : {
    1342        5636 :         mvc *sql = query->sql;
    1343        5636 :         const char *triggerschema = qname_schema(qname);
    1344        5636 :         const char *triggername = qname_schema_object(qname);
    1345        5636 :         char *sname = tqname? qname_schema(tqname) : NULL;
    1346        5627 :         char *tname = tqname? qname_schema_object(tqname) : NULL;
    1347        5636 :         int instantiate = (sql->emode == m_instantiate);
    1348        5636 :         int create = (!instantiate && sql->emode != m_deps), event, orientation;
    1349        5636 :         sql_schema *ss = cur_schema(sql), *old_schema = cur_schema(sql);
    1350        5636 :         sql_table *t = NULL;
    1351        5636 :         list *sq = NULL;
    1352        5636 :         sql_rel *r = NULL;
    1353        5636 :         char *q, *base = replace ? "CREATE OR REPLACE TRIGGER" : "CREATE TRIGGER";
    1354        5636 :         dlist *columns = trigger_event->data.lval;
    1355        5636 :         const char *old_name = NULL, *new_name = NULL;
    1356        5636 :         dlist *stmts = triggered_action->h->next->next->data.lval;
    1357        5636 :         symbol *condition = triggered_action->h->next->data.sym;
    1358        5636 :         bool old_useviews = sql->use_views;
    1359             : 
    1360        5636 :         if (opt_ref) {
    1361         178 :                 dnode *dl = opt_ref->h;
    1362         401 :                 for ( ; dl; dl = dl->next) {
    1363             :                         /* list (new(1)/old(0)), char */
    1364         223 :                         char *n = dl->data.lval->h->next->data.sval;
    1365             : 
    1366         223 :                         assert(dl->data.lval->h->type == type_int);
    1367         223 :                         if (!dl->data.lval->h->data.i_val) /*?l_val?*/
    1368             :                                 old_name = n;
    1369             :                         else
    1370         143 :                                 new_name = n;
    1371             :                 }
    1372             :         }
    1373             : 
    1374        5636 :         if (sname && !(ss = mvc_bind_schema(sql, sname)))
    1375           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "%s: no such schema '%s'", base, sname);
    1376             : 
    1377        5636 :         if (create) {
    1378         355 :                 if (triggerschema)
    1379           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: a trigger will be placed on the respective table's schema, specify the schema on the table reference, ie ON clause instead", base);
    1380         353 :                 if (tname) {
    1381         349 :                         if (!(t = mvc_bind_table(sql, ss, tname)))
    1382           4 :                                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "%s: no such table %s%s%s'%s'", base, sname ? "'":"", sname ? sname : "", sname ? "'.":"", tname);
    1383         347 :                         if (isView(t))
    1384           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot create trigger on view '%s'", base, tname);
    1385         346 :                         sname = t->s->base.name;
    1386         346 :                         tname = t->base.name;
    1387             :                 }
    1388         350 :                 if (!mvc_schema_privs(sql, ss))
    1389           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: access denied for %s to schema '%s'", base, get_string_global_var(sql, "current_user"), ss->base.name);
    1390         349 :                 if (!replace && mvc_bind_trigger(sql, ss, triggername) != NULL)
    1391           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: name '%s' already in use", base, triggername);
    1392         349 :                 switch (trigger_event->token) {
    1393          43 :                         case SQL_INSERT: {
    1394          43 :                                 if (old_name)
    1395           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: old name not allowed at insert events", base);
    1396             :                                 event = 0;
    1397             :                         }       break;
    1398          29 :                         case SQL_DELETE: {
    1399          29 :                                 if (new_name)
    1400           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: new name not allowed at delete events", base);
    1401             :                                 event = 1;
    1402             :                         }       break;
    1403           1 :                         case SQL_TRUNCATE: {
    1404           1 :                                 if (new_name)
    1405           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: new name not allowed at truncate events", base);
    1406             :                                 event = 3;
    1407             :                         }       break;
    1408         272 :                         case SQL_UPDATE: {
    1409         272 :                                 if (old_name && new_name && !strcmp(old_name, new_name))
    1410           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: old and new names cannot be the same", base);
    1411         271 :                                 if (!old_name && new_name && !strcmp("old", new_name))
    1412           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: old and new names cannot be the same", base);
    1413         270 :                                 if (!new_name && old_name && !strcmp("new", old_name))
    1414           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: old and new names cannot be the same", base);
    1415             :                                 event = 2;
    1416             :                         }       break;
    1417             :                         case SQL_LOGIN:
    1418             :                                 // TODO any checks here?
    1419             :                                 event = LOGIN_EVENT;
    1420             :                                 break;
    1421           0 :                         default:
    1422           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: invalid event: %s", base, token2string(trigger_event->token));
    1423             :                 }
    1424             : 
    1425         346 :                 assert(triggered_action->h->type == type_int);
    1426         346 :                 orientation = triggered_action->h->data.i_val;
    1427         346 :                 q = query_cleaned(sql->ta, QUERY(sql->scanner));
    1428         346 :                 return rel_create_trigger(sql, sname, tname, triggername, time, orientation, event, old_name, new_name, condition, q, replace);
    1429             :         }
    1430             : 
    1431        5281 :         if (!instantiate) {
    1432         345 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    1433           0 :                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1434         345 :                 if (tname) {
    1435         340 :                         if (!(t = mvc_bind_table(sql, ss, tname)))
    1436           0 :                                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "%s: no such table %s%s%s'%s'", base, sname ? "'":"", sname ? sname : "", sname ? "'.":"", tname);
    1437             :                         /* we need to add the old and new tables */
    1438         340 :                         if (new_name && !_stack_push_table(sql, new_name, t)) {
    1439           0 :                                 stack_pop_frame(sql);
    1440           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1441             :                         }
    1442         340 :                         if (old_name && !_stack_push_table(sql, old_name, t)) {
    1443           0 :                                 stack_pop_frame(sql);
    1444           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1445             :                         }
    1446             :                 }
    1447             :         }
    1448        5281 :         if (condition) {
    1449           8 :                 sql_rel *rel = NULL;
    1450             : 
    1451           8 :                 if (new_name) /* in case of updates same relations is available via both names */
    1452           6 :                         rel = stack_find_rel_view(sql, new_name);
    1453           8 :                 if (!rel && old_name)
    1454           0 :                         rel = stack_find_rel_view(sql, old_name);
    1455           8 :                 if (!rel)
    1456           2 :                         rel = stack_find_rel_view(sql, "old");
    1457           2 :                 if (!rel)
    1458           2 :                         rel = stack_find_rel_view(sql, "new");
    1459           8 :                 rel = rel_logical_exp(query, rel, condition, sql_where);
    1460           8 :                 if (!rel) {
    1461           2 :                         if (!instantiate)
    1462           2 :                                 stack_pop_frame(sql);
    1463           2 :                         return NULL;
    1464             :                 }
    1465             :                 /* transition tables */
    1466             :                 /* insert: rel_select(table [new], searchcondition) */
    1467             :                 /* delete: rel_select(table [old], searchcondition) */
    1468             :                 /* update: rel_select(table [old,new]), searchcondition) */
    1469           6 :                 if (new_name)
    1470           6 :                         stack_update_rel_view(sql, new_name, rel);
    1471           6 :                 if (old_name)
    1472           0 :                         stack_update_rel_view(sql, old_name, new_name?rel_dup(rel):rel);
    1473             :         }
    1474        5279 :         sql->use_views = true; /* leave the 'use_views' hack to where it belongs */
    1475        5279 :         sql->session->schema = ss;
    1476        5279 :         sq = sequential_block(query, NULL, NULL, stmts, NULL, 1);
    1477        5279 :         sql->session->schema = old_schema;
    1478        5279 :         sql->use_views = old_useviews;
    1479        5279 :         if (!sq) {
    1480           6 :                 if (!instantiate)
    1481           3 :                         stack_pop_frame(sql);
    1482           6 :                 return NULL;
    1483             :         }
    1484        5273 :         r = rel_psm_block(sql->sa, sq);
    1485             : 
    1486        5273 :         if (!instantiate)
    1487         340 :                 stack_pop_frame(sql);
    1488             :         /* todo trigger_columns */
    1489             :         (void)columns;
    1490             :         return r;
    1491             : }
    1492             : 
    1493             : static sql_rel *
    1494          84 : rel_drop_trigger(mvc *sql, const char *sname, const char *tname, int if_exists)
    1495             : {
    1496          84 :         sql_rel *rel = rel_create(sql->sa);
    1497          84 :         list *exps = new_exp_list(sql->sa);
    1498          84 :         if(!rel || !exps)
    1499             :                 return NULL;
    1500             : 
    1501          84 :         append(exps, exp_atom_str(sql->sa, sname, sql_bind_localtype("str") ));
    1502          84 :         append(exps, exp_atom_str(sql->sa, tname, sql_bind_localtype("str") ));
    1503          84 :         append(exps, exp_atom_int(sql->sa, if_exists));
    1504          84 :         rel->l = NULL;
    1505          84 :         rel->r = NULL;
    1506          84 :         rel->op = op_ddl;
    1507          84 :         rel->flag = ddl_drop_trigger;
    1508          84 :         rel->exps = exps;
    1509          84 :         rel->card = CARD_MULTI;
    1510          84 :         rel->nrcols = 0;
    1511          84 :         return rel;
    1512             : }
    1513             : 
    1514             : static sql_rel *
    1515          96 : drop_trigger(mvc *sql, dlist *qname, int if_exists)
    1516             : {
    1517          96 :         const char *sname = qname_schema(qname);
    1518          96 :         const char *tname = qname_schema_object(qname);
    1519          96 :         sql_trigger *tr = NULL;
    1520             : 
    1521          96 :         if (!(tr = find_trigger_on_scope(sql, sname, tname, "DROP TRIGGER"))) {
    1522          12 :                 if (if_exists) {
    1523           1 :                         sql->errstr[0] = '\0'; /* reset trigger not found error */
    1524           1 :                         sql->session->status = 0;
    1525           1 :                         return rel_psm_block(sql->sa, new_exp_list(sql->sa));
    1526             :                 }
    1527             :                 return NULL;
    1528             :         }
    1529          84 :         if (tr->t && !mvc_schema_privs(sql, tr->t->s))
    1530           0 :                 return sql_error(sql, 02, SQLSTATE(3F000) "DROP TRIGGER: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), tr->t->s->base.name);
    1531          84 :         return rel_drop_trigger(sql, tr->t?tr->t->s->base.name:NULL, tname, if_exists);
    1532             : }
    1533             : 
    1534             : static sql_rel*
    1535           2 : create_table_from_loader(sql_query *query, dlist *qname, symbol *fcall)
    1536             : {
    1537           2 :         mvc *sql = query->sql;
    1538           2 :         sql_schema *s = cur_schema(sql);
    1539           2 :         char *sname = qname_schema(qname);
    1540           2 :         char *tname = qname_schema_object(qname);
    1541           2 :         sql_subfunc *loader = NULL;
    1542           2 :         sql_rel *rel = NULL;
    1543           2 :         sql_table *t = NULL;
    1544             : 
    1545           2 :         if (sname && !(s = mvc_bind_schema(sql, sname)))
    1546           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "CREATE TABLE FROM LOADER: no such schema '%s'", sname);
    1547           2 :         if ((t = mvc_bind_table(sql, s, tname)))
    1548           0 :                 return sql_error(sql, 02, SQLSTATE(42S01) "CREATE TABLE FROM LOADER: name '%s' already in use", tname);
    1549           2 :         if (!mvc_schema_privs(sql, s))
    1550           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "CREATE TABLE FROM LOADER: insufficient privileges for user '%s' in schema '%s'", get_string_global_var(sql, "current_user"), s->base.name);
    1551             : 
    1552           2 :         rel = rel_loader_function(query, fcall, new_exp_list(sql->sa), &loader);
    1553           2 :         if (!rel || !loader)
    1554             :                 return NULL;
    1555             : 
    1556           1 :         loader->sname = s ? sa_strdup(sql->sa, s->base.name) : NULL;
    1557           1 :         loader->tname = tname ? sa_strdup(sql->sa, tname) : NULL;
    1558             : 
    1559           1 :         return rel;
    1560             : }
    1561             : 
    1562             : static list *
    1563           4 : rel_paramlist( sql_query *query, symbol *nop)
    1564             : {
    1565           4 :         dnode *ops = nop->data.lval->h->next->next->data.lval->h;
    1566           4 :         list *exps = sa_list(query->sql->sa);
    1567           4 :         exp_kind iek = {type_value, card_column, FALSE};
    1568             : 
    1569           9 :         for (; ops; ops = ops->next) {
    1570           6 :                 sql_exp *e = rel_value_exp(query, NULL, ops->data.sym, sql_farg, iek);
    1571           6 :                 if (!e)
    1572             :                         return NULL;
    1573           6 :                 ops = ops->next;
    1574           6 :                 sql_arg *a = sql_find_param(query->sql, ops->data.sval);
    1575           6 :                 if (!a)
    1576           1 :                         return sql_error(query->sql, 06, SQLSTATE(42000) "Named placeholder ('%s') not used in the query.", ops->data.sval);
    1577           5 :                 a->type = *exp_subtype(e);
    1578           5 :                 append(exps, e);
    1579             :         }
    1580             :         return exps;
    1581             : }
    1582             : 
    1583             : 
    1584             : sql_rel *
    1585      260364 : rel_psm(sql_query *query, symbol *s)
    1586             : {
    1587      260364 :         mvc *sql = query->sql;
    1588      260364 :         sql_rel *ret = NULL;
    1589             : 
    1590      260364 :         switch (s->token) {
    1591      244520 :         case SQL_CREATE_FUNC:
    1592             :         {
    1593      244520 :                 dlist *l = s->data.lval;
    1594      244520 :                 sql_ftype type = (sql_ftype) l->h->next->next->next->next->next->data.i_val;
    1595      244520 :                 sql_flang lang = (sql_flang) l->h->next->next->next->next->next->next->data.i_val;
    1596      244520 :                 int repl = l->h->next->next->next->next->next->next->next->data.i_val;
    1597      244520 :                 int order_spec = l->h->next->next->next->next->next->next->next->next->data.i_val;
    1598             : 
    1599      244520 :                 ret = rel_create_func(query, l->h->data.lval, l->h->next->data.lval, l->h->next->next->data.sym, l->h->next->next->next->data.lval, l->h->next->next->next->next->data.lval, type, lang, repl, order_spec);
    1600      244520 :                 sql->type = Q_SCHEMA;
    1601      244520 :         }       break;
    1602         796 :         case SQL_DROP_FUNC:
    1603             :         {
    1604         796 :                 dlist *l = s->data.lval;
    1605         796 :                 dlist *qname = l->h->data.lval;
    1606         796 :                 dlist *typelist = l->h->next->data.lval;
    1607         796 :                 sql_ftype type = (sql_ftype) l->h->next->next->data.i_val;
    1608         796 :                 int if_exists = l->h->next->next->next->data.i_val;
    1609         796 :                 int all = l->h->next->next->next->next->data.i_val;
    1610         796 :                 int drop_action = l->h->next->next->next->next->next->data.i_val;
    1611             : 
    1612         796 :                 if (store_readonly(sql->session->tr->store))
    1613           0 :                         return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
    1614             : 
    1615         796 :                 if (all)
    1616         110 :                         ret = rel_drop_all_func(sql, qname, drop_action, type);
    1617             :                 else
    1618         686 :                         ret = rel_drop_func(sql, qname, typelist, drop_action, type, if_exists);
    1619             : 
    1620         796 :                 sql->type = Q_SCHEMA;
    1621         796 :         }       break;
    1622         393 :         case SQL_SET:
    1623         393 :                 ret = rel_psm_stmt(sql->sa, psm_set_exp(query, s->data.lval->h));
    1624         393 :                 sql->type = Q_SCHEMA;
    1625         393 :                 break;
    1626          11 :         case SQL_DECLARE:
    1627          11 :                 return sql_error(sql, 02, SQLSTATE(42000) "Variables cannot be declared on the global scope");
    1628        8870 :         case SQL_CALL:
    1629        8870 :                 sql->type = Q_UPDATE;
    1630        8870 :                 if (s->type == type_list) {
    1631           4 :                         list *params = rel_paramlist( query, s->data.lval->h->next->data.sym);
    1632           4 :                         if (!params)
    1633             :                                 return NULL;
    1634           3 :                         ret = rel_semantic(query, s->data.lval->h->data.sym);
    1635           3 :             query->last_rel = ret;
    1636           3 :                         if (ret)
    1637           3 :                                 ret = rel_psm_stmt(sql->sa, rel_psm_call(query, s->data.lval->h->next->data.sym));
    1638           3 :                         ret = rel_list(sql->sa, query->last_rel, ret);
    1639             :                 } else
    1640        8866 :                         ret = rel_psm_stmt(sql->sa, rel_psm_call(query, s->data.sym));
    1641             :                 break;
    1642           2 :         case SQL_CREATE_TABLE_LOADER:
    1643             :         {
    1644           2 :                 dlist *l = s->data.lval;
    1645           2 :                 dlist *qname = l->h->data.lval;
    1646           2 :                 symbol *sym = l->h->next->data.sym;
    1647             : 
    1648           2 :                 ret = create_table_from_loader(query, qname, sym);
    1649           2 :                 if (ret == NULL)
    1650             :                         return NULL;
    1651           1 :                 ret = rel_psm_stmt(sql->sa, exp_rel(sql, ret));
    1652           1 :                 sql->type = Q_SCHEMA;
    1653           1 :         }       break;
    1654        5636 :         case SQL_CREATE_TRIGGER:
    1655             :         {
    1656        5636 :                 dlist *l = s->data.lval;
    1657             : 
    1658        5636 :                 assert(l->h->next->type == type_int);
    1659        5636 :                 ret = create_trigger(query, l->h->data.lval, l->h->next->data.i_val, l->h->next->next->data.sym, l->h->next->next->next->data.lval, l->h->next->next->next->next->data.lval, l->h->next->next->next->next->next->data.lval, l->h->next->next->next->next->next->next->data.i_val);
    1660        5636 :                 sql->type = Q_SCHEMA;
    1661        5636 :         } break;
    1662          96 :         case SQL_DROP_TRIGGER:
    1663             :         {
    1664          96 :                 dlist *l = s->data.lval;
    1665          96 :                 dlist *qname = l->h->data.lval;
    1666          96 :                 int if_exists = l->h->next->data.i_val;
    1667             : 
    1668          96 :                 ret = drop_trigger(sql, qname, if_exists);
    1669          96 :                 sql->type = Q_SCHEMA;
    1670          96 :         } break;
    1671          40 :         case SQL_ANALYZE: {
    1672          40 :                 dlist *l = s->data.lval;
    1673             : 
    1674             :                 /* Jan2022 update: The 'sample' and 'minmax' parameters are now ignored because they are no longer used in the backend */
    1675          40 :                 list *calls = psm_analyze(query, l->h->data.lval /* qualified table name */, l->h->next->data.lval /* opt list of column */);
    1676          40 :                 ret = rel_psm_block(sql->sa, calls);
    1677          40 :                 sql->type = Q_UPDATE;
    1678          40 :         }       break;
    1679           0 :         default:
    1680           0 :                 return sql_error(sql, 01, SQLSTATE(42000) "Schema statement unknown symbol(%p)->token = %s", s, token2string(s->token));
    1681             :         }
    1682             :         return ret;
    1683             : }

Generated by: LCOV version 1.14