Commit 47b7ca62 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-18796 Synchronize PS grammar between sql_yacc.yy and sql_yacc_ora.yy

parent 3b47587f
...@@ -4663,7 +4663,7 @@ EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING (SELECT 1); ...@@ -4663,7 +4663,7 @@ EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING (SELECT 1);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
CREATE FUNCTION f1() RETURNS VARCHAR(10) RETURN 'test'; CREATE FUNCTION f1() RETURNS VARCHAR(10) RETURN 'test';
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1(); EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
ERROR 42000: EXECUTE..USING does not support subqueries or stored functions ERROR 42000: EXECUTE IMMEDIATE does not support subqueries or stored functions
DROP FUNCTION f1; DROP FUNCTION f1;
# #
# DDL # DDL
......
...@@ -163,7 +163,7 @@ RETURN 'test'; ...@@ -163,7 +163,7 @@ RETURN 'test';
END; END;
$$ $$
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1(); EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
ERROR 42000: EXECUTE..USING does not support subqueries or stored functions ERROR 42000: EXECUTE IMMEDIATE does not support subqueries or stored functions
DROP FUNCTION f1; DROP FUNCTION f1;
# #
# Testing simple expressions # Testing simple expressions
......
...@@ -1338,11 +1338,10 @@ bool Protocol_text::store_time(MYSQL_TIME *tm, int decimals) ...@@ -1338,11 +1338,10 @@ bool Protocol_text::store_time(MYSQL_TIME *tm, int decimals)
bool Protocol_text::send_out_parameters(List<Item_param> *sp_params) bool Protocol_text::send_out_parameters(List<Item_param> *sp_params)
{ {
DBUG_ASSERT(sp_params->elements == DBUG_ASSERT(sp_params->elements == thd->lex->prepared_stmt.param_count());
thd->lex->prepared_stmt_params.elements);
List_iterator_fast<Item_param> item_param_it(*sp_params); List_iterator_fast<Item_param> item_param_it(*sp_params);
List_iterator_fast<Item> param_it(thd->lex->prepared_stmt_params); List_iterator_fast<Item> param_it(thd->lex->prepared_stmt.params());
while (true) while (true)
{ {
......
...@@ -1214,7 +1214,7 @@ class Statement_map ...@@ -1214,7 +1214,7 @@ class Statement_map
int insert(THD *thd, Statement *statement); int insert(THD *thd, Statement *statement);
Statement *find_by_name(LEX_CSTRING *name) Statement *find_by_name(const LEX_CSTRING *name)
{ {
Statement *stmt; Statement *stmt;
stmt= (Statement*)my_hash_search(&names_hash, (uchar*)name->str, stmt= (Statement*)my_hash_search(&names_hash, (uchar*)name->str,
......
...@@ -705,7 +705,7 @@ void LEX::start(THD *thd_arg) ...@@ -705,7 +705,7 @@ void LEX::start(THD *thd_arg)
with_persistent_for_clause= FALSE; with_persistent_for_clause= FALSE;
column_list= NULL; column_list= NULL;
index_list= NULL; index_list= NULL;
prepared_stmt_params.empty(); prepared_stmt.lex_start();
auxiliary_table_list.empty(); auxiliary_table_list.empty();
unit.next= unit.master= unit.link_next= unit.return_to= 0; unit.next= unit.master= unit.link_next= unit.return_to= 0;
unit.prev= unit.link_prev= 0; unit.prev= unit.link_prev= 0;
...@@ -10216,3 +10216,50 @@ bool LEX::stmt_uninstall_plugin_by_soname(const DDL_options_st &opt, ...@@ -10216,3 +10216,50 @@ bool LEX::stmt_uninstall_plugin_by_soname(const DDL_options_st &opt,
ident= soname; ident= soname;
return false; return false;
} }
bool LEX::stmt_prepare_validate(const char *stmt_type)
{
if (unlikely(table_or_sp_used()))
{
my_error(ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), stmt_type);
return true;
}
return check_main_unit_semantics();
}
bool LEX::stmt_prepare(const Lex_ident_sys_st &ident, Item *code)
{
sql_command= SQLCOM_PREPARE;
if (stmt_prepare_validate("PREPARE..FROM"))
return true;
prepared_stmt.set(ident, code, NULL);
return false;
}
bool LEX::stmt_execute_immediate(Item *code, List<Item> *params)
{
sql_command= SQLCOM_EXECUTE_IMMEDIATE;
if (stmt_prepare_validate("EXECUTE IMMEDIATE"))
return true;
static const Lex_ident_sys immediate(STRING_WITH_LEN("IMMEDIATE"));
prepared_stmt.set(immediate, code, params);
return false;
}
bool LEX::stmt_execute(const Lex_ident_sys_st &ident, List<Item> *params)
{
sql_command= SQLCOM_EXECUTE;
prepared_stmt.set(ident, NULL, params);
return stmt_prepare_validate("EXECUTE..USING");
}
void LEX::stmt_deallocate_prepare(const Lex_ident_sys_st &ident)
{
sql_command= SQLCOM_DEALLOCATE_PREPARE;
prepared_stmt.set(ident, NULL, NULL);
}
...@@ -169,6 +169,16 @@ class Lex_ident_sys: public Lex_ident_sys_st ...@@ -169,6 +169,16 @@ class Lex_ident_sys: public Lex_ident_sys_st
{ {
((LEX_CSTRING &) *this)= null_clex_str; ((LEX_CSTRING &) *this)= null_clex_str;
} }
Lex_ident_sys(const char *name, size_t length)
{
LEX_CSTRING tmp= {name, length};
set_valid_utf8(&tmp);
}
Lex_ident_sys & operator=(const Lex_ident_sys_st &name)
{
Lex_ident_sys_st::operator=(name);
return *this;
}
}; };
...@@ -2990,6 +3000,56 @@ struct Account_options: public USER_RESOURCES ...@@ -2990,6 +3000,56 @@ struct Account_options: public USER_RESOURCES
class Query_arena_memroot; class Query_arena_memroot;
/* The state of the lex parsing. This is saved in the THD struct */ /* The state of the lex parsing. This is saved in the THD struct */
class Lex_prepared_stmt
{
Lex_ident_sys m_name; // Statement name (in all queries)
Item *m_code; // PREPARE or EXECUTE IMMEDIATE source expression
List<Item> m_params; // List of parameters for EXECUTE [IMMEDIATE]
public:
Lex_prepared_stmt()
:m_code(NULL)
{ }
const Lex_ident_sys &name() const
{
return m_name;
}
uint param_count() const
{
return m_params.elements;
}
List<Item> &params()
{
return m_params;
}
void set(const Lex_ident_sys_st &ident, Item *code, List<Item> *params)
{
DBUG_ASSERT(m_params.elements == 0);
m_name= ident;
m_code= code;
if (params)
m_params= *params;
}
bool params_fix_fields(THD *thd)
{
// Fix Items in the EXECUTE..USING list
List_iterator_fast<Item> param_it(m_params);
while (Item *param= param_it++)
{
if (param->fix_fields_if_needed_for_scalar(thd, 0))
return true;
}
return false;
}
bool get_dynamic_sql_string(THD *thd, LEX_CSTRING *dst, String *buffer);
void lex_start()
{
m_params.empty();
}
};
struct LEX: public Query_tables_list struct LEX: public Query_tables_list
{ {
SELECT_LEX_UNIT unit; /* most upper unit */ SELECT_LEX_UNIT unit; /* most upper unit */
...@@ -3254,12 +3314,7 @@ struct LEX: public Query_tables_list ...@@ -3254,12 +3314,7 @@ struct LEX: public Query_tables_list
creating or last of tables referenced by foreign keys). creating or last of tables referenced by foreign keys).
*/ */
TABLE_LIST *create_last_non_select_table; TABLE_LIST *create_last_non_select_table;
/* Prepared statements SQL syntax:*/ Lex_prepared_stmt prepared_stmt;
LEX_CSTRING prepared_stmt_name; /* Statement name (in all queries) */
/* PREPARE or EXECUTE IMMEDIATE source expression */
Item *prepared_stmt_code;
/* Names of user variables holding parameters (in EXECUTE) */
List<Item> prepared_stmt_params;
sp_head *sphead; sp_head *sphead;
sp_name *spname; sp_name *spname;
bool sp_lex_in_use; // Keep track on lex usage in SPs for error handling bool sp_lex_in_use; // Keep track on lex usage in SPs for error handling
...@@ -3647,18 +3702,6 @@ struct LEX: public Query_tables_list ...@@ -3647,18 +3702,6 @@ struct LEX: public Query_tables_list
bool sp_proc_stmt_statement_finalize_buf(THD *, const LEX_CSTRING &qbuf); bool sp_proc_stmt_statement_finalize_buf(THD *, const LEX_CSTRING &qbuf);
bool sp_proc_stmt_statement_finalize(THD *, bool no_lookahead); bool sp_proc_stmt_statement_finalize(THD *, bool no_lookahead);
bool get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer);
bool prepared_stmt_params_fix_fields(THD *thd)
{
// Fix Items in the EXECUTE..USING list
List_iterator_fast<Item> param_it(prepared_stmt_params);
while (Item *param= param_it++)
{
if (param->fix_fields_if_needed_for_scalar(thd, 0))
return true;
}
return false;
}
sp_variable *sp_param_init(LEX_CSTRING *name); sp_variable *sp_param_init(LEX_CSTRING *name);
bool sp_param_fill_definition(sp_variable *spvar); bool sp_param_fill_definition(sp_variable *spvar);
...@@ -4403,6 +4446,11 @@ struct LEX: public Query_tables_list ...@@ -4403,6 +4446,11 @@ struct LEX: public Query_tables_list
const Lex_ident_sys_st &name); const Lex_ident_sys_st &name);
bool stmt_uninstall_plugin_by_soname(const DDL_options_st &opt, bool stmt_uninstall_plugin_by_soname(const DDL_options_st &opt,
const LEX_CSTRING &soname); const LEX_CSTRING &soname);
bool stmt_prepare_validate(const char *stmt_type);
bool stmt_prepare(const Lex_ident_sys_st &ident, Item *code);
bool stmt_execute(const Lex_ident_sys_st &ident, List<Item> *params);
bool stmt_execute_immediate(Item *code, List<Item> *params);
void stmt_deallocate_prepare(const Lex_ident_sys_st &ident);
}; };
......
...@@ -518,6 +518,12 @@ template <class T> class List :public base_list ...@@ -518,6 +518,12 @@ template <class T> class List :public base_list
empty(); empty();
} }
T *elem(uint n) { return (T*) base_list::elem(n); } T *elem(uint n) { return (T*) base_list::elem(n); }
// Create a new list with one element
static List<T> *make(MEM_ROOT *mem_root, T *first)
{
List<T> *res= new (mem_root) List<T>;
return res == NULL || res->push_back(first, mem_root) ? NULL : res;
}
}; };
......
...@@ -190,7 +190,7 @@ class Prepared_statement: public Statement ...@@ -190,7 +190,7 @@ class Prepared_statement: public Statement
void setup_set_params(); void setup_set_params();
virtual Query_arena::Type type() const; virtual Query_arena::Type type() const;
virtual void cleanup_stmt(); virtual void cleanup_stmt();
bool set_name(LEX_CSTRING *name); bool set_name(const LEX_CSTRING *name);
inline void close_cursor() { delete cursor; cursor= 0; } inline void close_cursor() { delete cursor; cursor= 0; }
inline bool is_in_use() { return flags & (uint) IS_IN_USE; } inline bool is_in_use() { return flags & (uint) IS_IN_USE; }
inline bool is_sql_prepare() const { return flags & (uint) IS_SQL_PREPARE; } inline bool is_sql_prepare() const { return flags & (uint) IS_SQL_PREPARE; }
...@@ -2664,7 +2664,7 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length) ...@@ -2664,7 +2664,7 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
} }
/** /**
Get an SQL statement from an item in lex->prepared_stmt_code. Get an SQL statement from an item in m_code.
This function can return pointers to very different memory classes: This function can return pointers to very different memory classes:
- a static string "NULL", if the item returned NULL - a static string "NULL", if the item returned NULL
...@@ -2689,13 +2689,15 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length) ...@@ -2689,13 +2689,15 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
@retval true on error (out of memory) @retval true on error (out of memory)
*/ */
bool LEX::get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer) bool Lex_prepared_stmt::get_dynamic_sql_string(THD *thd,
LEX_CSTRING *dst,
String *buffer)
{ {
if (prepared_stmt_code->fix_fields_if_needed_for_scalar(thd, NULL)) if (m_code->fix_fields_if_needed_for_scalar(thd, NULL))
return true; return true;
const String *str= prepared_stmt_code->val_str(buffer); const String *str= m_code->val_str(buffer);
if (prepared_stmt_code->null_value) if (m_code->null_value)
{ {
/* /*
Prepare source was NULL, so we need to set "str" to Prepare source was NULL, so we need to set "str" to
...@@ -2776,7 +2778,7 @@ bool LEX::get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer) ...@@ -2776,7 +2778,7 @@ bool LEX::get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer)
void mysql_sql_stmt_prepare(THD *thd) void mysql_sql_stmt_prepare(THD *thd)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
LEX_CSTRING *name= &lex->prepared_stmt_name; const LEX_CSTRING *name= &lex->prepared_stmt.name();
Prepared_statement *stmt; Prepared_statement *stmt;
LEX_CSTRING query; LEX_CSTRING query;
DBUG_ENTER("mysql_sql_stmt_prepare"); DBUG_ENTER("mysql_sql_stmt_prepare");
...@@ -2801,7 +2803,7 @@ void mysql_sql_stmt_prepare(THD *thd) ...@@ -2801,7 +2803,7 @@ void mysql_sql_stmt_prepare(THD *thd)
See comments in get_dynamic_sql_string(). See comments in get_dynamic_sql_string().
*/ */
StringBuffer<256> buffer; StringBuffer<256> buffer;
if (lex->get_dynamic_sql_string(&query, &buffer) || if (lex->prepared_stmt.get_dynamic_sql_string(thd, &query, &buffer) ||
! (stmt= new Prepared_statement(thd))) ! (stmt= new Prepared_statement(thd)))
{ {
DBUG_VOID_RETURN; /* out of memory */ DBUG_VOID_RETURN; /* out of memory */
...@@ -2864,7 +2866,7 @@ void mysql_sql_stmt_execute_immediate(THD *thd) ...@@ -2864,7 +2866,7 @@ void mysql_sql_stmt_execute_immediate(THD *thd)
LEX_CSTRING query; LEX_CSTRING query;
DBUG_ENTER("mysql_sql_stmt_execute_immediate"); DBUG_ENTER("mysql_sql_stmt_execute_immediate");
if (lex->prepared_stmt_params_fix_fields(thd)) if (lex->prepared_stmt.params_fix_fields(thd))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
/* /*
...@@ -2876,7 +2878,7 @@ void mysql_sql_stmt_execute_immediate(THD *thd) ...@@ -2876,7 +2878,7 @@ void mysql_sql_stmt_execute_immediate(THD *thd)
See comments in get_dynamic_sql_string(). See comments in get_dynamic_sql_string().
*/ */
StringBuffer<256> buffer; StringBuffer<256> buffer;
if (lex->get_dynamic_sql_string(&query, &buffer) || if (lex->prepared_stmt.get_dynamic_sql_string(thd, &query, &buffer) ||
!(stmt= new Prepared_statement(thd))) !(stmt= new Prepared_statement(thd)))
DBUG_VOID_RETURN; // out of memory DBUG_VOID_RETURN; // out of memory
...@@ -3265,7 +3267,7 @@ void mysql_sql_stmt_execute(THD *thd) ...@@ -3265,7 +3267,7 @@ void mysql_sql_stmt_execute(THD *thd)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
Prepared_statement *stmt; Prepared_statement *stmt;
LEX_CSTRING *name= &lex->prepared_stmt_name; const LEX_CSTRING *name= &lex->prepared_stmt.name();
/* Query text for binary, general or slow log, if any of them is open */ /* Query text for binary, general or slow log, if any of them is open */
String expanded_query; String expanded_query;
DBUG_ENTER("mysql_sql_stmt_execute"); DBUG_ENTER("mysql_sql_stmt_execute");
...@@ -3278,7 +3280,7 @@ void mysql_sql_stmt_execute(THD *thd) ...@@ -3278,7 +3280,7 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if (stmt->param_count != lex->prepared_stmt_params.elements) if (stmt->param_count != lex->prepared_stmt.param_count())
{ {
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -3286,7 +3288,7 @@ void mysql_sql_stmt_execute(THD *thd) ...@@ -3286,7 +3288,7 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_PRINT("info",("stmt: %p", stmt)); DBUG_PRINT("info",("stmt: %p", stmt));
if (lex->prepared_stmt_params_fix_fields(thd)) if (lex->prepared_stmt.params_fix_fields(thd))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
/* /*
...@@ -3506,7 +3508,7 @@ void mysqld_stmt_close(THD *thd, char *packet) ...@@ -3506,7 +3508,7 @@ void mysqld_stmt_close(THD *thd, char *packet)
void mysql_sql_stmt_close(THD *thd) void mysql_sql_stmt_close(THD *thd)
{ {
Prepared_statement* stmt; Prepared_statement* stmt;
LEX_CSTRING *name= &thd->lex->prepared_stmt_name; const LEX_CSTRING *name= &thd->lex->prepared_stmt.name();
DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", (int) name->length, DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", (int) name->length,
name->str)); name->str));
...@@ -3871,7 +3873,7 @@ void Prepared_statement::cleanup_stmt() ...@@ -3871,7 +3873,7 @@ void Prepared_statement::cleanup_stmt()
} }
bool Prepared_statement::set_name(LEX_CSTRING *name_arg) bool Prepared_statement::set_name(const LEX_CSTRING *name_arg)
{ {
name.length= name_arg->length; name.length= name_arg->length;
name.str= (char*) memdup_root(mem_root, name_arg->str, name_arg->length); name.str= (char*) memdup_root(mem_root, name_arg->str, name_arg->length);
...@@ -4120,7 +4122,7 @@ Prepared_statement::set_parameters(String *expanded_query, ...@@ -4120,7 +4122,7 @@ Prepared_statement::set_parameters(String *expanded_query,
if (is_sql_ps) if (is_sql_ps)
{ {
/* SQL prepared statement */ /* SQL prepared statement */
res= set_params_from_actual_params(this, thd->lex->prepared_stmt_params, res= set_params_from_actual_params(this, thd->lex->prepared_stmt.params(),
expanded_query); expanded_query);
} }
else if (param_count) else if (param_count)
...@@ -4849,7 +4851,7 @@ bool Prepared_statement::execute_immediate(const char *query, uint query_len) ...@@ -4849,7 +4851,7 @@ bool Prepared_statement::execute_immediate(const char *query, uint query_len)
if (unlikely(prepare(query, query_len))) if (unlikely(prepare(query, query_len)))
DBUG_RETURN(true); DBUG_RETURN(true);
if (param_count != thd->lex->prepared_stmt_params.elements) if (param_count != thd->lex->prepared_stmt.param_count())
{ {
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
deallocate_immediate(); deallocate_immediate();
......
...@@ -1856,7 +1856,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -1856,7 +1856,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <item> %type <item>
literal insert_ident order_ident temporal_literal literal insert_ident order_ident temporal_literal
simple_ident expr sum_expr in_sum_expr simple_ident expr prepare_src sum_expr in_sum_expr
variable variable_aux bool_pri variable variable_aux bool_pri
predicate bit_expr parenthesized_expr predicate bit_expr parenthesized_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr table_wild simple_expr column_default_non_parenthesized_expr udf_expr
...@@ -1897,6 +1897,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -1897,6 +1897,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else
ident_list ident_list_arg opt_expr_list ident_list ident_list_arg opt_expr_list
decode_when_list_oracle decode_when_list_oracle
execute_using
execute_params
%type <sp_cursor_stmt> %type <sp_cursor_stmt>
sp_cursor_stmt_lex sp_cursor_stmt_lex
...@@ -2054,7 +2056,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -2054,7 +2056,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
select_var_list select_var_list_init help select_var_list select_var_list_init help
opt_extended_describe shutdown opt_extended_describe shutdown
opt_format_json opt_format_json
prepare prepare_src execute deallocate prepare execute deallocate
statement statement
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
...@@ -2306,9 +2308,7 @@ statement: ...@@ -2306,9 +2308,7 @@ statement:
deallocate: deallocate:
deallocate_or_drop PREPARE_SYM ident deallocate_or_drop PREPARE_SYM ident
{ {
LEX *lex= thd->lex; Lex->stmt_deallocate_prepare($3);
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
lex->prepared_stmt_name= $3;
} }
; ;
...@@ -2320,14 +2320,8 @@ deallocate_or_drop: ...@@ -2320,14 +2320,8 @@ deallocate_or_drop:
prepare: prepare:
PREPARE_SYM ident FROM prepare_src PREPARE_SYM ident FROM prepare_src
{ {
LEX *lex= thd->lex; if (Lex->stmt_prepare($2, $4))
if (unlikely(lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"PREPARE..FROM"));
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2;
} }
; ;
...@@ -2335,63 +2329,48 @@ prepare_src: ...@@ -2335,63 +2329,48 @@ prepare_src:
{ Lex->expr_allows_subselect= false; } { Lex->expr_allows_subselect= false; }
expr expr
{ {
Lex->prepared_stmt_code= $2;
Lex->expr_allows_subselect= true; Lex->expr_allows_subselect= true;
$$= $2;
} }
; ;
execute: execute:
EXECUTE_SYM ident EXECUTE_SYM ident execute_using
{
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_EXECUTE;
lex->prepared_stmt_name= $2;
}
execute_using
{ {
if (Lex->check_main_unit_semantics()) if (Lex->stmt_execute($2, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| EXECUTE_SYM IMMEDIATE_SYM prepare_src | EXECUTE_SYM IMMEDIATE_SYM prepare_src execute_using
{
if (unlikely(Lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"EXECUTE IMMEDIATE"));
Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
}
execute_using
{ {
if (Lex->check_main_unit_semantics()) if (Lex->stmt_execute_immediate($3, $4))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
execute_using: execute_using:
/* nothing */ /* nothing */ { $$= NULL; }
| USING { Lex->expr_allows_subselect= false; } | USING { Lex->expr_allows_subselect= false; }
execute_var_list execute_params
{ {
if (unlikely(Lex->table_or_sp_used())) $$= $3;
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"EXECUTE..USING"));
Lex->expr_allows_subselect= true; Lex->expr_allows_subselect= true;
} }
; ;
execute_var_list: execute_params:
execute_var_list ',' execute_var_ident
| execute_var_ident
;
execute_var_ident:
expr_or_default expr_or_default
{ {
if (unlikely(Lex->prepared_stmt_params.push_back($1, if (unlikely(!($$= List<Item>::make(thd->mem_root, $1))))
thd->mem_root))) MYSQL_YYABORT;
}
| execute_params ',' expr_or_default
{
if (($$= $1)->push_back($3, thd->mem_root))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
/* help */ /* help */
help: help:
...@@ -11833,9 +11812,7 @@ opt_expr_list: ...@@ -11833,9 +11812,7 @@ opt_expr_list:
expr_list: expr_list:
expr expr
{ {
$$= new (thd->mem_root) List<Item>; if (unlikely(!($$= List<Item>::make(thd->mem_root, $1))))
if (unlikely($$ == NULL) ||
unlikely($$->push_back($1, thd->mem_root)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| expr_list ',' expr | expr_list ',' expr
......
...@@ -1357,7 +1357,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -1357,7 +1357,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <item> %type <item>
literal insert_ident order_ident temporal_literal literal insert_ident order_ident temporal_literal
simple_ident expr sum_expr in_sum_expr simple_ident expr prepare_src sum_expr in_sum_expr
variable variable_aux bool_pri variable variable_aux bool_pri
predicate bit_expr parenthesized_expr predicate bit_expr parenthesized_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr table_wild simple_expr column_default_non_parenthesized_expr udf_expr
...@@ -1398,6 +1398,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -1398,6 +1398,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else
ident_list ident_list_arg opt_expr_list ident_list ident_list_arg opt_expr_list
decode_when_list_oracle decode_when_list_oracle
execute_using
execute_params
%type <sp_cursor_stmt> %type <sp_cursor_stmt>
sp_cursor_stmt_lex sp_cursor_stmt_lex
...@@ -1557,7 +1559,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -1557,7 +1559,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
select_var_list select_var_list_init help select_var_list select_var_list_init help
opt_extended_describe shutdown opt_extended_describe shutdown
opt_format_json opt_format_json
prepare prepare_src execute deallocate prepare execute deallocate
statement statement
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
...@@ -1827,9 +1829,7 @@ statement: ...@@ -1827,9 +1829,7 @@ statement:
deallocate: deallocate:
deallocate_or_drop PREPARE_SYM ident deallocate_or_drop PREPARE_SYM ident
{ {
LEX *lex= thd->lex; Lex->stmt_deallocate_prepare($3);
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
lex->prepared_stmt_name= $3;
} }
; ;
...@@ -1841,12 +1841,8 @@ deallocate_or_drop: ...@@ -1841,12 +1841,8 @@ deallocate_or_drop:
prepare: prepare:
PREPARE_SYM ident FROM prepare_src PREPARE_SYM ident FROM prepare_src
{ {
LEX *lex= thd->lex; if (Lex->stmt_prepare($2, $4))
if (unlikely(lex->table_or_sp_used())) MYSQL_YYABORT;
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"PREPARE..FROM"));
lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2;
} }
; ;
...@@ -1854,57 +1850,48 @@ prepare_src: ...@@ -1854,57 +1850,48 @@ prepare_src:
{ Lex->expr_allows_subselect= false; } { Lex->expr_allows_subselect= false; }
expr expr
{ {
Lex->prepared_stmt_code= $2;
Lex->expr_allows_subselect= true; Lex->expr_allows_subselect= true;
$$= $2;
} }
; ;
execute: execute:
EXECUTE_SYM ident EXECUTE_SYM ident execute_using
{ {
LEX *lex= thd->lex; if (Lex->stmt_execute($2, $3))
lex->sql_command= SQLCOM_EXECUTE; MYSQL_YYABORT;
lex->prepared_stmt_name= $2;
} }
execute_using | EXECUTE_SYM IMMEDIATE_SYM prepare_src execute_using
{}
| EXECUTE_SYM IMMEDIATE_SYM prepare_src
{ {
if (unlikely(Lex->table_or_sp_used())) if (Lex->stmt_execute_immediate($3, $4))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), MYSQL_YYABORT;
"EXECUTE IMMEDIATE"));
Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
} }
execute_using
{}
; ;
execute_using: execute_using:
/* nothing */ /* nothing */ { $$= NULL; }
| USING { Lex->expr_allows_subselect= false; } | USING { Lex->expr_allows_subselect= false; }
execute_var_list execute_params
{ {
if (unlikely(Lex->table_or_sp_used())) $$= $3;
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"EXECUTE..USING"));
Lex->expr_allows_subselect= true; Lex->expr_allows_subselect= true;
} }
; ;
execute_var_list: execute_params:
execute_var_list ',' execute_var_ident
| execute_var_ident
;
execute_var_ident:
expr_or_default expr_or_default
{ {
if (unlikely(Lex->prepared_stmt_params.push_back($1, if (unlikely(!($$= List<Item>::make(thd->mem_root, $1))))
thd->mem_root))) MYSQL_YYABORT;
}
| execute_params ',' expr_or_default
{
if (($$= $1)->push_back($3, thd->mem_root))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
/* help */ /* help */
help: help:
...@@ -11919,9 +11906,7 @@ opt_expr_list: ...@@ -11919,9 +11906,7 @@ opt_expr_list:
expr_list: expr_list:
expr expr
{ {
$$= new (thd->mem_root) List<Item>; if (unlikely(!($$= List<Item>::make(thd->mem_root, $1))))
if (unlikely($$ == NULL) ||
unlikely($$->push_back($1, thd->mem_root)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| expr_list ',' expr | expr_list ',' expr
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment