Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
6db77efb
Commit
6db77efb
authored
Dec 10, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Plain Diff
merging
parents
857d447e
4506ab9e
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
571 additions
and
50 deletions
+571
-50
mysql-test/r/func_in.result
mysql-test/r/func_in.result
+86
-1
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+102
-0
mysql-test/t/func_in.test
mysql-test/t/func_in.test
+32
-0
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+45
-0
sql/item.cc
sql/item.cc
+42
-1
sql/item.h
sql/item.h
+66
-15
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+61
-1
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+23
-1
sql/item_subselect.cc
sql/item_subselect.cc
+93
-25
sql/item_subselect.h
sql/item_subselect.h
+19
-4
sql/sql_class.cc
sql/sql_class.cc
+1
-1
sql/sql_union.cc
sql/sql_union.cc
+1
-1
No files found.
mysql-test/r/func_in.result
View file @
6db77efb
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;
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));
INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL);
field
SELECT * from t1 WHERE field NOT IN (NULL);
field
A
SELECT * from t1 where field = field;
field
A
...
...
@@ -16,6 +100,7 @@ NULL
DELETE FROM t1 WHERE field NOT IN (NULL);
SELECT * FROM t1;
field
A
NULL
drop table t1;
create table t1 (id int(10) primary key);
...
...
mysql-test/r/subselect.result
View file @
6db77efb
...
...
@@ -598,3 +598,105 @@ INSERT INTO t1 values (1),(1);
UPDATE t SET id=(SELECT * FROM t1);
Subselect returns more than 1 record
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;
mysql-test/t/func_in.test
View file @
6db77efb
...
...
@@ -2,7 +2,39 @@
# 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
;
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
));
INSERT
INTO
t1
VALUES
(
'A'
),(
NULL
);
SELECT
*
from
t1
WHERE
field
IN
(
NULL
);
...
...
mysql-test/t/subselect.test
View file @
6db77efb
...
...
@@ -362,3 +362,48 @@ INSERT INTO t1 values (1),(1);
--
error
1240
UPDATE
t
SET
id
=
(
SELECT
*
FROM
t1
);
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
;
sql/item.cc
View file @
6db77efb
...
...
@@ -46,6 +46,12 @@ Item::Item():
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
)
{
DBUG_ENTER
(
"Item::check_loop"
);
...
...
@@ -436,6 +442,20 @@ String *Item_copy_string::val_str(String *str)
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)
*/
...
...
@@ -511,10 +531,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
res
=
item
->
fix_fields
(
thd
,
list
,
&
item
);
else
thd
->
fatal_error
=
1
;
// no item given => out of memory
*
ref
=
item
;
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
)
{
...
...
sql/item.h
View file @
6db77efb
...
...
@@ -122,6 +122,18 @@ public:
String
*
val_str
(
String
*
s
)
{
return
item
->
val_str
(
s
);
}
void
make_field
(
Send_field
*
f
)
{
item
->
make_field
(
f
);
}
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
);
};
/*
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
Item_ident
:
public
Item
{
...
...
@@ -384,9 +383,13 @@ public:
enum
Item_result
result_type
()
const
{
return
STRING_RESULT
;
}
bool
basic_const_item
()
const
{
return
1
;
}
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
;
}
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
);
};
...
...
@@ -505,6 +508,54 @@ public:
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
...
...
sql/item_cmpfunc.cc
View file @
6db77efb
...
...
@@ -263,6 +263,61 @@ int Arg_comparator::compare_e_row()
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
()
{
...
...
@@ -1106,6 +1161,8 @@ void Item_func_in::fix_length_and_dec()
array
->
set
(
j
,
args
[
i
]);
if
(
!
args
[
i
]
->
null_value
)
// Skip NULL values
j
++
;
else
have_null
=
1
;
}
if
((
array
->
used_count
=
j
))
array
->
sort
();
...
...
@@ -1152,17 +1209,20 @@ longlong Item_func_in::val_int()
if
(
array
)
{
int
tmp
=
array
->
find
(
item
);
null_value
=
item
->
null_value
;
null_value
=
item
->
null_value
||
(
!
tmp
&&
have_null
)
;
return
tmp
;
}
in_item
->
store_value
(
item
);
if
((
null_value
=
item
->
null_value
))
return
0
;
have_null
=
0
;
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
{
if
(
!
in_item
->
cmp
(
args
[
i
])
&&
!
args
[
i
]
->
null_value
)
return
1
;
// Would maybe be nice with i ?
have_null
|=
args
[
i
]
->
null_value
;
}
null_value
=
have_null
;
return
0
;
}
...
...
sql/item_cmpfunc.h
View file @
6db77efb
...
...
@@ -87,6 +87,27 @@ public:
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
{
/* Bool with 2 string args */
protected:
...
...
@@ -488,9 +509,10 @@ class Item_func_in :public Item_int_func
Item
*
item
;
in_vector
*
array
;
cmp_item
*
in_item
;
bool
have_null
;
public:
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
();
bool
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tlist
,
Item
**
ref
)
{
...
...
sql/item_subselect.cc
View file @
6db77efb
...
...
@@ -33,9 +33,10 @@ SUBSELECT TODO:
#include "sql_select.h"
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
(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
;
substitution
->
name
=
name
;
if
(
have_to_be_excluded
)
engine
->
exclude
();
return
substitution
->
fix_fields
(
thd
,
tables
,
ref
);
substitution
=
0
;
return
(
*
ref
)
->
fix_fields
(
thd
,
tables
,
ref
);
}
char
const
*
save_where
=
thd
->
where
;
...
...
@@ -159,7 +162,7 @@ double Item_singleval_subselect::val ()
{
if
(
engine
->
exec
())
{
assign_null
();
reset
();
return
0
;
}
return
real_value
;
...
...
@@ -169,7 +172,7 @@ longlong Item_singleval_subselect::val_int ()
{
if
(
engine
->
exec
())
{
assign_null
();
reset
();
return
0
;
}
return
int_value
;
...
...
@@ -179,7 +182,7 @@ String *Item_singleval_subselect::val_str (String *str)
{
if
(
engine
->
exec
()
||
null_value
)
{
assign_null
();
reset
();
return
0
;
}
return
&
string_value
;
...
...
@@ -208,9 +211,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
left_expr
=
left_exp
;
init
(
thd
,
select_lex
,
new
select_exists_subselect
(
this
));
max_columns
=
UINT_MAX
;
null_value
=
0
;
//can't be NULL
maybe_null
=
0
;
//can't be NULL
value
=
0
;
maybe_null
=
1
;
reset
();
// We need only 1 row to determinate existence
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
=
1
;
DBUG_VOID_RETURN
;
...
...
@@ -226,9 +228,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
func
=
f
;
init
(
thd
,
select_lex
,
new
select_exists_subselect
(
this
));
max_columns
=
UINT_MAX
;
null_value
=
0
;
//can't be NULL
maybe_null
=
0
;
//can't be NULL
value
=
0
;
reset
();
// We need only 1 row to determinate existence
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
=
1
;
DBUG_VOID_RETURN
;
...
...
@@ -237,6 +237,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void
Item_exists_subselect
::
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
1
;
}
...
...
@@ -244,7 +245,7 @@ double Item_exists_subselect::val ()
{
if
(
engine
->
exec
())
{
assign_null
();
reset
();
return
0
;
}
return
(
double
)
value
;
...
...
@@ -254,7 +255,7 @@ longlong Item_exists_subselect::val_int ()
{
if
(
engine
->
exec
())
{
assign_null
();
reset
();
return
0
;
}
return
value
;
...
...
@@ -264,7 +265,50 @@ String *Item_exists_subselect::val_str(String *str)
{
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
;
}
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
)
{
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
())
{
select_lex
->
dependent
=
1
;
Item
*
item
;
if
(
sl
->
item_list
.
elements
>
1
)
{
...
...
@@ -299,14 +358,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else
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
||
sl
->
order_list
.
first
)
{
sl
->
item_list
.
push_back
(
item
);
item
=
(
*
func
)(
expr
,
new
Item_ref
(
sl
->
item_list
.
head_ref
(),
0
,
(
char
*
)
"<result>"
));
item
=
(
*
func
)(
expr
,
new
Item_ref_null_helper
(
this
,
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
->
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
));
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
)
sl
->
where
=
new
Item_cond_and
(
sl
->
where
,
item
);
else
...
...
@@ -340,14 +401,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
}
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
{
// it is single select without tables => possible optimization
item
=
(
*
func
)(
left_expr
,
item
);
substitution
=
item
;
have_to_be_excluded
=
1
;
THD
*
thd
=
current_thd
;
if
(
thd
->
lex
.
describe
)
{
...
...
@@ -489,7 +557,7 @@ int subselect_single_select_engine::exec()
join
->
thd
->
where
=
save_where
;
DBUG_RETURN
(
1
);
}
item
->
assign_null
();
item
->
reset
();
item
->
assigned
((
executed
=
0
));
}
if
(
!
executed
)
...
...
sql/item_subselect.h
View file @
6db77efb
...
...
@@ -42,6 +42,8 @@ protected:
subselect_engine
*
engine
;
/* allowed number of columns (1 for single value subqueries) */
uint
max_columns
;
/* work with 'substitution' */
bool
have_to_be_excluded
;
public:
Item_subselect
();
...
...
@@ -65,7 +67,7 @@ public:
select_subselect
*
result
);
~
Item_subselect
();
virtual
void
assign_null
()
virtual
void
reset
()
{
null_value
=
1
;
}
...
...
@@ -110,7 +112,7 @@ public:
decimals
=
item
->
decimals
;
res_type
=
item
->
res_type
;
}
virtual
void
assign_null
()
virtual
void
reset
()
{
null_value
=
1
;
int_value
=
0
;
...
...
@@ -144,7 +146,7 @@ public:
}
Item_exists_subselect
()
:
Item_subselect
()
{}
virtual
void
assign_null
()
virtual
void
reset
()
{
value
=
0
;
}
...
...
@@ -155,6 +157,7 @@ public:
double
val
();
String
*
val_str
(
String
*
);
void
fix_length_and_dec
();
friend
class
select_exists_subselect
;
};
...
...
@@ -164,14 +167,26 @@ class Item_in_subselect :public Item_exists_subselect
{
protected:
Item
*
left_expr
;
bool
was_null
;
public:
Item_in_subselect
(
THD
*
thd
,
Item
*
left_expr
,
st_select_lex
*
select_lex
);
Item_in_subselect
(
Item_in_subselect
*
item
);
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
);
void
single_value_transformer
(
st_select_lex
*
select_lex
,
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 */
...
...
sql/sql_class.cc
View file @
6db77efb
...
...
@@ -935,7 +935,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
it
->
real_value
=
val_item
->
val_result
();
if
((
it
->
null_value
=
val_item
->
is_null_result
()))
{
it
->
assign_null
();
it
->
reset
();
}
else
{
...
...
sql/sql_union.cc
View file @
6db77efb
...
...
@@ -216,7 +216,7 @@ int st_select_lex_unit::exec()
if
(
optimized
&&
item
&&
item
->
assigned
())
{
item
->
assigned
(
0
);
// We will reinit & rexecute unit
item
->
assign_null
();
item
->
reset
();
table
->
file
->
delete_all_rows
();
}
for
(
SELECT_LEX
*
sl
=
first_select
();
sl
;
sl
=
sl
->
next_select
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment