Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
10.3.21
-
None
-
AWS Linux
Description
I don't have a testcase, I only have a customer's core file.
As far as I was able to investigate, the following has happened:
1. There is a big query with nested SELECTs and non-recursive CTEs. Some CTEs are used multiple times.
2. The query is submitted to server as a Prepared Statement. The prepared statement has many '?' parameters.
3. [At least] one of the parameters is inside in a CTE that's reused and it used like so:
WHERE |
table.key= ? |
We crash in optimize_keyuse(), when we are trying to process a KEYUSE element created from the above equality.
We crash somewhere here:
 |
if (keyuse->used_tables & |
(map= (keyuse->used_tables & ~join->const_table_map &
|
~OUTER_REF_TABLE_BIT)))
|
{
|
uint n_tables= my_count_bits(map);
|
if (n_tables == 1) // Only one table |
{
|
Table_map_iterator it(map);
|
int tablenr= it.next_bit(); |
DBUG_ASSERT(tablenr != Table_map_iterator::BITMAP_END);
|
TABLE *tmp_table=join->table[tablenr];
|
if (tmp_table) // already created |
keyuse->ref_table_rows= MY_MAX(tmp_table->file->stats.records, 100);
|
}
|
The cause is that the keyuse has:
keyuse->used_tables = PARAM_TABLE_BIT
|
keyuse->val = Item_param
|
With PARAM_TABLE_BIT, the "if (n_tables == 1)" branch is taken, and we get a tablenr value, but join->table[tablenr] is not pointing to a valid TABLE object hence we get a poorly-reproducible crash.
We should not get {{ keyuse->used_tables = PARAM_TABLE_BIT}}. We do, because
$keyuse->val->state == Item_param::NO_VALUE
|
(which also shouldn't be happening).
There is Prepared_statement::param_array which is an array of "primary" parameter instances, and
$keyuse->val != $prepared_statement->param_array[$i] for any value of $i.
|
However, I can find $keyuse->val in
$prepared_statement->param_array[$a].m_clones.m_array[$b]
|
That is, it is a "secondary" Item_param object that was created for a CTE.
Further, I observe that
- The "primary" Item_param objects from $prepared_statement->param_array[i] all have state=Item_param::SHORT_DATA_VALUE or other similar states
- The "secondary" Item_param objects from "m_clones" arrays all have state=Item_param::NO_VALUE.