Commit 39ada424 authored by Rex's avatar Rex

MDEV-34931 MDEV-31466 name resolution fails in --view

Fix for MDEV-31466 - add optional derived table column names.
Column names within a SELECT_LEX structure can be left in a non-reparsable
state (as printed out from *::print) after JOIN::prepare.  This caused
an incorrect view definition to be written into the .FRM file.
Fixed by resetting item list names in SELECT_LEX structures representing
derived tables before writing out the view definition.

Reviewed by Igor Babaev (igor@mariadb.com)
parent 5d30009c
...@@ -2084,6 +2084,15 @@ union ...@@ -2084,6 +2084,15 @@ union
select c1, c2, sum(c3) as s from t2 group by c1, c2 having s > 3 select c1, c2, sum(c3) as s from t2 group by c1, c2 having s > 3
) )
as d2 (f1, f2, f3); as d2 (f1, f2, f3);
create view v6 as select a1 from
(
select * from t1 union select * from t2 order by c1
) as d3 (a1, a2, a3);
create view v7 (b1) as select a1 from (select c1 from t1) dt (a1);
create view v8 (b1, b2, b3) as select a1, a2, a3 from
(
select * from t1 union select * from t2 order by c1
) as d3 (a1, a2, a3);
# test parent query mergability # test parent query mergability
explain format=json select a1 from v1; explain format=json select a1 from v1;
EXPLAIN EXPLAIN
...@@ -2156,6 +2165,31 @@ select * from v4 where e3 < 10; ...@@ -2156,6 +2165,31 @@ select * from v4 where e3 < 10;
e1 e2 e3 e1 e2 e3
1 2 3 1 2 3
4 5 6 4 5 6
select * from v6;
a1
1
4
7
10
show create view v6;
View Create View character_set_client collation_connection
v6 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v6` AS select `d3`.`a1` AS `a1` from (select `t1`.`c1` AS `a1`,`t1`.`c2` AS `a2`,`t1`.`c3` AS `a3` from `t1` union select `t2`.`c1` AS `c1`,`t2`.`c2` AS `c2`,`t2`.`c3` AS `c3` from `t2` order by `c1`) `d3`(`a1`,`a2`,`a3`) latin1 latin1_swedish_ci
select * from v7;
b1
1
4
show create view v7;
View Create View character_set_client collation_connection
v7 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v7` AS select `dt`.`a1` AS `b1` from (select `t1`.`c1` AS `a1` from `t1`) `dt`(`a1`) latin1 latin1_swedish_ci
select * from v8;
b1 b2 b3
1 2 3
4 5 6
7 8 9
10 11 12
show create view v8;
View Create View character_set_client collation_connection
v8 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v8` AS select `d3`.`a1` AS `b1`,`d3`.`a2` AS `b2`,`d3`.`a3` AS `b3` from (select `t1`.`c1` AS `a1`,`t1`.`c2` AS `a2`,`t1`.`c3` AS `a3` from `t1` union select `t2`.`c1` AS `c1`,`t2`.`c2` AS `c2`,`t2`.`c3` AS `c3` from `t2` order by `c1`) `d3`(`a1`,`a2`,`a3`) latin1 latin1_swedish_ci
# show materialization and condition pushdown into having # show materialization and condition pushdown into having
explain format=json select * from v4 where e3 < 10; explain format=json select * from v4 where e3 < 10;
EXPLAIN EXPLAIN
...@@ -3169,9 +3203,9 @@ EXPLAIN ...@@ -3169,9 +3203,9 @@ EXPLAIN
} }
# pushdown through GROUP BY # pushdown through GROUP BY
create function f1(a int) returns int DETERMINISTIC return (a+1); create function f1(a int) returns int DETERMINISTIC return (a+1);
create view v6 as select * from create view v9 as select * from
(select c1, f1(c2), sum(c3) from t1 group by c1, f1(c2)) as f (c1, c2, c3); (select c1, f1(c2), sum(c3) from t1 group by c1, f1(c2)) as f (c1, c2, c3);
explain format=json select * from v6 where (c3+1) > 10 and c1 > 1 and c2 > 123; explain format=json select * from v9 where (c3+1) > 10 and c1 > 1 and c2 > 123;
EXPLAIN EXPLAIN
{ {
"query_block": { "query_block": {
...@@ -5124,7 +5158,7 @@ where c1=d2 limit 1) ...@@ -5124,7 +5158,7 @@ where c1=d2 limit 1)
alter table t1 rename column c1 to cc1; alter table t1 rename column c1 to cc1;
select * from v1; select * from v1;
ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
drop view v1, v2, v3, v4, v5, v6; drop view v1, v2, v3, v4, v5, v6, v7, v8, v9;
drop table t1, t2, t3; drop table t1, t2, t3;
create table t10 (a int); create table t10 (a int);
create table t20 (b int); create table t20 (b int);
...@@ -5148,14 +5182,14 @@ select * from v20; ...@@ -5148,14 +5182,14 @@ select * from v20;
c x u1 y1 b2 c x u1 y1 b2
1 X U Y 1 1 X U Y 1
3 NULL NULL NULL NULL 3 NULL NULL NULL NULL
select * from v20 limit 9; select * from v20 order by c limit 9;
c x u1 y1 b2 c x u1 y1 b2
1 X U Y 1 1 X U Y 1
3 NULL NULL NULL NULL 3 NULL NULL NULL NULL
select * from v21; select * from v21 order by c;
c x u1 b1 c x u1 b1
3 NULL NULL NULL
1 X U 1 1 X U 1
3 NULL NULL NULL
drop view v10, v20, v11, v21; drop view v10, v20, v11, v21;
drop table t10, t20, t30; drop table t10, t20, t30;
# #
......
...@@ -1637,6 +1637,15 @@ create view v5 as select * from ...@@ -1637,6 +1637,15 @@ create view v5 as select * from
select c1, c2, sum(c3) as s from t2 group by c1, c2 having s > 3 select c1, c2, sum(c3) as s from t2 group by c1, c2 having s > 3
) )
as d2 (f1, f2, f3); as d2 (f1, f2, f3);
create view v6 as select a1 from
(
select * from t1 union select * from t2 order by c1
) as d3 (a1, a2, a3);
create view v7 (b1) as select a1 from (select c1 from t1) dt (a1);
create view v8 (b1, b2, b3) as select a1, a2, a3 from
(
select * from t1 union select * from t2 order by c1
) as d3 (a1, a2, a3);
--echo # test parent query mergability --echo # test parent query mergability
--source include/explain-no-costs.inc --source include/explain-no-costs.inc
...@@ -1652,6 +1661,12 @@ select a1, a2 from v1 union select b1, b2 from v2; ...@@ -1652,6 +1661,12 @@ select a1, a2 from v1 union select b1, b2 from v2;
select * from v1 union select * from v2; select * from v1 union select * from v2;
select * from v3 intersect select * from v2 union select * from v1; select * from v3 intersect select * from v2 union select * from v1;
select * from v4 where e3 < 10; select * from v4 where e3 < 10;
select * from v6;
show create view v6;
select * from v7;
show create view v7;
select * from v8;
show create view v8;
--echo # show materialization and condition pushdown into having --echo # show materialization and condition pushdown into having
--source include/explain-no-costs.inc --source include/explain-no-costs.inc
explain format=json select * from v4 where e3 < 10; explain format=json select * from v4 where e3 < 10;
...@@ -1811,9 +1826,9 @@ explain format=json select * from v1 where if( a1 regexp 'def', 'foo', a2 ) ...@@ -1811,9 +1826,9 @@ explain format=json select * from v1 where if( a1 regexp 'def', 'foo', a2 )
--echo # pushdown through GROUP BY --echo # pushdown through GROUP BY
create function f1(a int) returns int DETERMINISTIC return (a+1); create function f1(a int) returns int DETERMINISTIC return (a+1);
create view v6 as select * from create view v9 as select * from
(select c1, f1(c2), sum(c3) from t1 group by c1, f1(c2)) as f (c1, c2, c3); (select c1, f1(c2), sum(c3) from t1 group by c1, f1(c2)) as f (c1, c2, c3);
explain format=json select * from v6 where (c3+1) > 10 and c1 > 1 and c2 > 123; explain format=json select * from v9 where (c3+1) > 10 and c1 > 1 and c2 > 123;
drop function f1; drop function f1;
--echo # name resolution for multi select units --echo # name resolution for multi select units
...@@ -2054,7 +2069,7 @@ alter table t1 rename column c1 to cc1; ...@@ -2054,7 +2069,7 @@ alter table t1 rename column c1 to cc1;
--error ER_VIEW_INVALID --error ER_VIEW_INVALID
select * from v1; select * from v1;
drop view v1, v2, v3, v4, v5, v6; drop view v1, v2, v3, v4, v5, v6, v7, v8, v9;
drop table t1, t2, t3; drop table t1, t2, t3;
# test derived embedded in views # test derived embedded in views
...@@ -2077,8 +2092,8 @@ create view v21 as select * from t30 ...@@ -2077,8 +2092,8 @@ create view v21 as select * from t30
left join (select 'X' as x, v11.u, v11.b1 from v11) dt2 (x, u1, b1) left join (select 'X' as x, v11.u, v11.b1 from v11) dt2 (x, u1, b1)
on t30.c=dt2.b1 order by x; on t30.c=dt2.b1 order by x;
select * from v20; select * from v20;
select * from v20 limit 9; select * from v20 order by c limit 9;
select * from v21; select * from v21 order by c;
drop view v10, v20, v11, v21; drop view v10, v20, v11, v21;
drop table t10, t20, t30; drop table t10, t20, t30;
......
...@@ -1354,7 +1354,7 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) ...@@ -1354,7 +1354,7 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->get_unit())); derived->get_unit()));
st_select_lex_unit *unit= derived->get_unit(); st_select_lex_unit *unit= derived->get_unit();
if (derived->original_names_are_saved) if (derived->original_names_source)
unit->first_select()->set_item_list_names(derived->original_names); unit->first_select()->set_item_list_names(derived->original_names);
// reset item names to that saved after wildcard expansion in JOIN::prepare // reset item names to that saved after wildcard expansion in JOIN::prepare
......
...@@ -662,6 +662,19 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -662,6 +662,19 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
} }
#endif #endif
/*
Reset item list names within derived tables so that when reparsed in the
view, references elsewhere within this select_lex can be correctly resolved
*/
for (SELECT_LEX *sl= lex->all_selects_list; sl; sl= sl->next_select_in_list())
{
for (TABLE_LIST *tl= sl->get_table_list(); tl && !res; tl= tl->next_local)
{
if (tl->original_names_source)
tl->original_names_source->set_item_list_names(tl->original_names);
}
}
res= mysql_register_view(thd, &ddl_log_state, view, mode, backup_file_name); res= mysql_register_view(thd, &ddl_log_state, view, mode, backup_file_name);
/* /*
......
...@@ -10333,7 +10333,7 @@ bool TABLE_LIST::save_original_names(st_select_lex *derived) ...@@ -10333,7 +10333,7 @@ bool TABLE_LIST::save_original_names(st_select_lex *derived)
{ {
if (unlikely(derived->with_wild)) if (unlikely(derived->with_wild))
return false; return false;
if (original_names_are_saved) if (original_names_source)
return false; return false;
// these elements allocated in LEX::parsed_derived_table // these elements allocated in LEX::parsed_derived_table
...@@ -10353,7 +10353,7 @@ bool TABLE_LIST::save_original_names(st_select_lex *derived) ...@@ -10353,7 +10353,7 @@ bool TABLE_LIST::save_original_names(st_select_lex *derived)
(original_name= overwrite_iterator++)) (original_name= overwrite_iterator++))
lex_string_set( original_name, item_list_element->name.str); lex_string_set( original_name, item_list_element->name.str);
original_names_are_saved= true; original_names_source= derived;
return false; return false;
} }
......
...@@ -2575,7 +2575,7 @@ struct TABLE_LIST ...@@ -2575,7 +2575,7 @@ struct TABLE_LIST
With_element *with; /* With element defining this table (if any) */ With_element *with; /* With element defining this table (if any) */
List<Lex_ident_sys> *column_names; /* list of correlation column names */ List<Lex_ident_sys> *column_names; /* list of correlation column names */
List<Lex_ident_sys> *original_names;/* list of original column names */ List<Lex_ident_sys> *original_names;/* list of original column names */
bool original_names_are_saved:1; st_select_lex *original_names_source;
bool save_original_names(st_select_lex *derived); bool save_original_names(st_select_lex *derived);
/* Bitmap of the defining with element */ /* Bitmap of the defining with element */
......
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