mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
_NEW_ IN/ALL/ANY/SOME behaviour with NULL (SCRUM related)
optimization of left expression evaluation more descriptive method name mysql-test/r/func_in.result: test of _NEW_ IN behaviour with NULL mysql-test/r/subselect.result: test of _NEW_ IN/ALL/ANY/SOME behaviour with NULL mysql-test/t/func_in.test: test of _NEW_ IN behaviour with NULL mysql-test/t/subselect.test: test of _NEW_ IN/ALL/ANY/SOME behaviour with NULL sql/item.cc: _NEW_ IN/ALL/ANY/SOME behaviour with NULL optimization of left expression evaluation sql/item.h: _NEW_ IN/ALL/ANY/SOME behaviour with NULL optimization of left expression evaluation sql/item_cmpfunc.cc: _NEW_ IN/ALL/ANY/SOME behaviour with NULL optimization of left expression evaluation sql/item_cmpfunc.h: _NEW_ IN/ALL/ANY/SOME behaviour with NULL optimization of left expression evaluation sql/item_subselect.cc: _NEW_ IN/ALL/ANY/SOME behaviour with NULL optimization of left expression evaluation sql/item_subselect.h: _NEW_ IN/ALL/ANY/SOME behaviour with NULL optimization of left expression evaluation sql/sql_class.cc: more descriptive method name sql/sql_union.cc: more descriptive method name
This commit is contained in:
parent
f67abe26fb
commit
59b3711986
12 changed files with 572 additions and 51 deletions
|
@ -1,11 +1,95 @@
|
||||||
|
select 1 in (1,2,3);
|
||||||
|
1 in (1,2,3)
|
||||||
|
1
|
||||||
|
select 10 in (1,2,3);
|
||||||
|
10 in (1,2,3)
|
||||||
|
0
|
||||||
|
select NULL in (1,2,3);
|
||||||
|
NULL in (1,2,3)
|
||||||
|
NULL
|
||||||
|
select 1 in (1,NULL,3);
|
||||||
|
1 in (1,NULL,3)
|
||||||
|
1
|
||||||
|
select 3 in (1,NULL,3);
|
||||||
|
3 in (1,NULL,3)
|
||||||
|
1
|
||||||
|
select 10 in (1,NULL,3);
|
||||||
|
10 in (1,NULL,3)
|
||||||
|
NULL
|
||||||
|
select 1.5 in (1.5,2.5,3.5);
|
||||||
|
1.5 in (1.5,2.5,3.5)
|
||||||
|
1
|
||||||
|
select 10.5 in (1.5,2.5,3.5);
|
||||||
|
10.5 in (1.5,2.5,3.5)
|
||||||
|
0
|
||||||
|
select NULL in (1.5,2.5,3.5);
|
||||||
|
NULL in (1.5,2.5,3.5)
|
||||||
|
NULL
|
||||||
|
select 1.5 in (1.5,NULL,3.5);
|
||||||
|
1.5 in (1.5,NULL,3.5)
|
||||||
|
1
|
||||||
|
select 3.5 in (1.5,NULL,3.5);
|
||||||
|
3.5 in (1.5,NULL,3.5)
|
||||||
|
1
|
||||||
|
select 10.5 in (1.5,NULL,3.5);
|
||||||
|
10.5 in (1.5,NULL,3.5)
|
||||||
|
NULL
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
|
CREATE TABLE t1 (a int, b int, c int);
|
||||||
|
insert into t1 values (1,2,3), (1,NULL,3);
|
||||||
|
select 1 in (a,b,c) from t1;
|
||||||
|
1 in (a,b,c)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 3 in (a,b,c) from t1;
|
||||||
|
3 in (a,b,c)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 10 in (a,b,c) from t1;
|
||||||
|
10 in (a,b,c)
|
||||||
|
0
|
||||||
|
NULL
|
||||||
|
select NULL in (a,b,c) from t1;
|
||||||
|
NULL in (a,b,c)
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a float, b float, c float);
|
||||||
|
insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
|
||||||
|
select 1.5 in (a,b,c) from t1;
|
||||||
|
1.5 in (a,b,c)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 3.5 in (a,b,c) from t1;
|
||||||
|
3.5 in (a,b,c)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 10.5 in (a,b,c) from t1;
|
||||||
|
10.5 in (a,b,c)
|
||||||
|
0
|
||||||
|
NULL
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
|
||||||
|
insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
|
||||||
|
select 'A' in (a,b,c) from t1;
|
||||||
|
'A' in (a,b,c)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 'EFD' in (a,b,c) from t1;
|
||||||
|
'EFD' in (a,b,c)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 'XSFGGHF' in (a,b,c) from t1;
|
||||||
|
'XSFGGHF' in (a,b,c)
|
||||||
|
0
|
||||||
|
NULL
|
||||||
|
drop table t1;
|
||||||
CREATE TABLE t1 (field char(1));
|
CREATE TABLE t1 (field char(1));
|
||||||
INSERT INTO t1 VALUES ('A'),(NULL);
|
INSERT INTO t1 VALUES ('A'),(NULL);
|
||||||
SELECT * from t1 WHERE field IN (NULL);
|
SELECT * from t1 WHERE field IN (NULL);
|
||||||
field
|
field
|
||||||
SELECT * from t1 WHERE field NOT IN (NULL);
|
SELECT * from t1 WHERE field NOT IN (NULL);
|
||||||
field
|
field
|
||||||
A
|
|
||||||
SELECT * from t1 where field = field;
|
SELECT * from t1 where field = field;
|
||||||
field
|
field
|
||||||
A
|
A
|
||||||
|
@ -16,6 +100,7 @@ NULL
|
||||||
DELETE FROM t1 WHERE field NOT IN (NULL);
|
DELETE FROM t1 WHERE field NOT IN (NULL);
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
field
|
field
|
||||||
|
A
|
||||||
NULL
|
NULL
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (id int(10) primary key);
|
create table t1 (id int(10) primary key);
|
||||||
|
|
|
@ -598,3 +598,105 @@ INSERT INTO t1 values (1),(1);
|
||||||
UPDATE t SET id=(SELECT * FROM t1);
|
UPDATE t SET id=(SELECT * FROM t1);
|
||||||
Subselect returns more than 1 record
|
Subselect returns more than 1 record
|
||||||
drop table t;
|
drop table t;
|
||||||
|
create table t (a int);
|
||||||
|
insert into t values (1),(2),(3);
|
||||||
|
select 1 IN (SELECT * from t);
|
||||||
|
1 IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 10 IN (SELECT * from t);
|
||||||
|
10 IN (SELECT * from t)
|
||||||
|
0
|
||||||
|
select NULL IN (SELECT * from t);
|
||||||
|
NULL IN (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
update t set a=NULL where a=2;
|
||||||
|
select 1 IN (SELECT * from t);
|
||||||
|
1 IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 3 IN (SELECT * from t);
|
||||||
|
3 IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 10 IN (SELECT * from t);
|
||||||
|
10 IN (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 1 > ALL (SELECT * from t);
|
||||||
|
1 > ALL (SELECT * from t)
|
||||||
|
0
|
||||||
|
select 10 > ALL (SELECT * from t);
|
||||||
|
10 > ALL (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 1 > ANY (SELECT * from t);
|
||||||
|
1 > ANY (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 10 > ANY (SELECT * from t);
|
||||||
|
10 > ANY (SELECT * from t)
|
||||||
|
1
|
||||||
|
drop table t;
|
||||||
|
create table t (a varchar(20));
|
||||||
|
insert into t values ('A'),('BC'),('DEF');
|
||||||
|
select 'A' IN (SELECT * from t);
|
||||||
|
'A' IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 'XYZS' IN (SELECT * from t);
|
||||||
|
'XYZS' IN (SELECT * from t)
|
||||||
|
0
|
||||||
|
select NULL IN (SELECT * from t);
|
||||||
|
NULL IN (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
update t set a=NULL where a='BC';
|
||||||
|
select 'A' IN (SELECT * from t);
|
||||||
|
'A' IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 'DEF' IN (SELECT * from t);
|
||||||
|
'DEF' IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 'XYZS' IN (SELECT * from t);
|
||||||
|
'XYZS' IN (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 'A' > ALL (SELECT * from t);
|
||||||
|
'A' > ALL (SELECT * from t)
|
||||||
|
0
|
||||||
|
select 'XYZS' > ALL (SELECT * from t);
|
||||||
|
'XYZS' > ALL (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 'A' > ANY (SELECT * from t);
|
||||||
|
'A' > ANY (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 'XYZS' > ANY (SELECT * from t);
|
||||||
|
'XYZS' > ANY (SELECT * from t)
|
||||||
|
1
|
||||||
|
drop table t;
|
||||||
|
create table t (a float);
|
||||||
|
insert into t values (1.5),(2.5),(3.5);
|
||||||
|
select 1.5 IN (SELECT * from t);
|
||||||
|
1.5 IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 10.5 IN (SELECT * from t);
|
||||||
|
10.5 IN (SELECT * from t)
|
||||||
|
0
|
||||||
|
select NULL IN (SELECT * from t);
|
||||||
|
NULL IN (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
update t set a=NULL where a=2.5;
|
||||||
|
select 1.5 IN (SELECT * from t);
|
||||||
|
1.5 IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 3.5 IN (SELECT * from t);
|
||||||
|
3.5 IN (SELECT * from t)
|
||||||
|
1
|
||||||
|
select 10.5 IN (SELECT * from t);
|
||||||
|
10.5 IN (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 1.5 > ALL (SELECT * from t);
|
||||||
|
1.5 > ALL (SELECT * from t)
|
||||||
|
0
|
||||||
|
select 10.5 > ALL (SELECT * from t);
|
||||||
|
10.5 > ALL (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 1.5 > ANY (SELECT * from t);
|
||||||
|
1.5 > ANY (SELECT * from t)
|
||||||
|
NULL
|
||||||
|
select 10.5 > ANY (SELECT * from t);
|
||||||
|
10.5 > ANY (SELECT * from t)
|
||||||
|
1
|
||||||
|
drop table t;
|
||||||
|
|
|
@ -2,7 +2,39 @@
|
||||||
# test of IN (NULL)
|
# test of IN (NULL)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
select 1 in (1,2,3);
|
||||||
|
select 10 in (1,2,3);
|
||||||
|
select NULL in (1,2,3);
|
||||||
|
select 1 in (1,NULL,3);
|
||||||
|
select 3 in (1,NULL,3);
|
||||||
|
select 10 in (1,NULL,3);
|
||||||
|
select 1.5 in (1.5,2.5,3.5);
|
||||||
|
select 10.5 in (1.5,2.5,3.5);
|
||||||
|
select NULL in (1.5,2.5,3.5);
|
||||||
|
select 1.5 in (1.5,NULL,3.5);
|
||||||
|
select 3.5 in (1.5,NULL,3.5);
|
||||||
|
select 10.5 in (1.5,NULL,3.5);
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
|
CREATE TABLE t1 (a int, b int, c int);
|
||||||
|
insert into t1 values (1,2,3), (1,NULL,3);
|
||||||
|
select 1 in (a,b,c) from t1;
|
||||||
|
select 3 in (a,b,c) from t1;
|
||||||
|
select 10 in (a,b,c) from t1;
|
||||||
|
select NULL in (a,b,c) from t1;
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a float, b float, c float);
|
||||||
|
insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
|
||||||
|
select 1.5 in (a,b,c) from t1;
|
||||||
|
select 3.5 in (a,b,c) from t1;
|
||||||
|
select 10.5 in (a,b,c) from t1;
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
|
||||||
|
insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
|
||||||
|
select 'A' in (a,b,c) from t1;
|
||||||
|
select 'EFD' in (a,b,c) from t1;
|
||||||
|
select 'XSFGGHF' in (a,b,c) from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
CREATE TABLE t1 (field char(1));
|
CREATE TABLE t1 (field char(1));
|
||||||
INSERT INTO t1 VALUES ('A'),(NULL);
|
INSERT INTO t1 VALUES ('A'),(NULL);
|
||||||
SELECT * from t1 WHERE field IN (NULL);
|
SELECT * from t1 WHERE field IN (NULL);
|
||||||
|
|
|
@ -362,3 +362,48 @@ INSERT INTO t1 values (1),(1);
|
||||||
-- error 1240
|
-- error 1240
|
||||||
UPDATE t SET id=(SELECT * FROM t1);
|
UPDATE t SET id=(SELECT * FROM t1);
|
||||||
drop table t;
|
drop table t;
|
||||||
|
|
||||||
|
|
||||||
|
#NULL test
|
||||||
|
create table t (a int);
|
||||||
|
insert into t values (1),(2),(3);
|
||||||
|
select 1 IN (SELECT * from t);
|
||||||
|
select 10 IN (SELECT * from t);
|
||||||
|
select NULL IN (SELECT * from t);
|
||||||
|
update t set a=NULL where a=2;
|
||||||
|
select 1 IN (SELECT * from t);
|
||||||
|
select 3 IN (SELECT * from t);
|
||||||
|
select 10 IN (SELECT * from t);
|
||||||
|
select 1 > ALL (SELECT * from t);
|
||||||
|
select 10 > ALL (SELECT * from t);
|
||||||
|
select 1 > ANY (SELECT * from t);
|
||||||
|
select 10 > ANY (SELECT * from t);
|
||||||
|
drop table t;
|
||||||
|
create table t (a varchar(20));
|
||||||
|
insert into t values ('A'),('BC'),('DEF');
|
||||||
|
select 'A' IN (SELECT * from t);
|
||||||
|
select 'XYZS' IN (SELECT * from t);
|
||||||
|
select NULL IN (SELECT * from t);
|
||||||
|
update t set a=NULL where a='BC';
|
||||||
|
select 'A' IN (SELECT * from t);
|
||||||
|
select 'DEF' IN (SELECT * from t);
|
||||||
|
select 'XYZS' IN (SELECT * from t);
|
||||||
|
select 'A' > ALL (SELECT * from t);
|
||||||
|
select 'XYZS' > ALL (SELECT * from t);
|
||||||
|
select 'A' > ANY (SELECT * from t);
|
||||||
|
select 'XYZS' > ANY (SELECT * from t);
|
||||||
|
drop table t;
|
||||||
|
create table t (a float);
|
||||||
|
insert into t values (1.5),(2.5),(3.5);
|
||||||
|
select 1.5 IN (SELECT * from t);
|
||||||
|
select 10.5 IN (SELECT * from t);
|
||||||
|
select NULL IN (SELECT * from t);
|
||||||
|
update t set a=NULL where a=2.5;
|
||||||
|
select 1.5 IN (SELECT * from t);
|
||||||
|
select 3.5 IN (SELECT * from t);
|
||||||
|
select 10.5 IN (SELECT * from t);
|
||||||
|
select 1.5 > ALL (SELECT * from t);
|
||||||
|
select 10.5 > ALL (SELECT * from t);
|
||||||
|
select 1.5 > ANY (SELECT * from t);
|
||||||
|
select 10.5 > ANY (SELECT * from t);
|
||||||
|
drop table t;
|
||||||
|
|
43
sql/item.cc
43
sql/item.cc
|
@ -46,6 +46,12 @@ Item::Item():
|
||||||
loop_id= 0;
|
loop_id= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item_ref_in_optimizer::Item_ref_in_optimizer(Item_in_optimizer *master,
|
||||||
|
char *table_name_par,
|
||||||
|
char *field_name_par):
|
||||||
|
Item_ref(master->args, table_name_par, field_name_par), owner(master) {}
|
||||||
|
|
||||||
|
|
||||||
bool Item::check_loop(uint id)
|
bool Item::check_loop(uint id)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item::check_loop");
|
DBUG_ENTER("Item::check_loop");
|
||||||
|
@ -436,6 +442,20 @@ String *Item_copy_string::val_str(String *str)
|
||||||
return &str_value;
|
return &str_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Item_ref_in_optimizer::val()
|
||||||
|
{
|
||||||
|
return owner->get_cache();
|
||||||
|
}
|
||||||
|
longlong Item_ref_in_optimizer::val_int()
|
||||||
|
{
|
||||||
|
return owner->get_cache_int();
|
||||||
|
}
|
||||||
|
String* Item_ref_in_optimizer::val_str(String* s)
|
||||||
|
{
|
||||||
|
return owner->get_cache_str(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Functions to convert item to field (for send_fields)
|
Functions to convert item to field (for send_fields)
|
||||||
*/
|
*/
|
||||||
|
@ -511,10 +531,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
|
||||||
res= item->fix_fields(thd, list, &item);
|
res= item->fix_fields(thd, list, &item);
|
||||||
else
|
else
|
||||||
thd->fatal_error= 1; // no item given => out of memory
|
thd->fatal_error= 1; // no item given => out of memory
|
||||||
*ref= item;
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Item_ref_null_helper::val()
|
||||||
|
{
|
||||||
|
double tmp= (*ref)->val_result();
|
||||||
|
owner->was_null|= null_value= (*ref)->is_null_result();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
longlong Item_ref_null_helper::val_int()
|
||||||
|
{
|
||||||
|
longlong tmp= (*ref)->val_int_result();
|
||||||
|
owner->was_null|= null_value= (*ref)->is_null_result();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
String* Item_ref_null_helper::val_str(String* s)
|
||||||
|
{
|
||||||
|
String* tmp= (*ref)->str_result(s);
|
||||||
|
owner->was_null|= null_value= (*ref)->is_null_result();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
|
||||||
|
{
|
||||||
|
return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
|
||||||
|
}
|
||||||
|
|
||||||
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
|
83
sql/item.h
83
sql/item.h
|
@ -122,6 +122,18 @@ public:
|
||||||
String* val_str(String* s) { return item->val_str(s); }
|
String* val_str(String* s) { return item->val_str(s); }
|
||||||
void make_field(Send_field* f) { item->make_field(f); }
|
void make_field(Send_field* f) { item->make_field(f); }
|
||||||
bool check_cols(uint col) { return item->check_cols(col); }
|
bool check_cols(uint col) { return item->check_cols(col); }
|
||||||
|
bool eq(const Item *item, bool binary_cmp) const
|
||||||
|
{ return item->eq(item, binary_cmp); }
|
||||||
|
bool is_null() { return item->is_null_result(); }
|
||||||
|
bool get_date(TIME *ltime, bool fuzzydate)
|
||||||
|
{
|
||||||
|
return (null_value=item->get_date(ltime, fuzzydate));
|
||||||
|
}
|
||||||
|
bool send(THD *thd, String *tmp) { return item->send(thd, tmp); }
|
||||||
|
int save_in_field(Field *field) { return item->save_in_field(field); }
|
||||||
|
void save_org_in_field(Field *field) { item->save_org_in_field(field); }
|
||||||
|
enum Item_result result_type () const { return item->result_type(); }
|
||||||
|
table_map used_tables() const { return item->used_tables(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,19 +150,6 @@ public:
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
To resolve '*' field moved to condition
|
|
||||||
*/
|
|
||||||
class Item_asterisk_remover :public Item_wrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Item_asterisk_remover(Item *it)
|
|
||||||
{
|
|
||||||
item= it;
|
|
||||||
}
|
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
|
||||||
};
|
|
||||||
|
|
||||||
class st_select_lex;
|
class st_select_lex;
|
||||||
class Item_ident :public Item
|
class Item_ident :public Item
|
||||||
{
|
{
|
||||||
|
@ -378,9 +377,13 @@ public:
|
||||||
enum Item_result result_type () const { return STRING_RESULT; }
|
enum Item_result result_type () const { return STRING_RESULT; }
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
bool eq(const Item *item, bool binary_cmp) const;
|
bool eq(const Item *item, bool binary_cmp) const;
|
||||||
Item *new_item() { return new Item_string(name,str_value.ptr(),max_length,default_charset_info); }
|
Item *new_item()
|
||||||
|
{
|
||||||
|
return new Item_string(name, str_value.ptr(), max_length,
|
||||||
|
default_charset_info);
|
||||||
|
}
|
||||||
String *const_string() { return &str_value; }
|
String *const_string() { return &str_value; }
|
||||||
inline void append(char *str,uint length) { str_value.append(str,length); }
|
inline void append(char *str, uint length) { str_value.append(str, length); }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -491,13 +494,61 @@ public:
|
||||||
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
|
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
|
||||||
void make_field(Send_field *field) { (*ref)->make_field(field); }
|
void make_field(Send_field *field) { (*ref)->make_field(field); }
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||||
int save_in_field(Field *field) { return (*ref)->save_in_field(field); }
|
int save_in_field(Field *field) { return (*ref)->save_in_field(field); }
|
||||||
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
||||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||||
table_map used_tables() const { return (*ref)->used_tables(); }
|
table_map used_tables() const { return (*ref)->used_tables(); }
|
||||||
bool check_loop(uint id);
|
bool check_loop(uint id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Item_in_subselect;
|
||||||
|
class Item_ref_null_helper: public Item_ref
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Item_in_subselect* owner;
|
||||||
|
public:
|
||||||
|
Item_ref_null_helper(Item_in_subselect* master, Item **item,
|
||||||
|
char *table_name_par,char *field_name_par):
|
||||||
|
Item_ref(item, table_name_par, field_name_par), owner(master) {}
|
||||||
|
double val();
|
||||||
|
longlong val_int();
|
||||||
|
String* val_str(String* s);
|
||||||
|
bool get_date(TIME *ltime, bool fuzzydate);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
To resolve '*' field moved to condition
|
||||||
|
and register NULL values
|
||||||
|
*/
|
||||||
|
class Item_asterisk_remover :public Item_ref_null_helper
|
||||||
|
{
|
||||||
|
Item *item;
|
||||||
|
public:
|
||||||
|
Item_asterisk_remover(Item_in_subselect *master, Item *it,
|
||||||
|
char *table, char *field):
|
||||||
|
Item_ref_null_helper(master, &item, table, field),
|
||||||
|
item(it)
|
||||||
|
{}
|
||||||
|
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Item_in_optimizer;
|
||||||
|
class Item_ref_in_optimizer: public Item_ref
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Item_in_optimizer* owner;
|
||||||
|
public:
|
||||||
|
Item_ref_in_optimizer(Item_in_optimizer* master,
|
||||||
|
char *table_name_par,char *field_name_par);
|
||||||
|
double val();
|
||||||
|
longlong val_int();
|
||||||
|
String* val_str(String* s);
|
||||||
|
bool fix_fields(THD *, struct st_table_list *, Item ** ref)
|
||||||
|
{
|
||||||
|
fixed= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following class is used to optimize comparing of date columns
|
The following class is used to optimize comparing of date columns
|
||||||
|
|
|
@ -263,6 +263,61 @@ int Arg_comparator::compare_e_row()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
longlong Item_in_optimizer::val_int()
|
||||||
|
{
|
||||||
|
int_cache_ok= 1;
|
||||||
|
flt_cache_ok= 0;
|
||||||
|
str_cache_ok= 0;
|
||||||
|
int_cache= args[0]->val_int_result();
|
||||||
|
if (args[0]->is_null_result())
|
||||||
|
{
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
longlong tmp= args[1]->val_int_result();
|
||||||
|
null_value= args[1]->is_null_result();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
longlong Item_in_optimizer::get_cache_int()
|
||||||
|
{
|
||||||
|
if (!int_cache_ok)
|
||||||
|
{
|
||||||
|
int_cache_ok= 1;
|
||||||
|
flt_cache_ok= 0;
|
||||||
|
str_cache_ok= 0;
|
||||||
|
int_cache= args[0]->val_int_result();
|
||||||
|
null_value= args[0]->is_null_result();
|
||||||
|
}
|
||||||
|
return int_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Item_in_optimizer::get_cache()
|
||||||
|
{
|
||||||
|
if (!flt_cache_ok)
|
||||||
|
{
|
||||||
|
int_cache_ok= 0;
|
||||||
|
flt_cache_ok= 1;
|
||||||
|
str_cache_ok= 0;
|
||||||
|
flt_cache= args[0]->val_result();
|
||||||
|
null_value= args[0]->is_null_result();
|
||||||
|
}
|
||||||
|
return flt_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
String *Item_in_optimizer::get_cache_str(String *s)
|
||||||
|
{
|
||||||
|
if (!str_cache_ok)
|
||||||
|
{
|
||||||
|
int_cache_ok= 0;
|
||||||
|
flt_cache_ok= 0;
|
||||||
|
str_cache_ok= 1;
|
||||||
|
str_cache_buff.set(buffer, sizeof(buffer), s->charset());
|
||||||
|
str_cache= args[0]->str_result(&str_cache_buff);
|
||||||
|
null_value= args[0]->is_null_result();
|
||||||
|
}
|
||||||
|
return str_cache;
|
||||||
|
}
|
||||||
|
|
||||||
longlong Item_func_eq::val_int()
|
longlong Item_func_eq::val_int()
|
||||||
{
|
{
|
||||||
|
@ -1092,6 +1147,8 @@ void Item_func_in::fix_length_and_dec()
|
||||||
array->set(j,args[i]);
|
array->set(j,args[i]);
|
||||||
if (!args[i]->null_value) // Skip NULL values
|
if (!args[i]->null_value) // Skip NULL values
|
||||||
j++;
|
j++;
|
||||||
|
else
|
||||||
|
have_null= 1;
|
||||||
}
|
}
|
||||||
if ((array->used_count=j))
|
if ((array->used_count=j))
|
||||||
array->sort();
|
array->sort();
|
||||||
|
@ -1138,17 +1195,20 @@ longlong Item_func_in::val_int()
|
||||||
if (array)
|
if (array)
|
||||||
{
|
{
|
||||||
int tmp=array->find(item);
|
int tmp=array->find(item);
|
||||||
null_value=item->null_value;
|
null_value=item->null_value || (!tmp && have_null);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
in_item->store_value(item);
|
in_item->store_value(item);
|
||||||
if ((null_value=item->null_value))
|
if ((null_value=item->null_value))
|
||||||
return 0;
|
return 0;
|
||||||
|
have_null= 0;
|
||||||
for (uint i=0 ; i < arg_count ; i++)
|
for (uint i=0 ; i < arg_count ; i++)
|
||||||
{
|
{
|
||||||
if (!in_item->cmp(args[i]) && !args[i]->null_value)
|
if (!in_item->cmp(args[i]) && !args[i]->null_value)
|
||||||
return 1; // Would maybe be nice with i ?
|
return 1; // Would maybe be nice with i ?
|
||||||
|
have_null|= args[i]->null_value;
|
||||||
}
|
}
|
||||||
|
null_value= have_null;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,27 @@ public:
|
||||||
void fix_length_and_dec() { decimals=0; max_length=1; }
|
void fix_length_and_dec() { decimals=0; max_length=1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Item_in_optimizer: public Item_bool_func
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
char buffer[80];
|
||||||
|
longlong int_cache;
|
||||||
|
double flt_cache;
|
||||||
|
String str_cache_buff, *str_cache;
|
||||||
|
bool int_cache_ok, flt_cache_ok, str_cache_ok;
|
||||||
|
public:
|
||||||
|
Item_in_optimizer(Item *a,Item *b):
|
||||||
|
Item_bool_func(a,b), int_cache_ok(0), flt_cache_ok(0), str_cache_ok(0) {}
|
||||||
|
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
|
||||||
|
longlong val_int();
|
||||||
|
|
||||||
|
double get_cache();
|
||||||
|
longlong get_cache_int();
|
||||||
|
String *get_cache_str(String *s);
|
||||||
|
|
||||||
|
friend class Item_ref_in_optimizer;
|
||||||
|
};
|
||||||
|
|
||||||
class Item_bool_func2 :public Item_int_func
|
class Item_bool_func2 :public Item_int_func
|
||||||
{ /* Bool with 2 string args */
|
{ /* Bool with 2 string args */
|
||||||
protected:
|
protected:
|
||||||
|
@ -488,9 +509,10 @@ class Item_func_in :public Item_int_func
|
||||||
Item *item;
|
Item *item;
|
||||||
in_vector *array;
|
in_vector *array;
|
||||||
cmp_item *in_item;
|
cmp_item *in_item;
|
||||||
|
bool have_null;
|
||||||
public:
|
public:
|
||||||
Item_func_in(Item *a,List<Item> &list)
|
Item_func_in(Item *a,List<Item> &list)
|
||||||
:Item_int_func(list),item(a),array(0),in_item(0) {}
|
:Item_int_func(list), item(a), array(0), in_item(0), have_null(0) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
|
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,9 +33,10 @@ SUBSELECT TODO:
|
||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
|
|
||||||
Item_subselect::Item_subselect():
|
Item_subselect::Item_subselect():
|
||||||
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0)
|
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
|
||||||
|
have_to_be_excluded(0)
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
/*
|
/*
|
||||||
item value is NULL if select_subselect not changed this value
|
item value is NULL if select_subselect not changed this value
|
||||||
(i.e. some rows will be found returned)
|
(i.e. some rows will be found returned)
|
||||||
|
@ -93,8 +94,10 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
(*ref)= substitution;
|
(*ref)= substitution;
|
||||||
substitution->name= name;
|
substitution->name= name;
|
||||||
engine->exclude();
|
if (have_to_be_excluded)
|
||||||
return substitution->fix_fields(thd, tables, ref);
|
engine->exclude();
|
||||||
|
substitution= 0;
|
||||||
|
return (*ref)->fix_fields(thd, tables, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *save_where= thd->where;
|
char const *save_where= thd->where;
|
||||||
|
@ -159,7 +162,7 @@ double Item_singleval_subselect::val ()
|
||||||
{
|
{
|
||||||
if (engine->exec())
|
if (engine->exec())
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return real_value;
|
return real_value;
|
||||||
|
@ -169,7 +172,7 @@ longlong Item_singleval_subselect::val_int ()
|
||||||
{
|
{
|
||||||
if (engine->exec())
|
if (engine->exec())
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return int_value;
|
return int_value;
|
||||||
|
@ -179,7 +182,7 @@ String *Item_singleval_subselect::val_str (String *str)
|
||||||
{
|
{
|
||||||
if (engine->exec() || null_value)
|
if (engine->exec() || null_value)
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return &string_value;
|
return &string_value;
|
||||||
|
@ -208,9 +211,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
|
||||||
left_expr= left_exp;
|
left_expr= left_exp;
|
||||||
init(thd, select_lex, new select_exists_subselect(this));
|
init(thd, select_lex, new select_exists_subselect(this));
|
||||||
max_columns= UINT_MAX;
|
max_columns= UINT_MAX;
|
||||||
null_value= 0; //can't be NULL
|
maybe_null= 1;
|
||||||
maybe_null= 0; //can't be NULL
|
reset();
|
||||||
value= 0;
|
|
||||||
// We need only 1 row to determinate existence
|
// We need only 1 row to determinate existence
|
||||||
select_lex->master_unit()->global_parameters->select_limit= 1;
|
select_lex->master_unit()->global_parameters->select_limit= 1;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -226,9 +228,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
|
||||||
func= f;
|
func= f;
|
||||||
init(thd, select_lex, new select_exists_subselect(this));
|
init(thd, select_lex, new select_exists_subselect(this));
|
||||||
max_columns= UINT_MAX;
|
max_columns= UINT_MAX;
|
||||||
null_value= 0; //can't be NULL
|
reset();
|
||||||
maybe_null= 0; //can't be NULL
|
|
||||||
value= 0;
|
|
||||||
// We need only 1 row to determinate existence
|
// We need only 1 row to determinate existence
|
||||||
select_lex->master_unit()->global_parameters->select_limit= 1;
|
select_lex->master_unit()->global_parameters->select_limit= 1;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -237,14 +237,15 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
|
||||||
|
|
||||||
void Item_exists_subselect::fix_length_and_dec()
|
void Item_exists_subselect::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
max_length= 1;
|
decimals=0;
|
||||||
|
max_length= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Item_exists_subselect::val ()
|
double Item_exists_subselect::val ()
|
||||||
{
|
{
|
||||||
if (engine->exec())
|
if (engine->exec())
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (double) value;
|
return (double) value;
|
||||||
|
@ -254,7 +255,7 @@ longlong Item_exists_subselect::val_int ()
|
||||||
{
|
{
|
||||||
if (engine->exec())
|
if (engine->exec())
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
@ -264,7 +265,50 @@ String *Item_exists_subselect::val_str(String *str)
|
||||||
{
|
{
|
||||||
if (engine->exec())
|
if (engine->exec())
|
||||||
{
|
{
|
||||||
assign_null();
|
reset();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
str->set(value,thd_charset());
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Item_in_subselect::val ()
|
||||||
|
{
|
||||||
|
if (engine->exec())
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (was_null && !value)
|
||||||
|
null_value= 1;
|
||||||
|
return (double) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
longlong Item_in_subselect::val_int ()
|
||||||
|
{
|
||||||
|
if (engine->exec())
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (was_null && !value)
|
||||||
|
null_value= 1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String *Item_in_subselect::val_str(String *str)
|
||||||
|
{
|
||||||
|
if (engine->exec())
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (was_null && !value)
|
||||||
|
{
|
||||||
|
null_value= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
str->set(value,thd_charset());
|
str->set(value,thd_charset());
|
||||||
|
@ -288,8 +332,23 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
|
||||||
compare_func_creator func)
|
compare_func_creator func)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_in_subselect::single_value_transformer");
|
DBUG_ENTER("Item_in_subselect::single_value_transformer");
|
||||||
|
Item_in_optimizer *optimizer;
|
||||||
|
substitution= optimizer= new Item_in_optimizer(left_expr, this);
|
||||||
|
if (!optimizer)
|
||||||
|
{
|
||||||
|
current_thd->fatal_error= 1;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
As far as Item_ref_in_optimizer do not substitude itself on fix_fields
|
||||||
|
we can use same item for all selects.
|
||||||
|
*/
|
||||||
|
Item *expr= new Item_ref_in_optimizer(optimizer, (char *)"<no matter>",
|
||||||
|
(char*)"<left expr>");
|
||||||
|
select_lex->master_unit()->dependent= 1;
|
||||||
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
|
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
|
select_lex->dependent= 1;
|
||||||
Item *item;
|
Item *item;
|
||||||
if (sl->item_list.elements > 1)
|
if (sl->item_list.elements > 1)
|
||||||
{
|
{
|
||||||
|
@ -299,14 +358,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
|
||||||
else
|
else
|
||||||
item= (Item*) sl->item_list.pop();
|
item= (Item*) sl->item_list.pop();
|
||||||
|
|
||||||
Item *expr= new Item_outer_select_context_saver(left_expr);
|
|
||||||
|
|
||||||
if (sl->having || sl->with_sum_func || sl->group_list.first ||
|
if (sl->having || sl->with_sum_func || sl->group_list.first ||
|
||||||
sl->order_list.first)
|
sl->order_list.first)
|
||||||
{
|
{
|
||||||
sl->item_list.push_back(item);
|
sl->item_list.push_back(item);
|
||||||
item= (*func)(expr, new Item_ref(sl->item_list.head_ref(),
|
item= (*func)(expr, new Item_ref_null_helper(this,
|
||||||
0, (char*)"<result>"));
|
sl->item_list.head_ref(),
|
||||||
|
(char *)"<no matter>",
|
||||||
|
(char*)"<result>"));
|
||||||
if (sl->having || sl->with_sum_func || sl->group_list.first)
|
if (sl->having || sl->with_sum_func || sl->group_list.first)
|
||||||
if (sl->having)
|
if (sl->having)
|
||||||
sl->having= new Item_cond_and(sl->having, item);
|
sl->having= new Item_cond_and(sl->having, item);
|
||||||
|
@ -324,7 +383,9 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
|
||||||
sl->item_list.push_back(new Item_int(1));
|
sl->item_list.push_back(new Item_int(1));
|
||||||
if (sl->table_list.elements)
|
if (sl->table_list.elements)
|
||||||
{
|
{
|
||||||
item= (*func)(expr, new Item_asterisk_remover(item));
|
item= (*func)(expr, new Item_asterisk_remover(this, item,
|
||||||
|
(char *)"<no matter>",
|
||||||
|
(char*)"<result>"));
|
||||||
if (sl->where)
|
if (sl->where)
|
||||||
sl->where= new Item_cond_and(sl->where, item);
|
sl->where= new Item_cond_and(sl->where, item);
|
||||||
else
|
else
|
||||||
|
@ -340,14 +401,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
|
||||||
}
|
}
|
||||||
if (select_lex->next_select())
|
if (select_lex->next_select())
|
||||||
{
|
{
|
||||||
// it is in union => we should perform it
|
/*
|
||||||
sl->having= (*func)(expr, item);
|
It is in union => we should perform it.
|
||||||
|
Item_asterisk_remover used only as wrapper to receine NULL value
|
||||||
|
*/
|
||||||
|
sl->having= (*func)(expr,
|
||||||
|
new Item_asterisk_remover(this, item,
|
||||||
|
(char *)"<no matter>",
|
||||||
|
(char*)"<result>"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// it is single select without tables => possible optimization
|
// it is single select without tables => possible optimization
|
||||||
item= (*func)(left_expr, item);
|
item= (*func)(left_expr, item);
|
||||||
substitution= item;
|
substitution= item;
|
||||||
|
have_to_be_excluded= 1;
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
if (thd->lex.describe)
|
if (thd->lex.describe)
|
||||||
{
|
{
|
||||||
|
@ -489,7 +557,7 @@ int subselect_single_select_engine::exec()
|
||||||
join->thd->where= save_where;
|
join->thd->where= save_where;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
item->assign_null();
|
item->reset();
|
||||||
item->assigned((executed= 0));
|
item->assigned((executed= 0));
|
||||||
}
|
}
|
||||||
if (!executed)
|
if (!executed)
|
||||||
|
|
|
@ -42,6 +42,8 @@ protected:
|
||||||
subselect_engine *engine;
|
subselect_engine *engine;
|
||||||
/* allowed number of columns (1 for single value subqueries) */
|
/* allowed number of columns (1 for single value subqueries) */
|
||||||
uint max_columns;
|
uint max_columns;
|
||||||
|
/* work with 'substitution' */
|
||||||
|
bool have_to_be_excluded;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_subselect();
|
Item_subselect();
|
||||||
|
@ -65,7 +67,7 @@ public:
|
||||||
select_subselect *result);
|
select_subselect *result);
|
||||||
|
|
||||||
~Item_subselect();
|
~Item_subselect();
|
||||||
virtual void assign_null()
|
virtual void reset()
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +112,7 @@ public:
|
||||||
decimals= item->decimals;
|
decimals= item->decimals;
|
||||||
res_type= item->res_type;
|
res_type= item->res_type;
|
||||||
}
|
}
|
||||||
virtual void assign_null()
|
virtual void reset()
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
int_value= 0;
|
int_value= 0;
|
||||||
|
@ -144,7 +146,7 @@ public:
|
||||||
}
|
}
|
||||||
Item_exists_subselect(): Item_subselect() {}
|
Item_exists_subselect(): Item_subselect() {}
|
||||||
|
|
||||||
virtual void assign_null()
|
virtual void reset()
|
||||||
{
|
{
|
||||||
value= 0;
|
value= 0;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +157,7 @@ public:
|
||||||
double val();
|
double val();
|
||||||
String *val_str(String*);
|
String *val_str(String*);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
|
||||||
friend class select_exists_subselect;
|
friend class select_exists_subselect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,14 +167,26 @@ class Item_in_subselect :public Item_exists_subselect
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Item * left_expr;
|
Item * left_expr;
|
||||||
|
bool was_null;
|
||||||
public:
|
public:
|
||||||
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
|
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
|
||||||
Item_in_subselect(Item_in_subselect *item);
|
Item_in_subselect(Item_in_subselect *item);
|
||||||
Item_in_subselect(): Item_exists_subselect() {}
|
Item_in_subselect(): Item_exists_subselect() {}
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
value= 0;
|
||||||
|
null_value= 0;
|
||||||
|
was_null= 0;
|
||||||
|
}
|
||||||
virtual void select_transformer(st_select_lex *select_lex);
|
virtual void select_transformer(st_select_lex *select_lex);
|
||||||
void single_value_transformer(st_select_lex *select_lex,
|
void single_value_transformer(st_select_lex *select_lex,
|
||||||
Item *left_expr, compare_func_creator func);
|
Item *left_expr, compare_func_creator func);
|
||||||
|
longlong val_int();
|
||||||
|
double val();
|
||||||
|
String *val_str(String*);
|
||||||
|
|
||||||
|
friend class Item_asterisk_remover;
|
||||||
|
friend class Item_ref_null_helper;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ALL/ANY/SOME subselect */
|
/* ALL/ANY/SOME subselect */
|
||||||
|
|
|
@ -937,7 +937,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
|
||||||
it->real_value= val_item->val_result();
|
it->real_value= val_item->val_result();
|
||||||
if ((it->null_value= val_item->is_null_result()))
|
if ((it->null_value= val_item->is_null_result()))
|
||||||
{
|
{
|
||||||
it->assign_null();
|
it->reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -216,7 +216,7 @@ int st_select_lex_unit::exec()
|
||||||
if (optimized && item && item->assigned())
|
if (optimized && item && item->assigned())
|
||||||
{
|
{
|
||||||
item->assigned(0); // We will reinit & rexecute unit
|
item->assigned(0); // We will reinit & rexecute unit
|
||||||
item->assign_null();
|
item->reset();
|
||||||
table->file->delete_all_rows();
|
table->file->delete_all_rows();
|
||||||
}
|
}
|
||||||
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
||||||
|
|
Loading…
Add table
Reference in a new issue