- Let join buffering code correctly take into account rowids needed
by DuplicateElimination when it is calculating minimum record sizes.
- In JOIN_CACHE::write_record_data, added asserts that prevent us from
writing beyond the end of the buffer.
sql/item_subselect.cc:
Added check of error condtions (safety)
sql/sql_join_cache.cc:
Added DBUG to some functions.
Added error checking for calls to check_match(); This fixed the bug.
sql/sql_select.cc:
Moved variable assignment to be close to where it's used (cleanup)
This crashing bug could manifest itself at execution of join queries
over materialized derived tables with IN subquery predicates in the
where clause. If for such a query the optimizer chose to use duplicate
weed-out with duplicates in a materialized derived table and chose to
employ join cache the the execution could cause a crash of the server.
It happened because the JOIN_CACHE::init method assumed that the value
of TABLE::file::ref is set at the moment when the method was called
for the employed join cache. It's true for regular tables, but it's
not true for materialized derived tables that are filled now at the
first access to them, i.e. after the JOIN_CACHE::init has done its job.
To fix this problem for any ROWID field of materialized derived table
the procedure that copies fields from record buffers into the employed
join buffer first checks whether the value of TABLE::file::ref has
been set for the table, and if it's not so the procedure sets this value.
- "Using MRR" is no longer shown with range access.
- Instead, both range and BKA accesses will show one of the following:
= "Rowid-ordered scan"
= "Key-ordered scan"
= "Key-ordered Rowid-ordered scan"
depending on whether DS-MRR implementation will do scan keys in order, rowids in order,
or both.
- The patch also introduces a way for other storage engines/MRR implementations to
pass information to EXPLAIN output about the properties of employed MRR scans.
- In join buffering code, call join_tab_execution_startup() (#1) before we call join_tab_scan->open() (#2).
This is important with SJ-Materialization because #1 fills the materialized table, while
#2 will actually try to read the first row. Attempt to read the first row before we have
populated the materialized table would cause zero rows to be returned when actually there were matches.
When this flag is 'off' the size of the used join buffer
is taken directly from the system variable 'join_buffer_size'.
When this flag is 'on' then the size of the buffer depends
on the estimated number of rows in the partial join whose
records are to be stored in the buffer.
By default this flag is set 'on'.
An assertion failure was triggered for a 6-way join query that used two
join buffers.
The failure happened because every call of JOIN_CACHE::join_matching_records
saved and restored status of all tables that were accessed before the table
join_tab. It must do it only for those of them that follow the last table
using a join buffer.
Date: Mon, 01 Nov 2010 15:15:25 -0000
3272 Roy Lyseng 2010-11-01
Bug#52068: Optimizer generates invalid semijoin materialization plan
When MaterializeScan semijoin strategy was used and there were one
or more outer dependent tables before the semijoin tables, the scan
over the materialized table was not properly reset for each row of
the prefix outer tables.
Example: suppose we have a join order:
ot1 SJ-Mat-Scan(it2 it3) ot4
Notice that this is called a MaterializeScan, even though there is an
outer table ahead of the materialized tables. Usually a MaterializeScan
has the outer tables after the materialized table, but this is
a special (but legal) case with outer dependent tables both before and
after the materialized table.
For each qualifying row from ot1, a new scan over the materialized
table must be set up. The code failed to do that, so all scans after
the first one returned zero rows from the materialized table.
One of the hash functions employed by the BNLH join algorithm
calculates the the value of hash index for key value utilizing
every byte of the key buffer. To make this calculation valid
one has to ensure that for any key value unused bytes of the
buffer are filled with with a certain filler. We choose 0 as
a filler for these bytes.
Added an optional boolean parameter with_zerofill to the function
key_copy. If the value of the parameter is TRUE all unused bytes
of the key buffer is filled with 0.
The bug happened when BKA join algorithm used an incremental buffer
and some of the fields over which access keys were constructed
- were allocated in the previous join buffers
- were non-nullable
- belonged to inner tables of outer joins.
For such fields an offset to the field value in the record is saved
in the postfix of the record, and a zero offset indicates that the value
is null. Before the key using the field value is constructed the
value is read into the corresponding field of the record buffer and
the null bit is set for the field if the offset is 0. However if
the field is non-nullable the table->null_row must be set to 1
for null values and to 0 for non-null values to ensure proper reading
of the value from the record buffer.
The patch that introduced the new enumeration type Match_flag
for the values of match flags in the records put into join buffers
missed the necessary modifications in JOIN_CACHE::set_match_flag_if_none.
This could cause wrong results for outer joins with on expressions
only over outer tables.
Miscalculation of the minimum possible buffer size could trigger
an assert in JOIN_CACHE_HASHED::put_record when if join_buffer_size
was set to the values that is less than the length of one record to
stored in the join buffer.
It happened due to the following mistakes:
- underestimation of space needed for a key in the hash table
(we have to take into account that hash table can have more
buckets than the expected number of records).
- the value of maximum total length of all records stored in
the join buffer was not saved in the field max_used_fieldlength
by the function calc_used_field_length.