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
20232ada
Commit
20232ada
authored
Dec 27, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Plain Diff
Merge sanja.is.com.ua:/home/bell/mysql/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/work-row-4.1
parents
d85a01db
521ec316
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
840 additions
and
306 deletions
+840
-306
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+103
-2
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+42
-2
sql/item.cc
sql/item.cc
+163
-31
sql/item.h
sql/item.h
+150
-83
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+54
-40
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+11
-15
sql/item_row.cc
sql/item_row.cc
+8
-1
sql/item_row.h
sql/item_row.h
+1
-0
sql/item_subselect.cc
sql/item_subselect.cc
+265
-58
sql/item_subselect.h
sql/item_subselect.h
+29
-37
sql/sql_class.cc
sql/sql_class.cc
+6
-29
sql/sql_class.h
sql/sql_class.h
+2
-2
sql/sql_yacc.yy
sql/sql_yacc.yy
+6
-6
No files found.
mysql-test/r/subselect.result
View file @
20232ada
...
@@ -52,6 +52,54 @@ a
...
@@ -52,6 +52,54 @@ a
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
a
a
1
1
SELECT (SELECT 1,2,3) = ROW(1,2,3);
(SELECT 1,2,3) = ROW(1,2,3)
1
SELECT (SELECT 1,2,3) = ROW(1,2,1);
(SELECT 1,2,3) = ROW(1,2,1)
0
SELECT (SELECT 1,2,3) < ROW(1,2,1);
(SELECT 1,2,3) < ROW(1,2,1)
0
SELECT (SELECT 1,2,3) > ROW(1,2,1);
(SELECT 1,2,3) > ROW(1,2,1)
1
SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
(SELECT 1,2,3) = ROW(1,2,NULL)
NULL
SELECT ROW(1,2,3) = (SELECT 1,2,3);
ROW(1,2,3) = (SELECT 1,2,3)
1
SELECT ROW(1,2,3) = (SELECT 1,2,1);
ROW(1,2,3) = (SELECT 1,2,1)
0
SELECT ROW(1,2,3) < (SELECT 1,2,1);
ROW(1,2,3) < (SELECT 1,2,1)
0
SELECT ROW(1,2,3) > (SELECT 1,2,1);
ROW(1,2,3) > (SELECT 1,2,1)
1
SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
ROW(1,2,3) = (SELECT 1,2,NULL)
NULL
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
(SELECT 1.5,2,'a') = ROW(1.5,2,'a')
1
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
(SELECT 1.5,2,'a') = ROW(1.5,2,'b')
0
SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
(SELECT 1.5,2,'a') = ROW('b',2,'b')
0
SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
(SELECT 'b',2,'a') = ROW(1.5,2,'a')
0
SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
(SELECT 1.5,2,'a') = ROW(1.5,'c','a')
0
SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
(SELECT 1.5,'c','a') = ROW(1.5,2,'a')
0
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
create table t1 (a int);
create table t2 (a int, b int);
create table t2 (a int, b int);
...
@@ -586,7 +634,7 @@ EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
...
@@ -586,7 +634,7 @@ EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
id select_type table type possible_keys key key_len ref rows Extra
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
3
DEPENDENT
UNION NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
id
id
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);
...
@@ -602,7 +650,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
...
@@ -602,7 +650,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
INSERT INTO t1 values (1),(1);
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
, t1
;
create table t (a int);
create table t (a int);
insert into t values (1),(2),(3);
insert into t values (1),(2),(3);
select 1 IN (SELECT * from t);
select 1 IN (SELECT * from t);
...
@@ -711,3 +759,56 @@ This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
...
@@ -711,3 +759,56 @@ This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table t;
drop table t;
create table t1 (a int, b int, c varchar(10));
create table t2 (a int);
insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
insert into t2 values (1),(2),(NULL);
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t1 where a=t2.a) from t2;
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a') (select c from t1 where a=t2.a)
1 1 a
2 0 b
NULL NULL NULL
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b') (select c from t1 where a=t2.a)
1 0 a
2 1 b
NULL NULL NULL
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where a=t2.a)
1 0 a
2 0 b
NULL NULL NULL
drop table t1,t2;
drop table if exists t;
create table t (a int, b real, c varchar(10));
insert into t values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
select ROW(1, 1, 'a') IN (select a,b,c from t);
ROW(1, 1, 'a') IN (select a,b,c from t)
1
select ROW(1, 2, 'a') IN (select a,b,c from t);
ROW(1, 2, 'a') IN (select a,b,c from t)
NULL
select ROW(1, 1, 'a') IN (select b,a,c from t);
ROW(1, 1, 'a') IN (select b,a,c from t)
1
select ROW(1, 1, 'a') IN (select a,b,c from t where a is not null);
ROW(1, 1, 'a') IN (select a,b,c from t where a is not null)
1
select ROW(1, 2, 'a') IN (select a,b,c from t where a is not null);
ROW(1, 2, 'a') IN (select a,b,c from t where a is not null)
0
select ROW(1, 1, 'a') IN (select b,a,c from t where a is not null);
ROW(1, 1, 'a') IN (select b,a,c from t where a is not null)
1
select ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a');
ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a')
1
select ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a');
ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a')
NULL
select ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a');
ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a')
1
select ROW(1, 1, 'a') IN (select b,a,c from t limit 2);
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table if exists t;
mysql-test/t/subselect.test
View file @
20232ada
...
@@ -26,6 +26,22 @@ select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
...
@@ -26,6 +26,22 @@ select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
SELECT
1
FROM
(
SELECT
1
)
a
PROCEDURE
ANALYSE
((
SELECT
1
));
SELECT
1
FROM
(
SELECT
1
)
a
PROCEDURE
ANALYSE
((
SELECT
1
));
SELECT
(
SELECT
1
)
as
a
FROM
(
SELECT
1
)
b
WHERE
(
SELECT
a
)
IS
NULL
;
SELECT
(
SELECT
1
)
as
a
FROM
(
SELECT
1
)
b
WHERE
(
SELECT
a
)
IS
NULL
;
SELECT
(
SELECT
1
)
as
a
FROM
(
SELECT
1
)
b
WHERE
(
SELECT
a
)
IS
NOT
NULL
;
SELECT
(
SELECT
1
)
as
a
FROM
(
SELECT
1
)
b
WHERE
(
SELECT
a
)
IS
NOT
NULL
;
SELECT
(
SELECT
1
,
2
,
3
)
=
ROW
(
1
,
2
,
3
);
SELECT
(
SELECT
1
,
2
,
3
)
=
ROW
(
1
,
2
,
1
);
SELECT
(
SELECT
1
,
2
,
3
)
<
ROW
(
1
,
2
,
1
);
SELECT
(
SELECT
1
,
2
,
3
)
>
ROW
(
1
,
2
,
1
);
SELECT
(
SELECT
1
,
2
,
3
)
=
ROW
(
1
,
2
,
NULL
);
SELECT
ROW
(
1
,
2
,
3
)
=
(
SELECT
1
,
2
,
3
);
SELECT
ROW
(
1
,
2
,
3
)
=
(
SELECT
1
,
2
,
1
);
SELECT
ROW
(
1
,
2
,
3
)
<
(
SELECT
1
,
2
,
1
);
SELECT
ROW
(
1
,
2
,
3
)
>
(
SELECT
1
,
2
,
1
);
SELECT
ROW
(
1
,
2
,
3
)
=
(
SELECT
1
,
2
,
NULL
);
SELECT
(
SELECT
1.5
,
2
,
'a'
)
=
ROW
(
1.5
,
2
,
'a'
);
SELECT
(
SELECT
1.5
,
2
,
'a'
)
=
ROW
(
1.5
,
2
,
'b'
);
SELECT
(
SELECT
1.5
,
2
,
'a'
)
=
ROW
(
'b'
,
2
,
'b'
);
SELECT
(
SELECT
'b'
,
2
,
'a'
)
=
ROW
(
1.5
,
2
,
'a'
);
SELECT
(
SELECT
1.5
,
2
,
'a'
)
=
ROW
(
1.5
,
'c'
,
'a'
);
SELECT
(
SELECT
1.5
,
'c'
,
'a'
)
=
ROW
(
1.5
,
2
,
'a'
);
drop
table
if
exists
t1
,
t2
,
t3
,
t4
,
t5
,
t6
,
t7
,
t8
;
drop
table
if
exists
t1
,
t2
,
t3
,
t4
,
t5
,
t6
,
t7
,
t8
;
create
table
t1
(
a
int
);
create
table
t1
(
a
int
);
...
@@ -363,7 +379,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
...
@@ -363,7 +379,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
INSERT
INTO
t1
values
(
1
),(
1
);
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
,
t1
;
#NULL test
#NULL test
...
@@ -416,4 +432,28 @@ create table t (a float);
...
@@ -416,4 +432,28 @@ create table t (a float);
select
10.5
IN
(
SELECT
*
from
t
LIMIT
1
);
select
10.5
IN
(
SELECT
*
from
t
LIMIT
1
);
--
error
1235
--
error
1235
select
10.5
IN
(
SELECT
*
from
t
LIMIT
1
UNION
SELECT
1.5
);
select
10.5
IN
(
SELECT
*
from
t
LIMIT
1
UNION
SELECT
1.5
);
drop
table
t
;
drop
table
t
;
\ No newline at end of file
create
table
t1
(
a
int
,
b
int
,
c
varchar
(
10
));
create
table
t2
(
a
int
);
insert
into
t1
values
(
1
,
2
,
'a'
),(
2
,
3
,
'b'
),(
3
,
4
,
'c'
);
insert
into
t2
values
(
1
),(
2
),(
NULL
);
select
a
,
(
select
a
,
b
,
c
from
t1
where
t1
.
a
=
t2
.
a
)
=
ROW
(
a
,
2
,
'a'
),(
select
c
from
t1
where
a
=
t2
.
a
)
from
t2
;
select
a
,
(
select
a
,
b
,
c
from
t1
where
t1
.
a
=
t2
.
a
)
=
ROW
(
a
,
3
,
'b'
),(
select
c
from
t1
where
a
=
t2
.
a
)
from
t2
;
select
a
,
(
select
a
,
b
,
c
from
t1
where
t1
.
a
=
t2
.
a
)
=
ROW
(
a
,
4
,
'c'
),(
select
c
from
t1
where
a
=
t2
.
a
)
from
t2
;
drop
table
t1
,
t2
;
drop
table
if
exists
t
;
create
table
t
(
a
int
,
b
real
,
c
varchar
(
10
));
insert
into
t
values
(
1
,
1
,
'a'
),
(
2
,
2
,
'b'
),
(
NULL
,
2
,
'b'
);
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
a
,
b
,
c
from
t
);
select
ROW
(
1
,
2
,
'a'
)
IN
(
select
a
,
b
,
c
from
t
);
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
b
,
a
,
c
from
t
);
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
a
,
b
,
c
from
t
where
a
is
not
null
);
select
ROW
(
1
,
2
,
'a'
)
IN
(
select
a
,
b
,
c
from
t
where
a
is
not
null
);
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
b
,
a
,
c
from
t
where
a
is
not
null
);
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
a
,
b
,
c
from
t
where
c
=
'b'
or
c
=
'a'
);
select
ROW
(
1
,
2
,
'a'
)
IN
(
select
a
,
b
,
c
from
t
where
c
=
'b'
or
c
=
'a'
);
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
b
,
a
,
c
from
t
where
c
=
'b'
or
c
=
'a'
);
--
error
1235
select
ROW
(
1
,
1
,
'a'
)
IN
(
select
b
,
a
,
c
from
t
limit
2
);
drop
table
if
exists
t
;
sql/item.cc
View file @
20232ada
...
@@ -47,11 +47,6 @@ Item::Item():
...
@@ -47,11 +47,6 @@ 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
)
{
{
...
@@ -437,20 +432,6 @@ String *Item_copy_string::val_str(String *str)
...
@@ -437,20 +432,6 @@ 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)
*/
*/
...
@@ -464,18 +445,6 @@ bool Item::fix_fields(THD *thd,
...
@@ -464,18 +445,6 @@ bool Item::fix_fields(THD *thd,
return
0
;
return
0
;
}
}
bool
Item_outer_select_context_saver
::
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
list
,
Item
**
ref
)
{
DBUG_ENTER
(
"Item_outer_select_context_saver::fix_fields"
);
bool
res
=
item
->
fix_fields
(
thd
,
0
,
// do not show current subselect fields
&
item
);
*
ref
=
item
;
DBUG_RETURN
(
res
);
}
bool
Item_asterisk_remover
::
fix_fields
(
THD
*
thd
,
bool
Item_asterisk_remover
::
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
list
,
struct
st_table_list
*
list
,
Item
**
ref
)
Item
**
ref
)
...
@@ -529,6 +498,27 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
...
@@ -529,6 +498,27 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
DBUG_RETURN
(
res
);
DBUG_RETURN
(
res
);
}
}
bool
Item_ref_on_list_position
::
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tables
,
Item
**
reference
)
{
ref
=
0
;
List_iterator
<
Item
>
li
(
list
);
Item
*
item
;
uint
i
=
0
;
for
(;
(
item
=
li
++
)
&&
i
<
pos
;
i
++
);
if
(
i
==
pos
)
{
ref
=
li
.
ref
();
return
Item_ref_null_helper
::
fix_fields
(
thd
,
tables
,
reference
);
}
else
{
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
pos
);
return
1
;
}
}
double
Item_ref_null_helper
::
val
()
double
Item_ref_null_helper
::
val
()
{
{
double
tmp
=
(
*
ref
)
->
val_result
();
double
tmp
=
(
*
ref
)
->
val_result
();
...
@@ -1221,6 +1211,148 @@ bool field_is_equal_to_item(Field *field,Item *item)
...
@@ -1221,6 +1211,148 @@ bool field_is_equal_to_item(Field *field,Item *item)
return
result
==
field
->
val_real
();
return
result
==
field
->
val_real
();
}
}
Item_cache
*
Item_cache
::
get_cache
(
Item_result
type
)
{
switch
(
type
)
{
case
INT_RESULT
:
return
new
Item_cache_int
();
case
REAL_RESULT
:
return
new
Item_cache_real
();
case
STRING_RESULT
:
return
new
Item_cache_str
();
case
ROW_RESULT
:
return
new
Item_cache_row
();
default:
// should never be in real life
DBUG_ASSERT
(
0
);
return
0
;
}
}
void
Item_cache_str
::
store
(
Item
*
item
)
{
str_value
.
set
(
buffer
,
sizeof
(
buffer
),
item
->
charset
());
value
=
item
->
str_result
(
&
str_value
);
if
((
null_value
=
item
->
null_value
))
value
=
0
;
else
if
(
value
!=
&
str_value
)
{
/*
We copy string value to avoid changing value if 'item' is table field
in queries like following (where t1.c is varchar):
select a,
(select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),
(select c from t1 where a=t2.a)
from t2;
*/
str_value
.
copy
(
*
value
);
value
=
&
str_value
;
}
}
double
Item_cache_str
::
val
()
{
if
(
value
)
return
my_strntod
(
value
->
charset
(),
value
->
ptr
(),
value
->
length
(),
(
char
**
)
0
);
else
return
(
double
)
0
;
}
longlong
Item_cache_str
::
val_int
()
{
if
(
value
)
return
my_strntoll
(
value
->
charset
(),
value
->
ptr
(),
value
->
length
(),
(
char
**
)
0
,
10
);
else
return
(
longlong
)
0
;
}
bool
Item_cache_row
::
allocate
(
uint
num
)
{
n
=
num
;
THD
*
thd
=
current_thd
;
if
(
!
(
values
=
(
Item_cache
**
)
thd
->
calloc
(
sizeof
(
Item_cache
*
)
*
n
)))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
thd
->
fatal_error
=
1
;
return
1
;
}
return
0
;
}
bool
Item_cache_row
::
setup
(
Item
*
item
)
{
if
(
!
values
&&
allocate
(
item
->
cols
()))
return
1
;
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
if
(
!
(
values
[
i
]
=
Item_cache
::
get_cache
(
item
->
el
(
i
)
->
result_type
())))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
current_thd
->
fatal_error
=
1
;
return
1
;
}
values
[
i
]
->
setup
(
item
->
el
(
i
));
}
return
0
;
}
void
Item_cache_row
::
store
(
Item
*
item
)
{
null_value
=
0
;
item
->
bring_value
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
values
[
i
]
->
store
(
item
->
el
(
i
));
null_value
|=
values
[
i
]
->
null_value
;
}
}
void
Item_cache_row
::
illegal_method_call
(
const
char
*
method
)
{
DBUG_ENTER
(
"Item_cache_row::illegal_method_call"
);
DBUG_PRINT
(
"error"
,
(
"!!! %s method was called for row item"
,
method
));
DBUG_ASSERT
(
0
);
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
1
);
DBUG_VOID_RETURN
;
}
bool
Item_cache_row
::
check_cols
(
uint
c
)
{
if
(
c
!=
n
)
{
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
c
);
return
1
;
}
return
0
;
}
bool
Item_cache_row
::
null_inside
()
{
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
if
(
values
[
i
]
->
cols
()
>
1
)
{
if
(
values
[
i
]
->
null_inside
())
return
1
;
}
else
{
values
[
i
]
->
val_int
();
if
(
values
[
i
]
->
null_value
)
return
1
;
}
}
return
0
;
}
void
Item_cache_row
::
bring_value
()
{
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
values
[
i
]
->
bring_value
();
return
;
}
/*****************************************************************************
/*****************************************************************************
** Instantiate templates
** Instantiate templates
...
...
sql/item.h
View file @
20232ada
...
@@ -31,12 +31,12 @@ public:
...
@@ -31,12 +31,12 @@ public:
static
void
*
operator
new
(
size_t
size
)
{
return
(
void
*
)
sql_alloc
((
uint
)
size
);
}
static
void
*
operator
new
(
size_t
size
)
{
return
(
void
*
)
sql_alloc
((
uint
)
size
);
}
static
void
operator
delete
(
void
*
ptr
,
size_t
size
)
{}
/*lint -e715 */
static
void
operator
delete
(
void
*
ptr
,
size_t
size
)
{}
/*lint -e715 */
enum
Type
{
FIELD_ITEM
,
FUNC_ITEM
,
SUM_FUNC_ITEM
,
STRING_ITEM
,
enum
Type
{
FIELD_ITEM
,
FUNC_ITEM
,
SUM_FUNC_ITEM
,
STRING_ITEM
,
INT_ITEM
,
REAL_ITEM
,
NULL_ITEM
,
VARBIN_ITEM
,
INT_ITEM
,
REAL_ITEM
,
NULL_ITEM
,
VARBIN_ITEM
,
COPY_STR_ITEM
,
FIELD_AVG_ITEM
,
DEFAULT_ITEM
,
COPY_STR_ITEM
,
FIELD_AVG_ITEM
,
DEFAULT_ITEM
,
PROC_ITEM
,
COND_ITEM
,
REF_ITEM
,
FIELD_STD_ITEM
,
PROC_ITEM
,
COND_ITEM
,
REF_ITEM
,
FIELD_STD_ITEM
,
FIELD_VARIANCE_ITEM
,
CONST_ITEM
,
FIELD_VARIANCE_ITEM
,
CONST_ITEM
,
SUBSELECT_ITEM
,
ROW_ITEM
};
SUBSELECT_ITEM
,
ROW_ITEM
,
CACHE_ITEM
};
enum
cond_result
{
COND_UNDEF
,
COND_OK
,
COND_TRUE
,
COND_FALSE
};
enum
cond_result
{
COND_UNDEF
,
COND_OK
,
COND_TRUE
,
COND_FALSE
};
String
str_value
;
/* used to store value */
String
str_value
;
/* used to store value */
...
@@ -103,64 +103,12 @@ public:
...
@@ -103,64 +103,12 @@ public:
virtual
Item
**
addr
(
uint
i
)
{
return
0
;
}
virtual
Item
**
addr
(
uint
i
)
{
return
0
;
}
virtual
bool
check_cols
(
uint
c
);
virtual
bool
check_cols
(
uint
c
);
// It is not row => null inside is impossible
// It is not row => null inside is impossible
virtual
bool
null_inside
()
{
return
0
;
};
virtual
bool
null_inside
()
{
return
0
;
}
// used in row subselects to get value of elements
virtual
void
bring_value
()
{}
};
};
/*
Wrapper base class
*/
class
Item_wrapper
:
public
Item
{
protected:
Item
*
item
;
public:
/*
Following methods should not be used, because fix_fields exclude this
item (it assign '*ref' with field 'item' in derived classes)
*/
enum
Type
type
()
const
{
return
item
->
type
();
}
enum_field_types
field_type
()
const
{
return
item
->
field_type
();
}
double
val
()
{
return
item
->
val
();
}
longlong
val_int
()
{
return
item
->
val_int
();
}
String
*
val_str
(
String
*
s
)
{
return
item
->
val_str
(
s
);
}
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
()
{
item
->
val_int
();
return
item
->
null_value
;
}
bool
get_date
(
TIME
*
ltime
,
bool
fuzzydate
)
{
return
(
null_value
=
item
->
get_date
(
ltime
,
fuzzydate
));
}
bool
send
(
Protocol
*
prot
,
String
*
tmp
)
{
return
item
->
send
(
prot
,
tmp
);
}
int
save_in_field
(
Field
*
field
,
bool
no_conversions
)
{
return
item
->
save_in_field
(
field
,
no_conversions
);
}
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
();
}
};
/*
Save context of name resolution for Item, used in subselect transformer.
*/
class
Item_outer_select_context_saver
:
public
Item_wrapper
{
public:
Item_outer_select_context_saver
(
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
{
{
...
@@ -381,7 +329,8 @@ public:
...
@@ -381,7 +329,8 @@ public:
name
=
(
char
*
)
str_value
.
ptr
();
name
=
(
char
*
)
str_value
.
ptr
();
decimals
=
NOT_FIXED_DEC
;
decimals
=
NOT_FIXED_DEC
;
}
}
Item_string
(
const
char
*
name_par
,
const
char
*
str
,
uint
length
,
CHARSET_INFO
*
cs
)
Item_string
(
const
char
*
name_par
,
const
char
*
str
,
uint
length
,
CHARSET_INFO
*
cs
)
{
{
str_value
.
set
(
str
,
length
,
cs
);
str_value
.
set
(
str
,
length
,
cs
);
max_length
=
length
;
max_length
=
length
;
...
@@ -392,11 +341,13 @@ public:
...
@@ -392,11 +341,13 @@ public:
enum
Type
type
()
const
{
return
STRING_ITEM
;
}
enum
Type
type
()
const
{
return
STRING_ITEM
;
}
double
val
()
double
val
()
{
{
return
my_strntod
(
str_value
.
charset
(),
str_value
.
ptr
(),
str_value
.
length
(),(
char
**
)
NULL
);
return
my_strntod
(
str_value
.
charset
(),
str_value
.
ptr
(),
str_value
.
length
(),
(
char
**
)
0
);
}
}
longlong
val_int
()
longlong
val_int
()
{
{
return
my_strntoll
(
str_value
.
charset
(),
str_value
.
ptr
(),
str_value
.
length
(),(
char
**
)
0
,
10
);
return
my_strntoll
(
str_value
.
charset
(),
str_value
.
ptr
(),
str_value
.
length
(),
(
char
**
)
0
,
10
);
}
}
String
*
val_str
(
String
*
)
{
return
(
String
*
)
&
str_value
;
}
String
*
val_str
(
String
*
)
{
return
(
String
*
)
&
str_value
;
}
int
save_in_field
(
Field
*
field
,
bool
no_conversions
);
int
save_in_field
(
Field
*
field
,
bool
no_conversions
);
...
@@ -550,7 +501,7 @@ protected:
...
@@ -550,7 +501,7 @@ protected:
Item_in_subselect
*
owner
;
Item_in_subselect
*
owner
;
public:
public:
Item_ref_null_helper
(
Item_in_subselect
*
master
,
Item
**
item
,
Item_ref_null_helper
(
Item_in_subselect
*
master
,
Item
**
item
,
char
*
table_name_par
,
char
*
field_name_par
)
:
char
*
table_name_par
,
char
*
field_name_par
)
:
Item_ref
(
item
,
table_name_par
,
field_name_par
),
owner
(
master
)
{}
Item_ref
(
item
,
table_name_par
,
field_name_par
),
owner
(
master
)
{}
double
val
();
double
val
();
longlong
val_int
();
longlong
val_int
();
...
@@ -558,6 +509,24 @@ public:
...
@@ -558,6 +509,24 @@ public:
bool
get_date
(
TIME
*
ltime
,
bool
fuzzydate
);
bool
get_date
(
TIME
*
ltime
,
bool
fuzzydate
);
};
};
/*
Used to find item in list of select items after '*' items processing.
*/
class
Item_ref_on_list_position
:
public
Item_ref_null_helper
{
protected:
List
<
Item
>
&
list
;
uint
pos
;
public:
Item_ref_on_list_position
(
Item_in_subselect
*
master
,
List
<
Item
>
&
li
,
uint
num
,
char
*
table_name
,
char
*
field_name
)
:
Item_ref_null_helper
(
master
,
0
,
table_name
,
field_name
),
list
(
li
),
pos
(
num
)
{}
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
ref
);
};
/*
/*
To resolve '*' field moved to condition
To resolve '*' field moved to condition
and register NULL values
and register NULL values
...
@@ -574,24 +543,6 @@ public:
...
@@ -574,24 +543,6 @@ public:
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
ref
);
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
We need to save the original item, to be able to set the field to the
We need to save the original item, to be able to set the field to the
...
@@ -706,6 +657,122 @@ public:
...
@@ -706,6 +657,122 @@ public:
bool
cmp
(
void
);
bool
cmp
(
void
);
};
};
class
Item_cache
:
public
Item
{
public:
virtual
bool
allocate
(
uint
i
)
{
return
0
;
};
virtual
bool
setup
(
Item
*
)
{
return
0
;
};
virtual
void
store
(
Item
*
)
=
0
;
void
set_len_n_dec
(
uint32
max_len
,
uint8
dec
)
{
max_length
=
max_len
;
decimals
=
dec
;
}
enum
Type
type
()
const
{
return
CACHE_ITEM
;
}
static
Item_cache
*
get_cache
(
Item_result
type
);
};
class
Item_cache_int
:
public
Item_cache
{
longlong
value
;
public:
Item_cache_int
()
{
fixed
=
1
;
null_value
=
1
;
}
void
store
(
Item
*
item
)
{
value
=
item
->
val_int_result
();
null_value
=
item
->
null_value
;
}
double
val
()
{
return
(
double
)
value
;
}
longlong
val_int
()
{
return
value
;
}
String
*
val_str
(
String
*
str
)
{
str
->
set
(
value
,
thd_charset
());
return
str
;
}
enum
Item_result
result_type
()
const
{
return
INT_RESULT
;
}
};
class
Item_cache_real
:
public
Item_cache
{
double
value
;
public:
Item_cache_real
()
{
fixed
=
1
;
null_value
=
1
;
}
void
store
(
Item
*
item
)
{
value
=
item
->
val_result
();
null_value
=
item
->
null_value
;
}
double
val
()
{
return
value
;
}
longlong
val_int
()
{
return
(
longlong
)
(
value
+
(
value
>
0
?
0.5
:
-
0.5
));
}
String
*
val_str
(
String
*
str
)
{
str
->
set
(
value
,
decimals
,
thd_charset
());
return
str
;
}
enum
Item_result
result_type
()
const
{
return
REAL_RESULT
;
}
};
class
Item_cache_str
:
public
Item_cache
{
char
buffer
[
80
];
String
*
value
;
public:
Item_cache_str
()
{
fixed
=
1
;
null_value
=
1
;
}
void
store
(
Item
*
item
);
double
val
();
longlong
val_int
();
String
*
val_str
(
String
*
)
{
return
value
;
}
enum
Item_result
result_type
()
const
{
return
STRING_RESULT
;
}
CHARSET_INFO
*
charset
()
const
{
return
value
->
charset
();
};
};
class
Item_cache_row
:
public
Item_cache
{
Item_cache
**
values
;
uint
n
;
public:
Item_cache_row
()
:
values
(
0
),
n
(
2
)
{
fixed
=
1
;
null_value
=
1
;
}
/*
'allocate' used only in row transformer, to preallocate space for row
cache.
*/
bool
allocate
(
uint
num
);
/*
'setup' is needed only by row => it not called by simple row subselect
(only by IN subselect (in subselect optimizer))
*/
bool
setup
(
Item
*
item
);
void
store
(
Item
*
item
);
void
illegal_method_call
(
const
char
*
);
void
make_field
(
Send_field
*
)
{
illegal_method_call
((
const
char
*
)
"make_field"
);
};
double
val
()
{
illegal_method_call
((
const
char
*
)
"val"
);
return
0
;
};
longlong
val_int
()
{
illegal_method_call
((
const
char
*
)
"val_int"
);
return
0
;
};
String
*
val_str
(
String
*
)
{
illegal_method_call
((
const
char
*
)
"val_str"
);
return
0
;
};
enum
Item_result
result_type
()
const
{
return
ROW_RESULT
;
}
uint
cols
()
{
return
n
;
}
Item
*
el
(
uint
i
)
{
return
values
[
i
];
}
Item
**
addr
(
uint
i
)
{
return
(
Item
**
)
(
values
+
i
);
}
bool
check_cols
(
uint
c
);
bool
null_inside
();
void
bring_value
();
};
extern
Item_buff
*
new_Item_buff
(
Item
*
item
);
extern
Item_buff
*
new_Item_buff
(
Item
*
item
);
extern
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
extern
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
extern
Item
*
resolve_const_item
(
Item
*
item
,
Item
*
cmp_item
);
extern
Item
*
resolve_const_item
(
Item
*
item
,
Item
*
cmp_item
);
...
...
sql/item_cmpfunc.cc
View file @
20232ada
...
@@ -247,6 +247,8 @@ int Arg_comparator::compare_e_int()
...
@@ -247,6 +247,8 @@ int Arg_comparator::compare_e_int()
int
Arg_comparator
::
compare_row
()
int
Arg_comparator
::
compare_row
()
{
{
int
res
=
0
;
int
res
=
0
;
(
*
a
)
->
bring_value
();
(
*
b
)
->
bring_value
();
uint
n
=
(
*
a
)
->
cols
();
uint
n
=
(
*
a
)
->
cols
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
{
...
@@ -261,6 +263,8 @@ int Arg_comparator::compare_row()
...
@@ -261,6 +263,8 @@ int Arg_comparator::compare_row()
int
Arg_comparator
::
compare_e_row
()
int
Arg_comparator
::
compare_e_row
()
{
{
int
res
=
0
;
int
res
=
0
;
(
*
a
)
->
bring_value
();
(
*
b
)
->
bring_value
();
uint
n
=
(
*
a
)
->
cols
();
uint
n
=
(
*
a
)
->
cols
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
{
...
@@ -270,60 +274,67 @@ int Arg_comparator::compare_e_row()
...
@@ -270,60 +274,67 @@ int Arg_comparator::compare_e_row()
return
1
;
return
1
;
}
}
longlong
Item_in_optimizer
::
val_int
()
bool
Item_in_optimizer
::
preallocate_row
()
{
{
int_cache_ok
=
1
;
if
((
cache
=
Item_cache
::
get_cache
(
ROW_RESULT
)))
flt_cache_ok
=
0
;
str_cache_ok
=
0
;
int_cache
=
args
[
0
]
->
val_int_result
();
if
(
args
[
0
]
->
null_value
)
{
null_value
=
1
;
return
0
;
return
0
;
}
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
longlong
tmp
=
args
[
1
]
->
val_int_result
();
current_thd
->
fatal_error
=
1
;
null_value
=
args
[
1
]
->
null_value
;
return
1
;
return
tmp
;
}
}
longlong
Item_in_optimizer
::
get_cache_int
()
bool
Item_in_optimizer
::
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tables
,
Item
**
ref
)
{
{
if
(
!
int_cache_ok
)
if
(
args
[
0
]
->
fix_fields
(
thd
,
tables
,
args
))
return
1
;
if
(
args
[
0
]
->
maybe_null
)
maybe_null
=
1
;
if
(
args
[
0
]
->
binary
())
set_charset
(
my_charset_bin
);
with_sum_func
=
args
[
0
]
->
with_sum_func
;
used_tables_cache
=
args
[
0
]
->
used_tables
();
const_item_cache
=
args
[
0
]
->
const_item
();
if
(
!
cache
&&
!
(
cache
=
Item_cache
::
get_cache
(
args
[
0
]
->
result_type
())))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
thd
->
fatal_error
=
1
;
return
1
;
}
cache
->
setup
(
args
[
0
]);
if
(
args
[
1
]
->
fix_fields
(
thd
,
tables
,
args
))
return
1
;
Item_in_subselect
*
sub
=
(
Item_in_subselect
*
)
args
[
1
];
if
(
args
[
0
]
->
cols
()
!=
sub
->
engine
->
cols
())
{
{
int_cache_ok
=
1
;
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
args
[
0
]
->
cols
());
flt_cache_ok
=
0
;
return
1
;
str_cache_ok
=
0
;
int_cache
=
args
[
0
]
->
val_int_result
();
null_value
=
args
[
0
]
->
null_value
;
}
}
return
int_cache
;
if
(
args
[
1
]
->
maybe_null
)
maybe_null
=
1
;
with_sum_func
=
with_sum_func
||
args
[
1
]
->
with_sum_func
;
used_tables_cache
|=
args
[
1
]
->
used_tables
();
const_item_cache
&=
args
[
1
]
->
const_item
();
return
0
;
}
}
double
Item_in_optimizer
::
get_cache
()
longlong
Item_in_optimizer
::
val_int
()
{
{
if
(
!
flt_cache_ok
)
cache
->
store
(
args
[
0
]);
if
(
cache
->
null_value
)
{
{
flt_cache_ok
=
1
;
null_value
=
1
;
int_cache_ok
=
0
;
return
0
;
str_cache_ok
=
0
;
flt_cache
=
args
[
0
]
->
val_result
();
null_value
=
args
[
0
]
->
null_value
;
}
}
return
flt_cache
;
longlong
tmp
=
args
[
1
]
->
val_int_result
();
null_value
=
args
[
1
]
->
null_value
;
return
tmp
;
}
}
String
*
Item_in_optimizer
::
get_cache_str
(
String
*
s
)
bool
Item_in_optimizer
::
is_null
(
)
{
{
if
(
!
str_cache_ok
)
cache
->
store
(
args
[
0
]);
{
return
(
null_value
=
(
cache
->
null_value
||
args
[
1
]
->
is_null
()));
str_cache_ok
=
1
;
int_cache_ok
=
0
;
flt_cache_ok
=
0
;
str_value
.
set
(
buffer
,
sizeof
(
buffer
),
s
->
charset
());
str_cache
=
args
[
0
]
->
str_result
(
&
str_value
);
null_value
=
args
[
0
]
->
null_value
;
}
return
str_cache
;
}
}
longlong
Item_func_eq
::
val_int
()
longlong
Item_func_eq
::
val_int
()
...
@@ -1217,8 +1228,9 @@ void cmp_item_row::store_value(Item *item)
...
@@ -1217,8 +1228,9 @@ void cmp_item_row::store_value(Item *item)
{
{
THD
*
thd
=
current_thd
;
THD
*
thd
=
current_thd
;
n
=
item
->
cols
();
n
=
item
->
cols
();
if
((
comparators
=
(
cmp_item
**
)
thd
->
alloc
(
sizeof
(
cmp_item
*
)
*
n
)))
if
((
comparators
=
(
cmp_item
**
)
thd
->
c
alloc
(
sizeof
(
cmp_item
*
)
*
n
)))
{
{
item
->
bring_value
();
item
->
null_value
=
0
;
item
->
null_value
=
0
;
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
if
((
comparators
[
i
]
=
cmp_item
::
get_comparator
(
item
->
el
(
i
))))
if
((
comparators
[
i
]
=
cmp_item
::
get_comparator
(
item
->
el
(
i
))))
...
@@ -1252,6 +1264,7 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
...
@@ -1252,6 +1264,7 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
n
=
tmpl
->
n
;
n
=
tmpl
->
n
;
if
((
comparators
=
(
cmp_item
**
)
sql_alloc
(
sizeof
(
cmp_item
*
)
*
n
)))
if
((
comparators
=
(
cmp_item
**
)
sql_alloc
(
sizeof
(
cmp_item
*
)
*
n
)))
{
{
item
->
bring_value
();
item
->
null_value
=
0
;
item
->
null_value
=
0
;
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
if
((
comparators
[
i
]
=
tmpl
->
comparators
[
i
]
->
make_same
()))
if
((
comparators
[
i
]
=
tmpl
->
comparators
[
i
]
->
make_same
()))
...
@@ -1284,6 +1297,7 @@ int cmp_item_row::cmp(Item *arg)
...
@@ -1284,6 +1297,7 @@ int cmp_item_row::cmp(Item *arg)
return
1
;
return
1
;
}
}
bool
was_null
=
0
;
bool
was_null
=
0
;
arg
->
bring_value
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
if
(
comparators
[
i
]
->
cmp
(
arg
->
el
(
i
)))
if
(
comparators
[
i
]
->
cmp
(
arg
->
el
(
i
)))
{
{
...
...
sql/item_cmpfunc.h
View file @
20232ada
...
@@ -85,25 +85,21 @@ public:
...
@@ -85,25 +85,21 @@ public:
void
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
1
;
}
void
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
1
;
}
};
};
class
Item_cache
;
class
Item_in_optimizer
:
public
Item_bool_func
class
Item_in_optimizer
:
public
Item_bool_func
{
{
protected:
protected:
char
buffer
[
80
];
Item_cache
*
cache
;
longlong
int_cache
;
public:
double
flt_cache
;
Item_in_optimizer
(
Item
*
a
,
Item_in_subselect
*
b
)
:
String
*
str_cache
;
Item_bool_func
(
a
,
(
Item
*
)
b
),
cache
(
0
)
{}
bool
int_cache_ok
,
flt_cache_ok
,
str_cache_ok
;
// used by row in transformer
public:
bool
preallocate_row
();
Item_in_optimizer
(
Item
*
a
,
Item
*
b
)
:
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
);
Item_bool_func
(
a
,
b
),
int_cache_ok
(
0
),
flt_cache_ok
(
0
),
str_cache_ok
(
0
)
{}
bool
is_null
();
bool
is_null
()
{
return
test
(
args
[
0
]
->
is_null
()
||
args
[
1
]
->
is_null
());
}
longlong
val_int
();
longlong
val_int
();
double
get_cache
();
Item_cache
**
get_cache
()
{
return
&
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
...
...
sql/item_row.cc
View file @
20232ada
...
@@ -41,7 +41,7 @@ void Item_row::illegal_method_call(const char *method)
...
@@ -41,7 +41,7 @@ void Item_row::illegal_method_call(const char *method)
DBUG_ENTER
(
"Item_row::illegal_method_call"
);
DBUG_ENTER
(
"Item_row::illegal_method_call"
);
DBUG_PRINT
(
"error"
,
(
"!!! %s method was called for row item"
,
method
));
DBUG_PRINT
(
"error"
,
(
"!!! %s method was called for row item"
,
method
));
DBUG_ASSERT
(
0
);
DBUG_ASSERT
(
0
);
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
arg_count
);
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
1
);
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
...
@@ -100,3 +100,10 @@ bool Item_row::null_inside()
...
@@ -100,3 +100,10 @@ bool Item_row::null_inside()
}
}
return
0
;
return
0
;
}
}
void
Item_row
::
bring_value
()
{
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
items
[
i
]
->
bring_value
();
return
;
}
sql/item_row.h
View file @
20232ada
...
@@ -70,4 +70,5 @@ public:
...
@@ -70,4 +70,5 @@ public:
Item
**
addr
(
uint
i
)
{
return
items
+
i
;
}
Item
**
addr
(
uint
i
)
{
return
items
+
i
;
}
bool
check_cols
(
uint
c
);
bool
check_cols
(
uint
c
);
bool
null_inside
();
bool
null_inside
();
void
bring_value
();
};
};
sql/item_subselect.cc
View file @
20232ada
...
@@ -51,7 +51,7 @@ void Item_subselect::init(THD *thd, st_select_lex *select_lex,
...
@@ -51,7 +51,7 @@ void Item_subselect::init(THD *thd, st_select_lex *select_lex,
DBUG_ENTER
(
"Item_subselect::init"
);
DBUG_ENTER
(
"Item_subselect::init"
);
DBUG_PRINT
(
"subs"
,
(
"select_lex 0x%xl"
,
(
ulong
)
select_lex
));
DBUG_PRINT
(
"subs"
,
(
"select_lex 0x%xl"
,
(
ulong
)
select_lex
));
select_transformer
(
select_lex
);
select_transformer
(
select_lex
->
master_unit
()
);
if
(
select_lex
->
next_select
())
if
(
select_lex
->
next_select
())
engine
=
new
subselect_union_engine
(
thd
,
select_lex
->
master_unit
(),
result
,
engine
=
new
subselect_union_engine
(
thd
,
select_lex
->
master_unit
(),
result
,
this
);
this
);
...
@@ -67,7 +67,7 @@ Item_subselect::~Item_subselect()
...
@@ -67,7 +67,7 @@ Item_subselect::~Item_subselect()
delete
engine
;
delete
engine
;
}
}
void
Item_subselect
::
select_transformer
(
st_select_lex
*
select_lex
)
void
Item_subselect
::
select_transformer
(
st_select_lex
_unit
*
unit
)
{
{
DBUG_ENTER
(
"Item_subselect::select_transformer"
);
DBUG_ENTER
(
"Item_subselect::select_transformer"
);
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
...
@@ -112,9 +112,14 @@ bool Item_subselect::check_loop(uint id)
...
@@ -112,9 +112,14 @@ bool Item_subselect::check_loop(uint id)
DBUG_RETURN
(
engine
->
check_loop
(
id
));
DBUG_RETURN
(
engine
->
check_loop
(
id
));
}
}
Item
::
Type
Item_subselect
::
type
()
const
{
return
SUBSELECT_ITEM
;
}
void
Item_subselect
::
fix_length_and_dec
()
void
Item_subselect
::
fix_length_and_dec
()
{
{
engine
->
fix_length_and_dec
();
engine
->
fix_length_and_dec
(
0
);
}
}
inline
table_map
Item_subselect
::
used_tables
()
const
inline
table_map
Item_subselect
::
used_tables
()
const
...
@@ -122,56 +127,131 @@ inline table_map Item_subselect::used_tables() const
...
@@ -122,56 +127,131 @@ inline table_map Item_subselect::used_tables() const
return
(
table_map
)
engine
->
depended
()
?
1L
:
0L
;
return
(
table_map
)
engine
->
depended
()
?
1L
:
0L
;
}
}
Item_single
val_subselect
::
Item_singleval
_subselect
(
THD
*
thd
,
Item_single
row_subselect
::
Item_singlerow
_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
)
:
st_select_lex
*
select_lex
)
:
Item_subselect
()
Item_subselect
()
,
value
(
0
)
{
{
DBUG_ENTER
(
"Item_single
val_subselect::Item_singleval
_subselect"
);
DBUG_ENTER
(
"Item_single
row_subselect::Item_singlerow
_subselect"
);
init
(
thd
,
select_lex
,
new
select_single
val
_subselect
(
this
));
init
(
thd
,
select_lex
,
new
select_single
row
_subselect
(
this
));
max_columns
=
1
;
max_columns
=
1
;
maybe_null
=
1
;
maybe_null
=
1
;
max_columns
=
UINT_MAX
;
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
void
Item_singleval_subselect
::
fix_length_and_dec
()
void
Item_singlerow_subselect
::
reset
()
{
null_value
=
1
;
if
(
value
)
value
->
null_value
=
1
;
}
void
Item_singlerow_subselect
::
store
(
uint
i
,
Item
*
item
)
{
{
engine
->
fix_length_and_dec
();
row
[
i
]
->
store
(
item
);
res_type
=
engine
->
type
();
}
}
Item
::
Type
Item_subselect
::
type
()
const
enum
Item_result
Item_singlerow_subselect
::
result_type
()
const
{
{
return
SUBSELECT_ITEM
;
return
engine
->
type
()
;
}
}
double
Item_singleval_subselect
::
val
()
void
Item_singlerow_subselect
::
fix_length_and_dec
()
{
{
if
(
engine
->
exec
())
if
((
max_columns
=
engine
->
cols
())
==
1
)
{
engine
->
fix_length_and_dec
(
row
=
&
value
);
if
(
!
(
value
=
Item_cache
::
get_cache
(
engine
->
type
())))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
current_thd
->
fatal_error
=
1
;
return
;
}
}
else
{
THD
*
thd
=
current_thd
;
if
(
!
(
row
=
(
Item_cache
**
)
thd
->
alloc
(
sizeof
(
Item_cache
*
)
*
max_columns
)))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
thd
->
fatal_error
=
1
;
return
;
}
engine
->
fix_length_and_dec
(
row
);
value
=
*
row
;
}
}
uint
Item_singlerow_subselect
::
cols
()
{
return
engine
->
cols
();
}
bool
Item_singlerow_subselect
::
check_cols
(
uint
c
)
{
if
(
c
!=
engine
->
cols
())
{
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
c
);
return
1
;
}
return
0
;
}
bool
Item_singlerow_subselect
::
null_inside
()
{
for
(
uint
i
=
0
;
i
<
max_columns
;
i
++
)
{
if
(
row
[
i
]
->
null_value
)
return
1
;
}
return
0
;
}
void
Item_singlerow_subselect
::
bring_value
()
{
engine
->
exec
();
}
double
Item_singlerow_subselect
::
val
()
{
if
(
!
engine
->
exec
()
&&
!
value
->
null_value
)
{
null_value
=
0
;
return
value
->
val
();
}
else
{
{
reset
();
reset
();
return
0
;
return
0
;
}
}
return
real_value
;
}
}
longlong
Item_single
val
_subselect
::
val_int
()
longlong
Item_single
row
_subselect
::
val_int
()
{
{
if
(
engine
->
exec
())
if
(
!
engine
->
exec
()
&&
!
value
->
null_value
)
{
null_value
=
0
;
return
value
->
val_int
();
}
else
{
{
reset
();
reset
();
return
0
;
return
0
;
}
}
return
int_value
;
}
}
String
*
Item_single
val
_subselect
::
val_str
(
String
*
str
)
String
*
Item_single
row
_subselect
::
val_str
(
String
*
str
)
{
{
if
(
engine
->
exec
()
||
null_value
)
if
(
!
engine
->
exec
()
&&
!
value
->
null_value
)
{
null_value
=
0
;
return
value
->
val_str
(
str
);
}
else
{
{
reset
();
reset
();
return
0
;
return
0
;
}
}
return
&
string_value
;
}
}
Item_exists_subselect
::
Item_exists_subselect
(
THD
*
thd
,
Item_exists_subselect
::
Item_exists_subselect
(
THD
*
thd
,
...
@@ -213,7 +293,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
...
@@ -213,7 +293,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
left_expr
=
left_exp
;
left_expr
=
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
=
1
;
reset
();
reset
();
// 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
;
...
@@ -223,8 +303,9 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
...
@@ -223,8 +303,9 @@ 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
()
{
{
decimals
=
0
;
decimals
=
0
;
max_length
=
1
;
max_length
=
1
;
max_columns
=
engine
->
cols
();
}
}
double
Item_exists_subselect
::
val
()
double
Item_exists_subselect
::
val
()
...
@@ -313,13 +394,12 @@ Item_allany_subselect::Item_allany_subselect(Item_allany_subselect *item):
...
@@ -313,13 +394,12 @@ Item_allany_subselect::Item_allany_subselect(Item_allany_subselect *item):
func
=
item
->
func
;
func
=
item
->
func
;
}
}
void
Item_in_subselect
::
single_value_transformer
(
st_select_lex
*
select_lex
,
void
Item_in_subselect
::
single_value_transformer
(
st_select_lex
_unit
*
unit
,
Item
*
left_expr
,
Item
*
left_expr
,
compare_func_creator
func
)
compare_func_creator
func
)
{
{
DBUG_ENTER
(
"Item_in_subselect::single_value_transformer"
);
DBUG_ENTER
(
"Item_in_subselect::single_value_transformer"
);
if
(
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
!=
if
(
unit
->
global_parameters
->
select_limit
!=
HA_POS_ERROR
)
HA_POS_ERROR
)
{
{
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
"LIMIT & IN/ALL/ANY/SOME subquery"
);
"LIMIT & IN/ALL/ANY/SOME subquery"
);
...
@@ -336,19 +416,20 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
...
@@ -336,19 +416,20 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
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.
*/
*/
Item
*
expr
=
new
Item_ref_in_optimizer
(
optimizer
,
(
char
*
)
"<no matter>"
,
Item
*
expr
=
new
Item_ref
((
Item
**
)
optimizer
->
get_cache
(),
(
char
*
)
"<left expr>"
);
(
char
*
)
"<no matter>"
,
select_lex
->
master_unit
()
->
dependent
=
1
;
(
char
*
)
"<left expr>"
);
for
(
SELECT_LEX
*
sl
=
select_lex
;
sl
;
sl
=
sl
->
next_select
())
unit
->
dependent
=
1
;
for
(
SELECT_LEX
*
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
{
if
(
s
elect_lex
->
select_limit
!=
HA_POS_ERROR
)
if
(
s
l
->
select_limit
!=
HA_POS_ERROR
)
{
{
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
"LIMIT & IN/ALL/ANY/SOME subquery"
);
"LIMIT & IN/ALL/ANY/SOME subquery"
);
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
s
elect_lex
->
dependent
=
1
;
s
l
->
dependent
=
1
;
Item
*
item
;
Item
*
item
;
if
(
sl
->
item_list
.
elements
>
1
)
if
(
sl
->
item_list
.
elements
>
1
)
{
{
...
@@ -373,7 +454,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
...
@@ -373,7 +454,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
sl
->
having
=
item
;
sl
->
having
=
item
;
else
else
if
(
sl
->
where
)
if
(
sl
->
where
)
sl
->
where
=
new
Item_cond_and
(
sl
->
having
,
item
);
sl
->
where
=
new
Item_cond_and
(
sl
->
where
,
item
);
else
else
sl
->
where
=
item
;
sl
->
where
=
item
;
}
}
...
@@ -399,7 +480,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
...
@@ -399,7 +480,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
my_error
(
ER_NO_TABLES_USED
,
MYF
(
0
));
my_error
(
ER_NO_TABLES_USED
,
MYF
(
0
));
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
if
(
select_lex
->
next_select
())
if
(
unit
->
first_select
()
->
next_select
())
{
{
/*
/*
It is in union => we should perform it.
It is in union => we should perform it.
...
@@ -431,15 +512,87 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
...
@@ -431,15 +512,87 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
void
Item_in_subselect
::
select_transformer
(
st_select_lex
*
select_lex
)
void
Item_in_subselect
::
row_value_transformer
(
st_select_lex_unit
*
unit
,
Item
*
left_expr
)
{
{
single_value_transformer
(
select_lex
,
left_expr
,
DBUG_ENTER
(
"Item_in_subselect::row_value_transformer"
);
&
Item_bool_func2
::
eq_creator
);
if
(
unit
->
global_parameters
->
select_limit
!=
HA_POS_ERROR
)
{
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
"LIMIT & IN/ALL/ANY/SOME subquery"
);
DBUG_VOID_RETURN
;
}
Item_in_optimizer
*
optimizer
;
substitution
=
optimizer
=
new
Item_in_optimizer
(
left_expr
,
this
);
if
(
!
optimizer
)
{
current_thd
->
fatal_error
=
1
;
DBUG_VOID_RETURN
;
}
unit
->
dependent
=
1
;
uint
n
=
left_expr
->
cols
();
if
(
optimizer
->
preallocate_row
()
||
(
*
optimizer
->
get_cache
())
->
allocate
(
n
))
DBUG_VOID_RETURN
;
for
(
SELECT_LEX
*
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
if
(
sl
->
select_limit
!=
HA_POS_ERROR
)
{
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
"LIMIT & IN/ALL/ANY/SOME subquery"
);
DBUG_VOID_RETURN
;
}
sl
->
dependent
=
1
;
Item
*
item
=
0
;
List_iterator_fast
<
Item
>
li
(
sl
->
item_list
);
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
Item
*
func
=
new
Item_ref_on_list_position
(
this
,
sl
->
item_list
,
i
,
(
char
*
)
"<no matter>"
,
(
char
*
)
"<list ref>"
);
func
=
Item_bool_func2
::
eq_creator
(
new
Item_ref
((
*
optimizer
->
get_cache
())
->
addr
(
i
),
(
char
*
)
"<no matter>"
,
(
char
*
)
"<left expr>"
),
func
);
if
(
!
item
)
item
=
func
;
else
item
=
new
Item_cond_and
(
item
,
func
);
}
if
(
sl
->
having
||
sl
->
with_sum_func
||
sl
->
group_list
.
first
||
!
sl
->
table_list
.
elements
)
if
(
sl
->
having
)
sl
->
having
=
new
Item_cond_and
(
sl
->
having
,
item
);
else
sl
->
having
=
item
;
else
if
(
sl
->
where
)
sl
->
where
=
new
Item_cond_and
(
sl
->
where
,
item
);
else
sl
->
where
=
item
;
}
DBUG_VOID_RETURN
;
}
}
void
Item_allany_subselect
::
select_transformer
(
st_select_lex
*
select_lex
)
void
Item_in_subselect
::
select_transformer
(
st_select_lex_unit
*
unit
)
{
{
single_value_transformer
(
select_lex
,
left_expr
,
func
);
if
(
left_expr
->
cols
()
==
1
)
single_value_transformer
(
unit
,
left_expr
,
&
Item_bool_func2
::
eq_creator
);
else
row_value_transformer
(
unit
,
left_expr
);
}
void
Item_allany_subselect
::
select_transformer
(
st_select_lex_unit
*
unit
)
{
single_value_transformer
(
unit
,
left_expr
,
func
);
}
}
subselect_single_select_engine
::
subselect_single_select_engine
(
THD
*
thd
,
subselect_single_select_engine
::
subselect_single_select_engine
(
THD
*
thd
,
...
@@ -509,31 +662,85 @@ int subselect_union_engine::prepare()
...
@@ -509,31 +662,85 @@ int subselect_union_engine::prepare()
return
unit
->
prepare
(
thd
,
result
);
return
unit
->
prepare
(
thd
,
result
);
}
}
void
subselect_single_select_engine
::
fix_length_and_dec
()
static
Item_result
set_row
(
SELECT_LEX
*
select_lex
,
Item
*
item
,
Item_cache
**
row
)
{
{
Item_result
res_type
=
STRING_RESULT
;
Item
*
sel_item
;
List_iterator_fast
<
Item
>
li
(
select_lex
->
item_list
);
List_iterator_fast
<
Item
>
li
(
select_lex
->
item_list
);
Item
*
sel_item
=
li
++
;
for
(
uint
i
=
0
;
(
sel_item
=
li
++
);
i
++
)
item
->
max_length
=
sel_item
->
max_length
;
{
res_type
=
sel_item
->
result_type
();
item
->
max_length
=
sel_item
->
max_length
;
item
->
decimals
=
sel_item
->
decimals
;
res_type
=
sel_item
->
result_type
();
item
->
decimals
=
sel_item
->
decimals
;
if
(
row
)
{
if
(
!
(
row
[
i
]
=
Item_cache
::
get_cache
(
res_type
)))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
current_thd
->
fatal_error
=
1
;
return
STRING_RESULT
;
// we should return something
}
row
[
i
]
->
set_len_n_dec
(
sel_item
->
max_length
,
sel_item
->
decimals
);
}
}
if
(
select_lex
->
item_list
.
elements
>
1
)
res_type
=
ROW_RESULT
;
return
res_type
;
}
}
void
subselect_
union_engine
::
fix_length_and_dec
(
)
void
subselect_
single_select_engine
::
fix_length_and_dec
(
Item_cache
**
row
)
{
{
uint32
mlen
=
0
,
len
;
DBUG_ASSERT
(
row
||
select_lex
->
item_list
.
elements
==
1
);
Item
*
sel_item
=
0
;
res_type
=
set_row
(
select_lex
,
item
,
row
);
for
(
SELECT_LEX
*
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
}
void
subselect_union_engine
::
fix_length_and_dec
(
Item_cache
**
row
)
{
DBUG_ASSERT
(
row
||
unit
->
first_select
()
->
item_list
.
elements
==
1
);
if
(
unit
->
first_select
()
->
item_list
.
elements
==
1
)
{
{
List_iterator_fast
<
Item
>
li
(
sl
->
item_list
);
uint32
mlen
=
0
,
len
;
Item
*
s_item
=
li
++
;
Item
*
sel_item
=
0
;
if
((
len
=
s_item
->
max_length
))
for
(
SELECT_LEX
*
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
mlen
=
len
;
{
if
(
!
sel_item
)
List_iterator_fast
<
Item
>
li
(
sl
->
item_list
);
sel_item
=
s_item
;
Item
*
s_item
=
li
++
;
}
if
((
len
=
s_item
->
max_length
)
>
mlen
)
item
->
max_length
=
mlen
;
mlen
=
len
;
res_type
=
sel_item
->
result_type
();
if
(
!
sel_item
)
item
->
decimals
=
sel_item
->
decimals
;
sel_item
=
s_item
;
}
item
->
max_length
=
mlen
;
res_type
=
sel_item
->
result_type
();
item
->
decimals
=
sel_item
->
decimals
;
if
(
row
)
{
if
(
!
(
row
[
0
]
=
Item_cache
::
get_cache
(
res_type
)))
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
current_thd
->
fatal_error
=
1
;
return
;
}
row
[
0
]
->
set_len_n_dec
(
mlen
,
sel_item
->
decimals
);
}
}
else
{
SELECT_LEX
*
sl
=
unit
->
first_select
();
res_type
=
set_row
(
sl
,
item
,
row
);
for
(
sl
=
sl
->
next_select
();
sl
;
sl
->
next_select
())
{
List_iterator_fast
<
Item
>
li
(
sl
->
item_list
);
Item
*
sel_item
;
for
(
uint
i
=
0
;
(
sel_item
=
li
++
);
i
++
)
{
if
(
sel_item
->
max_length
>
row
[
i
]
->
max_length
)
row
[
i
]
->
max_length
=
sel_item
->
max_length
;
}
}
}
}
}
int
subselect_single_select_engine
::
exec
()
int
subselect_single_select_engine
::
exec
()
...
...
sql/item_subselect.h
View file @
20232ada
...
@@ -71,7 +71,7 @@ public:
...
@@ -71,7 +71,7 @@ public:
{
{
null_value
=
1
;
null_value
=
1
;
}
}
virtual
void
select_transformer
(
st_select_lex
*
select_lex
);
virtual
void
select_transformer
(
st_select_lex
_unit
*
unit
);
bool
assigned
()
{
return
value_assigned
;
}
bool
assigned
()
{
return
value_assigned
;
}
void
assigned
(
bool
a
)
{
value_assigned
=
a
;
}
void
assigned
(
bool
a
)
{
value_assigned
=
a
;
}
enum
Type
type
()
const
;
enum
Type
type
()
const
;
...
@@ -86,51 +86,42 @@ public:
...
@@ -86,51 +86,42 @@ public:
bool
check_loop
(
uint
id
);
bool
check_loop
(
uint
id
);
friend
class
select_subselect
;
friend
class
select_subselect
;
friend
class
Item_in_optimizer
;
};
};
/* single value subselect */
/* single value subselect */
class
Item_singleval_subselect
:
public
Item_subselect
class
Item_cache
;
class
Item_singlerow_subselect
:
public
Item_subselect
{
{
protected:
protected:
longlong
int_value
;
/* Here stored integer value of this item */
Item_cache
*
value
,
**
row
;
double
real_value
;
/* Here stored real value of this item */
/*
Here stored string value of this item.
(str_value used only as temporary buffer, because it can be changed
by Item::save_field)
*/
String
string_value
;
enum
Item_result
res_type
;
/* type of results */
public:
public:
Item_single
val
_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_single
row
_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_single
val_subselect
(
Item_singleval
_subselect
*
item
)
:
Item_single
row_subselect
(
Item_singlerow
_subselect
*
item
)
:
Item_subselect
(
item
)
Item_subselect
(
item
)
{
{
int_value
=
item
->
int_value
;
value
=
item
->
value
;
real_value
=
item
->
real_value
;
string_value
.
set
(
item
->
string_value
,
0
,
item
->
string_value
.
length
());
max_length
=
item
->
max_length
;
max_length
=
item
->
max_length
;
decimals
=
item
->
decimals
;
decimals
=
item
->
decimals
;
res_type
=
item
->
res_type
;
}
virtual
void
reset
()
{
null_value
=
1
;
int_value
=
0
;
real_value
=
0
;
max_length
=
4
;
res_type
=
STRING_RESULT
;
}
}
double
val
();
void
reset
();
void
store
(
uint
i
,
Item
*
item
);
double
val
();
longlong
val_int
();
longlong
val_int
();
String
*
val_str
(
String
*
);
String
*
val_str
(
String
*
);
Item
*
new_item
()
{
return
new
Item_single
val
_subselect
(
this
);
}
Item
*
new_item
()
{
return
new
Item_single
row
_subselect
(
this
);
}
enum
Item_result
result_type
()
const
{
return
res_type
;
}
enum
Item_result
result_type
()
const
;
void
fix_length_and_dec
();
void
fix_length_and_dec
();
friend
class
select_singleval_subselect
;
uint
cols
();
Item
*
el
(
uint
i
)
{
return
(
Item
*
)
row
[
i
];
}
Item
**
addr
(
uint
i
)
{
return
(
Item
**
)
row
+
i
;
}
bool
check_cols
(
uint
c
);
bool
null_inside
();
void
bring_value
();
friend
class
select_singlerow_subselect
;
};
};
/* exists subselect */
/* exists subselect */
...
@@ -149,7 +140,7 @@ public:
...
@@ -149,7 +140,7 @@ public:
}
}
Item_exists_subselect
()
:
Item_subselect
()
{}
Item_exists_subselect
()
:
Item_subselect
()
{}
v
irtual
v
oid
reset
()
void
reset
()
{
{
value
=
0
;
value
=
0
;
}
}
...
@@ -181,9 +172,10 @@ public:
...
@@ -181,9 +172,10 @@ public:
null_value
=
0
;
null_value
=
0
;
was_null
=
0
;
was_null
=
0
;
}
}
virtual
void
select_transformer
(
st_select_lex
*
select_lex
);
virtual
void
select_transformer
(
st_select_lex
_unit
*
unit
);
void
single_value_transformer
(
st_select_lex
*
select_lex
,
void
single_value_transformer
(
st_select_lex
_unit
*
unit
,
Item
*
left_expr
,
compare_func_creator
func
);
Item
*
left_expr
,
compare_func_creator
func
);
void
row_value_transformer
(
st_select_lex_unit
*
unit
,
Item
*
left_expr
);
longlong
val_int
();
longlong
val_int
();
double
val
();
double
val
();
String
*
val_str
(
String
*
);
String
*
val_str
(
String
*
);
...
@@ -202,7 +194,7 @@ public:
...
@@ -202,7 +194,7 @@ public:
Item_allany_subselect
(
THD
*
thd
,
Item
*
left_expr
,
compare_func_creator
f
,
Item_allany_subselect
(
THD
*
thd
,
Item
*
left_expr
,
compare_func_creator
f
,
st_select_lex
*
select_lex
);
st_select_lex
*
select_lex
);
Item_allany_subselect
(
Item_allany_subselect
*
item
);
Item_allany_subselect
(
Item_allany_subselect
*
item
);
virtual
void
select_transformer
(
st_select_lex
*
select_lex
);
virtual
void
select_transformer
(
st_select_lex
_unit
*
unit
);
};
};
class
subselect_engine
class
subselect_engine
...
@@ -228,7 +220,7 @@ public:
...
@@ -228,7 +220,7 @@ public:
}
}
virtual
int
prepare
()
=
0
;
virtual
int
prepare
()
=
0
;
virtual
void
fix_length_and_dec
()
=
0
;
virtual
void
fix_length_and_dec
(
Item_cache
**
row
)
=
0
;
virtual
int
exec
()
=
0
;
virtual
int
exec
()
=
0
;
virtual
uint
cols
()
=
0
;
/* return number of columnss in select */
virtual
uint
cols
()
=
0
;
/* return number of columnss in select */
virtual
bool
depended
()
=
0
;
/* depended from outer select */
virtual
bool
depended
()
=
0
;
/* depended from outer select */
...
@@ -249,7 +241,7 @@ public:
...
@@ -249,7 +241,7 @@ public:
select_subselect
*
result
,
select_subselect
*
result
,
Item_subselect
*
item
);
Item_subselect
*
item
);
int
prepare
();
int
prepare
();
void
fix_length_and_dec
();
void
fix_length_and_dec
(
Item_cache
**
row
);
int
exec
();
int
exec
();
uint
cols
();
uint
cols
();
bool
depended
();
bool
depended
();
...
@@ -266,7 +258,7 @@ public:
...
@@ -266,7 +258,7 @@ public:
select_subselect
*
result
,
select_subselect
*
result
,
Item_subselect
*
item
);
Item_subselect
*
item
);
int
prepare
();
int
prepare
();
void
fix_length_and_dec
();
void
fix_length_and_dec
(
Item_cache
**
row
);
int
exec
();
int
exec
();
uint
cols
();
uint
cols
();
bool
depended
();
bool
depended
();
...
...
sql/sql_class.cc
View file @
20232ada
...
@@ -917,10 +917,10 @@ select_subselect::select_subselect(Item_subselect *item)
...
@@ -917,10 +917,10 @@ select_subselect::select_subselect(Item_subselect *item)
this
->
item
=
item
;
this
->
item
=
item
;
}
}
bool
select_single
val
_subselect
::
send_data
(
List
<
Item
>
&
items
)
bool
select_single
row
_subselect
::
send_data
(
List
<
Item
>
&
items
)
{
{
DBUG_ENTER
(
"select_single
val
_subselect::send_data"
);
DBUG_ENTER
(
"select_single
row
_subselect::send_data"
);
Item_single
val_subselect
*
it
=
(
Item_singleval
_subselect
*
)
item
;
Item_single
row_subselect
*
it
=
(
Item_singlerow
_subselect
*
)
item
;
if
(
it
->
assigned
())
if
(
it
->
assigned
())
{
{
my_message
(
ER_SUBSELECT_NO_1_ROW
,
ER
(
ER_SUBSELECT_NO_1_ROW
),
MYF
(
0
));
my_message
(
ER_SUBSELECT_NO_1_ROW
,
ER
(
ER_SUBSELECT_NO_1_ROW
),
MYF
(
0
));
...
@@ -932,32 +932,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
...
@@ -932,32 +932,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
}
}
List_iterator_fast
<
Item
>
li
(
items
);
List_iterator_fast
<
Item
>
li
(
items
);
Item
*
val_item
=
li
++
;
// Only one (single value subselect)
Item
*
val_item
;
/*
for
(
uint
i
=
0
;
(
val_item
=
li
++
);
i
++
)
Following val() call have to be first, because function AVG() & STD()
it
->
store
(
i
,
val_item
);
calculate value on it & determinate "is it NULL?".
*/
it
->
real_value
=
val_item
->
val_result
();
if
((
it
->
null_value
=
val_item
->
null_value
))
{
it
->
reset
();
}
else
{
it
->
max_length
=
val_item
->
max_length
;
it
->
decimals
=
val_item
->
decimals
;
it
->
set_charset
(
val_item
->
charset
());
it
->
int_value
=
val_item
->
val_int_result
();
String
*
s
=
val_item
->
str_result
(
&
it
->
string_value
);
if
(
s
!=
&
it
->
string_value
)
{
it
->
string_value
.
set
(
*
s
,
0
,
s
->
length
());
}
// TODO: remove when correct charset handling appeared for Item
it
->
str_value
.
set
(
*
s
,
0
,
s
->
length
());
// store charset
it
->
res_type
=
val_item
->
result_type
();
}
it
->
assigned
(
1
);
it
->
assigned
(
1
);
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
}
}
...
...
sql/sql_class.h
View file @
20232ada
...
@@ -824,10 +824,10 @@ public:
...
@@ -824,10 +824,10 @@ public:
};
};
/* Single value subselect interface class */
/* Single value subselect interface class */
class
select_single
val
_subselect
:
public
select_subselect
class
select_single
row
_subselect
:
public
select_subselect
{
{
public:
public:
select_single
val
_subselect
(
Item_subselect
*
item
)
:
select_subselect
(
item
){}
select_single
row
_subselect
(
Item_subselect
*
item
)
:
select_subselect
(
item
){}
bool
send_data
(
List
<
Item
>
&
items
);
bool
send_data
(
List
<
Item
>
&
items
);
};
};
...
...
sql/sql_yacc.yy
View file @
20232ada
...
@@ -587,7 +587,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
...
@@ -587,7 +587,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
using_list expr_or_default set_expr_or_default
using_list expr_or_default set_expr_or_default
param_marker single
val_subselect singleval
_subselect_init
param_marker single
row_subselect singlerow
_subselect_init
exists_subselect exists_subselect_init
exists_subselect exists_subselect_init
%type <item_list>
%type <item_list>
...
@@ -2018,7 +2018,7 @@ simple_expr:
...
@@ -2018,7 +2018,7 @@ simple_expr:
$$= new Item_row(*$5);
$$= new Item_row(*$5);
}
}
| EXISTS exists_subselect { $$= $2; }
| EXISTS exists_subselect { $$= $2; }
| single
val
_subselect { $$= $1; }
| single
row
_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
| MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->add_ftfunc_to_list((Item_func_match *)
{ Select->add_ftfunc_to_list((Item_func_match *)
...
@@ -4488,17 +4488,17 @@ union_option:
...
@@ -4488,17 +4488,17 @@ union_option:
/* empty */ {}
/* empty */ {}
| ALL {Select->master_unit()->union_option= 1;};
| ALL {Select->master_unit()->union_option= 1;};
single
val
_subselect:
single
row
_subselect:
subselect_start single
val
_subselect_init
subselect_start single
row
_subselect_init
subselect_end
subselect_end
{
{
$$= $2;
$$= $2;
};
};
single
val
_subselect_init:
single
row
_subselect_init:
select_init2
select_init2
{
{
$$= new Item_single
val
_subselect(YYTHD,
$$= new Item_single
row
_subselect(YYTHD,
Lex->current_select->master_unit()->
Lex->current_select->master_unit()->
first_select());
first_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