Commit 2e1bfbd2 authored by unknown's avatar unknown

Cleanup patch for handling of subselects in commands which cannot

handle them.

Problem:
CREATE|ALTER EVENT, HANDLER READ, KILL, Partitioning uses `expr` from the
parser. This rule comes with all the rings and bells including subqueries.
However, these commands are not subquery safe. For this reason there are two
fuse checks in the parser. They were checking by command id. CREATE EVENT
should forbid subquery is the fix for
bug#16394 Events: Crash if schedule contains SELECT
The fix has been incorporated as part of the patch for WL#3337 (Event scheduler
new architecture).

Solution:
A new flag was added to LEX command_forbids_subselect. The fuse checks were
changed. The commands are responsible to set the value to true whenever
they can't handle subselects.


sql/sql_lex.cc:
  initialize the variable
sql/sql_lex.h:
  Add a new flag whether the parser should allow a subselect when
  parsing. This is temporarily turned off by commands like CREATE|ALTER EVENT,
  HA_READ, KILL. Could be used by other parts which reuse `expr` rule of the
  grammar and should not allow subqueries as part of it.
sql/sql_yacc.yy:
  Forbid subselects in some commands in a better way.
  CREATE|ALTER EVENT, HANDLER READ, KILL, are not subselect
  safe for parameters and therefore they should be forbidden already in
  the parser.
  This patch makes it easier for the developer to add new commands in that
  sense similar to the mentioned above.
parent e10aed52
...@@ -175,6 +175,7 @@ void lex_start(THD *thd, const uchar *buf, uint length) ...@@ -175,6 +175,7 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->proc_list.first= 0; lex->proc_list.first= 0;
lex->escape_used= FALSE; lex->escape_used= FALSE;
lex->reset_query_tables_list(FALSE); lex->reset_query_tables_list(FALSE);
lex->expr_allows_subselect= TRUE;
lex->name= 0; lex->name= 0;
lex->event_parse_data= NULL; lex->event_parse_data= NULL;
......
...@@ -958,6 +958,14 @@ typedef struct st_lex : public Query_tables_list ...@@ -958,6 +958,14 @@ typedef struct st_lex : public Query_tables_list
*/ */
nesting_map allow_sum_func; nesting_map allow_sum_func;
enum_sql_command sql_command; enum_sql_command sql_command;
/*
Usually `expr` rule of yacc is quite reused but some commands better
not support subqueries which comes standard with this rule, like
KILL, HA_READ, CREATE/ALTER EVENT etc. Set this to `false` to get
syntax error back.
*/
bool expr_allows_subselect;
thr_lock_type lock_option; thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */ enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state; enum my_lex_states next_state;
......
...@@ -1302,8 +1302,9 @@ event_tail: ...@@ -1302,8 +1302,9 @@ event_tail:
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
/* We need that for disallowing subqueries */
Lex->sql_command= SQLCOM_CREATE_EVENT; Lex->sql_command= SQLCOM_CREATE_EVENT;
/* We need that for disallowing subqueries */
Lex->expr_allows_subselect= FALSE;
} }
ON SCHEDULE_SYM ev_schedule_time ON SCHEDULE_SYM ev_schedule_time
opt_ev_on_completion opt_ev_on_completion
...@@ -1325,6 +1326,7 @@ event_tail: ...@@ -1325,6 +1326,7 @@ event_tail:
can overwrite it can overwrite it
*/ */
Lex->sql_command= SQLCOM_CREATE_EVENT; Lex->sql_command= SQLCOM_CREATE_EVENT;
Lex->expr_allows_subselect= TRUE;
} }
...@@ -4697,8 +4699,9 @@ alter: ...@@ -4697,8 +4699,9 @@ alter:
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
/* we need that for disallowing subqueries */
Lex->sql_command= SQLCOM_ALTER_EVENT; Lex->sql_command= SQLCOM_ALTER_EVENT;
/* we need that for disallowing subqueries */
Lex->expr_allows_subselect= FALSE;
} }
ev_alter_on_schedule_completion ev_alter_on_schedule_completion
opt_ev_rename_to opt_ev_rename_to
...@@ -4724,6 +4727,7 @@ alter: ...@@ -4724,6 +4727,7 @@ alter:
can overwrite it can overwrite it
*/ */
Lex->sql_command= SQLCOM_ALTER_EVENT; Lex->sql_command= SQLCOM_ALTER_EVENT;
Lex->expr_allows_subselect= TRUE;
} }
| ALTER TABLESPACE alter_tablespace_info | ALTER TABLESPACE alter_tablespace_info
{ {
...@@ -7048,10 +7052,7 @@ select_derived2: ...@@ -7048,10 +7052,7 @@ select_derived2:
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->derived_tables|= DERIVED_SUBQUERY; lex->derived_tables|= DERIVED_SUBQUERY;
if (lex->sql_command == SQLCOM_HA_READ || if (!lex->expr_allows_subselect)
lex->sql_command == SQLCOM_KILL ||
lex->sql_command == SQLCOM_CREATE_EVENT ||
lex->sql_command == SQLCOM_ALTER_EVENT)
{ {
yyerror(ER(ER_SYNTAX_ERROR)); yyerror(ER(ER_SYNTAX_ERROR));
YYABORT; YYABORT;
...@@ -8554,11 +8555,17 @@ purge_option: ...@@ -8554,11 +8555,17 @@ purge_option:
/* kill threads */ /* kill threads */
kill: kill:
KILL_SYM { Lex->sql_command= SQLCOM_KILL; } kill_option expr KILL_SYM
{
Lex->sql_command= SQLCOM_KILL;
Lex->expr_allows_subselect= FALSE;
}
kill_option expr
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->value_list.empty(); lex->value_list.empty();
lex->value_list.push_front($4); lex->value_list.push_front($4);
Lex->expr_allows_subselect= TRUE;
}; };
kill_option: kill_option:
...@@ -10038,6 +10045,7 @@ handler: ...@@ -10038,6 +10045,7 @@ handler:
my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER"); my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
YYABORT; YYABORT;
} }
lex->expr_allows_subselect= FALSE;
lex->sql_command = SQLCOM_HA_READ; lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
lex->current_select->select_limit= new Item_int((int32) 1); lex->current_select->select_limit= new Item_int((int32) 1);
...@@ -10045,7 +10053,10 @@ handler: ...@@ -10045,7 +10053,10 @@ handler:
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT; YYABORT;
} }
handler_read_or_scan where_clause opt_limit_clause {} handler_read_or_scan where_clause opt_limit_clause
{
Lex->expr_allows_subselect= TRUE;
}
; ;
handler_read_or_scan: handler_read_or_scan:
...@@ -10670,10 +10681,7 @@ subselect_start: ...@@ -10670,10 +10681,7 @@ subselect_start:
'(' SELECT_SYM '(' SELECT_SYM
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->sql_command == SQLCOM_HA_READ || if (!lex->expr_allows_subselect)
lex->sql_command == SQLCOM_KILL ||
lex->sql_command == SQLCOM_CREATE_EVENT ||
lex->sql_command == SQLCOM_ALTER_EVENT)
{ {
yyerror(ER(ER_SYNTAX_ERROR)); yyerror(ER(ER_SYNTAX_ERROR));
YYABORT; YYABORT;
......
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