Commit 0bd2b802 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-15347: Valgrind or ASAN errors in mysql_make_view on query from information_schema

Make each lex pointing to statement lex instead of global pointer in THD (no
need store and restore the global pointer and put it on SP stack).
parent 3b99a274
......@@ -8242,4 +8242,15 @@ DROP PROCEDURE proc_13;
DROP PROCEDURE proc_select;
DROP TABLE t1, t2;
SET max_sp_recursion_depth=default;
#
# MDEV-15347: Valgrind or ASAN errors in mysql_make_view on query
# from information_schema
#
CREATE VIEW v AS SELECT 1;
CREATE FUNCTION f() RETURNS INT RETURN 1;
SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS
UNION
SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS;
DROP FUNCTION f;
DROP VIEW v;
#End of 10.1 tests
......@@ -9754,4 +9754,19 @@ DROP TABLE t1, t2;
SET max_sp_recursion_depth=default;
--echo #
--echo # MDEV-15347: Valgrind or ASAN errors in mysql_make_view on query
--echo # from information_schema
--echo #
CREATE VIEW v AS SELECT 1;
CREATE FUNCTION f() RETURNS INT RETURN 1;
--disable_result_log
SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS
UNION
SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS;
--enable_result_log
DROP FUNCTION f;
DROP VIEW v;
--echo #End of 10.1 tests
......@@ -840,7 +840,7 @@ sp_head::~sp_head()
thd->lex->sphead= NULL;
lex_end(thd->lex);
delete thd->lex;
thd->lex= thd->stmt_lex= lex;
thd->lex= lex;
}
my_hash_free(&m_sptabs);
......@@ -1121,7 +1121,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
backup_arena;
query_id_t old_query_id;
TABLE *old_derived_tables;
LEX *old_lex, *old_stmt_lex;
LEX *old_lex;
Item_change_list old_change_list;
String old_packet;
uint old_server_status;
......@@ -1224,7 +1224,6 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
do it in each instruction
*/
old_lex= thd->lex;
old_stmt_lex= thd->stmt_lex;
/*
We should also save Item tree change list to avoid rollback something
too early in the calling query.
......@@ -1372,7 +1371,6 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
DBUG_ASSERT(thd->change_list.is_empty());
old_change_list.move_elements_to(&thd->change_list);
thd->lex= old_lex;
thd->stmt_lex= old_stmt_lex;
thd->set_query_id(old_query_id);
DBUG_ASSERT(!thd->derived_tables);
thd->derived_tables= old_derived_tables;
......@@ -2207,7 +2205,7 @@ sp_head::reset_lex(THD *thd)
if (sublex == 0)
DBUG_RETURN(TRUE);
thd->lex= thd->stmt_lex= sublex;
thd->lex= sublex;
(void)m_lex.push_front(oldlex);
/* Reset most stuff. */
......@@ -2953,7 +2951,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
We should not save old value since it is saved/restored in
sp_head::execute() when we are entering/leaving routine.
*/
thd->lex= thd->stmt_lex= m_lex;
thd->lex= m_lex;
thd->set_query_id(next_query_id());
......
......@@ -3654,7 +3654,7 @@ void Statement::set_statement(Statement *stmt)
{
id= stmt->id;
mark_used_columns= stmt->mark_used_columns;
stmt_lex= lex= stmt->lex;
lex= stmt->lex;
query_string= stmt->query_string;
}
......
......@@ -1027,21 +1027,6 @@ class Statement: public ilink, public Query_arena
LEX_STRING name; /* name for named prepared statements */
LEX *lex; // parse tree descriptor
/*
LEX which represents current statement (conventional, SP or PS)
For example during view parsing THD::lex will point to the views LEX and
THD::stmt_lex will point to LEX of the statement where the view will be
included
Currently it is used to have always correct select numbering inside
statement (LEX::current_select_number) without storing and restoring a
global counter which was THD::select_number.
TODO: make some unified statement representation (now SP has different)
to store such data like LEX::current_select_number.
*/
LEX *stmt_lex;
/*
Points to the query associated with this statement. It's const, but
we need to declare it char * because all table handlers are written
......
......@@ -657,10 +657,11 @@ void lex_start(THD *thd)
{
LEX *lex= thd->lex;
DBUG_ENTER("lex_start");
DBUG_PRINT("info", ("Lex %p stmt_lex: %p", thd->lex, thd->stmt_lex));
DBUG_PRINT("info", ("Lex %p", thd->lex));
lex->thd= lex->unit.thd= thd;
lex->stmt_lex= lex; // default, should be rewritten for VIEWs And CTEs
DBUG_ASSERT(!lex->explain);
lex->context_stack.empty();
......
......@@ -730,7 +730,7 @@ class st_select_lex: public st_select_lex_node
/*
Point to the LEX in which it was created, used in view subquery detection.
TODO: make also st_select_lex::parent_stmt_lex (see THD::stmt_lex)
TODO: make also st_select_lex::parent_stmt_lex (see LEX::stmt_lex)
and use st_select_lex::parent_lex & st_select_lex::parent_stmt_lex
instead of global (from THD) references where it is possible.
*/
......@@ -2435,6 +2435,21 @@ struct LEX: public Query_tables_list
// type information
char *length,*dec;
CHARSET_INFO *charset;
/*
LEX which represents current statement (conventional, SP or PS)
For example during view parsing THD::lex will point to the views LEX and
lex::stmt_lex will point to LEX of the statement where the view will be
included
Currently it is used to have always correct select numbering inside
statement (LEX::current_select_number) without storing and restoring a
global counter which was THD::select_number.
TODO: make some unified statement representation (now SP has different)
to store such data like LEX::current_select_number.
*/
LEX *stmt_lex;
LEX_STRING name;
char *help_arg;
......
......@@ -6927,8 +6927,9 @@ void THD::reset_for_next_command(bool do_clear_error)
We also assign thd->stmt_lex in lex_start(), but during bootstrap this
code is executed first.
*/
thd->stmt_lex= &main_lex; thd->stmt_lex->current_select_number= 1;
DBUG_PRINT("info", ("Lex %p stmt_lex: %p", thd->lex, thd->stmt_lex));
DBUG_ASSERT(lex == &main_lex);
main_lex.stmt_lex= &main_lex; main_lex.current_select_number= 1;
DBUG_PRINT("info", ("Lex and stmt_lex: %p", &main_lex));
/*
Those two lines below are theoretically unneeded as
THD::cleanup_after_query() should take care of this already.
......@@ -7046,7 +7047,7 @@ mysql_new_select(LEX *lex, bool move_down)
if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
DBUG_RETURN(1);
select_lex->select_number= ++thd->stmt_lex->current_select_number;
select_lex->select_number= ++thd->lex->stmt_lex->current_select_number;
select_lex->parent_lex= lex; /* Used in init_query. */
select_lex->init_query();
select_lex->init_select();
......
......@@ -3635,7 +3635,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
if (! (lex= new (mem_root) st_lex_local))
DBUG_RETURN(TRUE);
stmt_lex= lex;
lex->stmt_lex= lex;
if (set_db(thd->db, thd->db_length))
DBUG_RETURN(TRUE);
......
......@@ -1374,13 +1374,13 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
List_iterator_fast<LEX_STRING> it_client_cs_name(triggers->client_cs_names);
List_iterator_fast<LEX_STRING> it_connection_cl_name(triggers->connection_cl_names);
List_iterator_fast<LEX_STRING> it_db_cl_name(triggers->db_cl_names);
LEX *old_lex= thd->lex, *old_stmt_lex= thd->stmt_lex;
LEX *old_lex= thd->lex;
LEX lex;
sp_rcontext *save_spcont= thd->spcont;
ulonglong save_sql_mode= thd->variables.sql_mode;
LEX_STRING *on_table_name;
thd->lex= thd->stmt_lex= &lex;
thd->lex= &lex;
save_db.str= thd->db;
save_db.length= thd->db_length;
......@@ -1579,7 +1579,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
}
thd->reset_db(save_db.str, save_db.length);
thd->lex= old_lex;
thd->stmt_lex= old_stmt_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
......@@ -1592,7 +1591,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
// QQ: anything else ?
lex_end(&lex);
thd->lex= old_lex;
thd->stmt_lex= old_stmt_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
thd->reset_db(save_db.str, save_db.length);
......
......@@ -1315,6 +1315,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
now Lex placed in statement memory
*/
table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
if (!table->view)
{
......@@ -1340,8 +1341,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
goto end;
lex_start(thd);
lex->stmt_lex= old_lex;
view_select= &lex->select_lex;
view_select->select_number= ++thd->stmt_lex->current_select_number;
view_select->select_number= ++thd->lex->stmt_lex->current_select_number;
ulonglong saved_mode= thd->variables.sql_mode;
/* switch off modes which can prevent normal parsing of VIEW
......
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