Commit bf5a144e authored by Alexander Barkov's avatar Alexander Barkov

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.
parent f859789e
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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);
......
......@@ -3741,15 +3741,15 @@ struct LEX: public Query_tables_list
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 @@ struct LEX: public Query_tables_list
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 @@ struct LEX: public Query_tables_list
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 @@ struct LEX: public Query_tables_list
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 @@ class sp_lex_local: public st_lex_local
};
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);
......
......@@ -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();
}
......
This diff is collapsed.
This diff is collapsed.
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