LCOV - code coverage report
Current view: top level - sql/server - rel_psm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 841 939 89.6 %
Date: 2021-10-13 02:24:04 Functions: 33 33 100.0 %

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

Generated by: LCOV version 1.14