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
f6899b07
Commit
f6899b07
authored
Oct 13, 2005
by
konstantin@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/opt/local/work/mysql-5.0-12736
parents
93d8c03d
b2ff3820
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
151 additions
and
14 deletions
+151
-14
mysql-test/r/subselect_innodb.result
mysql-test/r/subselect_innodb.result
+20
-0
mysql-test/t/subselect_innodb.test
mysql-test/t/subselect_innodb.test
+22
-0
sql/item_subselect.cc
sql/item_subselect.cc
+6
-0
sql/item_subselect.h
sql/item_subselect.h
+16
-0
sql/sql_lex.h
sql/sql_lex.h
+6
-1
sql/sql_select.cc
sql/sql_select.cc
+66
-12
sql/sql_select.h
sql/sql_select.h
+1
-1
sql/sql_union.cc
sql/sql_union.cc
+14
-0
No files found.
mysql-test/r/subselect_innodb.result
View file @
f6899b07
...
...
@@ -152,3 +152,23 @@ EXECUTE my_stmt;
b count(*)
deallocate prepare my_stmt;
drop table t1,t2;
CREATE TABLE t1 (
school_name varchar(45) NOT NULL,
country varchar(45) NOT NULL,
funds_requested float NOT NULL,
schooltype varchar(45) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into t1 values ("the school", "USA", 1200, "Human");
select count(country) as countrycount, sum(funds_requested) as smcnt,
country, (select sum(funds_requested) from t1) as total_funds
from t1
group by country;
countrycount smcnt country total_funds
1 1200 USA 1200
select count(country) as countrycount, sum(funds_requested) as smcnt,
country, (select sum(funds_requested) from t1) as total_funds
from t1
group by country;
countrycount smcnt country total_funds
1 1200 USA 1200
drop table t1;
mysql-test/t/subselect_innodb.test
View file @
f6899b07
...
...
@@ -161,3 +161,25 @@ deallocate prepare my_stmt;
drop
table
t1
,
t2
;
# End of 4.1 tests
CREATE
TABLE
t1
(
school_name
varchar
(
45
)
NOT
NULL
,
country
varchar
(
45
)
NOT
NULL
,
funds_requested
float
NOT
NULL
,
schooltype
varchar
(
45
)
NOT
NULL
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8
;
insert
into
t1
values
(
"the school"
,
"USA"
,
1200
,
"Human"
);
select
count
(
country
)
as
countrycount
,
sum
(
funds_requested
)
as
smcnt
,
country
,
(
select
sum
(
funds_requested
)
from
t1
)
as
total_funds
from
t1
group
by
country
;
select
count
(
country
)
as
countrycount
,
sum
(
funds_requested
)
as
smcnt
,
country
,
(
select
sum
(
funds_requested
)
from
t1
)
as
total_funds
from
t1
group
by
country
;
drop
table
t1
;
sql/item_subselect.cc
View file @
f6899b07
...
...
@@ -1413,6 +1413,12 @@ void subselect_union_engine::cleanup()
}
bool
subselect_union_engine
::
is_executed
()
const
{
return
unit
->
executed
;
}
void
subselect_uniquesubquery_engine
::
cleanup
()
{
DBUG_ENTER
(
"subselect_uniquesubquery_engine::cleanup"
);
...
...
sql/item_subselect.h
View file @
f6899b07
...
...
@@ -109,6 +109,12 @@ class Item_subselect :public Item_result_field
engine_changed
=
1
;
return
eng
==
0
;
}
/*
True if this subquery has been already evaluated. Implemented only for
single select and union subqueries only.
*/
bool
is_evaluated
()
const
;
/*
Used by max/min subquery to initialize value presence registration
mechanism. Engine call this method before rexecution query.
...
...
@@ -317,6 +323,7 @@ class subselect_engine: public Sql_alloc
virtual
void
print
(
String
*
str
)
=
0
;
virtual
bool
change_result
(
Item_subselect
*
si
,
select_subselect
*
result
)
=
0
;
virtual
bool
no_tables
()
=
0
;
virtual
bool
is_executed
()
const
{
return
FALSE
;
}
};
...
...
@@ -342,6 +349,7 @@ class subselect_single_select_engine: public subselect_engine
void
print
(
String
*
str
);
bool
change_result
(
Item_subselect
*
si
,
select_subselect
*
result
);
bool
no_tables
();
bool
is_executed
()
const
{
return
executed
;
}
};
...
...
@@ -363,6 +371,7 @@ class subselect_union_engine: public subselect_engine
void
print
(
String
*
str
);
bool
change_result
(
Item_subselect
*
si
,
select_subselect
*
result
);
bool
no_tables
();
bool
is_executed
()
const
;
};
...
...
@@ -411,3 +420,10 @@ class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine
int
exec
();
void
print
(
String
*
str
);
};
inline
bool
Item_subselect
::
is_evaluated
()
const
{
return
engine
->
is_executed
();
}
sql/sql_lex.h
View file @
f6899b07
...
...
@@ -386,12 +386,12 @@ class st_select_lex_unit: public st_select_lex_node {
select_result
*
result
;
ulong
found_rows_for_union
;
bool
res
;
public:
bool
prepared
,
// prepare phase already performed for UNION (unit)
optimized
,
// optimize phase already performed for UNION (unit)
executed
,
// already executed
cleaned
;
public:
// list of fields which points to temporary table for union
List
<
Item
>
item_list
;
/*
...
...
@@ -638,6 +638,11 @@ class st_select_lex: public st_select_lex_node
SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs).
*/
bool
cleanup
();
/*
Recursively cleanup the join of this select lex and of all nested
select lexes.
*/
void
cleanup_all_joins
(
bool
full
);
};
typedef
class
st_select_lex
SELECT_LEX
;
...
...
sql/sql_select.cc
View file @
f6899b07
...
...
@@ -1377,7 +1377,7 @@ JOIN::exec()
DBUG_PRINT
(
"info"
,(
"Creating group table"
));
/* Free first data from old join */
curr_join
->
join_free
(
0
);
curr_join
->
join_free
();
if
(
make_simple_join
(
curr_join
,
curr_tmp_table
))
DBUG_VOID_RETURN
;
calc_group_buffer
(
curr_join
,
group_list
);
...
...
@@ -1475,7 +1475,7 @@ JOIN::exec()
if
(
curr_tmp_table
->
distinct
)
curr_join
->
select_distinct
=
0
;
/* Each row is unique */
curr_join
->
join_free
(
0
);
/* Free quick selects */
curr_join
->
join_free
();
/* Free quick selects */
if
(
curr_join
->
select_distinct
&&
!
curr_join
->
group_list
)
{
thd
->
proc_info
=
"Removing duplicates"
;
...
...
@@ -5718,34 +5718,88 @@ void JOIN_TAB::cleanup()
end_read_record
(
&
read_record
);
}
/*
Partially cleanup JOIN after it has executed: close index or rnd read
(table cursors), free quick selects.
DESCRIPTION
This function is called in the end of execution of a JOIN, before the used
tables are unlocked and closed.
For a join that is resolved using a temporary table, the first sweep is
performed against actual tables and an intermediate result is inserted
into the temprorary table.
The last sweep is performed against the temporary table. Therefore,
the base tables and associated buffers used to fill the temporary table
are no longer needed, and this function is called to free them.
void
JOIN
::
join_free
(
bool
full
)
For a join that is performed without a temporary table, this function
is called after all rows are sent, but before EOF packet is sent.
For a simple SELECT with no subqueries this function performs a full
cleanup of the JOIN and calls mysql_unlock_read_tables to free used base
tables.
If a JOIN is executed for a subquery or if it has a subquery, we can't
do the full cleanup and need to do a partial cleanup only.
o If a JOIN is not the top level join, we must not unlock the tables
because the outer select may not have been evaluated yet, and we
can't unlock only selected tables of a query.
o Additionally, if this JOIN corresponds to a correlated subquery, we
should not free quick selects and join buffers because they will be
needed for the next execution of the correlated subquery.
o However, if this is a JOIN for a [sub]select, which is not
a correlated subquery itself, but has subqueries, we can free it
fully and also free JOINs of all its subqueries. The exception
is a subquery in SELECT list, e.g:
SELECT a, (select max(b) from t1) group by c
This subquery will not be evaluated at first sweep and its value will
not be inserted into the temporary table. Instead, it's evaluated
when selecting from the temporary table. Therefore, it can't be freed
here even though it's not correlated.
*/
void
JOIN
::
join_free
()
{
SELECT_LEX_UNIT
*
unit
;
SELECT_LEX
*
sl
;
DBUG_ENTER
(
"JOIN::join_free"
);
/*
Optimization: if not EXPLAIN and we are done with the JOIN,
free all tables.
*/
full
=
full
||
(
!
select_lex
->
uncacheable
&&
!
thd
->
lex
->
describe
);
bool
full
=
(
!
select_lex
->
uncacheable
&&
!
thd
->
lex
->
describe
);
bool
can_unlock
=
full
;
DBUG_ENTER
(
"JOIN::join_free"
);
cleanup
(
full
);
for
(
unit
=
select_lex
->
first_inner_unit
();
unit
;
unit
=
unit
->
next_unit
())
for
(
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
JOIN
*
join
=
sl
->
join
;
if
(
join
)
join
->
join_free
(
full
);
Item_subselect
*
subselect
=
sl
->
master_unit
()
->
item
;
bool
full_local
=
full
&&
(
!
subselect
||
subselect
->
is_evaluated
());
/*
If this join is evaluated, we can fully clean it up and clean up all
its underlying joins even if they are correlated -- they will not be
used any more anyway.
If this join is not yet evaluated, we still must clean it up to
close its table cursors -- it may never get evaluated, as in case of
... HAVING FALSE OR a IN (SELECT ...))
but all table cursors must be closed before the unlock.
*/
sl
->
cleanup_all_joins
(
full_local
);
/* Can't unlock if at least one JOIN is still needed */
can_unlock
=
can_unlock
&&
full_local
;
}
/*
We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement.
*/
if
(
full
&&
lock
&&
thd
->
lock
&&
!
(
select_options
&
SELECT_NO_UNLOCK
)
&&
if
(
can_unlock
&&
lock
&&
thd
->
lock
&&
!
(
select_options
&
SELECT_NO_UNLOCK
)
&&
!
select_lex
->
subquery_in_having
&&
(
select_lex
==
(
thd
->
lex
->
unit
.
fake_select_lex
?
thd
->
lex
->
unit
.
fake_select_lex
:
&
thd
->
lex
->
select_lex
)))
...
...
@@ -6059,7 +6113,7 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
DBUG_RETURN
(
0
);
}
join
->
join_free
(
0
);
join
->
join_free
();
if
(
send_row
)
{
...
...
@@ -9019,7 +9073,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
The following will unlock all cursors if the command wasn't an
update command
*/
join
->
join_free
(
0
);
// Unlock all cursors
join
->
join_free
(
);
// Unlock all cursors
if
(
join
->
result
->
send_eof
())
rc
=
1
;
// Don't send error
}
...
...
sql/sql_select.h
View file @
f6899b07
...
...
@@ -358,7 +358,7 @@ class JOIN :public Sql_alloc
the end of execution in order to increase concurrency and reduce
memory consumption.
*/
void
join_free
(
bool
full
);
void
join_free
();
/* Cleanup this JOIN, possibly for reuse */
void
cleanup
(
bool
full
);
void
clear
();
...
...
sql/sql_union.cc
View file @
f6899b07
...
...
@@ -720,3 +720,17 @@ bool st_select_lex::cleanup()
DBUG_RETURN
(
error
);
}
void
st_select_lex
::
cleanup_all_joins
(
bool
full
)
{
SELECT_LEX_UNIT
*
unit
;
SELECT_LEX
*
sl
;
if
(
join
)
join
->
cleanup
(
full
);
for
(
unit
=
first_inner_unit
();
unit
;
unit
=
unit
->
next_unit
())
for
(
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
sl
->
cleanup_all_joins
(
full
);
}
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