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
07727576
Commit
07727576
authored
Oct 27, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
IN subselect
parent
8ec9edac
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
232 additions
and
13 deletions
+232
-13
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+11
-0
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+6
-0
sql/item.cc
sql/item.cc
+47
-0
sql/item.h
sql/item.h
+49
-0
sql/item_subselect.cc
sql/item_subselect.cc
+68
-6
sql/item_subselect.h
sql/item_subselect.h
+18
-3
sql/sql_yacc.yy
sql/sql_yacc.yy
+33
-4
No files found.
mysql-test/r/subselect.result
View file @
07727576
...
@@ -96,6 +96,17 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a);
...
@@ -96,6 +96,17 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a);
a
a
6
6
3
3
select * from t3 where a in (select b from t2);
a
7
select * from t3 where a not in (select b from t2);
a
6
3
select * from t3 where a in (select a,b from t2);
Subselect returns more than 1 field
select * from t3 where a in (select * from t2);
Subselect returns more than 1 field
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b);
from t2 where t2.b=t4.b);
...
...
mysql-test/t/subselect.test
View file @
07727576
...
@@ -34,6 +34,12 @@ select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2
...
@@ -34,6 +34,12 @@ select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2
explain
select
b
,(
select
avg
(
t2
.
a
+
(
select
min
(
t3
.
a
)
from
t3
where
t3
.
a
>=
t4
.
a
))
from
t2
)
from
t4
;
explain
select
b
,(
select
avg
(
t2
.
a
+
(
select
min
(
t3
.
a
)
from
t3
where
t3
.
a
>=
t4
.
a
))
from
t2
)
from
t4
;
select
*
from
t3
where
exists
(
select
*
from
t2
where
t2
.
b
=
t3
.
a
);
select
*
from
t3
where
exists
(
select
*
from
t2
where
t2
.
b
=
t3
.
a
);
select
*
from
t3
where
not
exists
(
select
*
from
t2
where
t2
.
b
=
t3
.
a
);
select
*
from
t3
where
not
exists
(
select
*
from
t2
where
t2
.
b
=
t3
.
a
);
select
*
from
t3
where
a
in
(
select
b
from
t2
);
select
*
from
t3
where
a
not
in
(
select
b
from
t2
);
--
error
1239
select
*
from
t3
where
a
in
(
select
a
,
b
from
t2
);
--
error
1239
select
*
from
t3
where
a
in
(
select
*
from
t2
);
insert
into
t4
values
(
12
,
7
),(
1
,
7
),(
10
,
9
),(
9
,
6
),(
7
,
6
),(
3
,
9
);
insert
into
t4
values
(
12
,
7
),(
1
,
7
),(
10
,
9
),(
9
,
6
),(
7
,
6
),(
3
,
9
);
select
b
,
max
(
a
)
as
ma
from
t4
group
by
b
having
b
<
(
select
max
(
t2
.
a
)
select
b
,
max
(
a
)
as
ma
from
t4
group
by
b
having
b
<
(
select
max
(
t2
.
a
)
from
t2
where
t2
.
b
=
t4
.
b
);
from
t2
where
t2
.
b
=
t4
.
b
);
...
...
sql/item.cc
View file @
07727576
...
@@ -424,6 +424,53 @@ bool Item::fix_fields(THD *thd,
...
@@ -424,6 +424,53 @@ 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
,
struct
st_table_list
*
list
,
Item
**
ref
)
{
DBUG_ENTER
(
"Item_asterisk_remover::fix_fields"
);
bool
res
;
if
(
item
)
if
(
item
->
type
()
==
Item
::
FIELD_ITEM
&&
((
Item_field
*
)
item
)
->
field_name
[
0
]
==
'*'
)
{
List
<
Item
>
fields
;
fields
.
push_back
(
item
);
List_iterator
<
Item
>
it
(
fields
);
it
++
;
uint
elem
=
fields
.
elements
;
if
(
insert_fields
(
thd
,
list
,
((
Item_field
*
)
item
)
->
db_name
,
((
Item_field
*
)
item
)
->
table_name
,
&
it
))
res
=
-
1
;
else
if
(
fields
.
elements
>
1
)
{
my_message
(
ER_SUBSELECT_NO_1_COL
,
ER
(
ER_SUBSELECT_NO_1_COL
),
MYF
(
0
));
res
=
-
1
;
}
}
else
res
=
item
->
fix_fields
(
thd
,
list
,
&
item
);
else
res
=
-
1
;
*
ref
=
item
;
DBUG_RETURN
(
res
);
}
bool
Item_field
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
bool
Item_field
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
{
{
if
(
!
field
)
// If field is not checked
if
(
!
field
)
// If field is not checked
...
...
sql/item.h
View file @
07727576
...
@@ -90,6 +90,55 @@ public:
...
@@ -90,6 +90,55 @@ public:
};
};
/*
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
();
}
double
val
()
{
return
item
->
val
();
}
longlong
val_int
()
{
return
item
->
val_int
();
}
String
*
val_str
(
String
*
s
)
{
return
item
->
val_str
(
s
);
}
void
make_field
(
Send_field
*
f
)
{
item
->
make_field
(
f
);
}
};
/*
Save context of name resolution for Item, used in subselect transformer.
*/
class
Item_outer_select_context_saver
:
public
Item_wrapper
{
Item
*
item
;
public:
Item_outer_select_context_saver
(
Item
*
i
)
:
item
(
i
)
{
}
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
ref
);
};
/*
To resolve '*' field moved to condition
*/
class
Item_asterisk_remover
:
public
Item_wrapper
{
Item
*
item
;
public:
Item_asterisk_remover
(
Item
*
i
)
:
item
(
i
)
{
}
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
{
{
...
...
sql/item_subselect.cc
View file @
07727576
...
@@ -44,12 +44,13 @@ Item_subselect::Item_subselect():
...
@@ -44,12 +44,13 @@ Item_subselect::Item_subselect():
}
}
void
Item_subselect
::
init
(
THD
*
thd
,
st_select_lex
*
select_lex
,
void
Item_subselect
::
init
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
)
select_subselect
*
result
,
Item
*
left_expr
)
{
{
DBUG_ENTER
(
"Item_subselect::init"
);
DBUG_ENTER
(
"Item_subselect::init"
);
DBUG_PRINT
(
"subs"
,
(
"select_lex 0x%xl"
,
(
long
)
select_lex
));
DBUG_PRINT
(
"subs"
,
(
"select_lex 0x%xl"
,
(
u
long
)
select_lex
));
select_transformer
(
select_lex
,
left_expr
);
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
);
...
@@ -65,6 +66,14 @@ Item_subselect::~Item_subselect()
...
@@ -65,6 +66,14 @@ Item_subselect::~Item_subselect()
delete
engine
;
delete
engine
;
}
}
void
Item_subselect
::
select_transformer
(
st_select_lex
*
select_lex
,
Item
*
left_expr
)
{
DBUG_ENTER
(
"Item_subselect::select_transformer"
);
DBUG_VOID_RETURN
;
}
void
Item_subselect
::
make_field
(
Send_field
*
tmp_field
)
void
Item_subselect
::
make_field
(
Send_field
*
tmp_field
)
{
{
if
(
null_value
)
if
(
null_value
)
...
@@ -109,9 +118,11 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd,
...
@@ -109,9 +118,11 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex
*
select_lex
)
:
st_select_lex
*
select_lex
)
:
Item_subselect
()
Item_subselect
()
{
{
init
(
thd
,
select_lex
,
new
select_singleval_subselect
(
this
));
DBUG_ENTER
(
"Item_singleval_subselect::Item_singleval_subselect"
);
init
(
thd
,
select_lex
,
new
select_singleval_subselect
(
this
),
0
);
max_columns
=
1
;
max_columns
=
1
;
maybe_null
=
1
;
maybe_null
=
1
;
DBUG_VOID_RETURN
;
}
}
void
Item_singleval_subselect
::
fix_length_and_dec
()
void
Item_singleval_subselect
::
fix_length_and_dec
()
...
@@ -156,17 +167,37 @@ String *Item_singleval_subselect::val_str (String *str)
...
@@ -156,17 +167,37 @@ String *Item_singleval_subselect::val_str (String *str)
}
}
Item_exists_subselect
::
Item_exists_subselect
(
THD
*
thd
,
Item_exists_subselect
::
Item_exists_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
)
:
st_select_lex
*
select_lex
,
Item
*
left_expr
)
:
Item_subselect
()
Item_subselect
()
{
{
init
(
thd
,
select_lex
,
new
select_exists_subselect
(
this
));
DBUG_ENTER
(
"Item_exists_subselect::Item_exists_subselect"
);
init
(
thd
,
select_lex
,
new
select_exists_subselect
(
this
),
left_expr
);
max_columns
=
UINT_MAX
;
max_columns
=
UINT_MAX
;
null_value
=
0
;
//can't be NULL
null_value
=
0
;
//can't be NULL
maybe_null
=
0
;
//can't be NULL
maybe_null
=
0
;
//can't be NULL
value
=
0
;
value
=
0
;
select_lex
->
select_limit
=
1
;
// 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
;
DBUG_VOID_RETURN
;
}
}
Item_in_subselect
::
Item_in_subselect
(
THD
*
thd
,
Item
*
left_expr
,
st_select_lex
*
select_lex
)
:
Item_exists_subselect
()
{
DBUG_ENTER
(
"Item_in_subselect::Item_in_subselect"
);
init
(
thd
,
select_lex
,
new
select_exists_subselect
(
this
),
left_expr
);
max_columns
=
UINT_MAX
;
null_value
=
0
;
//can't be NULL
maybe_null
=
0
;
//can't be NULL
value
=
0
;
// We need only 1 row to determinate existence
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
=
1
;
DBUG_VOID_RETURN
;
}
void
Item_exists_subselect
::
fix_length_and_dec
()
void
Item_exists_subselect
::
fix_length_and_dec
()
{
{
max_length
=
1
;
max_length
=
1
;
...
@@ -204,6 +235,37 @@ String *Item_exists_subselect::val_str(String *str)
...
@@ -204,6 +235,37 @@ String *Item_exists_subselect::val_str(String *str)
return
str
;
return
str
;
}
}
Item_in_subselect
::
Item_in_subselect
(
Item_in_subselect
*
item
)
:
Item_exists_subselect
(
item
)
{
}
void
Item_in_subselect
::
select_transformer
(
st_select_lex
*
select_lex
,
Item
*
left_expr
)
{
DBUG_ENTER
(
"Item_in_subselect::select_transformer"
);
for
(
SELECT_LEX
*
sl
=
select_lex
;
sl
;
sl
=
sl
->
next_select
())
{
Item
*
item
;
if
(
sl
->
item_list
.
elements
>
1
)
{
my_message
(
ER_SUBSELECT_NO_1_COL
,
ER
(
ER_SUBSELECT_NO_1_COL
),
MYF
(
0
));
item
=
0
;
// Item_asterisk_remover mast fail
}
else
item
=
(
Item
*
)
sl
->
item_list
.
pop
();
sl
->
item_list
.
empty
();
sl
->
item_list
.
push_back
(
new
Item_int
(
1
));
left_expr
=
new
Item_outer_select_context_saver
(
left_expr
);
item
=
new
Item_asterisk_remover
(
item
);
if
(
sl
->
where
)
sl
->
where
=
new
Item_cond_and
(
sl
->
where
,
new
Item_func_eq
(
item
,
left_expr
));
else
sl
->
where
=
new
Item_func_eq
(
item
,
left_expr
);
}
DBUG_VOID_RETURN
;
}
subselect_single_select_engine
::
subselect_single_select_engine
(
THD
*
thd
,
subselect_single_select_engine
::
subselect_single_select_engine
(
THD
*
thd
,
st_select_lex
*
select
,
st_select_lex
*
select
,
...
...
sql/item_subselect.h
View file @
07727576
...
@@ -55,13 +55,16 @@ public:
...
@@ -55,13 +55,16 @@ public:
pointer in constructor initialization list, but we need pass pointer
pointer in constructor initialization list, but we need pass pointer
to subselect Item class to select_subselect classes constructor.
to subselect Item class to select_subselect classes constructor.
*/
*/
void
init
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
);
virtual
void
init
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
,
Item
*
left_expr
=
0
);
~
Item_subselect
();
~
Item_subselect
();
virtual
void
assign_null
()
virtual
void
assign_null
()
{
{
null_value
=
1
;
null_value
=
1
;
}
}
virtual
void
select_transformer
(
st_select_lex
*
select_lex
,
Item
*
left_expr
);
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
;
...
@@ -74,7 +77,6 @@ public:
...
@@ -74,7 +77,6 @@ public:
friend
class
select_subselect
;
friend
class
select_subselect
;
};
};
/* single value subselect */
/* single value subselect */
class
Item_singleval_subselect
:
public
Item_subselect
class
Item_singleval_subselect
:
public
Item_subselect
...
@@ -127,12 +129,15 @@ protected:
...
@@ -127,12 +129,15 @@ protected:
longlong
value
;
/* value of this item (boolean: exists/not-exists) */
longlong
value
;
/* value of this item (boolean: exists/not-exists) */
public:
public:
Item_exists_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_exists_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
Item
*
left_expr
=
0
);
Item_exists_subselect
(
Item_exists_subselect
*
item
)
:
Item_exists_subselect
(
Item_exists_subselect
*
item
)
:
Item_subselect
(
item
)
Item_subselect
(
item
)
{
{
value
=
item
->
value
;
value
=
item
->
value
;
}
}
Item_exists_subselect
()
:
Item_subselect
()
{}
virtual
void
assign_null
()
virtual
void
assign_null
()
{
{
value
=
0
;
value
=
0
;
...
@@ -147,6 +152,16 @@ public:
...
@@ -147,6 +152,16 @@ public:
friend
class
select_exists_subselect
;
friend
class
select_exists_subselect
;
};
};
/* IN subselect */
class
Item_in_subselect
:
public
Item_exists_subselect
{
public:
Item_in_subselect
(
THD
*
thd
,
Item
*
left_expr
,
st_select_lex
*
select_lex
);
Item_in_subselect
(
Item_in_subselect
*
item
);
virtual
void
select_transformer
(
st_select_lex
*
select_lex
,
Item
*
left_exp
);
};
class
subselect_engine
class
subselect_engine
{
{
protected:
protected:
...
...
sql/sql_yacc.yy
View file @
07727576
...
@@ -70,6 +70,7 @@ inline Item *or_or_concat(Item* A, Item* B)
...
@@ -70,6 +70,7 @@ inline Item *or_or_concat(Item* A, Item* B)
enum Item_udftype udf_type;
enum Item_udftype udf_type;
CHARSET_INFO *charset;
CHARSET_INFO *charset;
interval_type interval;
interval_type interval;
st_select_lex *select_lex;
}
}
%{
%{
...
@@ -528,7 +529,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
...
@@ -528,7 +529,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_str>
%type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET
ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET
%type <lex_str_ptr>
%type <lex_str_ptr>
opt_table_alias
opt_table_alias
...
@@ -610,6 +612,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
...
@@ -610,6 +612,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <variable> internal_variable_name
%type <variable> internal_variable_name
%type <select_lex> in_subselect in_subselect_init
%type <NONE>
%type <NONE>
query verb_clause create change select do drop insert replace insert2
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
insert_values update delete truncate rename
...
@@ -1706,10 +1710,16 @@ expr: expr_expr { $$= $1; }
...
@@ -1706,10 +1710,16 @@ expr: expr_expr { $$= $1; }
/* expressions that begin with 'expr' */
/* expressions that begin with 'expr' */
expr_expr:
expr_expr:
expr IN_SYM '(' expr_list ')'
expr IN_SYM '(' expr_list ')'
{ $$= new Item_func_in($1,*$4); }
{ $$= new Item_func_in($1,*$4); }
| expr NOT IN_SYM '(' expr_list ')'
| expr NOT IN_SYM '(' expr_list ')'
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
| expr IN_SYM in_subselect
{ $$= new Item_in_subselect(current_thd, $1, $3); }
| expr NOT IN_SYM in_subselect
{
$$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4));
}
| expr BETWEEN_SYM no_and_expr AND expr
| expr BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_between($1,$3,$5); }
{ $$= new Item_func_between($1,$3,$5); }
| expr NOT BETWEEN_SYM no_and_expr AND expr
| expr NOT BETWEEN_SYM no_and_expr AND expr
...
@@ -1789,10 +1799,16 @@ no_in_expr:
...
@@ -1789,10 +1799,16 @@ no_in_expr:
/* expressions that begin with 'expr' that does NOT follow AND */
/* expressions that begin with 'expr' that does NOT follow AND */
no_and_expr:
no_and_expr:
no_and_expr IN_SYM '(' expr_list ')'
no_and_expr IN_SYM '(' expr_list ')'
{ $$= new Item_func_in($1,*$4); }
{ $$= new Item_func_in($1,*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
| no_and_expr NOT IN_SYM '(' expr_list ')'
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
| no_and_expr IN_SYM in_subselect
{ $$= new Item_in_subselect(current_thd, $1, $3); }
| no_and_expr NOT IN_SYM in_subselect
{
$$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4));
}
| no_and_expr BETWEEN_SYM no_and_expr AND expr
| no_and_expr BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_between($1,$3,$5); }
{ $$= new Item_func_between($1,$3,$5); }
| no_and_expr NOT BETWEEN_SYM no_and_expr AND expr
| no_and_expr NOT BETWEEN_SYM no_and_expr AND expr
...
@@ -4180,6 +4196,19 @@ exists_subselect_init:
...
@@ -4180,6 +4196,19 @@ exists_subselect_init:
Lex->select->master_unit()->first_select());
Lex->select->master_unit()->first_select());
};
};
in_subselect:
subselect_start in_subselect_init
subselect_end
{
$$= $2;
};
in_subselect_init:
select_init
{
$$= Lex->select->master_unit()->first_select();
};
subselect_start:
subselect_start:
'('
'('
{
{
...
...
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