MDEV-19639 + MDEV-19640 fix + preparatory changes for WL#4179

This patch includes:
- MDEV-19639 sql_mode=ORACLE: Wrong SHOW PROCEDURE output for sysvar:=expr
- MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
- Preparatory refactoring for MySQL WL#4179

Detailed change list:

1. Changing sp_create_assignment_lex() to accept the position
   in the exact query buffer instead of a "bool no_lookahead".
   This actually fixes MDEV-19639.
   In the previous reduction sp_create_assignment_lex() was
   called too late, when the parser went far the from beginning
   of the statement, so only a part of the statement got into
   sp_instr_stmt.

2. Generating "SET" or "SET GLOBAL" inside sp_create_assignment_instr()
   depending on the option type.
   This fixes MDEV-19640.
   In the previous reduction the code passed (through no_lookahead)
   the position of the
   word GLOBAL inside sp_create_assignment_lex(), which
   worked only for the left-most assignment.

3. Fixing the affected rules to use:
   - ident_cli instead of ident
   - ident_cli_set_usual_case instead of ident_set_usual_case

4. Changing the input parameter in:
   - LEX::set_system_variable()
   - LEX::call_statement_start()
   - LEX::set_variable()
   from just LEX_CSTRING to Lex_ident_sys_st for stricter data type constrol:
   to make sure that noone passes an ident_cli
   (a fragment of the original query in the client character set)
   instead of server-side identifier
   (utf8 identifier allocated on THD when needed).

5. Adding Lex_ident_sys() in places where the affected functions are called.

6. Moving all calls of sp_create_assignment_lex() to the places
   just before parsing set_expr_or_default.
   This makes the grammar clearer, because
   sp_create_assignment_lex() and sp_create_assignment_instr()
   now stay near each other, so the balance of LEX's push/pop
   can be read easier.
   This will also help to WL#4179.

7. Adding class sp_lex_set_var
   Moving the initialization code from
   sp_create_assignment_lex() to the constructor of sp_lex_set_var.
   This will also help to WL#4179.

8. Moving a part of the "set" grammar rule into a separate
   rule "set_param".
   This makes the grammar easier to read and removes
   one shift/reduce conflict.
This commit is contained in:
Alexander Barkov 2019-05-31 16:44:17 +04:00
parent f859789e7d
commit bf5a144e16
9 changed files with 639 additions and 331 deletions

View file

@ -847,8 +847,8 @@ drop procedure if exists p_20906_b;
create procedure p_20906_a() SET @a=@a+1, @b=@b+1;
show procedure code p_20906_a;
Pos Instruction
0 stmt 31 "SET @a=@a+1"
1 stmt 31 "SET @b=@b+1"
0 stmt 31 "SET @a=@a+1"
1 stmt 31 "SET @b=@b+1"
set @a=1;
set @b=1;
call p_20906_a();
@ -858,9 +858,9 @@ select @a, @b;
create procedure p_20906_b() SET @a=@a+1, @b=@b+1, @c=@c+1;
show procedure code p_20906_b;
Pos Instruction
0 stmt 31 "SET @a=@a+1"
1 stmt 31 "SET @b=@b+1"
2 stmt 31 "SET @c=@c+1"
0 stmt 31 "SET @a=@a+1"
1 stmt 31 "SET @b=@b+1"
2 stmt 31 "SET @c=@c+1"
set @a=1;
set @b=1;
set @c=1;
@ -1328,3 +1328,18 @@ Pos Instruction
4 jump 2
5 hpop 1
drop function f1;
#
# MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
#
CREATE OR REPLACE PROCEDURE p1()
BEGIN
SET GLOBAL max_allowed_packet=16000000, max_error_count=60;
SELECT @@GLOBAL.max_allowed_packet, @@GLOBAL.max_error_count;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 stmt 31 "SET GLOBAL max_allowed_packet=16000000"
1 stmt 31 "SET GLOBAL max_error_count=60"
2 stmt 0 "SELECT @@GLOBAL.max_allowed_packet, @..."
DROP PROCEDURE p1;

View file

@ -946,3 +946,19 @@ end|
delimiter ;|
show function code f1;
drop function f1;
--echo #
--echo # MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
--echo #
DELIMITER $$;
CREATE OR REPLACE PROCEDURE p1()
BEGIN
SET GLOBAL max_allowed_packet=16000000, max_error_count=60;
SELECT @@GLOBAL.max_allowed_packet, @@GLOBAL.max_error_count;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1;

View file

@ -1487,3 +1487,30 @@ CALL p1();
x0 x1.a x1.b
100 101 102
DROP PROCEDURE p1;
#
# MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
#
CREATE OR REPLACE PROCEDURE p1() AS
BEGIN
SET GLOBAL max_allowed_packet=16000000, max_error_count=60;
SELECT @@GLOBAL.max_allowed_packet, @@GLOBAL.max_error_count;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 stmt 31 "SET GLOBAL max_allowed_packet=16000000"
1 stmt 31 "SET GLOBAL max_error_count=60"
2 stmt 0 "SELECT @@GLOBAL.max_allowed_packet, @..."
DROP PROCEDURE p1;
#
# MDEV-19639 sql_mode=ORACLE: Wrong SHOW PROCEDURE output for sysvar:=expr
#
CREATE OR REPLACE PROCEDURE p1() AS
BEGIN
max_error_count:=10;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 stmt 31 "max_error_count:=10"
DROP PROCEDURE p1;

View file

@ -1055,3 +1055,34 @@ DELIMITER ;$$
SHOW PROCEDURE CODE p1;
CALL p1();
DROP PROCEDURE p1;
--echo #
--echo # MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
--echo #
DELIMITER $$;
CREATE OR REPLACE PROCEDURE p1() AS
BEGIN
SET GLOBAL max_allowed_packet=16000000, max_error_count=60;
SELECT @@GLOBAL.max_allowed_packet, @@GLOBAL.max_error_count;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1;
--echo #
--echo # MDEV-19639 sql_mode=ORACLE: Wrong SHOW PROCEDURE output for sysvar:=expr
--echo #
DELIMITER $$;
CREATE OR REPLACE PROCEDURE p1() AS
BEGIN
max_error_count:=10;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1;

View file

@ -2023,7 +2023,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
next_state= MY_LEX_HOSTNAME;
break;
}
yylval->lex_str.str= (char*) get_ptr();
yylval->lex_str.str= (char*) get_ptr() - 1;
yylval->lex_str.length= 1;
return((int) '@');
case MY_LEX_HOSTNAME: // end '@' of user@hostname
@ -5579,6 +5579,7 @@ void LEX::set_stmt_init()
mysql_init_select(this);
option_type= OPT_SESSION;
autocommit= 0;
var_list.empty();
};
@ -7574,7 +7575,7 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
bool LEX::set_variable(const LEX_CSTRING *name, Item *item)
bool LEX::set_variable(const Lex_ident_sys_st *name, Item *item)
{
sp_pcontext *ctx;
const Sp_rcontext_handler *rh;
@ -7588,8 +7589,8 @@ bool LEX::set_variable(const LEX_CSTRING *name, Item *item)
Generate instructions for:
SET x.y= expr;
*/
bool LEX::set_variable(const LEX_CSTRING *name1,
const LEX_CSTRING *name2,
bool LEX::set_variable(const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2,
Item *item)
{
const Sp_rcontext_handler *rh;
@ -7619,10 +7620,10 @@ bool LEX::set_variable(const LEX_CSTRING *name1,
bool LEX::set_default_system_variable(enum_var_type var_type,
const LEX_CSTRING *name,
const Lex_ident_sys_st *name,
Item *val)
{
static LEX_CSTRING default_base_name= {STRING_WITH_LEN("default")};
static Lex_ident_sys default_base_name= {STRING_WITH_LEN("default")};
sys_var *var= find_sys_var(thd, name->str, name->length);
if (!var)
return true;
@ -7636,18 +7637,19 @@ bool LEX::set_default_system_variable(enum_var_type var_type,
bool LEX::set_system_variable(enum_var_type var_type,
const LEX_CSTRING *name,
const Lex_ident_sys_st *name,
Item *val)
{
sys_var *var= find_sys_var(thd, name->str, name->length);
DBUG_ASSERT(thd->is_error() || var != NULL);
return likely(var) ? set_system_variable(var_type, var, &null_clex_str, val) : true;
static Lex_ident_sys null_str;
return likely(var) ? set_system_variable(var_type, var, &null_str, val) : true;
}
bool LEX::set_system_variable(THD *thd, enum_var_type var_type,
const LEX_CSTRING *name1,
const LEX_CSTRING *name2,
const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2,
Item *val)
{
sys_var *tmp;
@ -8328,15 +8330,15 @@ bool LEX::call_statement_start(THD *thd, sp_name *name)
}
bool LEX::call_statement_start(THD *thd, const LEX_CSTRING *name)
bool LEX::call_statement_start(THD *thd, const Lex_ident_sys_st *name)
{
sp_name *spname= make_sp_name(thd, name);
return unlikely(!spname) || call_statement_start(thd, spname);
}
bool LEX::call_statement_start(THD *thd, const LEX_CSTRING *name1,
const LEX_CSTRING *name2)
bool LEX::call_statement_start(THD *thd, const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2)
{
sp_name *spname= make_sp_name(thd, name1, name2);
return unlikely(!spname) || call_statement_start(thd, spname);

View file

@ -3741,15 +3741,15 @@ public:
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
Item *val);
bool set_system_variable(enum_var_type var_type, sys_var *var,
const LEX_CSTRING *base_name, Item *val);
bool set_system_variable(enum_var_type var_type, const LEX_CSTRING *name,
Item *val);
const Lex_ident_sys_st *base_name, Item *val);
bool set_system_variable(enum_var_type var_type,
const Lex_ident_sys_st *name, Item *val);
bool set_system_variable(THD *thd, enum_var_type var_type,
const LEX_CSTRING *name1,
const LEX_CSTRING *name2,
const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2,
Item *val);
bool set_default_system_variable(enum_var_type var_type,
const LEX_CSTRING *name,
const Lex_ident_sys_st *name,
Item *val);
bool set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val);
void set_stmt_init();
@ -3779,9 +3779,9 @@ public:
const char *body_start,
const char *body_end);
bool call_statement_start(THD *thd, sp_name *name);
bool call_statement_start(THD *thd, const LEX_CSTRING *name);
bool call_statement_start(THD *thd, const LEX_CSTRING *name1,
const LEX_CSTRING *name2);
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name);
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2);
sp_variable *find_variable(const LEX_CSTRING *name,
sp_pcontext **ctx,
const Sp_rcontext_handler **rh) const;
@ -3791,9 +3791,9 @@ public:
sp_pcontext *not_used_ctx;
return find_variable(name, &not_used_ctx, rh);
}
bool set_variable(const LEX_CSTRING *name, Item *item);
bool set_variable(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
Item *item);
bool set_variable(const Lex_ident_sys_st *name, Item *item);
bool set_variable(const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2, Item *item);
void sp_variable_declarations_init(THD *thd, int nvars);
bool sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
@ -4439,6 +4439,12 @@ public:
SELECT_LEX_UNIT *create_unit(SELECT_LEX*);
SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit);
SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel);
void init_select()
{
current_select->init_select();
wild= 0;
exchange= 0;
}
bool main_select_push();
bool insert_select_hack(SELECT_LEX *sel);
SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest);
@ -4747,6 +4753,22 @@ public:
};
class sp_lex_set_var: public sp_lex_local
{
public:
sp_lex_set_var(THD *thd, const LEX *oldlex)
:sp_lex_local(thd, oldlex)
{
// Set new LEX as if we at start of set rule
init_select();
sql_command= SQLCOM_SET_OPTION;
var_list.empty();
autocommit= 0;
option_type= oldlex->option_type; // Inherit from the outer lex
}
};
/**
An assignment specific LEX, which additionally has an Item (an expression)
and an associated with the Item free_list, which is usually freed
@ -4826,8 +4848,9 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr);
Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
Item *expr);
void sp_create_assignment_lex(THD *thd, bool no_lookahead);
bool sp_create_assignment_instr(THD *thd, bool no_lookahead);
bool sp_create_assignment_lex(THD *thd, const char *pos);
bool sp_create_assignment_instr(THD *thd, bool no_lookahead,
bool need_set_keyword= true);
void mark_or_conds_to_avoid_pushdown(Item *cond);

View file

@ -7760,10 +7760,7 @@ void THD::reset_for_next_command(bool do_clear_error)
void
mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
lex->wild= 0;
lex->exchange= 0;
lex->init_select();
}

View file

@ -289,7 +289,7 @@ int LEX::case_stmt_action_then()
bool
LEX::set_system_variable(enum enum_var_type var_type,
sys_var *sysvar, const LEX_CSTRING *base_name,
sys_var *sysvar, const Lex_ident_sys_st *base_name,
Item *val)
{
set_var *setvar;
@ -506,34 +506,22 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
@see sp_create_assignment_instr
@param thd Thread context
@param no_lookahead True if the parser has no lookahead
@param pos The position in the raw SQL buffer
*/
void sp_create_assignment_lex(THD *thd, bool no_lookahead)
bool sp_create_assignment_lex(THD *thd, const char *pos)
{
LEX *lex= thd->lex;
if (lex->sphead)
if (thd->lex->sphead)
{
Lex_input_stream *lip= &thd->m_parser_state->m_lip;
LEX *old_lex= lex;
lex->sphead->reset_lex(thd);
lex= thd->lex;
/* Set new LEX as if we at start of set rule. */
lex->sql_command= SQLCOM_SET_OPTION;
mysql_init_select(lex);
lex->var_list.empty();
lex->autocommit= 0;
/* get_ptr() is only correct with no lookahead. */
if (no_lookahead)
lex->sphead->m_tmp_query= lip->get_ptr();
else
lex->sphead->m_tmp_query= lip->get_tok_end();
/* Inherit from outer lex. */
lex->option_type= old_lex->option_type;
lex->main_select_push();
sp_lex_local *new_lex;
if (!(new_lex= new (thd->mem_root) sp_lex_set_var(thd, thd->lex)) ||
new_lex->main_select_push())
return true;
new_lex->sphead->m_tmp_query= pos;
return thd->lex->sphead->reset_lex(thd, new_lex);
}
return false;
}
@ -542,13 +530,15 @@ void sp_create_assignment_lex(THD *thd, bool no_lookahead)
@see sp_create_assignment_lex
@param thd Thread context
@param no_lookahead True if the parser has no lookahead
@param thd - Thread context
@param no_lookahead - True if the parser has no lookahead
@param need_set_keyword - if a SET statement "SET a=10",
or a direct assignment overwise "a:=10"
@return false if success, true otherwise.
*/
bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
bool sp_create_assignment_instr(THD *thd, bool no_lookahead,
bool need_set_keyword)
{
LEX *lex= thd->lex;
@ -556,6 +546,24 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
{
if (!lex->var_list.is_empty())
{
/*
- Every variable assignment from the same SET command, e.g.:
SET @var1=expr1, @var2=expr2;
produce each own sp_create_assignment_instr() call
lex->var_list.elements is 1 in this case.
- This query:
SET TRANSACTION READ ONLY, ISOLATION LEVEL SERIALIZABLE;
in translated to:
SET tx_read_only=1, tx_isolation=ISO_SERIALIZABLE;
but produces a single sp_create_assignment_instr() call
which includes the query fragment covering both options.
*/
DBUG_ASSERT(lex->var_list.elements >= 1 && lex->var_list.elements <= 2);
/*
sql_mode=ORACLE's direct assignment of a global variable
is not possible by the grammar.
*/
DBUG_ASSERT(Lex->option_type != OPT_GLOBAL || need_set_keyword);
/*
We have assignment to user or system variable or
option setting, so we should construct sp_instr_stmt
@ -568,10 +576,15 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
end is either lip->ptr, if there was no lookahead,
lip->tok_end otherwise.
*/
static const LEX_CSTRING setsp= { STRING_WITH_LEN("SET ") };
static const LEX_CSTRING setlc= { STRING_WITH_LEN("SET ") };
static const LEX_CSTRING setgl= { STRING_WITH_LEN("SET GLOBAL ") };
const char *qend= no_lookahead ? lip->get_ptr() : lip->get_tok_end();
Lex_cstring qbuf(lex->sphead->m_tmp_query, qend);
if (lex->new_sp_instr_stmt(thd, setsp, qbuf))
if (lex->new_sp_instr_stmt(thd,
Lex->option_type == OPT_GLOBAL ? setgl :
need_set_keyword ? setlc :
null_clex_str,
qbuf))
return true;
}
lex->pop_select();
@ -820,7 +833,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
Currently there are 48 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 48
%expect 47
/*
Comments for TOKENS.
@ -842,6 +855,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
*/
%token <lex_str> '@'
/*
Reserved keywords and operators
*/
@ -874,7 +889,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token CASE_SYM /* SQL-2003-R */
%token CAST_SYM /* SQL-2003-R */
%token CHANGE
%token CHAR_SYM /* SQL-2003-R */
%token <kwd> CHAR_SYM /* SQL-2003-R */
%token CHECK_SYM /* SQL-2003-R */
%token COLLATE_SYM /* SQL-2003-R */
%token CONDITION_SYM /* SQL-2003-R, SQL-2008-R */
@ -903,7 +918,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token DECIMAL_SYM /* SQL-2003-R */
%token DECLARE_MARIADB_SYM /* SQL-2003-R */
%token DECLARE_ORACLE_SYM /* Oracle-R */
%token DEFAULT /* SQL-2003-R */
%token <kwd> DEFAULT /* SQL-2003-R */
%token DELETE_DOMAIN_ID_SYM
%token DELETE_SYM /* SQL-2003-R */
%token DENSE_RANK_SYM
@ -1748,7 +1763,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
ident
label_ident
sp_decl_ident
ident_set_usual_case
ident_or_empty
ident_table_alias
ident_sysvar_name
@ -1766,6 +1780,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
IDENT_QUOTED
IDENT_cli
ident_cli
ident_cli_set_usual_case
%type <kwd>
keyword_data_type
@ -1782,6 +1797,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
keyword_sysvar_type
keyword_table_alias
keyword_verb_clause
charset
%type <table>
table_ident table_ident_nodb references xid
@ -2070,7 +2086,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild
opt_and charset
opt_and
select_var_list select_var_list_init help
opt_extended_describe shutdown
opt_format_json
@ -7284,8 +7300,8 @@ type_with_opt_collate:
;
charset:
CHAR_SYM SET {}
| CHARSET {}
CHAR_SYM SET { $$= $1; }
| CHARSET { $$= $1; }
;
charset_name:
@ -15540,13 +15556,9 @@ ident_table_alias:
}
;
ident_set_usual_case:
IDENT_sys
| keyword_set_usual_case
{
if (unlikely($$.copy_keyword(thd, &$1)))
MYSQL_YYABORT;
}
ident_cli_set_usual_case:
IDENT_cli { $$= $1; }
| keyword_set_usual_case { $$= $1; }
;
ident_sysvar_name:
@ -16256,57 +16268,23 @@ set:
if (lex->main_select_push())
MYSQL_YYABORT;
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
set_param
{
Lex->pop_select(); //main select
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
| SET STATEMENT_SYM
{
if (Lex->main_select_push())
MYSQL_YYABORT;
Lex->set_stmt_init();
}
set_stmt_option_value_following_option_type_list
{
LEX *lex= Lex;
if (unlikely(lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
Lex->pop_select(); //main select
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
FOR_SYM verb_clause
{}
;
set_stmt_option_value_following_option_type_list:
/*
Only system variables can be used here. If this condition is changed
please check careful code under lex->option_type == OPT_STATEMENT
condition on wrong type casts.
*/
option_value_following_option_type
| set_stmt_option_value_following_option_type_list ',' option_value_following_option_type
;
/* Start of option value list */
start_option_value_list:
set_param:
option_value_no_option_type
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
option_value_list_continued
| option_value_no_option_type ',' option_value_list
| TRANSACTION_SYM
{
Lex->option_type= OPT_DEFAULT;
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
transaction_characteristics
{
@ -16318,49 +16296,50 @@ start_option_value_list:
Lex->option_type= $1;
}
start_option_value_list_following_option_type
| STATEMENT_SYM
set_stmt_option_list
{
LEX *lex= Lex;
if (unlikely(lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
FOR_SYM verb_clause
;
set_stmt_option_list:
/*
Only system variables can be used here. If this condition is changed
please check careful code under lex->option_type == OPT_STATEMENT
condition on wrong type casts.
*/
set_stmt_option
| set_stmt_option_list ',' set_stmt_option
;
/* Start of option value list, option_type was given */
start_option_value_list_following_option_type:
option_value_following_option_type
| option_value_following_option_type ',' option_value_list
| TRANSACTION_SYM
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
transaction_characteristics
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
option_value_list_continued
| TRANSACTION_SYM transaction_characteristics
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;
/* Remainder of the option value list after first option value. */
option_value_list_continued:
/* empty */
| ',' option_value_list
;
/* Repeating list of option values after first option value. */
option_value_list:
{
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
option_value
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| option_value_list ','
{
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
option_value
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| option_value_list ',' option_value
;
/* Wrapper around option values following the first option value in the stmt. */
@ -16393,16 +16372,21 @@ opt_var_ident_type:
| SESSION_SYM '.' { $$=OPT_SESSION; }
;
/* Option values with preceding option_type. */
option_value_following_option_type:
ident equal set_expr_or_default
/*
SET STATEMENT options do not need their own LEX or Query_arena.
Let's put them to the main ones.
*/
set_stmt_option:
ident_cli equal set_expr_or_default
{
if (unlikely(Lex->set_system_variable(Lex->option_type, &$1, $3)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $3)))
MYSQL_YYABORT;
}
| ident '.' ident equal set_expr_or_default
| ident_cli '.' ident equal set_expr_or_default
{
if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &$1, &$3, $5)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $5)))
MYSQL_YYABORT;
}
| DEFAULT '.' ident equal set_expr_or_default
@ -16412,45 +16396,132 @@ option_value_following_option_type:
}
;
/* Option values with preceding option_type. */
option_value_following_option_type:
ident_cli equal
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ident_cli '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;
/* Option values without preceding option_type. */
option_value_no_option_type:
ident_set_usual_case equal set_expr_or_default
ident_cli_set_usual_case equal
{
if (unlikely(Lex->set_variable(&$1, $3)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
| ident '.' ident equal set_expr_or_default
set_expr_or_default
{
if (unlikely(Lex->set_variable(&$1, &$3, $5)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT '.' ident equal set_expr_or_default
| ident_cli_set_usual_case '.' ident equal
{
if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $5)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
| '@' ident_or_text equal expr
set_expr_or_default
{
if (unlikely(Lex->set_user_variable(thd, &$2, $4)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name equal set_expr_or_default
| DEFAULT '.' ident equal
{
if (unlikely(Lex->set_system_variable($3, &$4, $6)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal set_expr_or_default
set_expr_or_default
{
if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $8)))
if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)))
MYSQL_YYABORT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type DEFAULT '.' ident equal set_expr_or_default
| '@' ident_or_text equal
{
if (unlikely(Lex->set_default_system_variable($3, &$6, $8)))
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
expr
{
if (unlikely(Lex->set_user_variable(thd, &$2, $5)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name equal
{
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_system_variable($3, &$4, $7)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $9)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type DEFAULT '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_default_system_variable($3, &$6, $9)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| charset old_or_new_charset_name_or_default
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex= thd->lex;
CHARSET_INFO *cs2;
cs2= $2 ? $2: global_system_variables.character_set_client;
@ -16462,6 +16533,8 @@ option_value_no_option_type:
if (unlikely(var == NULL))
MYSQL_YYABORT;
lex->var_list.push_back(var, thd->mem_root);
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| NAMES_SYM equal expr
{
@ -16476,6 +16549,8 @@ option_value_no_option_type:
}
| NAMES_SYM charset_name_or_default opt_collate
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex= Lex;
CHARSET_INFO *cs2;
CHARSET_INFO *cs3;
@ -16490,11 +16565,14 @@ option_value_no_option_type:
set_var_collation_client *var;
var= new (thd->mem_root) set_var_collation_client(cs3, cs3, cs3);
if (unlikely(var == NULL) ||
unlikely(lex->var_list.push_back(var, thd->mem_root)))
unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT ROLE_SYM grant_role
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
LEX_USER *user;
if (unlikely(!(user=(LEX_USER *) thd->calloc(sizeof(LEX_USER)))))
@ -16510,9 +16588,13 @@ option_value_no_option_type:
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT ROLE_SYM grant_role FOR_SYM user
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
set_var_default_role *var= (new (thd->mem_root)
set_var_default_role($5, $3->user));
@ -16522,22 +16604,36 @@ option_value_no_option_type:
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ROLE_SYM ident_or_text
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
set_var_role *var= new (thd->mem_root) set_var_role($2);
if (unlikely(var == NULL) ||
unlikely(lex->var_list.push_back(var, thd->mem_root)))
unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ROLE_SYM equal set_expr_or_default
| ROLE_SYM equal
{
if (unlikely(Lex->set_variable(&$1, $3)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| PASSWORD_SYM opt_for_user text_or_password
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
set_var_password *var= (new (thd->mem_root)
set_var_password(lex->definer));
@ -16547,6 +16643,8 @@ option_value_no_option_type:
lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;

View file

@ -295,10 +295,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
Currently there are 49 shift/reduce conflicts.
Currently there are 48 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 49
%expect 48
/*
Comments for TOKENS.
@ -320,6 +320,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
*/
%token <lex_str> '@'
/*
Reserved keywords and operators
*/
@ -352,7 +354,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token CASE_SYM /* SQL-2003-R */
%token CAST_SYM /* SQL-2003-R */
%token CHANGE
%token CHAR_SYM /* SQL-2003-R */
%token <kwd> CHAR_SYM /* SQL-2003-R */
%token CHECK_SYM /* SQL-2003-R */
%token COLLATE_SYM /* SQL-2003-R */
%token CONDITION_SYM /* SQL-2003-R, SQL-2008-R */
@ -381,7 +383,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token DECIMAL_SYM /* SQL-2003-R */
%token DECLARE_MARIADB_SYM /* SQL-2003-R */
%token DECLARE_ORACLE_SYM /* Oracle-R */
%token DEFAULT /* SQL-2003-R */
%token <kwd> DEFAULT /* SQL-2003-R */
%token DELETE_DOMAIN_ID_SYM
%token DELETE_SYM /* SQL-2003-R */
%token DENSE_RANK_SYM
@ -1228,7 +1230,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
ident
label_ident
sp_decl_ident
ident_set_usual_case
ident_or_empty
ident_table_alias
ident_sysvar_name
@ -1247,6 +1248,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
IDENT_QUOTED
IDENT_cli
ident_cli
ident_cli_set_usual_case
ident_cli_directly_assignable
%type <kwd>
keyword_data_type
@ -1264,6 +1267,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
keyword_table_alias
keyword_verb_clause
keyword_directly_assignable
charset
%type <table>
table_ident table_ident_nodb references xid
@ -1557,7 +1561,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild
opt_and charset
opt_and
select_var_list select_var_list_init help
opt_extended_describe shutdown
opt_format_json
@ -4046,16 +4050,18 @@ sp_proc_stmt_if:
sp_statement:
statement
| ident_directly_assignable
| ident_cli_directly_assignable
{
// Direct procedure call (without the CALL keyword)
if (unlikely(Lex->call_statement_start(thd, &$1)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->call_statement_start(thd, &tmp)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
| ident_directly_assignable '.' ident
| ident_cli_directly_assignable '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$1, &$3)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->call_statement_start(thd, &tmp, &$3)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
@ -7385,8 +7391,8 @@ sp_param_type_with_opt_collate:
;
charset:
CHAR_SYM SET {}
| CHARSET {}
CHAR_SYM SET { $$= $1; }
| CHARSET { $$= $1; }
;
charset_name:
@ -15672,13 +15678,9 @@ ident_table_alias:
}
;
ident_set_usual_case:
IDENT_sys
| keyword_set_usual_case
{
if (unlikely($$.copy_keyword(thd, &$1)))
MYSQL_YYABORT;
}
ident_cli_set_usual_case:
IDENT_cli { $$= $1; }
| keyword_set_usual_case { $$= $1; }
;
ident_sysvar_name:
@ -15715,6 +15717,12 @@ ident_directly_assignable:
;
ident_cli_directly_assignable:
IDENT_cli
| keyword_directly_assignable { $$= $1; }
;
label_ident:
IDENT_sys
| keyword_label
@ -16424,107 +16432,23 @@ set:
if (lex->main_select_push())
MYSQL_YYABORT;
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
set_param
{
Lex->pop_select(); //main select
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
| SET STATEMENT_SYM
{
if (Lex->main_select_push())
MYSQL_YYABORT;
Lex->set_stmt_init();
}
set_stmt_option_value_following_option_type_list
{
LEX *lex= Lex;
if (unlikely(lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
Lex->pop_select(); //main select
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
FOR_SYM verb_clause
{}
;
set_assign:
ident_directly_assignable SET_VAR
{
LEX *lex=Lex;
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
set_expr_or_default
{
if (unlikely(Lex->set_variable(&$1, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ident_directly_assignable '.' ident SET_VAR
{
LEX *lex=Lex;
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
set_expr_or_default
{
LEX *lex= Lex;
DBUG_ASSERT(lex->var_list.is_empty());
if (unlikely(lex->set_variable(&$1, &$3, $6)) ||
unlikely(lex->sphead->restore_lex(thd)))
MYSQL_YYABORT;
}
| COLON_ORACLE_SYM ident '.' ident SET_VAR
{
LEX *lex= Lex;
if (unlikely(!lex->is_trigger_new_or_old_reference(&$2)))
{
thd->parse_error(ER_SYNTAX_ERROR, $1.pos());
MYSQL_YYABORT;
}
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
set_expr_or_default
{
LEX_CSTRING tmp= { $2.str, $2.length };
if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;
set_stmt_option_value_following_option_type_list:
/*
Only system variables can be used here. If this condition is changed
please check careful code under lex->option_type == OPT_STATEMENT
condition on wrong type casts.
*/
option_value_following_option_type
| set_stmt_option_value_following_option_type_list ',' option_value_following_option_type
;
/* Start of option value list */
start_option_value_list:
set_param:
option_value_no_option_type
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
option_value_list_continued
| option_value_no_option_type ',' option_value_list
| TRANSACTION_SYM
{
Lex->option_type= OPT_DEFAULT;
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
transaction_characteristics
{
@ -16536,49 +16460,105 @@ start_option_value_list:
Lex->option_type= $1;
}
start_option_value_list_following_option_type
| STATEMENT_SYM
set_stmt_option_list
{
LEX *lex= Lex;
if (unlikely(lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
FOR_SYM verb_clause
;
set_assign:
ident_cli_directly_assignable SET_VAR
{
LEX *lex=Lex;
lex->set_stmt_init();
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
}
| ident_cli_directly_assignable '.' ident SET_VAR
{
LEX *lex=Lex;
lex->set_stmt_init();
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
LEX *lex= Lex;
DBUG_ASSERT(lex->var_list.is_empty());
Lex_ident_sys tmp(thd, &$1);
if (unlikely(lex->set_variable(&tmp, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
}
| COLON_ORACLE_SYM ident '.' ident SET_VAR
{
LEX *lex= Lex;
if (unlikely(!lex->is_trigger_new_or_old_reference(&$2)))
{
thd->parse_error(ER_SYNTAX_ERROR, $1.pos());
MYSQL_YYABORT;
}
lex->set_stmt_init();
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
LEX_CSTRING tmp= { $2.str, $2.length };
if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
}
;
set_stmt_option_list:
/*
Only system variables can be used here. If this condition is changed
please check careful code under lex->option_type == OPT_STATEMENT
condition on wrong type casts.
*/
set_stmt_option
| set_stmt_option_list ',' set_stmt_option
;
/* Start of option value list, option_type was given */
start_option_value_list_following_option_type:
option_value_following_option_type
| option_value_following_option_type ',' option_value_list
| TRANSACTION_SYM
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
transaction_characteristics
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
option_value_list_continued
| TRANSACTION_SYM transaction_characteristics
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;
/* Remainder of the option value list after first option value. */
option_value_list_continued:
/* empty */
| ',' option_value_list
;
/* Repeating list of option values after first option value. */
option_value_list:
{
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
option_value
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| option_value_list ','
{
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
option_value
{
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| option_value_list ',' option_value
;
/* Wrapper around option values following the first option value in the stmt. */
@ -16611,16 +16591,21 @@ opt_var_ident_type:
| SESSION_SYM '.' { $$=OPT_SESSION; }
;
/* Option values with preceding option_type. */
option_value_following_option_type:
ident equal set_expr_or_default
/*
SET STATEMENT options do not need their own LEX or Query_arena.
Let's put them to the main ones.
*/
set_stmt_option:
ident_cli equal set_expr_or_default
{
if (unlikely(Lex->set_system_variable(Lex->option_type, &$1, $3)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $3)))
MYSQL_YYABORT;
}
| ident '.' ident equal set_expr_or_default
| ident_cli '.' ident equal set_expr_or_default
{
if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &$1, &$3, $5)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $5)))
MYSQL_YYABORT;
}
| DEFAULT '.' ident equal set_expr_or_default
@ -16630,45 +16615,132 @@ option_value_following_option_type:
}
;
/* Option values with preceding option_type. */
option_value_following_option_type:
ident_cli equal
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ident_cli '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;
/* Option values without preceding option_type. */
option_value_no_option_type:
ident_set_usual_case equal set_expr_or_default
ident_cli_set_usual_case equal
{
if (unlikely(Lex->set_variable(&$1, $3)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
| ident '.' ident equal set_expr_or_default
set_expr_or_default
{
if (unlikely(Lex->set_variable(&$1, &$3, $5)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT '.' ident equal set_expr_or_default
| ident_cli_set_usual_case '.' ident equal
{
if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $5)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
| '@' ident_or_text equal expr
set_expr_or_default
{
if (unlikely(Lex->set_user_variable(thd, &$2, $4)))
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, &$3, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name equal set_expr_or_default
| DEFAULT '.' ident equal
{
if (unlikely(Lex->set_system_variable($3, &$4, $6)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal set_expr_or_default
set_expr_or_default
{
if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $8)))
if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)))
MYSQL_YYABORT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type DEFAULT '.' ident equal set_expr_or_default
| '@' ident_or_text equal
{
if (unlikely(Lex->set_default_system_variable($3, &$6, $8)))
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
expr
{
if (unlikely(Lex->set_user_variable(thd, &$2, $5)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name equal
{
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_system_variable($3, &$4, $7)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $9)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| '@' '@' opt_var_ident_type DEFAULT '.' ident equal
{
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
set_expr_or_default
{
if (unlikely(Lex->set_default_system_variable($3, &$6, $9)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| charset old_or_new_charset_name_or_default
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex= thd->lex;
CHARSET_INFO *cs2;
cs2= $2 ? $2: global_system_variables.character_set_client;
@ -16680,6 +16752,8 @@ option_value_no_option_type:
if (unlikely(var == NULL))
MYSQL_YYABORT;
lex->var_list.push_back(var, thd->mem_root);
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| NAMES_SYM equal expr
{
@ -16694,6 +16768,8 @@ option_value_no_option_type:
}
| NAMES_SYM charset_name_or_default opt_collate
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex= Lex;
CHARSET_INFO *cs2;
CHARSET_INFO *cs3;
@ -16708,11 +16784,14 @@ option_value_no_option_type:
set_var_collation_client *var;
var= new (thd->mem_root) set_var_collation_client(cs3, cs3, cs3);
if (unlikely(var == NULL) ||
unlikely(lex->var_list.push_back(var, thd->mem_root)))
unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT ROLE_SYM grant_role
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
LEX_USER *user;
if (unlikely(!(user=(LEX_USER *) thd->calloc(sizeof(LEX_USER)))))
@ -16728,9 +16807,13 @@ option_value_no_option_type:
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| DEFAULT ROLE_SYM grant_role FOR_SYM user
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
set_var_default_role *var= (new (thd->mem_root)
set_var_default_role($5, $3->user));
@ -16740,22 +16823,36 @@ option_value_no_option_type:
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ROLE_SYM ident_or_text
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
set_var_role *var= new (thd->mem_root) set_var_role($2);
if (unlikely(var == NULL) ||
unlikely(lex->var_list.push_back(var, thd->mem_root)))
unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| ROLE_SYM equal set_expr_or_default
| ROLE_SYM equal
{
if (unlikely(Lex->set_variable(&$1, $3)))
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(Lex->set_variable(&tmp, $4)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
| PASSWORD_SYM opt_for_user text_or_password
{
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
LEX *lex = Lex;
set_var_password *var= (new (thd->mem_root)
set_var_password(lex->definer));
@ -16765,6 +16862,8 @@ option_value_no_option_type:
lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
;