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

Generated by: LCOV version 1.14