Re: [Maria-developers] [Commits] Rev 3249: Fix of LP BUG#872775. in file:///home/bell/maria/bzr/work-maria-5.3-lpb872775/
On Tue, Oct 25, 2011 at 11:59:37AM +0300, sanja@askmonty.org wrote:
At file:///home/bell/maria/bzr/work-maria-5.3-lpb872775/
------------------------------------------------------------ revno: 3249 revision-id: sanja@askmonty.org-20111025085936-h0jyyxtbv3qhp4f4 parent: igor@askmonty.org-20111023124603-sjv665ajk25b4dgi committer: sanja@askmonty.org branch nick: work-maria-5.3-lpb872775 timestamp: Tue 2011-10-25 11:59:36 +0300 message: Fix of LP BUG#872775.
The problem was that merged views has its own nest_level numbering => when we compare nest levels we should take into considiration basis (i.e. 0 level), if it is different then nest levels are not comparable.
:grep nest_level_base *.h *.c* item.h|1165| st_select_lex_unit *nest_level_base; sql_lex.h|687| SELECT_LEX_UNIT *nest_level_base; /* unit from which we count nest_level */ item.cc|759| depended_from->nest_level_base == prm->nest_level_base && item_subselect.cc|603| unit->first_select()->nest_level_base, item_sum.cc|363| ds->nest_level_base == prm->nest_level_base && sql_lex.cc|342| lex->select_lex.nest_level_base= &lex->unit; sql_parse.cc|5920| select_lex->nest_level_base= &thd->lex->unit; The only places where nest_level_base is assigned are: sql_lex.cc|342| lex->select_lex.nest_level_base= &lex->unit; sql_parse.cc|5920| select_lex->nest_level_base= &thd->lex->unit; both of these initialize it to the top-level unit. So what is the point of having nest_level_base in this case? Please clarify :)
=== modified file 'mysql-test/r/subselect_cache.result' --- a/mysql-test/r/subselect_cache.result 2011-07-19 20:19:10 +0000 +++ b/mysql-test/r/subselect_cache.result 2011-10-25 08:59:36 +0000 @@ -1,3 +1,5 @@ +drop table if exists t1,t2,t3,t4,t5; +drop view if exists v1; set optimizer_switch='subquery_cache=on'; create table t1 (a int, b int); insert into t1 values (1,2),(3,4),(1,2),(3,4),(3,4),(4,5),(4,5),(5,6),(5,6),(4,5); @@ -3354,5 +3356,31 @@ f1 f2 f3 f3 7 0 0 0 7 0 0 0 drop tables t1, t2, t3; +# +# Test of LP BUG#872775 view with "outer references" bug +# +set @@optimizer_switch= default; +set optimizer_switch='subquery_cache=on'; +CREATE TABLE t1 (a int) ; +CREATE TABLE t2 (b int, c varchar(1) NOT NULL ) ; +INSERT INTO t2 VALUES (1,'x'),(2,'y'); +CREATE TABLE t3 (a int) ; +CREATE TABLE t4 ( pk int(11) NOT NULL , b int(11) NOT NULL ) ; +INSERT INTO t4 VALUES (26,9),(27,5),(28,0),(29,3); +CREATE OR REPLACE VIEW v1 AS +SELECT t2.b +FROM t1 +JOIN t2 +WHERE t2 .c > ( +SELECT t2.c FROM t3 +); +SELECT * FROM t4 WHERE b NOT IN ( SELECT * FROM v1 ); +pk b +26 9 +27 5 +28 0 +29 3 +drop view v1; +drop table t1,t2,t3,t4; # restore default set @@optimizer_switch= default;
=== modified file 'mysql-test/t/subselect_cache.test' --- a/mysql-test/t/subselect_cache.test 2011-07-19 20:19:10 +0000 +++ b/mysql-test/t/subselect_cache.test 2011-10-25 08:59:36 +0000 @@ -1,4 +1,10 @@
+--disable_warnings +drop table if exists t1,t2,t3,t4,t5; +drop view if exists v1; +--enable_warnings + + set optimizer_switch='subquery_cache=on';
create table t1 (a int, b int); @@ -1664,5 +1670,33 @@ FROM t1 WHERE t2.f1 OR t2.f3 ); drop tables t1, t2, t3;
+--echo # +--echo # Test of LP BUG#872775 view with "outer references" bug +--echo # +set @@optimizer_switch= default; +set optimizer_switch='subquery_cache=on'; +CREATE TABLE t1 (a int) ; + +CREATE TABLE t2 (b int, c varchar(1) NOT NULL ) ; +INSERT INTO t2 VALUES (1,'x'),(2,'y'); + +CREATE TABLE t3 (a int) ; + +CREATE TABLE t4 ( pk int(11) NOT NULL , b int(11) NOT NULL ) ; +INSERT INTO t4 VALUES (26,9),(27,5),(28,0),(29,3); + +CREATE OR REPLACE VIEW v1 AS +SELECT t2.b +FROM t1 +JOIN t2 +WHERE t2 .c > ( + SELECT t2.c FROM t3 + ); + +SELECT * FROM t4 WHERE b NOT IN ( SELECT * FROM v1 ); + +drop view v1; +drop table t1,t2,t3,t4; + --echo # restore default set @@optimizer_switch= default;
=== modified file 'sql/item.cc' --- a/sql/item.cc 2011-10-22 07:14:27 +0000 +++ b/sql/item.cc 2011-10-25 08:59:36 +0000 @@ -755,7 +755,9 @@ bool Item_ident::remove_dependence_proce bool Item_ident::collect_outer_ref_processor(uchar *param) { Collect_deps_prm *prm= (Collect_deps_prm *)param; - if (depended_from && depended_from->nest_level < prm->nest_level) + if (depended_from && + depended_from->nest_level_base == prm->nest_level_base && + depended_from->nest_level < prm->nest_level) prm->parameters->add_unique(this, &cmp_items); return FALSE; }
=== modified file 'sql/item.h' --- a/sql/item.h 2011-10-22 07:14:27 +0000 +++ b/sql/item.h 2011-10-25 08:59:36 +0000 @@ -505,6 +505,7 @@ typedef void (*Cond_traverser) (const It class Item_equal; class COND_EQUAL;
+class st_select_lex_unit;
class Item { Item(const Item &); /* Prevent use of these */ @@ -1159,8 +1160,10 @@ public: } struct Collect_deps_prm { - int nest_level; List<Item> *parameters; + /* unit from which we count nest_level */ + st_select_lex_unit *nest_level_base; + int nest_level; }; /** Collect outer references
=== modified file 'sql/item_subselect.cc' --- a/sql/item_subselect.cc 2011-10-22 07:14:27 +0000 +++ b/sql/item_subselect.cc 2011-10-25 08:59:36 +0000 @@ -599,7 +599,9 @@ bool Item_subselect::exec()
void Item_subselect::get_cache_parameters(List<Item> ¶meters) { - Collect_deps_prm prm= { unit->first_select()->nest_level, ¶meters }; + Collect_deps_prm prm= {¶meters, + unit->first_select()->nest_level_base, + unit->first_select()->nest_level}; walk(&Item::collect_outer_ref_processor, TRUE, (uchar*)&prm); }
=== modified file 'sql/item_sum.cc' --- a/sql/item_sum.cc 2011-07-19 20:19:10 +0000 +++ b/sql/item_sum.cc 2011-10-25 08:59:36 +0000 @@ -359,7 +359,9 @@ bool Item_sum::collect_outer_ref_process { Collect_deps_prm *prm= (Collect_deps_prm *)param; SELECT_LEX *ds; - if ((ds= depended_from()) && ds->nest_level < prm->nest_level) + if ((ds= depended_from()) && + ds->nest_level_base == prm->nest_level_base && + ds->nest_level < prm->nest_level) prm->parameters->add_unique(this, &cmp_items); return FALSE; }
=== modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2011-10-22 07:14:27 +0000 +++ b/sql/sql_lex.cc 2011-10-25 08:59:36 +0000 @@ -339,6 +339,7 @@ void lex_start(THD *thd) lex->event_parse_data= NULL; lex->profile_options= PROFILE_NONE; lex->nest_level=0 ; + lex->select_lex.nest_level_base= &lex->unit; lex->allow_sum_func= 0; lex->in_sum_func= NULL; lex->protect_against_global_read_lock= FALSE;
=== modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2011-09-22 22:13:38 +0000 +++ b/sql/sql_lex.h 2011-10-25 08:59:36 +0000 @@ -684,6 +684,7 @@ public: ulong table_join_options; uint in_sum_expr; uint select_number; /* number of select (used for EXPLAIN) */ + SELECT_LEX_UNIT *nest_level_base; /* unit from which we count nest_level */ int nest_level; /* nesting level of select */ Item_sum *inner_sum_func_list; /* list of sum func in nested selects */ uint with_wild; /* item list contain '*' */
=== modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2011-10-11 10:55:42 +0000 +++ b/sql/sql_parse.cc 2011-10-25 08:59:36 +0000 @@ -5917,6 +5917,7 @@ mysql_new_select(LEX *lex, bool move_dow DBUG_RETURN(1); } select_lex->nest_level= lex->nest_level; + select_lex->nest_level_base= &thd->lex->unit; if (move_down) { SELECT_LEX_UNIT *unit;
BR Sergey -- Sergei Petrunia, Software Developer Monty Program AB, http://askmonty.org Blog: http://s.petrunia.net/blog
25.10.2011 19:54, Sergei Petrunia пишет:
On Tue, Oct 25, 2011 at 11:59:37AM +0300, sanja@askmonty.org wrote:
At file:///home/bell/maria/bzr/work-maria-5.3-lpb872775/
------------------------------------------------------------ revno: 3249 revision-id: sanja@askmonty.org-20111025085936-h0jyyxtbv3qhp4f4 parent: igor@askmonty.org-20111023124603-sjv665ajk25b4dgi committer: sanja@askmonty.org branch nick: work-maria-5.3-lpb872775 timestamp: Tue 2011-10-25 11:59:36 +0300 message: Fix of LP BUG#872775.
The problem was that merged views has its own nest_level numbering => when we compare nest levels we should take into considiration basis (i.e. 0 level), if it is different then nest levels are not comparable. :grep nest_level_base *.h *.c* item.h|1165| st_select_lex_unit *nest_level_base; sql_lex.h|687| SELECT_LEX_UNIT *nest_level_base; /* unit from which we count nest_level */ item.cc|759| depended_from->nest_level_base == prm->nest_level_base&& item_subselect.cc|603| unit->first_select()->nest_level_base, item_sum.cc|363| ds->nest_level_base == prm->nest_level_base&& sql_lex.cc|342| lex->select_lex.nest_level_base=&lex->unit; sql_parse.cc|5920| select_lex->nest_level_base=&thd->lex->unit;
The only places where nest_level_base is assigned are:
sql_lex.cc|342| lex->select_lex.nest_level_base=&lex->unit; sql_parse.cc|5920| select_lex->nest_level_base=&thd->lex->unit;
both of these initialize it to the top-level unit. So what is the point of having nest_level_base in this case? Please clarify :)
It assign the top level UNIT (first for "main" SELECT, second for every other SELECT), but top level UNIT is different for main query and each view (each view parsed as separate SELECT with its own LEX and main UNIT and SELECT in it) [skip]
participants (2)
-
Oleksandr Byelkin
-
Sergei Petrunia