summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2004-12-11 17:13:19 +0200
committerunknown <bell@sanja.is.com.ua>2004-12-11 17:13:19 +0200
commit3ce0df59372a3598ae39423e35bab877459693ad (patch)
tree86caaaa83f2ad7be62b240348f2f59d7479968cc /sql
parent7a60d1558a89df5f198884d360a14bf2b48f2c49 (diff)
downloadmariadb-git-3ce0df59372a3598ae39423e35bab877459693ad.tar.gz
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
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc34
-rw-r--r--sql/item.h39
-rw-r--r--sql/item_subselect.cc13
3 files changed, 72 insertions, 14 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 31c35e87cd4..3fca0033be2 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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
tables
*/
@@ -114,7 +114,7 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_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(thd, item),
orig_db_name(item->orig_db_name),
@@ -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)
{
+ enum_parsing_place place;
DBUG_ASSERT(fixed == 0);
if (!field) // If field is not checked
{
@@ -1419,8 +1420,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
Item_subselect *prev_subselect_item= prev_unit->item;
- enum_parsing_place place=
- prev_subselect_item->parsing_place;
+ place= prev_subselect_item->parsing_place;
/*
check table fields only if subquery used somewhere out of HAVING
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)
return -1;
}
- Item_ref *rf= new Item_ref(last->ref_pointer_array + counter,
- (char *)table_name, (char *)field_name);
+ Item_ref *rf= (place == IN_HAVING ?
+ 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)
return 1;
thd->change_item_tree(ref, rf);
@@ -2039,6 +2044,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
DBUG_ASSERT(fixed == 0);
uint counter;
+ enum_parsing_place place;
bool not_used;
if (!ref)
{
@@ -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
table_list= table_list->next;
}
- enum_parsing_place place=
- prev_subselect_item->parsing_place;
+ place= prev_subselect_item->parsing_place;
/*
check table fields only if subquery used somewhere out of HAVING
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)
}
mark_as_dependent(thd, last, thd->lex->current_select,
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;
}
else if (!ref)
diff --git a/sql/item.h b/sql/item.h
index 3c4f80e3857..3ae1da23f15 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -889,6 +889,45 @@ public:
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_ref_null_helper: public Item_ref
{
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 69941b36ca0..ffa3b072801 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -797,9 +797,9 @@ Item_in_subselect::single_value_transformer(JOIN *join,
As far as Item_ref_in_optimizer do not substitude itself on fix_fields
we can use same item for all selects.
*/
- expr= new Item_ref((Item**)optimizer->get_cache(),
- (char *)"<no matter>",
- (char *)in_left_expr_name);
+ expr= new Item_direct_ref((Item**)optimizer->get_cache(),
+ (char *)"<no matter>",
+ (char *)in_left_expr_name);
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
}
@@ -993,9 +993,10 @@ Item_in_subselect::row_value_transformer(JOIN *join)
(char *) "<no matter>",
(char *) "<list ref>");
func=
- eq_creator.create(new Item_ref((*optimizer->get_cache())->addr(i),
- (char *)"<no matter>",
- (char *)in_left_expr_name),
+ eq_creator.create(new Item_direct_ref((*optimizer->get_cache())->
+ addr(i),
+ (char *)"<no matter>",
+ (char *)in_left_expr_name),
func);
item= and_items(item, func);
}