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)
This commit is contained in:
Rex 2024-09-16 12:58:33 +11:00
parent 10008b3d3e
commit e90aab7acc
6 changed files with 77 additions and 15 deletions

View file

@ -2084,6 +2084,15 @@ union
select c1, c2, sum(c3) as s from t2 group by c1, c2 having s > 3
)
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
explain format=json select a1 from v1;
EXPLAIN
@ -2156,6 +2165,31 @@ select * from v4 where e3 < 10;
e1 e2 e3
1 2 3
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
explain format=json select * from v4 where e3 < 10;
EXPLAIN
@ -3169,9 +3203,9 @@ EXPLAIN
}
# pushdown through GROUP BY
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);
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
{
"query_block": {
@ -5124,7 +5158,7 @@ where c1=d2 limit 1)
alter table t1 rename column c1 to cc1;
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
drop view v1, v2, v3, v4, v5, v6;
drop view v1, v2, v3, v4, v5, v6, v7, v8, v9;
drop table t1, t2, t3;
create table t10 (a int);
create table t20 (b int);
@ -5148,14 +5182,14 @@ select * from v20;
c x u1 y1 b2
1 X U Y 1
3 NULL NULL NULL NULL
select * from v20 limit 9;
select * from v20 order by c limit 9;
c x u1 y1 b2
1 X U Y 1
3 NULL NULL NULL NULL
select * from v21;
select * from v21 order by c;
c x u1 b1
3 NULL NULL NULL
1 X U 1
3 NULL NULL NULL
drop view v10, v20, v11, v21;
drop table t10, t20, t30;
#

View file

@ -1640,6 +1640,15 @@ create view v5 as select * from
select c1, c2, sum(c3) as s from t2 group by c1, c2 having s > 3
)
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
--source include/explain-no-costs.inc
@ -1655,6 +1664,12 @@ select a1, a2 from v1 union select b1, b2 from v2;
select * from v1 union select * from v2;
select * from v3 intersect select * from v2 union select * from v1;
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
--source include/explain-no-costs.inc
explain format=json select * from v4 where e3 < 10;
@ -1814,9 +1829,9 @@ explain format=json select * from v1 where if( a1 regexp 'def', 'foo', a2 )
--echo # pushdown through GROUP BY
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);
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;
--echo # name resolution for multi select units
@ -2057,7 +2072,7 @@ alter table t1 rename column c1 to cc1;
--error ER_VIEW_INVALID
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;
# test derived embedded in views
@ -2080,8 +2095,8 @@ create view v21 as select * from t30
left join (select 'X' as x, v11.u, v11.b1 from v11) dt2 (x, u1, b1)
on t30.c=dt2.b1 order by x;
select * from v20;
select * from v20 limit 9;
select * from v21;
select * from v20 order by c limit 9;
select * from v21 order by c;
drop view v10, v20, v11, v21;
drop table t10, t20, t30;

View file

@ -1354,7 +1354,7 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
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);
// reset item names to that saved after wildcard expansion in JOIN::prepare

View file

@ -662,6 +662,19 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
}
#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);
/*

View file

@ -10336,7 +10336,7 @@ bool TABLE_LIST::save_original_names(st_select_lex *derived)
{
if (unlikely(derived->with_wild))
return false;
if (original_names_are_saved)
if (original_names_source)
return false;
// these elements allocated in LEX::parsed_derived_table
@ -10356,7 +10356,7 @@ bool TABLE_LIST::save_original_names(st_select_lex *derived)
(original_name= overwrite_iterator++))
lex_string_set( original_name, item_list_element->name.str);
original_names_are_saved= true;
original_names_source= derived;
return false;
}

View file

@ -2640,7 +2640,7 @@ struct TABLE_LIST
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> *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);
/* Bitmap of the defining with element */