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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
6ac8e9b9
Commit
6ac8e9b9
authored
Aug 12, 2003
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
optimisation of independent ALL/ANY with aggregate function (WL#1115) (SCRUM)
parent
c06786fa
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
184 additions
and
30 deletions
+184
-30
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+9
-0
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+6
-0
sql/item_subselect.cc
sql/item_subselect.cc
+54
-30
sql/item_subselect.h
sql/item_subselect.h
+10
-0
sql/sql_class.cc
sql/sql_class.cc
+89
-0
sql/sql_class.h
sql/sql_class.h
+16
-0
No files found.
mysql-test/r/subselect.result
View file @
6ac8e9b9
...
...
@@ -1347,4 +1347,13 @@ explain select * from t3 where a >= all (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
6
7
explain select * from t3 where a > all (select max(b) from t2 group by a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
drop table if exists t2, t3;
mysql-test/t/subselect.test
View file @
6ac8e9b9
...
...
@@ -877,6 +877,7 @@ insert into t1 values (1);
insert
into
t2
values
(
1
);
select
*
from
t1
where
exists
(
select
s1
from
t2
having
max
(
t2
.
s1
)
=
t1
.
s1
);
drop
table
t1
,
t2
;
#
# update subquery with wrong field (to force name resolving
# in UPDATE name space)
...
...
@@ -897,4 +898,9 @@ create table t3 (a int);
insert
into
t3
values
(
6
),(
7
),(
3
);
select
*
from
t3
where
a
>=
all
(
select
b
from
t2
);
explain
select
*
from
t3
where
a
>=
all
(
select
b
from
t2
);
# optimized static ALL/ANY with grouping
insert
into
t2
values
(
2
,
2
),
(
2
,
1
),
(
3
,
3
),
(
3
,
1
);
select
*
from
t3
where
a
>
all
(
select
max
(
b
)
from
t2
group
by
a
);
explain
select
*
from
t3
where
a
>
all
(
select
max
(
b
)
from
t2
group
by
a
);
drop
table
if
exists
t2
,
t3
;
sql/item_subselect.cc
View file @
6ac8e9b9
...
...
@@ -152,8 +152,8 @@ inline table_map Item_subselect::used_tables() const
}
Item_singlerow_subselect
::
Item_singlerow_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
)
:
Item_subselect
(),
value
(
0
)
st_select_lex
*
select_lex
)
:
Item_subselect
(),
value
(
0
)
{
DBUG_ENTER
(
"Item_singlerow_subselect::Item_singlerow_subselect"
);
init
(
thd
,
select_lex
,
new
select_singlerow_subselect
(
this
));
...
...
@@ -163,6 +163,19 @@ Item_singlerow_subselect::Item_singlerow_subselect(THD *thd,
DBUG_VOID_RETURN
;
}
Item_maxmin_subselect
::
Item_maxmin_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
bool
max
)
:
Item_singlerow_subselect
()
{
DBUG_ENTER
(
"Item_maxmin_subselect::Item_maxmin_subselect"
);
init
(
thd
,
select_lex
,
new
select_max_min_finder_subselect
(
this
,
max
));
max_columns
=
1
;
maybe_null
=
1
;
max_columns
=
1
;
DBUG_VOID_RETURN
;
}
void
Item_singlerow_subselect
::
reset
()
{
null_value
=
1
;
...
...
@@ -499,38 +512,50 @@ Item_in_subselect::single_value_transformer(JOIN *join,
(
func
==
&
Item_bool_func2
::
gt_creator
||
func
==
&
Item_bool_func2
::
lt_creator
||
func
==
&
Item_bool_func2
::
ge_creator
||
func
==
&
Item_bool_func2
::
le_creator
)
&&
!
select_lex
->
group_list
.
elements
&&
!
select_lex
->
with_sum_func
)
func
==
&
Item_bool_func2
::
le_creator
))
{
Item
*
item
;
subs_type
type
=
substype
();
if
(
func
==
&
Item_bool_func2
::
le_creator
||
func
==
&
Item_bool_func2
::
lt_creator
)
Item
*
subs
;
if
(
!
select_lex
->
group_list
.
elements
&&
!
select_lex
->
with_sum_func
)
{
/*
(ALL && (> || =>)) || (ANY && (< || =<))
for ALL condition is inverted
*/
item
=
new
Item_sum_max
(
*
select_lex
->
ref_pointer_array
);
Item
*
item
;
subs_type
type
=
substype
();
if
(
func
==
&
Item_bool_func2
::
le_creator
||
func
==
&
Item_bool_func2
::
lt_creator
)
{
/*
(ALL && (> || =>)) || (ANY && (< || =<))
for ALL condition is inverted
*/
item
=
new
Item_sum_max
(
*
select_lex
->
ref_pointer_array
);
}
else
{
/*
(ALL && (< || =<)) || (ANY && (> || =>))
for ALL condition is inverted
*/
item
=
new
Item_sum_min
(
*
select_lex
->
ref_pointer_array
);
}
*
select_lex
->
ref_pointer_array
=
item
;
select_lex
->
item_list
.
empty
();
select_lex
->
item_list
.
push_back
(
item
);
if
(
item
->
fix_fields
(
thd
,
join
->
tables_list
,
&
item
))
{
DBUG_RETURN
(
ERROR
);
}
subs
=
new
Item_singlerow_subselect
(
thd
,
select_lex
);
}
else
{
/*
(ALL && (< || =<)) || (ANY && (> || =>))
for ALL condition is inverted
*/
item
=
new
Item_sum_min
(
*
select_lex
->
ref_pointer_array
);
}
*
select_lex
->
ref_pointer_array
=
item
;
select_lex
->
item_list
.
empty
();
select_lex
->
item_list
.
push_back
(
item
);
if
(
item
->
fix_fields
(
thd
,
join
->
tables_list
,
&
item
))
{
DBUG_RETURN
(
ERROR
);
// remove LIMIT placed by ALL/ANY subquery
select_lex
->
master_unit
()
->
global_parameters
->
select_limit
=
HA_POS_ERROR
;
subs
=
new
Item_maxmin_subselect
(
thd
,
select_lex
,
(
func
==
&
Item_bool_func2
::
le_creator
||
func
==
&
Item_bool_func2
::
lt_creator
));
}
// left expression belong to outer select
SELECT_LEX
*
current
=
thd
->
lex
.
current_select
,
*
up
;
thd
->
lex
.
current_select
=
up
=
current
->
return_after_parsing
();
...
...
@@ -540,8 +565,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
DBUG_RETURN
(
ERROR
);
}
thd
->
lex
.
current_select
=
current
;
substitution
=
(
*
func
)(
left_expr
,
new
Item_singlerow_subselect
(
thd
,
select_lex
));
substitution
=
(
*
func
)(
left_expr
,
subs
);
DBUG_RETURN
(
OK
);
}
...
...
sql/item_subselect.h
View file @
6ac8e9b9
...
...
@@ -130,6 +130,7 @@ class Item_singlerow_subselect :public Item_subselect
max_length
=
item
->
max_length
;
decimals
=
item
->
decimals
;
}
Item_singlerow_subselect
()
:
Item_subselect
(),
value
(
0
),
row
(
0
)
{}
subs_type
substype
()
{
return
SINGLEROW_SUBS
;
}
...
...
@@ -153,6 +154,15 @@ class Item_singlerow_subselect :public Item_subselect
friend
class
select_singlerow_subselect
;
};
/* used in static ALL/ANY optimisation */
class
Item_maxmin_subselect
:
public
Item_singlerow_subselect
{
public:
Item_maxmin_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
bool
max
);
Item_maxmin_subselect
(
Item_maxmin_subselect
*
item
)
:
Item_singlerow_subselect
(
item
)
{}
};
/* exists subselect */
class
Item_exists_subselect
:
public
Item_subselect
...
...
sql/sql_class.cc
View file @
6ac8e9b9
...
...
@@ -986,6 +986,95 @@ bool select_singlerow_subselect::send_data(List<Item> &items)
DBUG_RETURN
(
0
);
}
bool
select_max_min_finder_subselect
::
send_data
(
List
<
Item
>
&
items
)
{
DBUG_ENTER
(
"select_max_min_finder_subselect::send_data"
);
Item_singlerow_subselect
*
it
=
(
Item_singlerow_subselect
*
)
item
;
List_iterator_fast
<
Item
>
li
(
items
);
Item
*
val_item
=
li
++
;
if
(
it
->
assigned
())
{
cache
->
store
(
val_item
);
if
((
this
->*
op
)())
it
->
store
(
0
,
cache
);
}
else
{
if
(
!
cache
)
{
cache
=
Item_cache
::
get_cache
(
val_item
->
result_type
());
switch
(
val_item
->
result_type
())
{
case
REAL_RESULT
:
op
=
&
select_max_min_finder_subselect
::
cmp_real
;
break
;
case
INT_RESULT
:
op
=
&
select_max_min_finder_subselect
::
cmp_int
;
break
;
case
STRING_RESULT
:
op
=
&
select_max_min_finder_subselect
::
cmp_str
;
break
;
case
ROW_RESULT
:
// This case should never be choosen
DBUG_ASSERT
(
0
);
op
=
0
;
}
}
cache
->
store
(
val_item
);
it
->
store
(
0
,
cache
);
}
it
->
assigned
(
1
);
DBUG_RETURN
(
0
);
}
bool
select_max_min_finder_subselect
::
cmp_real
()
{
Item
*
maxmin
=
((
Item_singlerow_subselect
*
)
item
)
->
el
(
0
);
double
val1
=
cache
->
val
(),
val2
=
maxmin
->
val
();
if
(
fmax
)
return
(
cache
->
null_value
&&
!
maxmin
->
null_value
)
||
(
!
cache
->
null_value
&&
!
maxmin
->
null_value
&&
val1
>
val2
);
else
return
(
maxmin
->
null_value
&&
!
cache
->
null_value
)
||
(
!
cache
->
null_value
&&
!
maxmin
->
null_value
&&
val1
<
val2
);
}
bool
select_max_min_finder_subselect
::
cmp_int
()
{
Item
*
maxmin
=
((
Item_singlerow_subselect
*
)
item
)
->
el
(
0
);
longlong
val1
=
cache
->
val_int
(),
val2
=
maxmin
->
val_int
();
if
(
fmax
)
return
(
cache
->
null_value
&&
!
maxmin
->
null_value
)
||
(
!
cache
->
null_value
&&
!
maxmin
->
null_value
&&
val1
>
val2
);
else
return
(
maxmin
->
null_value
&&
!
cache
->
null_value
)
||
(
!
cache
->
null_value
&&
!
maxmin
->
null_value
&&
val1
<
val2
);
}
bool
select_max_min_finder_subselect
::
cmp_str
()
{
String
*
val1
,
*
val2
,
buf1
,
buf2
;
Item
*
maxmin
=
((
Item_singlerow_subselect
*
)
item
)
->
el
(
0
);
/*
as far as both operand is Item_cache buf1 & buf2 will not be used,
but added for safety
*/
val1
=
cache
->
val_str
(
&
buf1
);
val2
=
maxmin
->
val_str
(
&
buf1
);
if
(
fmax
)
return
(
cache
->
null_value
&&
!
maxmin
->
null_value
)
||
(
!
cache
->
null_value
&&
!
maxmin
->
null_value
&&
sortcmp
(
val1
,
val2
,
cache
->
collation
.
collation
)
>
0
)
;
else
return
(
maxmin
->
null_value
&&
!
cache
->
null_value
)
||
(
!
cache
->
null_value
&&
!
maxmin
->
null_value
&&
sortcmp
(
val1
,
val2
,
cache
->
collation
.
collation
)
<
0
);
}
bool
select_exists_subselect
::
send_data
(
List
<
Item
>
&
items
)
{
DBUG_ENTER
(
"select_exists_subselect::send_data"
);
...
...
sql/sql_class.h
View file @
6ac8e9b9
...
...
@@ -920,6 +920,22 @@ class select_singlerow_subselect :public select_subselect
bool
send_data
(
List
<
Item
>
&
items
);
};
/* used in independent ALL/ANY optimisation */
class
select_max_min_finder_subselect
:
public
select_subselect
{
Item_cache
*
cache
;
bool
(
select_max_min_finder_subselect
::*
op
)();
bool
fmax
;
public:
select_max_min_finder_subselect
(
Item_subselect
*
item
,
bool
mx
)
:
select_subselect
(
item
),
cache
(
0
),
fmax
(
mx
)
{}
bool
send_data
(
List
<
Item
>
&
items
);
bool
cmp_real
();
bool
cmp_int
();
bool
cmp_str
();
};
/* EXISTS subselect interface class */
class
select_exists_subselect
:
public
select_subselect
{
...
...
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