Commit 3ce0df59 authored by unknown's avatar unknown

new reference which refer to current value not to result used for resolving outer

refernces if subqueri is not in HAVING clause (BUG#7079)
  and the same used for subquery transformetion


mysql-test/r/subselect.result:
  reference on changable fields from subquery
mysql-test/t/subselect.test:
  reference on changable fields from subquery
sql/item.cc:
  new reference which refer to current value not to result used
sql/item.h:
  new reference which refer to current value not to result used
sql/item_subselect.cc:
  new reference which refer to current value not to result used
parent 7a60d155
...@@ -2105,3 +2105,31 @@ s1 s1 < all (select s1 from t1) ...@@ -2105,3 +2105,31 @@ s1 s1 < all (select s1 from t1)
1 0 1 0
NULL NULL NULL NULL
drop table t1; drop table t1;
CREATE TABLE t1 (
Code char(3) NOT NULL default '',
Name char(52) NOT NULL default '',
Continent enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL default 'Asia',
Region char(26) NOT NULL default '',
SurfaceArea float(10,2) NOT NULL default '0.00',
IndepYear smallint(6) default NULL,
Population int(11) NOT NULL default '0',
LifeExpectancy float(3,1) default NULL,
GNP float(10,2) default NULL,
GNPOld float(10,2) default NULL,
LocalName char(45) NOT NULL default '',
GovernmentForm char(45) NOT NULL default '',
HeadOfState char(60) default NULL,
Capital int(11) default NULL,
Code2 char(2) NOT NULL default ''
) TYPE=MyISAM;
Warnings:
Warning 1287 'TYPE=storage_engine' is deprecated; use 'ENGINE=storage_engine' instead
INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX');
INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes franaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
/*!40000 ALTER TABLE t1 ENABLE KEYS */;
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
c
Oceania
drop table t1;
...@@ -1358,3 +1358,31 @@ insert into t1 values (1),(null); ...@@ -1358,3 +1358,31 @@ insert into t1 values (1),(null);
select * from t1 where s1 < all (select s1 from t1); select * from t1 where s1 < all (select s1 from t1);
select s1, s1 < all (select s1 from t1) from t1; select s1, s1 < all (select s1 from t1) from t1;
drop table t1; drop table t1;
#
# reference on changable fields from subquery
#
CREATE TABLE t1 (
Code char(3) NOT NULL default '',
Name char(52) NOT NULL default '',
Continent enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL default 'Asia',
Region char(26) NOT NULL default '',
SurfaceArea float(10,2) NOT NULL default '0.00',
IndepYear smallint(6) default NULL,
Population int(11) NOT NULL default '0',
LifeExpectancy float(3,1) default NULL,
GNP float(10,2) default NULL,
GNPOld float(10,2) default NULL,
LocalName char(45) NOT NULL default '',
GovernmentForm char(45) NOT NULL default '',
HeadOfState char(60) default NULL,
Capital int(11) default NULL,
Code2 char(2) NOT NULL default ''
) TYPE=MyISAM;
INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX');
INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes franaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
/*!40000 ALTER TABLE t1 ENABLE KEYS */;
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
drop table t1;
...@@ -69,7 +69,7 @@ Item::Item(): ...@@ -69,7 +69,7 @@ Item::Item():
} }
/* /*
Constructor used by Item_field, Item_ref & agregate (sum) functions. Constructor used by Item_field, Item_*_ref & agregate (sum) functions.
Used for duplicating lists in processing queries with temporary Used for duplicating lists in processing queries with temporary
tables tables
*/ */
...@@ -114,7 +114,7 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, ...@@ -114,7 +114,7 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
name = (char*) field_name_par; name = (char*) field_name_par;
} }
// Constructor used by Item_field & Item_ref (see Item comment) // Constructor used by Item_field & Item_*_ref (see Item comment)
Item_ident::Item_ident(THD *thd, Item_ident *item) Item_ident::Item_ident(THD *thd, Item_ident *item)
:Item(thd, item), :Item(thd, item),
orig_db_name(item->orig_db_name), orig_db_name(item->orig_db_name),
...@@ -1372,6 +1372,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, ...@@ -1372,6 +1372,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
enum_parsing_place place;
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (!field) // If field is not checked if (!field) // If field is not checked
{ {
...@@ -1419,8 +1420,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1419,8 +1420,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
} }
Item_subselect *prev_subselect_item= prev_unit->item; Item_subselect *prev_subselect_item= prev_unit->item;
enum_parsing_place place= place= prev_subselect_item->parsing_place;
prev_subselect_item->parsing_place;
/* /*
check table fields only if subquery used somewhere out of HAVING check table fields only if subquery used somewhere out of HAVING
or outer SELECT do not use groupping (i.e. tables are or outer SELECT do not use groupping (i.e. tables are
...@@ -1489,8 +1489,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1489,8 +1489,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return -1; return -1;
} }
Item_ref *rf= new Item_ref(last->ref_pointer_array + counter, Item_ref *rf= (place == IN_HAVING ?
(char *)table_name, (char *)field_name); new Item_ref(last->ref_pointer_array + counter,
(char *)table_name,
(char *)field_name) :
new Item_direct_ref(last->ref_pointer_array + counter,
(char *)table_name,
(char *)field_name));
if (!rf) if (!rf)
return 1; return 1;
thd->change_item_tree(ref, rf); thd->change_item_tree(ref, rf);
...@@ -2039,6 +2044,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -2039,6 +2044,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
uint counter; uint counter;
enum_parsing_place place;
bool not_used; bool not_used;
if (!ref) if (!ref)
{ {
...@@ -2097,8 +2103,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -2097,8 +2103,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// it is primary INSERT st_select_lex => skip first table resolving // it is primary INSERT st_select_lex => skip first table resolving
table_list= table_list->next; table_list= table_list->next;
} }
enum_parsing_place place= place= prev_subselect_item->parsing_place;
prev_subselect_item->parsing_place;
/* /*
check table fields only if subquery used somewhere out of HAVING check table fields only if subquery used somewhere out of HAVING
or SELECT list or outer SELECT do not use groupping (i.e. tables or SELECT list or outer SELECT do not use groupping (i.e. tables
...@@ -2168,6 +2173,19 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -2168,6 +2173,19 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
} }
mark_as_dependent(thd, last, thd->lex->current_select, mark_as_dependent(thd, last, thd->lex->current_select,
this); this);
if (place == IN_HAVING)
{
Item_ref *rf;
if (!(rf= new Item_direct_ref(last->ref_pointer_array + counter,
(char *)table_name,
(char *)field_name)))
return 1;
ref= 0; // Safety
if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
return 1;
thd->change_item_tree(reference, rf);
return 0;
}
ref= last->ref_pointer_array + counter; ref= last->ref_pointer_array + counter;
} }
else if (!ref) else if (!ref)
......
...@@ -889,6 +889,45 @@ public: ...@@ -889,6 +889,45 @@ public:
void print(String *str); void print(String *str);
}; };
class Item_direct_ref :public Item_ref
{
public:
Item_direct_ref(Item **item, const char *table_name_par,
const char *field_name_par)
:Item_ref(item, table_name_par, field_name_par) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
double val()
{
double tmp=(*ref)->val();
null_value=(*ref)->null_value;
return tmp;
}
longlong val_int()
{
longlong tmp=(*ref)->val_int();
null_value=(*ref)->null_value;
return tmp;
}
String *val_str(String* tmp)
{
tmp=(*ref)->val_str(tmp);
null_value=(*ref)->null_value;
return tmp;
}
bool is_null()
{
(void) (*ref)->val_int();
return (*ref)->null_value;
}
bool get_date(TIME *ltime,uint fuzzydate)
{
return (null_value=(*ref)->get_date(ltime,fuzzydate));
}
};
class Item_in_subselect; class Item_in_subselect;
class Item_ref_null_helper: public Item_ref class Item_ref_null_helper: public Item_ref
{ {
......
...@@ -797,7 +797,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -797,7 +797,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
As far as Item_ref_in_optimizer do not substitude itself on fix_fields As far as Item_ref_in_optimizer do not substitude itself on fix_fields
we can use same item for all selects. we can use same item for all selects.
*/ */
expr= new Item_ref((Item**)optimizer->get_cache(), expr= new Item_direct_ref((Item**)optimizer->get_cache(),
(char *)"<no matter>", (char *)"<no matter>",
(char *)in_left_expr_name); (char *)in_left_expr_name);
...@@ -993,7 +993,8 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -993,7 +993,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
(char *) "<no matter>", (char *) "<no matter>",
(char *) "<list ref>"); (char *) "<list ref>");
func= func=
eq_creator.create(new Item_ref((*optimizer->get_cache())->addr(i), eq_creator.create(new Item_direct_ref((*optimizer->get_cache())->
addr(i),
(char *)"<no matter>", (char *)"<no matter>",
(char *)in_left_expr_name), (char *)in_left_expr_name),
func); func);
......
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