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
2c6fca27
Commit
2c6fca27
authored
Dec 31, 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
ffb82a97
2ed22eab
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
850 additions
and
312 deletions
+850
-312
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+103
-2
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+41
-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
+271
-58
sql/item_subselect.h
sql/item_subselect.h
+34
-43
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 @
2c6fca27
...
...
@@ -52,6 +52,54 @@ a
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
a
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;
create table t1 (a int);
create table t2 (a int, b int);
...
...
@@ -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
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
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);
id
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
INSERT INTO t1 values (1),(1);
UPDATE t SET id=(SELECT * FROM t1);
Subselect returns more than 1 record
drop table t;
drop table t
, t1
;
create table t (a int);
insert into t values (1),(2),(3);
select 1 IN (SELECT * from t);
...
...
@@ -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);
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
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 @
2c6fca27
...
...
@@ -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
(
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
,
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
;
create
table
t1
(
a
int
);
...
...
@@ -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
);
--
error
1240
UPDATE
t
SET
id
=
(
SELECT
*
FROM
t1
);
drop
table
t
;
drop
table
t
,
t1
;
#NULL test
...
...
@@ -416,4 +432,27 @@ create table t (a float);
select
10.5
IN
(
SELECT
*
from
t
LIMIT
1
);
--
error
1235
select
10.5
IN
(
SELECT
*
from
t
LIMIT
1
UNION
SELECT
1.5
);
drop
table
t
;
\ No newline at end of file
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
;
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 @
2c6fca27
...
...
@@ -47,11 +47,6 @@ 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
)
{
...
...
@@ -437,20 +432,6 @@ 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)
*/
...
...
@@ -464,18 +445,6 @@ bool Item::fix_fields(THD *thd,
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
,
struct
st_table_list
*
list
,
Item
**
ref
)
...
...
@@ -529,6 +498,27 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
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
tmp
=
(
*
ref
)
->
val_result
();
...
...
@@ -1219,6 +1209,148 @@ bool field_is_equal_to_item(Field *field,Item *item)
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
...
...
sql/item.h
View file @
2c6fca27
...
...
@@ -31,12 +31,12 @@ public:
static
void
*
operator
new
(
size_t
size
)
{
return
(
void
*
)
sql_alloc
((
uint
)
size
);
}
static
void
operator
delete
(
void
*
ptr
,
size_t
size
)
{}
/*lint -e715 */
enum
Type
{
FIELD_ITEM
,
FUNC_ITEM
,
SUM_FUNC_ITEM
,
STRING_ITEM
,
INT_ITEM
,
REAL_ITEM
,
NULL_ITEM
,
VARBIN_ITEM
,
COPY_STR_ITEM
,
FIELD_AVG_ITEM
,
DEFAULT_ITEM
,
PROC_ITEM
,
COND_ITEM
,
REF_ITEM
,
FIELD_STD_ITEM
,
FIELD_VARIANCE_ITEM
,
CONST_ITEM
,
SUBSELECT_ITEM
,
ROW_ITEM
};
enum
Type
{
FIELD_ITEM
,
FUNC_ITEM
,
SUM_FUNC_ITEM
,
STRING_ITEM
,
INT_ITEM
,
REAL_ITEM
,
NULL_ITEM
,
VARBIN_ITEM
,
COPY_STR_ITEM
,
FIELD_AVG_ITEM
,
DEFAULT_ITEM
,
PROC_ITEM
,
COND_ITEM
,
REF_ITEM
,
FIELD_STD_ITEM
,
FIELD_VARIANCE_ITEM
,
CONST_ITEM
,
SUBSELECT_ITEM
,
ROW_ITEM
,
CACHE_ITEM
};
enum
cond_result
{
COND_UNDEF
,
COND_OK
,
COND_TRUE
,
COND_FALSE
};
String
str_value
;
/* used to store value */
...
...
@@ -103,64 +103,12 @@ public:
virtual
Item
**
addr
(
uint
i
)
{
return
0
;
}
virtual
bool
check_cols
(
uint
c
);
// 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
Item_ident
:
public
Item
{
...
...
@@ -381,7 +329,8 @@ public:
name
=
(
char
*
)
str_value
.
ptr
();
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
);
max_length
=
length
;
...
...
@@ -392,11 +341,13 @@ public:
enum
Type
type
()
const
{
return
STRING_ITEM
;
}
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
()
{
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
;
}
int
save_in_field
(
Field
*
field
,
bool
no_conversions
);
...
...
@@ -550,7 +501,7 @@ protected:
Item_in_subselect
*
owner
;
public:
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
)
{}
double
val
();
longlong
val_int
();
...
...
@@ -558,6 +509,24 @@ public:
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
and register NULL values
...
...
@@ -574,24 +543,6 @@ public:
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
We need to save the original item, to be able to set the field to the
...
...
@@ -706,6 +657,122 @@ public:
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_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
extern
Item
*
resolve_const_item
(
Item
*
item
,
Item
*
cmp_item
);
...
...
sql/item_cmpfunc.cc
View file @
2c6fca27
...
...
@@ -247,6 +247,8 @@ int Arg_comparator::compare_e_int()
int
Arg_comparator
::
compare_row
()
{
int
res
=
0
;
(
*
a
)
->
bring_value
();
(
*
b
)
->
bring_value
();
uint
n
=
(
*
a
)
->
cols
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
...
...
@@ -261,6 +263,8 @@ int Arg_comparator::compare_row()
int
Arg_comparator
::
compare_e_row
()
{
int
res
=
0
;
(
*
a
)
->
bring_value
();
(
*
b
)
->
bring_value
();
uint
n
=
(
*
a
)
->
cols
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
...
...
@@ -270,60 +274,67 @@ int Arg_comparator::compare_e_row()
return
1
;
}
longlong
Item_in_optimizer
::
val_int
()
bool
Item_in_optimizer
::
preallocate_row
()
{
int_cache_ok
=
1
;
flt_cache_ok
=
0
;
str_cache_ok
=
0
;
int_cache
=
args
[
0
]
->
val_int_result
();
if
(
args
[
0
]
->
null_value
)
{
null_value
=
1
;
if
((
cache
=
Item_cache
::
get_cache
(
ROW_RESULT
)))
return
0
;
}
longlong
tmp
=
args
[
1
]
->
val_int_result
();
null_value
=
args
[
1
]
->
null_value
;
return
tmp
;
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
current_thd
->
fatal_error
=
1
;
return
1
;
}
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
())))
{
int_cache_ok
=
1
;
flt_cache_ok
=
0
;
str_cache_ok
=
0
;
int_cache
=
args
[
0
]
->
val_int_result
();
null_value
=
args
[
0
]
->
null_value
;
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
())
{
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
args
[
0
]
->
cols
());
return
1
;
}
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
;
int_cache_ok
=
0
;
str_cache_ok
=
0
;
flt_cache
=
args
[
0
]
->
val_result
();
null_value
=
args
[
0
]
->
null_value
;
null_value
=
1
;
return
0
;
}
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
)
{
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
;
cache
->
store
(
args
[
0
]);
return
(
null_value
=
(
cache
->
null_value
||
args
[
1
]
->
is_null
()));
}
longlong
Item_func_eq
::
val_int
()
...
...
@@ -1217,8 +1228,9 @@ void cmp_item_row::store_value(Item *item)
{
THD
*
thd
=
current_thd
;
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
;
for
(
uint
i
=
0
;
i
<
n
;
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)
n
=
tmpl
->
n
;
if
((
comparators
=
(
cmp_item
**
)
sql_alloc
(
sizeof
(
cmp_item
*
)
*
n
)))
{
item
->
bring_value
();
item
->
null_value
=
0
;
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
if
((
comparators
[
i
]
=
tmpl
->
comparators
[
i
]
->
make_same
()))
...
...
@@ -1284,6 +1297,7 @@ int cmp_item_row::cmp(Item *arg)
return
1
;
}
bool
was_null
=
0
;
arg
->
bring_value
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
if
(
comparators
[
i
]
->
cmp
(
arg
->
el
(
i
)))
{
...
...
sql/item_cmpfunc.h
View file @
2c6fca27
...
...
@@ -85,25 +85,21 @@ public:
void
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
1
;
}
};
class
Item_cache
;
class
Item_in_optimizer
:
public
Item_bool_func
{
protected:
char
buffer
[
80
];
longlong
int_cache
;
double
flt_cache
;
String
*
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
());
}
Item_cache
*
cache
;
public:
Item_in_optimizer
(
Item
*
a
,
Item_in_subselect
*
b
)
:
Item_bool_func
(
a
,
(
Item
*
)
b
),
cache
(
0
)
{}
// used by row in transformer
bool
preallocate_row
();
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
);
bool
is_null
();
longlong
val_int
();
double
get_cache
();
longlong
get_cache_int
();
String
*
get_cache_str
(
String
*
s
);
friend
class
Item_ref_in_optimizer
;
Item_cache
**
get_cache
()
{
return
&
cache
;
}
};
class
Item_bool_func2
:
public
Item_int_func
...
...
sql/item_row.cc
View file @
2c6fca27
...
...
@@ -41,7 +41,7 @@ void Item_row::illegal_method_call(const char *method)
DBUG_ENTER
(
"Item_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
),
arg_count
);
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
1
);
DBUG_VOID_RETURN
;
}
...
...
@@ -100,3 +100,10 @@ bool Item_row::null_inside()
}
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 @
2c6fca27
...
...
@@ -70,4 +70,5 @@ public:
Item
**
addr
(
uint
i
)
{
return
items
+
i
;
}
bool
check_cols
(
uint
c
);
bool
null_inside
();
void
bring_value
();
};
sql/item_subselect.cc
View file @
2c6fca27
...
...
@@ -51,7 +51,7 @@ void Item_subselect::init(THD *thd, st_select_lex *select_lex,
DBUG_ENTER
(
"Item_subselect::init"
);
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
())
engine
=
new
subselect_union_engine
(
thd
,
select_lex
->
master_unit
(),
result
,
this
);
...
...
@@ -67,7 +67,7 @@ Item_subselect::~Item_subselect()
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_VOID_RETURN
;
...
...
@@ -112,9 +112,14 @@ bool Item_subselect::check_loop(uint id)
DBUG_RETURN
(
engine
->
check_loop
(
id
));
}
Item
::
Type
Item_subselect
::
type
()
const
{
return
SUBSELECT_ITEM
;
}
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
...
...
@@ -122,56 +127,132 @@ inline table_map Item_subselect::used_tables() const
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
)
:
Item_subselect
()
Item_subselect
()
,
value
(
0
)
{
DBUG_ENTER
(
"Item_single
val_subselect::Item_singleval
_subselect"
);
init
(
thd
,
select_lex
,
new
select_single
val
_subselect
(
this
));
DBUG_ENTER
(
"Item_single
row_subselect::Item_singlerow
_subselect"
);
init
(
thd
,
select_lex
,
new
select_single
row
_subselect
(
this
));
max_columns
=
1
;
maybe_null
=
1
;
max_columns
=
UINT_MAX
;
DBUG_VOID_RETURN
;
}
void
Item_single
val_subselect
::
fix_length_and_dec
()
void
Item_single
row_subselect
::
reset
()
{
engine
->
fix_length_and_dec
();
res_type
=
engine
->
type
();
null_value
=
1
;
if
(
value
)
value
->
null_value
=
1
;
}
Item
::
Type
Item_subselect
::
type
()
const
void
Item_singlerow_subselect
::
store
(
uint
i
,
Item
*
item
)
{
r
eturn
SUBSELECT_ITEM
;
r
ow
[
i
]
->
store
(
item
)
;
}
double
Item_singleval_subselect
::
val
()
enum
Item_result
Item_singlerow_subselect
::
result_type
()
const
{
if
(
engine
->
exec
())
return
engine
->
type
();
}
void
Item_singlerow_subselect
::
fix_length_and_dec
()
{
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
;
}
maybe_null
=
engine
->
may_be_null
();
}
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
();
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
();
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
();
return
0
;
}
return
&
string_value
;
}
Item_exists_subselect
::
Item_exists_subselect
(
THD
*
thd
,
...
...
@@ -213,7 +294,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
left_expr
=
left_exp
;
func
=
f
;
init
(
thd
,
select_lex
,
new
select_exists_subselect
(
this
));
max_columns
=
UINT_MAX
;
max_columns
=
1
;
reset
();
// We need only 1 row to determinate existence
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
=
1
;
...
...
@@ -223,8 +304,9 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void
Item_exists_subselect
::
fix_length_and_dec
()
{
decimals
=
0
;
decimals
=
0
;
max_length
=
1
;
max_columns
=
engine
->
cols
();
}
double
Item_exists_subselect
::
val
()
...
...
@@ -313,13 +395,12 @@ Item_allany_subselect::Item_allany_subselect(Item_allany_subselect *item):
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
,
compare_func_creator
func
)
{
DBUG_ENTER
(
"Item_in_subselect::single_value_transformer"
);
if
(
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
!=
HA_POS_ERROR
)
if
(
unit
->
global_parameters
->
select_limit
!=
HA_POS_ERROR
)
{
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
"LIMIT & IN/ALL/ANY/SOME subquery"
);
...
...
@@ -336,19 +417,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
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
*
)
"<no matter>"
,
(
char
*
)
"<left expr>"
);
select_lex
->
master_unit
()
->
dependent
=
1
;
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
),
"LIMIT & IN/ALL/ANY/SOME subquery"
);
DBUG_VOID_RETURN
;
}
s
elect_lex
->
dependent
=
1
;
s
l
->
dependent
=
1
;
Item
*
item
;
if
(
sl
->
item_list
.
elements
>
1
)
{
...
...
@@ -373,7 +455,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
sl
->
having
=
item
;
else
if
(
sl
->
where
)
sl
->
where
=
new
Item_cond_and
(
sl
->
having
,
item
);
sl
->
where
=
new
Item_cond_and
(
sl
->
where
,
item
);
else
sl
->
where
=
item
;
}
...
...
@@ -399,7 +481,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
my_error
(
ER_NO_TABLES_USED
,
MYF
(
0
));
DBUG_VOID_RETURN
;
}
if
(
select_lex
->
next_select
())
if
(
unit
->
first_select
()
->
next_select
())
{
/*
It is in union => we should perform it.
...
...
@@ -431,15 +513,87 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
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"
);
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_in_subselect
::
select_transformer
(
st_select_lex_unit
*
unit
)
{
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
*
select_lex
)
void
Item_allany_subselect
::
select_transformer
(
st_select_lex
_unit
*
unit
)
{
single_value_transformer
(
select_lex
,
left_expr
,
func
);
single_value_transformer
(
unit
,
left_expr
,
func
);
}
subselect_single_select_engine
::
subselect_single_select_engine
(
THD
*
thd
,
...
...
@@ -509,31 +663,90 @@ int subselect_union_engine::prepare()
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
,
bool
*
maybe_null
)
{
Item_result
res_type
=
STRING_RESULT
;
Item
*
sel_item
;
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
->
decimals
=
sel_item
->
decimals
;
*
maybe_null
=
sel_item
->
maybe_null
;
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_single_select_engine
::
fix_length_and_dec
(
Item_cache
**
row
)
{
DBUG_ASSERT
(
row
||
select_lex
->
item_list
.
elements
==
1
);
res_type
=
set_row
(
select_lex
,
item
,
row
,
&
maybe_null
);
if
(
cols
()
!=
1
)
maybe_null
=
0
;
}
void
subselect_union_engine
::
fix_length_and_dec
()
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
)
{
uint32
mlen
=
0
,
len
;
Item
*
sel_item
=
0
;
for
(
SELECT_LEX
*
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
List_iterator_fast
<
Item
>
li
(
sl
->
item_list
);
Item
*
s_item
=
li
++
;
if
((
len
=
s_item
->
max_length
)
)
if
((
len
=
s_item
->
max_length
)
>
mlen
)
mlen
=
len
;
if
(
!
sel_item
)
sel_item
=
s_item
;
maybe_null
!=
s_item
->
maybe_null
;
}
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
();
bool
fake
=
0
;
res_type
=
set_row
(
sl
,
item
,
row
,
&
fake
);
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
()
...
...
sql/item_subselect.h
View file @
2c6fca27
...
...
@@ -71,7 +71,7 @@ public:
{
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
;
}
void
assigned
(
bool
a
)
{
value_assigned
=
a
;
}
enum
Type
type
()
const
;
...
...
@@ -86,51 +86,42 @@ public:
bool
check_loop
(
uint
id
);
friend
class
select_subselect
;
friend
class
Item_in_optimizer
;
};
/* single value subselect */
class
Item_singleval_subselect
:
public
Item_subselect
class
Item_cache
;
class
Item_singlerow_subselect
:
public
Item_subselect
{
protected:
longlong
int_value
;
/* Here stored integer value of this item */
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 */
Item_cache
*
value
,
**
row
;
public:
Item_single
val
_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_single
val_subselect
(
Item_singleval
_subselect
*
item
)
:
Item_single
row
_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_single
row_subselect
(
Item_singlerow
_subselect
*
item
)
:
Item_subselect
(
item
)
{
int_value
=
item
->
int_value
;
real_value
=
item
->
real_value
;
string_value
.
set
(
item
->
string_value
,
0
,
item
->
string_value
.
length
());
value
=
item
->
value
;
max_length
=
item
->
max_length
;
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
();
String
*
val_str
(
String
*
);
Item
*
new_item
()
{
return
new
Item_single
val
_subselect
(
this
);
}
enum
Item_result
result_type
()
const
{
return
res_type
;
}
Item
*
new_item
()
{
return
new
Item_single
row
_subselect
(
this
);
}
enum
Item_result
result_type
()
const
;
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 */
...
...
@@ -149,7 +140,7 @@ public:
}
Item_exists_subselect
()
:
Item_subselect
()
{}
v
irtual
v
oid
reset
()
void
reset
()
{
value
=
0
;
}
...
...
@@ -181,9 +172,10 @@ public:
null_value
=
0
;
was_null
=
0
;
}
virtual
void
select_transformer
(
st_select_lex
*
select_lex
);
void
single_value_transformer
(
st_select_lex
*
select_lex
,
virtual
void
select_transformer
(
st_select_lex
_unit
*
unit
);
void
single_value_transformer
(
st_select_lex
_unit
*
unit
,
Item
*
left_expr
,
compare_func_creator
func
);
void
row_value_transformer
(
st_select_lex_unit
*
unit
,
Item
*
left_expr
);
longlong
val_int
();
double
val
();
String
*
val_str
(
String
*
);
...
...
@@ -202,22 +194,18 @@ public:
Item_allany_subselect
(
THD
*
thd
,
Item
*
left_expr
,
compare_func_creator
f
,
st_select_lex
*
select_lex
);
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
:
public
Sql_alloc
{
protected:
select_subselect
*
result
;
/* results storage class */
THD
*
thd
;
/* pointer to current THD */
Item_subselect
*
item
;
/* item, that use this engine */
enum
Item_result
res_type
;
/* type of results */
bool
maybe_null
;
/* may be null (first item in select) */
public:
static
void
*
operator
new
(
size_t
size
)
{
return
(
void
*
)
sql_alloc
((
uint
)
size
);
}
static
void
operator
delete
(
void
*
ptr
,
size_t
size
)
{}
subselect_engine
(
THD
*
thd
,
Item_subselect
*
si
,
select_subselect
*
res
)
{
...
...
@@ -225,16 +213,19 @@ public:
item
=
si
;
this
->
thd
=
thd
;
res_type
=
STRING_RESULT
;
maybe_null
=
0
;
}
virtual
~
subselect_engine
()
{};
// to satisfy compiler
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
uint
cols
()
=
0
;
/* return number of columnss in select */
virtual
bool
depended
()
=
0
;
/* depended from outer select */
enum
Item_result
type
()
{
return
res_type
;
}
virtual
bool
check_loop
(
uint
id
)
=
0
;
virtual
void
exclude
()
=
0
;
bool
may_be_null
()
{
return
maybe_null
;
};
};
class
subselect_single_select_engine
:
public
subselect_engine
...
...
@@ -249,7 +240,7 @@ public:
select_subselect
*
result
,
Item_subselect
*
item
);
int
prepare
();
void
fix_length_and_dec
();
void
fix_length_and_dec
(
Item_cache
**
row
);
int
exec
();
uint
cols
();
bool
depended
();
...
...
@@ -266,7 +257,7 @@ public:
select_subselect
*
result
,
Item_subselect
*
item
);
int
prepare
();
void
fix_length_and_dec
();
void
fix_length_and_dec
(
Item_cache
**
row
);
int
exec
();
uint
cols
();
bool
depended
();
...
...
sql/sql_class.cc
View file @
2c6fca27
...
...
@@ -917,10 +917,10 @@ select_subselect::select_subselect(Item_subselect *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"
);
Item_single
val_subselect
*
it
=
(
Item_singleval
_subselect
*
)
item
;
DBUG_ENTER
(
"select_single
row
_subselect::send_data"
);
Item_single
row_subselect
*
it
=
(
Item_singlerow
_subselect
*
)
item
;
if
(
it
->
assigned
())
{
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)
DBUG_RETURN
(
0
);
}
List_iterator_fast
<
Item
>
li
(
items
);
Item
*
val_item
=
li
++
;
// Only one (single value subselect)
/*
Following val() call have to be first, because function AVG() & STD()
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
();
}
Item
*
val_item
;
for
(
uint
i
=
0
;
(
val_item
=
li
++
);
i
++
)
it
->
store
(
i
,
val_item
);
it
->
assigned
(
1
);
DBUG_RETURN
(
0
);
}
...
...
sql/sql_class.h
View file @
2c6fca27
...
...
@@ -825,10 +825,10 @@ public:
};
/* Single value subselect interface class */
class
select_single
val
_subselect
:
public
select_subselect
class
select_single
row
_subselect
:
public
select_subselect
{
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
);
};
...
...
sql/sql_yacc.yy
View file @
2c6fca27
...
...
@@ -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
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
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
%type <item_list>
...
...
@@ -2037,7 +2037,7 @@ simple_expr:
$$= new Item_row(*$5);
}
| EXISTS exists_subselect { $$= $2; }
| single
val
_subselect { $$= $1; }
| single
row
_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->add_ftfunc_to_list((Item_func_match *)
...
...
@@ -4509,17 +4509,17 @@ union_option:
/* empty */ {}
| ALL {Select->master_unit()->union_option= 1;};
single
val
_subselect:
subselect_start single
val
_subselect_init
single
row
_subselect:
subselect_start single
row
_subselect_init
subselect_end
{
$$= $2;
};
single
val
_subselect_init:
single
row
_subselect_init:
select_init2
{
$$= new Item_single
val
_subselect(YYTHD,
$$= new Item_single
row
_subselect(YYTHD,
Lex->current_select->master_unit()->
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