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
0c808b43
Commit
0c808b43
authored
Jun 19, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Plain Diff
merged
parents
f4f4962d
f974c735
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
235 additions
and
79 deletions
+235
-79
mysql-test/create-test-result
mysql-test/create-test-result
+1
-1
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+7
-0
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+2
-0
sql/item_subselect.cc
sql/item_subselect.cc
+85
-36
sql/item_subselect.h
sql/item_subselect.h
+70
-19
sql/sql_class.cc
sql/sql_class.cc
+29
-14
sql/sql_class.h
sql/sql_class.h
+20
-3
sql/sql_yacc.yy
sql/sql_yacc.yy
+21
-6
No files found.
mysql-test/create-test-result
View file @
0c808b43
...
...
@@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch
$result_file
echo
"Running the test case against empty file, will fail, but don't worry"
./mysql-test-run
--
do-test
=
$test_name
./mysql-test-run
--
local
$test_name
reject_file
=
$result_file
.reject
...
...
mysql-test/r/subselect.result
View file @
0c808b43
...
...
@@ -67,4 +67,11 @@ b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000
8 6.0000
9 5.5000
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
a
6
3
drop table t1,t2,t3,t4;
mysql-test/t/subselect.test
View file @
0c808b43
...
...
@@ -26,4 +26,6 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from
select
*
from
t1
where
t1
.
a
=
(
select
t2
.
a
from
t2
where
t2
.
b
=
(
select
max
(
a
)
from
t3
where
t3
.
a
>
t1
.
a
)
order
by
1
desc
limit
1
);
select
*
from
t1
where
t1
.
a
=
(
select
t2
.
a
from
t2
where
t2
.
b
=
(
select
max
(
a
)
from
t3
where
t3
.
a
<
t1
.
a
)
order
by
1
desc
limit
1
);
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
not
exists
(
select
*
from
t2
where
t2
.
b
=
t3
.
a
);
drop
table
t1
,
t2
,
t3
,
t4
;
sql/item_subselect.cc
View file @
0c808b43
...
...
@@ -35,12 +35,13 @@ SUBSELECT TODO:
#include "mysql_priv.h"
#include "sql_select.h"
Item_subselect
::
Item_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
)
:
Item_subselect
::
Item_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
)
:
assigned
(
0
),
executed
(
0
),
optimized
(
0
),
error
(
0
)
{
DBUG_ENTER
(
"Item_subselect::Item_subselect"
);
DBUG_PRINT
(
"subs"
,
(
"select_lex 0x%xl"
,
(
long
)
select_lex
));
result
=
new
select_subselect
(
this
)
;
this
->
result
=
result
;
SELECT_LEX_UNIT
*
unit
=
select_lex
->
master_unit
();
unit
->
offset_limit_cnt
=
unit
->
global_parameters
->
offset_limit
;
unit
->
select_limit_cnt
=
unit
->
global_parameters
->
select_limit
+
...
...
@@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
join
=
new
JOIN
(
thd
,
select_lex
->
item_list
,
select_lex
->
options
,
result
);
this
->
select_lex
=
select_lex
;
maybe_null
=
1
;
assign_null
()
;
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
*/
assign_null
()
;
null_value
=
1
;
DBUG_VOID_RETURN
;
}
Item
::
Type
Item_subselect
::
type
()
const
{
return
SUBSELECT_ITEM
;
}
double
Item_subselect
::
val
()
{
if
(
exec
())
return
0
;
return
real_value
;
}
longlong
Item_subselect
::
val_int
()
{
if
(
exec
())
return
0
;
return
int_value
;
}
String
*
Item_subselect
::
val_str
(
String
*
str
)
{
if
(
exec
()
||
null_value
)
return
0
;
return
&
str_value
;
}
void
Item_subselect
::
make_field
(
Send_field
*
tmp_field
)
{
if
(
null_value
)
...
...
@@ -108,9 +83,9 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
//TODO: subselects in having do not suported now
my_printf_error
(
ER_SYNTAX_ERROR
,
ER
(
ER_SYNTAX_ERROR
),
MYF
(
0
));
return
1
;
}
}
// Is it one field subselect?
if
(
select_lex
->
item_list
.
elements
!=
1
)
if
(
select_lex
->
item_list
.
elements
>
max_columns
)
{
my_printf_error
(
ER_SUBSELECT_NO_1_COL
,
ER
(
ER_SUBSELECT_NO_1_COL
),
MYF
(
0
));
return
1
;
...
...
@@ -131,13 +106,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
int
Item_subselect
::
exec
()
{
DBUG_ENTER
(
"Item_subselect::exec"
);
if
(
!
optimized
)
{
optimized
=
1
;
if
(
join
->
optimize
())
{
executed
=
1
;
return
(
join
->
error
?
join
->
error
:
1
);
DBUG_RETURN
(
join
->
error
?
join
->
error
:
1
);
}
}
if
(
join
->
select_lex
->
depended
&&
executed
)
...
...
@@ -145,7 +121,7 @@ int Item_subselect::exec()
if
(
join
->
reinit
())
{
error
=
1
;
return
1
;
DBUG_RETURN
(
1
)
;
}
assign_null
();
executed
=
assigned
=
0
;
...
...
@@ -157,7 +133,80 @@ int Item_subselect::exec()
join
->
exec
();
join
->
thd
->
lex
.
select
=
save_select
;
executed
=
1
;
return
join
->
error
;
DBUG_RETURN
(
join
->
error
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
inline
table_map
Item_subselect
::
used_tables
()
const
{
return
(
table_map
)
select_lex
->
depended
?
1L
:
0L
;
}
Item_singleval_subselect
::
Item_singleval_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
)
:
Item_subselect
(
thd
,
select_lex
,
new
select_singleval_subselect
(
this
))
{
max_columns
=
1
;
maybe_null
=
1
;
}
Item
::
Type
Item_subselect
::
type
()
const
{
return
SUBSELECT_ITEM
;
}
double
Item_singleval_subselect
::
val
()
{
if
(
exec
())
return
0
;
return
real_value
;
}
longlong
Item_singleval_subselect
::
val_int
()
{
if
(
exec
())
return
0
;
return
int_value
;
}
String
*
Item_singleval_subselect
::
val_str
(
String
*
str
)
{
if
(
exec
()
||
null_value
)
return
0
;
return
&
str_value
;
}
Item_exists_subselect
::
Item_exists_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
)
:
Item_subselect
(
thd
,
select_lex
,
new
select_singleval_subselect
(
this
))
{
max_columns
=
UINT_MAX
;
null_value
=
0
;
//can't be NULL
maybe_null
=
0
;
//can't be NULL
value
=
0
;
select_lex
->
select_limit
=
1
;
// we need only 1 row to determinate existence
}
double
Item_exists_subselect
::
val
()
{
if
(
exec
())
return
0
;
return
(
double
)
value
;
}
longlong
Item_exists_subselect
::
val_int
()
{
if
(
exec
())
return
0
;
return
value
;
}
String
*
Item_exists_subselect
::
val_str
(
String
*
str
)
{
if
(
exec
())
return
0
;
str
->
set
(
value
);
return
str
;
}
sql/item_subselect.h
View file @
0c808b43
...
...
@@ -24,42 +24,34 @@ struct st_select_lex;
class
JOIN
;
class
select_subselect
;
/*
simple (not depended of covered select ) subselect
*/
/*
base class for subselects
*/
class
Item_subselect
:
public
Item
{
protected:
longlong
int_value
;
double
real_value
;
uint
max_columns
;
my_bool
assigned
;
/* value already assigned to subselect */
my_bool
executed
;
/* simple subselect is executed */
my_bool
optimized
;
/* simple subselect is optimized */
my_bool
error
;
/* error in query */
enum
Item_result
res_type
;
int
exec
();
void
assign_null
()
v
irtual
v
oid
assign_null
()
{
null_value
=
1
;
int_value
=
0
;
real_value
=
0
;
max_length
=
4
;
res_type
=
STRING_RESULT
;
}
public:
st_select_lex
*
select_lex
;
JOIN
*
join
;
select_subselect
*
result
;
Item_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
);
Item_subselect
(
Item_subselect
*
item
)
{
null_value
=
item
->
null_value
;
int_value
=
item
->
int_value
;
real_value
=
item
->
real_value
;
max_length
=
item
->
max_length
;
decimals
=
item
->
decimals
;
res_type
=
item
->
res_type
;
max_columns
=
item
->
max_columns
;
assigned
=
item
->
assigned
;
executed
=
item
->
executed
;
select_lex
=
item
->
select_lex
;
...
...
@@ -69,16 +61,75 @@ public:
error
=
item
->
error
;
}
enum
Type
type
()
const
;
double
val
();
longlong
val_int
();
String
*
val_str
(
String
*
);
bool
is_null
()
{
return
null_value
;
}
void
make_field
(
Send_field
*
);
bool
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
);
Item
*
new_item
()
{
return
new
Item_subselect
(
this
);
}
enum
Item_result
result_type
()
const
{
return
res_type
;
}
table_map
used_tables
()
const
;
friend
class
select_subselect
;
};
/* single value subselect */
class
Item_singleval_subselect
:
public
Item_subselect
{
protected:
longlong
int_value
;
double
real_value
;
enum
Item_result
res_type
;
virtual
void
assign_null
()
{
null_value
=
1
;
int_value
=
0
;
real_value
=
0
;
max_length
=
4
;
res_type
=
STRING_RESULT
;
}
public:
Item_singleval_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_singleval_subselect
(
Item_singleval_subselect
*
item
)
:
Item_subselect
(
item
)
{
int_value
=
item
->
int_value
;
real_value
=
item
->
real_value
;
max_length
=
item
->
max_length
;
decimals
=
item
->
decimals
;
res_type
=
item
->
res_type
;
}
double
val
();
longlong
val_int
();
String
*
val_str
(
String
*
);
Item
*
new_item
()
{
return
new
Item_singleval_subselect
(
this
);
}
enum
Item_result
result_type
()
const
{
return
res_type
;
}
friend
class
select_singleval_subselect
;
};
/* exists subselect */
class
Item_exists_subselect
:
public
Item_subselect
{
protected:
longlong
value
;
virtual
void
assign_null
()
{
value
=
0
;
}
public:
Item_exists_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_exists_subselect
(
Item_exists_subselect
*
item
)
:
Item_subselect
(
item
)
{
value
=
item
->
value
;
}
Item
*
new_item
()
{
return
new
Item_exists_subselect
(
this
);
}
enum
Item_result
result_type
()
const
{
return
INT_RESULT
;}
longlong
val_int
();
double
val
();
String
*
val_str
(
String
*
);
friend
class
select_exists_subselect
;
};
sql/sql_class.cc
View file @
0c808b43
...
...
@@ -766,7 +766,6 @@ void select_dump::send_error(uint errcode,const char *err)
file
=
-
1
;
}
bool
select_dump
::
send_eof
()
{
int
error
=
test
(
end_io_cache
(
&
cache
));
...
...
@@ -785,10 +784,11 @@ select_subselect::select_subselect(Item_subselect *item)
this
->
item
=
item
;
}
bool
select_subselect
::
send_data
(
List
<
Item
>
&
items
)
bool
select_s
ingleval_s
ubselect
::
send_data
(
List
<
Item
>
&
items
)
{
DBUG_ENTER
(
"select_subselect::send_data"
);
if
(
item
->
assigned
){
DBUG_ENTER
(
"select_singleval_subselect::send_data"
);
Item_singleval_subselect
*
it
=
(
Item_singleval_subselect
*
)
item
;
if
(
it
->
assigned
){
my_printf_error
(
ER_SUBSELECT_NO_1_ROW
,
ER
(
ER_SUBSELECT_NO_1_ROW
),
MYF
(
0
));
DBUG_RETURN
(
1
);
}
...
...
@@ -803,18 +803,33 @@ bool select_subselect::send_data(List<Item> &items)
Following val() call have to be first, because function AVG() & STD()
calculate value on it & determinate "is it NULL?".
*/
it
em
->
real_value
=
val_item
->
val
();
if
((
it
em
->
null_value
=
val_item
->
is_null
()))
it
->
real_value
=
val_item
->
val
();
if
((
it
->
null_value
=
val_item
->
is_null
()))
{
it
em
->
assign_null
();
it
->
assign_null
();
}
else
{
it
em
->
max_length
=
val_item
->
max_length
;
it
em
->
decimals
=
val_item
->
decimals
;
it
em
->
binary
=
val_item
->
binary
;
val_item
->
val_str
(
&
it
em
->
str_value
);
it
em
->
int_value
=
val_item
->
val_int
();
it
em
->
res_type
=
val_item
->
result_type
();
it
->
max_length
=
val_item
->
max_length
;
it
->
decimals
=
val_item
->
decimals
;
it
->
binary
=
val_item
->
binary
;
val_item
->
val_str
(
&
it
->
str_value
);
it
->
int_value
=
val_item
->
val_int
();
it
->
res_type
=
val_item
->
result_type
();
}
it
em
->
assigned
=
1
;
it
->
assigned
=
1
;
DBUG_RETURN
(
0
);
}
bool
select_exists_subselect
::
send_data
(
List
<
Item
>
&
items
)
{
DBUG_ENTER
(
"select_exists_subselect::send_data"
);
Item_exists_subselect
*
it
=
(
Item_exists_subselect
*
)
item
;
if
(
unit
->
offset_limit_cnt
)
{
// Using limit offset,count
unit
->
offset_limit_cnt
--
;
DBUG_RETURN
(
0
);
}
it
->
value
=
1
;
it
->
assigned
=
1
;
DBUG_RETURN
(
0
);
}
sql/sql_class.h
View file @
0c808b43
...
...
@@ -742,19 +742,36 @@ class select_union :public select_result {
bool
flush
();
};
/*
Single valu
e subselect interface class */
/*
Bas
e subselect interface class */
class
select_subselect
:
public
select_result
{
protected:
Item_subselect
*
item
;
public:
select_subselect
(
Item_subselect
*
item
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
};
bool
send_data
(
List
<
Item
>
&
items
);
bool
send_data
(
List
<
Item
>
&
items
)
=
0
;
bool
send_eof
()
{
return
0
;
};
friend
class
Ttem_subselect
;
};
/* Single value subselect interface class */
class
select_singleval_subselect
:
public
select_subselect
{
public:
select_singleval_subselect
(
Item_subselect
*
item
)
:
select_subselect
(
item
){}
bool
send_data
(
List
<
Item
>
&
items
);
};
/* EXISTS subselect interface class */
class
select_exists_subselect
:
public
select_subselect
{
public:
select_exists_subselect
(
Item_subselect
*
item
)
:
select_subselect
(
item
){}
bool
send_data
(
List
<
Item
>
&
items
);
};
/* Structs used when sorting */
typedef
struct
st_sort_field
{
...
...
sql/sql_yacc.yy
View file @
0c808b43
...
...
@@ -554,7 +554,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident
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 param_marker subselect subselect_init
using_list param_marker singleval_subselect singleval_subselect_init
exists_subselect exists_subselect_init
%type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg
...
...
@@ -1745,7 +1746,8 @@ simple_expr:
| NOT expr %prec NEG { $$= new Item_func_not($2); }
| '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; }
| subselect { $$= $1; }
| EXISTS exists_subselect { $$= $2; }
| singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->ftfunc_list.push_back((Item_func_match *)
...
...
@@ -3973,17 +3975,30 @@ union_option:
/* empty */ {}
| ALL {Lex->union_option=1;};
subselect:
subselect_start subselect_init
s
ingleval_s
ubselect:
subselect_start s
ingleval_s
ubselect_init
subselect_end
{
$$= $2;
};
subselect_init:
s
ingleval_s
ubselect_init:
select_init
{
$$= new Item_subselect(current_thd, Lex->select);
$$= new Item_singleval_subselect(current_thd, Lex->select);
};
exists_subselect:
subselect_start exists_subselect_init
subselect_end
{
$$= $2;
};
exists_subselect_init:
select_init
{
$$= new Item_exists_subselect(current_thd, Lex->select);
};
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