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
36430f01
Commit
36430f01
authored
Dec 08, 2011
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Plain Diff
Merge fix for BUG#868908
parents
d2e27452
ee24ec1e
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
226 additions
and
49 deletions
+226
-49
mysql-test/r/subselect_mat.result
mysql-test/r/subselect_mat.result
+23
-0
mysql-test/r/subselect_sj_mat.result
mysql-test/r/subselect_sj_mat.result
+23
-0
mysql-test/t/subselect_sj_mat.test
mysql-test/t/subselect_sj_mat.test
+23
-0
sql/item_subselect.cc
sql/item_subselect.cc
+4
-1
sql/item_subselect.h
sql/item_subselect.h
+2
-1
sql/lock.cc
sql/lock.cc
+7
-3
sql/opt_subselect.cc
sql/opt_subselect.cc
+14
-17
sql/sql_lex.cc
sql/sql_lex.cc
+3
-3
sql/sql_select.cc
sql/sql_select.cc
+105
-24
sql/table.cc
sql/table.cc
+2
-0
sql/table.h
sql/table.h
+20
-0
No files found.
mysql-test/r/subselect_mat.result
View file @
36430f01
...
...
@@ -1729,6 +1729,29 @@ FROM t4 , t5
f1 f5
DROP TABLE t1, t2, t3, t4, t5;
#
# BUG#868908: Crash in check_simple_equality() with semijoin + materialization + prepared statement
#
CREATE TABLE t1 ( a int );
CREATE TABLE t3 ( b int, c int) ;
CREATE TABLE t2 ( a int ) ;
CREATE TABLE t4 ( a int , c int) ;
PREPARE st1 FROM "
SELECT STRAIGHT_JOIN *
FROM t1
WHERE ( 3 ) IN (
SELECT t3.b
FROM t3
LEFT JOIN (
t2 STRAIGHT_JOIN t4 ON ( t4.c = t2.a )
) ON ( t4.a = t3.c )
);
";
EXECUTE st1;
a
EXECUTE st1;
a
DROP TABLE t1,t2,t3,t4;
#
# BUG#901032: Wrong result for MIN/MAX on an indexed column with materialization and semijoin
#
CREATE TABLE t1 ( a INT, KEY(a) );
...
...
mysql-test/r/subselect_sj_mat.result
View file @
36430f01
...
...
@@ -1765,6 +1765,29 @@ FROM t4 , t5
f1 f5
DROP TABLE t1, t2, t3, t4, t5;
#
# BUG#868908: Crash in check_simple_equality() with semijoin + materialization + prepared statement
#
CREATE TABLE t1 ( a int );
CREATE TABLE t3 ( b int, c int) ;
CREATE TABLE t2 ( a int ) ;
CREATE TABLE t4 ( a int , c int) ;
PREPARE st1 FROM "
SELECT STRAIGHT_JOIN *
FROM t1
WHERE ( 3 ) IN (
SELECT t3.b
FROM t3
LEFT JOIN (
t2 STRAIGHT_JOIN t4 ON ( t4.c = t2.a )
) ON ( t4.a = t3.c )
);
";
EXECUTE st1;
a
EXECUTE st1;
a
DROP TABLE t1,t2,t3,t4;
#
# BUG#901032: Wrong result for MIN/MAX on an indexed column with materialization and semijoin
#
CREATE TABLE t1 ( a INT, KEY(a) );
...
...
mysql-test/t/subselect_sj_mat.test
View file @
36430f01
...
...
@@ -1427,6 +1427,29 @@ ON ( t2.f5 ) IN (
);
DROP
TABLE
t1
,
t2
,
t3
,
t4
,
t5
;
--
echo
#
--
echo
# BUG#868908: Crash in check_simple_equality() with semijoin + materialization + prepared statement
--
echo
#
CREATE
TABLE
t1
(
a
int
);
CREATE
TABLE
t3
(
b
int
,
c
int
)
;
CREATE
TABLE
t2
(
a
int
)
;
CREATE
TABLE
t4
(
a
int
,
c
int
)
;
PREPARE
st1
FROM
"
SELECT STRAIGHT_JOIN *
FROM t1
WHERE ( 3 ) IN (
SELECT t3.b
FROM t3
LEFT JOIN (
t2 STRAIGHT_JOIN t4 ON ( t4.c = t2.a )
) ON ( t4.a = t3.c )
);
"
;
EXECUTE
st1
;
EXECUTE
st1
;
DROP
TABLE
t1
,
t2
,
t3
,
t4
;
--
echo
#
--
echo
# BUG#901032: Wrong result for MIN/MAX on an indexed column with materialization and semijoin
...
...
sql/item_subselect.cc
View file @
36430f01
...
...
@@ -1197,7 +1197,8 @@ Item_in_subselect::Item_in_subselect(Item * left_exp,
Item_exists_subselect
(),
left_expr_cache
(
0
),
first_execution
(
TRUE
),
in_strategy
(
SUBS_NOT_TRANSFORMED
),
optimizer
(
0
),
pushed_cond_guards
(
NULL
),
emb_on_expr_nest
(
NULL
),
is_jtbm_merged
(
FALSE
),
is_flattenable_semijoin
(
FALSE
),
is_jtbm_merged
(
FALSE
),
is_jtbm_const_tab
(
FALSE
),
is_flattenable_semijoin
(
FALSE
),
is_registered_semijoin
(
FALSE
),
upper_item
(
0
)
{
...
...
@@ -4182,6 +4183,8 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
*/
if
(
tmp_table
->
s
->
keys
==
0
)
{
//fprintf(stderr, "Q: %s\n", current_thd->query());
DBUG_ASSERT
(
0
);
DBUG_ASSERT
(
tmp_table
->
s
->
uniques
||
tmp_table
->
key_info
->
key_length
>=
tmp_table
->
file
->
max_key_length
()
||
...
...
sql/item_subselect.h
View file @
36430f01
...
...
@@ -449,6 +449,7 @@ class Item_in_subselect :public Item_exists_subselect
double
jtbm_read_time
;
double
jtbm_record_count
;
bool
is_jtbm_merged
;
bool
is_jtbm_const_tab
;
/*
TRUE<=>this is a flattenable semi-join, false overwise.
...
...
@@ -490,7 +491,7 @@ class Item_in_subselect :public Item_exists_subselect
:
Item_exists_subselect
(),
left_expr_cache
(
0
),
first_execution
(
TRUE
),
abort_on_null
(
0
),
in_strategy
(
SUBS_NOT_TRANSFORMED
),
optimizer
(
0
),
pushed_cond_guards
(
NULL
),
func
(
NULL
),
emb_on_expr_nest
(
NULL
),
is_jtbm_merged
(
FALSE
),
is_jtbm_merged
(
FALSE
),
is_jtbm_const_tab
(
FALSE
),
upper_item
(
0
)
{}
void
cleanup
();
...
...
sql/lock.cc
View file @
36430f01
...
...
@@ -866,8 +866,10 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
for
(
i
=
tables
=
lock_count
=
0
;
i
<
count
;
i
++
)
{
TABLE
*
t
=
table_ptr
[
i
];
if
(
t
->
s
->
tmp_table
!=
NON_TRANSACTIONAL_TMP_TABLE
)
if
(
t
->
s
->
tmp_table
!=
NON_TRANSACTIONAL_TMP_TABLE
&&
t
->
s
->
tmp_table
!=
INTERNAL_TMP_TABLE
)
{
tables
+=
t
->
file
->
lock_count
();
lock_count
++
;
...
...
@@ -895,7 +897,9 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
TABLE
*
table
;
enum
thr_lock_type
lock_type
;
THR_LOCK_DATA
**
locks_start
;
if
((
table
=
table_ptr
[
i
])
->
s
->
tmp_table
==
NON_TRANSACTIONAL_TMP_TABLE
)
table
=
table_ptr
[
i
];
if
(
table
->
s
->
tmp_table
==
NON_TRANSACTIONAL_TMP_TABLE
||
table
->
s
->
tmp_table
==
INTERNAL_TMP_TABLE
)
continue
;
lock_type
=
table
->
reginfo
.
lock_type
;
DBUG_ASSERT
(
lock_type
!=
TL_WRITE_DEFAULT
&&
lock_type
!=
TL_READ_DEFAULT
);
...
...
sql/opt_subselect.cc
View file @
36430f01
...
...
@@ -1266,10 +1266,9 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
List_iterator_fast
<
TABLE_LIST
>
si
(
subq_lex
->
leaf_tables
);
while
((
tl
=
si
++
))
{
tl
->
table
->
tablenr
=
table_no
;
tl
->
table
->
map
=
((
table_map
)
1
)
<<
table_no
;
tl
->
set_tablenr
(
table_no
);
if
(
tl
->
is_jtbm
())
tl
->
jtbm_table_no
=
t
l
->
table
->
tablenr
;
tl
->
jtbm_table_no
=
t
able_no
;
SELECT_LEX
*
old_sl
=
tl
->
select_lex
;
tl
->
select_lex
=
parent_join
->
select_lex
;
for
(
TABLE_LIST
*
emb
=
tl
->
embedding
;
...
...
@@ -1427,25 +1426,12 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
List
<
TABLE_LIST
>
*
emb_join_list
=
&
parent_lex
->
top_join_list
;
TABLE_LIST
*
emb_tbl_nest
=
NULL
;
// will change when we learn to handle outer joins
TABLE_LIST
*
tl
;
double
rows
;
double
read_time
;
DBUG_ENTER
(
"convert_subq_to_jtbm"
);
bool
optimization_delayed
=
TRUE
;
subq_pred
->
set_strategy
(
SUBS_MATERIALIZATION
);
if
(
subq_pred
->
optimize
(
&
rows
,
&
read_time
))
DBUG_RETURN
(
TRUE
);
subq_pred
->
jtbm_read_time
=
read_time
;
subq_pred
->
jtbm_record_count
=
rows
;
subq_pred
->
is_jtbm_merged
=
TRUE
;
if
(
subq_pred
->
engine
->
engine_type
()
!=
subselect_engine
::
HASH_SJ_ENGINE
)
{
*
remove_item
=
FALSE
;
DBUG_RETURN
(
FALSE
);
}
*
remove_item
=
TRUE
;
TABLE_LIST
*
jtbm
;
...
...
@@ -1481,7 +1467,18 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
tl
->
next_local
=
jtbm
;
/* A theory: no need to re-connect the next_global chain */
if
(
optimization_delayed
)
{
DBUG_ASSERT
(
parent_join
->
table_count
<
MAX_TABLES
);
jtbm
->
jtbm_table_no
=
parent_join
->
table_count
;
create_subquery_temptable_name
(
tbl_alias
,
subq_pred
->
unit
->
first_select
()
->
select_number
);
jtbm
->
alias
=
tbl_alias
;
parent_join
->
table_count
++
;
DBUG_RETURN
(
FALSE
);
}
subselect_hash_sj_engine
*
hash_sj_engine
=
((
subselect_hash_sj_engine
*
)
subq_pred
->
engine
);
jtbm
->
table
=
hash_sj_engine
->
tmp_table
;
...
...
sql/sql_lex.cc
View file @
36430f01
...
...
@@ -3644,12 +3644,12 @@ bool st_select_lex::save_leaf_tables(THD *thd)
{
if
(
leaf_tables_exec
.
push_back
(
table
))
return
1
;
table
->
tablenr_exec
=
table
->
table
->
tablenr
;
table
->
map_exec
=
table
->
table
->
map
;
table
->
tablenr_exec
=
table
->
get_tablenr
()
;
table
->
map_exec
=
table
->
get_map
()
;
if
(
join
&&
(
join
->
select_options
&
SELECT_DESCRIBE
))
table
->
maybe_null_exec
=
0
;
else
table
->
maybe_null_exec
=
table
->
table
->
maybe_null
;
table
->
maybe_null_exec
=
table
->
table
?
table
->
table
->
maybe_null
:
0
;
}
if
(
arena
)
thd
->
restore_active_arena
(
arena
,
&
backup
);
...
...
sql/sql_select.cc
View file @
36430f01
...
...
@@ -798,13 +798,46 @@ bool JOIN::prepare_stage2()
}
/*
Create a dummy temporary table, useful only for the sake of having a
TABLE* object with map,tablenr and maybe_null properties.
This is used by non-mergeable semi-join materilization code to handle
degenerate cases where materialized subquery produced "Impossible WHERE"
and thus wasn't materialized.
*/
TABLE
*
create_dummy_tmp_table
(
THD
*
thd
)
{
DBUG_ENTER
(
"create_dummy_tmp_table"
);
TABLE
*
table
;
TMP_TABLE_PARAM
sjm_table_param
;
sjm_table_param
.
init
();
sjm_table_param
.
field_count
=
1
;
List
<
Item
>
sjm_table_cols
;
Item
*
column_item
=
new
Item_int
(
1
);
sjm_table_cols
.
push_back
(
column_item
);
if
(
!
(
table
=
create_tmp_table
(
thd
,
&
sjm_table_param
,
sjm_table_cols
,
(
ORDER
*
)
0
,
TRUE
/* distinct */
,
1
,
/*save_sum_fields*/
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
,
HA_POS_ERROR
/*rows_limit */
,
(
char
*
)
"dummy"
,
TRUE
/* Do not open */
)))
{
DBUG_RETURN
(
NULL
);
}
DBUG_RETURN
(
table
);
}
void
inject_jtbm_cond
s
(
JOIN
*
join
,
List
<
TABLE_LIST
>
*
join_list
,
Item
**
join_where
)
setup_jtbm_semi_join
s
(
JOIN
*
join
,
List
<
TABLE_LIST
>
*
join_list
,
Item
**
join_where
)
{
TABLE_LIST
*
table
;
NESTED_JOIN
*
nested_join
;
List_iterator
<
TABLE_LIST
>
li
(
*
join_list
);
DBUG_ENTER
(
"
inject_jtbm_cond
s"
);
DBUG_ENTER
(
"
setup_jtbm_semi_join
s"
);
while
((
table
=
li
++
))
...
...
@@ -817,34 +850,60 @@ inject_jtbm_conds(JOIN *join, List<TABLE_LIST> *join_list, Item **join_where)
double
rows
;
double
read_time
;
//DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
subq_pred
->
optimize
(
&
rows
,
&
read_time
);
subq_pred
->
jtbm_read_time
=
read_time
;
subq_pred
->
jtbm_record_count
=
rows
;
subq_pred
->
is_jtbm_merged
=
TRUE
;
JOIN
*
subq_join
=
subq_pred
->
unit
->
first_select
()
->
join
;
if
(
!
subq_join
->
tables_list
||
!
subq_join
->
table_count
)
{
/*
This is an empty and constant table.
subselect_hash_sj_engine
*
hash_sj_engine
=
((
subselect_hash_sj_engine
*
)
item
->
engine
);
//repeat of convert_subq_to_jtbm:
table
->
table
=
hash_sj_engine
->
tmp_table
;
table
->
table
->
pos_in_table_list
=
table
;
TODO: what if this is not empty but still constant?
We'll need to check the equality but there's no materializatnion
table?
A: create an IN-equality from
- left_expr
- right_expr. Q: how can right-expr exist in the context of
parent select? We don't have refs from outside to inside!
A: create/check in the context of the child select?
for injection, check how in->exists is performed.
*/
subq_pred
->
is_jtbm_const_tab
=
TRUE
;
setup_table_map
(
table
->
table
,
table
,
table
->
jtbm_table_no
);
TABLE
*
dummy_table
=
create_dummy_tmp_table
(
join
->
thd
);
table
->
table
=
dummy_table
;
table
->
table
->
pos_in_table_list
=
table
;
Item
*
sj_conds
=
hash_sj_engine
->
semi_join_conds
;
setup_table_map
(
table
->
table
,
table
,
table
->
jtbm_table_no
);
}
else
{
DBUG_ASSERT
(
subq_pred
->
test_set_strategy
(
SUBS_MATERIALIZATION
));
subq_pred
->
is_jtbm_const_tab
=
FALSE
;
subselect_hash_sj_engine
*
hash_sj_engine
=
((
subselect_hash_sj_engine
*
)
item
->
engine
);
table
->
table
=
hash_sj_engine
->
tmp_table
;
table
->
table
->
pos_in_table_list
=
table
;
setup_table_map
(
table
->
table
,
table
,
table
->
jtbm_table_no
);
Item
*
sj_conds
=
hash_sj_engine
->
semi_join_conds
;
(
*
join_where
)
=
and_items
(
*
join_where
,
sj_conds
);
if
(
!
(
*
join_where
)
->
fixed
)
(
*
join_where
)
->
fix_fields
(
join
->
thd
,
join_where
);
//parent_join->select_lex->where= parent_join->conds;
(
*
join_where
)
=
and_items
(
*
join_where
,
sj_conds
);
if
(
!
(
*
join_where
)
->
fixed
)
(
*
join_where
)
->
fix_fields
(
join
->
thd
,
join_where
);
}
}
if
((
nested_join
=
table
->
nested_join
))
{
inject_jtbm_cond
s
(
join
,
&
nested_join
->
join_list
,
join_where
);
setup_jtbm_semi_join
s
(
join
,
&
nested_join
->
join_list
,
join_where
);
}
}
DBUG_VOID_RETURN
;
...
...
@@ -974,7 +1033,7 @@ JOIN::optimize()
thd
->
restore_active_arena
(
arena
,
&
backup
);
}
inject_jtbm_cond
s
(
this
,
join_list
,
&
conds
);
setup_jtbm_semi_join
s
(
this
,
join_list
,
&
conds
);
conds
=
optimize_cond
(
this
,
conds
,
join_list
,
&
cond_value
,
&
cond_equal
);
...
...
@@ -3120,6 +3179,14 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
set_position
(
join
,
const_count
++
,
s
,(
KEYUSE
*
)
0
);
no_rows_const_tables
|=
table
->
map
;
}
/* SJ-Materialization handling: */
if
(
table
->
pos_in_table_list
->
jtbm_subselect
&&
table
->
pos_in_table_list
->
jtbm_subselect
->
is_jtbm_const_tab
)
{
set_position
(
join
,
const_count
++
,
s
,(
KEYUSE
*
)
0
);
no_rows_const_tables
|=
table
->
map
;
}
}
stat_vector
[
i
]
=
0
;
...
...
@@ -9669,8 +9736,16 @@ void JOIN_TAB::cleanup()
if
(
table
->
pos_in_table_list
&&
table
->
pos_in_table_list
->
jtbm_subselect
)
{
end_read_record
(
&
read_record
);
table
->
pos_in_table_list
->
jtbm_subselect
->
cleanup
();
if
(
table
->
pos_in_table_list
->
jtbm_subselect
->
is_jtbm_const_tab
)
{
free_tmp_table
(
join
->
thd
,
table
);
table
=
NULL
;
}
else
{
end_read_record
(
&
read_record
);
table
->
pos_in_table_list
->
jtbm_subselect
->
cleanup
();
}
DBUG_VOID_RETURN
;
}
/*
...
...
@@ -11944,7 +12019,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
{
if
(
!
table
->
prep_on_expr
)
table
->
prep_on_expr
=
table
->
on_expr
;
used_tables
=
table
->
table
->
map
;
used_tables
=
table
->
get_map
()
;
if
(
conds
)
not_null_tables
=
conds
->
not_null_tables
();
}
...
...
@@ -12001,7 +12076,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
table
->
embedding
->
on_expr_dep_tables
|=
table
->
on_expr
->
used_tables
();
}
else
table
->
dep_tables
&=
~
table
->
table
->
map
;
table
->
dep_tables
&=
~
table
->
get_map
()
;
}
if
(
prev_table
)
...
...
@@ -12014,7 +12089,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
prev_table
->
dep_tables
|=
table
->
on_expr_dep_tables
;
table_map
prev_used_tables
=
prev_table
->
nested_join
?
prev_table
->
nested_join
->
used_tables
:
prev_table
->
table
->
map
;
prev_table
->
get_map
()
;
/*
If on expression contains only references to inner tables
we still make the inner tables dependent on the outer tables.
...
...
@@ -15577,6 +15652,12 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
/* Skip materialized derived tables/views. */
DBUG_RETURN
(
0
);
}
else
if
(
tab
->
table
->
pos_in_table_list
->
jtbm_subselect
&&
tab
->
table
->
pos_in_table_list
->
jtbm_subselect
->
is_jtbm_const_tab
)
{
/* Row will not be found */
DBUG_RETURN
(
-
1
);
}
else
if
(
tab
->
type
==
JT_SYSTEM
)
{
if
((
error
=
join_read_system
(
tab
)))
...
...
sql/table.cc
View file @
36430f01
...
...
@@ -5922,6 +5922,8 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
int
TABLE_LIST
::
fetch_number_of_rows
()
{
int
error
=
0
;
if
(
jtbm_subselect
)
return
0
;
if
(
is_materialized_derived
()
&&
!
fill_me
)
{
...
...
sql/table.h
View file @
36430f01
...
...
@@ -1377,6 +1377,26 @@ struct TABLE_LIST
select_union
*
derived_result
;
/* Stub used for materialized derived tables. */
table_map
map
;
/* ID bit of table (1,2,4,8,16...) */
table_map
get_map
()
{
return
jtbm_subselect
?
table_map
(
1
)
<<
jtbm_table_no
:
table
->
map
;
}
uint
get_tablenr
()
{
return
jtbm_subselect
?
jtbm_table_no
:
table
->
tablenr
;
}
void
set_tablenr
(
uint
new_tablenr
)
{
if
(
jtbm_subselect
)
{
jtbm_table_no
=
new_tablenr
;
}
if
(
table
)
{
table
->
tablenr
=
new_tablenr
;
table
->
map
=
table_map
(
1
)
<<
new_tablenr
;
}
}
/*
Reference from aux_tables to local list entry of main select of
multi-delete statement:
...
...
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