From de5e96e443c2509a5750ef2c8569430fbdbb2722 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 10:15:58 +0300 Subject: [PATCH] fixed BUG #679 outer resolved fields now do not marked as dependent if they is not really belong to outer SELECT one-letter variables name fixed mysql-test/r/subselect.result: test of bug 679 mysql-test/t/subselect.test: test of bug 679 sql/item.cc: outer resolved fields now do not marked as dependent if they is not really belong to outer SELECT one-letter variables name fixed --- mysql-test/r/subselect.result | 5 +++ mysql-test/t/subselect.test | 10 +++++ sql/item.cc | 78 +++++++++++++++++++++++------------ 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c41434336e5..ef1a7b02ace 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1151,3 +1151,8 @@ INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); REF_ID DROP TABLE t1; +create table t1(City VARCHAR(30),Location geometry); +insert into t1 values("Paris",GeomFromText('POINT(2.33 48.87)')); +select City from t1 where (select intersects(GeomFromText(AsText(Location)),GeomFromText('Polygon((2 50, 2.5 50, 2.5 47, 2 47, 2 50))'))=0); +City +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1528f53ff0d..32704e8667b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -732,3 +732,13 @@ CREATE TABLE t1 ( INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); DROP TABLE t1; + + +# +# correct behavoiur for function from reduced subselect +# +create table t1(City VARCHAR(30),Location geometry); +insert into t1 values("Paris",GeomFromText('POINT(2.33 48.87)')); +select City from t1 where (select intersects(GeomFromText(AsText(Location)),GeomFromText('Polygon((2 50, 2.5 50, 2.5 47, 2 47, 2 50))'))=0); +drop table t1; + diff --git a/sql/item.cc b/sql/item.cc index 868cf4466a6..0f16f07ed52 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -23,6 +23,10 @@ #include #include "my_dir.h" +static void mark_as_dependent(bool outer_resolving, + SELECT_LEX *last, SELECT_LEX_NODE *current, + Item_ident *item); + /***************************************************************************** ** Item functions *****************************************************************************/ @@ -769,6 +773,37 @@ bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate) return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate)); } + +/* + Mark item and SELECT_LEXs as dependent if it is not outer resolving + + SYNOPSIS + mark_as_dependent() + outer_resolving - flag of outer resolving + last - select from which current item depend + current - current select + item - item which should be marked +*/ + +static void mark_as_dependent(bool outer_resolving, + SELECT_LEX *last, SELECT_LEX_NODE *current, + Item_ident *item) +{ + /* + only last check is need, i.e. + "last != current" + first check added for speed up (check boolean should be faster + then comparing pointers and this condition usually true) + */ + if (!outer_resolving || ((SELECT_LEX_NODE *)last) != current) + { + // store pointer on SELECT_LEX from wich item is dependent + item->depended_from= last; + current->mark_as_dependent(last); + } +} + + bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!field) // If field is not checked @@ -833,29 +868,22 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return -1; } - Item_ref *r; - *ref= r= new Item_ref(last->ref_pointer_array + counter - , (char *)table_name, - (char *)field_name); - if (!r) + Item_ref *rf; + *ref= rf= new Item_ref(last->ref_pointer_array + counter, + (char *)table_name, + (char *)field_name); + if (!rf) return 1; - if (r->fix_fields(thd, tables, ref) || r->check_cols(1)) + if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1)) return 1; - // store pointer on SELECT_LEX from which item is dependent - r->depended_from= last; - cursel->mark_as_dependent(last); + + mark_as_dependent(outer_resolving, last, cursel, rf); return 0; } else { - // store pointer on SELECT_LEX from wich item is dependent - depended_from= last; - /* - Mark all selects from resolved to 1 before select where was - found table as depended (of select where was found table) - */ - thd->lex.current_select->mark_as_dependent(last); - if (depended_from->having_fix_field) + mark_as_dependent(outer_resolving, last, cursel, this); + if (last->having_fix_field) { Item_ref *rf; *ref= rf= new Item_ref((where->db[0]?where->db:0), @@ -1321,12 +1349,10 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) else if (tmp != not_found_field) { ref= 0; // To prevent "delete *ref;" on ~Item_erf() of this item - Item_field* f; - if (!((*reference)= f= new Item_field(tmp))) + Item_field* fld; + if (!((*reference)= fld= new Item_field(tmp))) return 1; - // store pointer on SELECT_LEX from wich item is dependent - f->depended_from= last; - thd->lex.current_select->mark_as_dependent(last); + mark_as_dependent(outer_resolving, last, thd->lex.current_select, fld); return 0; } else @@ -1337,11 +1363,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) "forward reference in item list"); return -1; } - /* - depended_from: pointer on SELECT_LEX from wich item is dependent - */ - ref= (depended_from= last)->ref_pointer_array + counter; - thd->lex.current_select->mark_as_dependent(last); + mark_as_dependent(outer_resolving, last, thd->lex.current_select, + this); + ref= last->ref_pointer_array + counter; } } else if (!ref)