Commit 0dea7c9
Guilhem Bichot
Fix for
Bug#16739050 PREPARED STATEMENT: CRASH IN ITEM_REF::REAL_ITEM OR PURE
VIRTUAL FUNCTION CALL
and 2 duplicates:
don't reach to real items when creating prep_having. Details:
First, let's review some bugs fixed in older 5.6 versions.
==========================================================
About the fix for 12603457 and 12603141:
WHERE condition is "WHERE field".
JOIN::conds is made, by change_item_tree(), to point to item_outer_ref
which points to item_field.
At fix_prepare_information() we do:
prep_where= JOIN::conds
When we rollback_item_tree_changes(), we restore conds, which does not
modify prep_where (only JOIN::conds was registered in the "list of
changes to roll back"...).
When next execution starts reinit_stmt_before_use() copies prep_where
into select_lex->where, which thus gets the now-destroyed
item_outer_ref, later this crashes.
Solution which was chosen: make reinit_stmt_before_use() copy
prep_where->real_item(), to reach to the field, avoiding the
now-destroyed item_outer_ref.
For uniformity, the same was done for prep_having.
About the fix for 12582849: (cousin of above)
WHERE condition is OR.
One argument of OR is made to point to item_outer_ref which points to
item_field.
At JOIN:: optimize:
prep_where= copy of conds => makes a copy of OR (a new item_cond_or).
When we rollback_item_tree_changes(), we restore one pointer argument
of the original OR, which does not modify the pointer argument of the
copy of this OR (do not modify prep_where); the now-destroyed
item_outer_ref remains in prep_where. Then it crashes at next
execution.
Solution which was chosen: make the copy code (copy_andor_structure)
use real_item().
About the fix for Bug #16163596:
regression caused by the fix for 12603457 and 12603141.
In sql_yacc, "HAVING a" leads to the creation of an Item_ref named
"a". In having->fix_fields(), we find that "a" is actually a field, so
we make the Item_ref's ref point to this field.
At next execution, reinit_stmt_before_use() uses real_item() which
makes the HAVING be item_field, not Item_ref anymore. This Item_ref
should have staid, it's a permanent, parse-time item.
There should never be Item_field in HAVING, see how sql_yacc creates
Item_ref instead of Item_field if in HAVING.
Removing this item_ref confused ROLLUP.
Solution which was chosen: undo the HAVING part of the fix for
12603457 and 12603141.
Now the new bugs.
=================
16317817:
HAVING condition is OR.
We resolve GROUP BY:
- initially order->item points to order->item_ptr which contains (per
parser) Item_field.
- in find_order_in_list(), *order_item (i.e. order->item_ptr) is made
to point to item_outer_ref, this change done in fix_fields() goes
through register_item_tree_change().
- again in find_order_in_list(), we append this item to
ref_pointer_array, and make order->item point to this new cell of the
array.
One argument of OR in HAVING is item_ref (per parser).
We resolve HAVING: this argument of OR is made to reference
order->item (id est: the ref_pointer_array cell which references the
item of GROUP BY). Keep in mind that Item_ref is Item**, not Item*.
Then we rollback_item_tree_changes(), which effectively restores
order->item_ptr.
reinit_stmt_before_use() restores order -> item to point to order ->
item_ptr. So GROUP BY is fine.
But the item_ref in HAVING still references the cell of
ref_pointer_array which was not restored.
reinit_stmt_before_use() makes a copy of HAVING, which uses
copy_andor_structure, which reaches to the real items
(per the fix for 12582849), but as HAVING is "item_ref to destroyed
item_outer_ref to item_field", this crashes.
If it would not reach to the real item, the copy would stop at the
item_ref, then the soon-coming name resolution would create a new
item_outer_ref and point the item_ref to it, all fine.
16739050: similar to above
16317685:
HAVING condition is OR.
In HAVING, one Item_ref is made to reference COUNT;
reinit_stmt_before_use(), using copy_andor_structure() which uses
real_item(), changes HAVING to COUNT, then ROLLUP crashes.
PROPOSED SOLUTION
=================
Avoid using real_item() in copy_andor_structure() when copying HAVING,
because it's only causing problems.
Keep real_item() when copying WHERE, in 5.6. We cannot remove it,
because of the "second copy" done in JOIN::optimize():
sel->prep_where=
conds ? conds->copy_andor_structure(thd, true) : NULL;
which creates new AND/OR items which "argument pointers" will not be properly restored
(re-read 12582849 above), thus forcing us to reach to the real items.
In WL#7082 (5.7), the second copy will go away, so real_item() can be
removed (done in my prototype).1 parent bb63a58 commit 0dea7c9
6 files changed
Lines changed: 40 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5390 | 5390 | | |
5391 | 5391 | | |
5392 | 5392 | | |
5393 | | - | |
| 5393 | + | |
5394 | 5394 | | |
5395 | 5395 | | |
5396 | 5396 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1338 | 1338 | | |
1339 | 1339 | | |
1340 | 1340 | | |
1341 | | - | |
| 1341 | + | |
| 1342 | + | |
| 1343 | + | |
| 1344 | + | |
| 1345 | + | |
| 1346 | + | |
| 1347 | + | |
1342 | 1348 | | |
1343 | 1349 | | |
1344 | 1350 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4739 | 4739 | | |
4740 | 4740 | | |
4741 | 4741 | | |
4742 | | - | |
| 4742 | + | |
4743 | 4743 | | |
4744 | 4744 | | |
4745 | 4745 | | |
4746 | | - | |
| 4746 | + | |
| 4747 | + | |
4747 | 4748 | | |
4748 | 4749 | | |
4749 | 4750 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
1682 | 1682 | | |
1683 | 1683 | | |
1684 | 1684 | | |
1685 | | - | |
| 1685 | + | |
1686 | 1686 | | |
1687 | 1687 | | |
1688 | 1688 | | |
| |||
1873 | 1873 | | |
1874 | 1874 | | |
1875 | 1875 | | |
1876 | | - | |
| 1876 | + | |
1877 | 1877 | | |
1878 | 1878 | | |
1879 | 1879 | | |
1880 | | - | |
| 1880 | + | |
1881 | 1881 | | |
1882 | 1882 | | |
1883 | 1883 | | |
| |||
1902 | 1902 | | |
1903 | 1903 | | |
1904 | 1904 | | |
1905 | | - | |
| 1905 | + | |
1906 | 1906 | | |
1907 | 1907 | | |
1908 | 1908 | | |
1909 | | - | |
| 1909 | + | |
1910 | 1910 | | |
1911 | 1911 | | |
1912 | 1912 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3657 | 3657 | | |
3658 | 3658 | | |
3659 | 3659 | | |
| 3660 | + | |
| 3661 | + | |
| 3662 | + | |
| 3663 | + | |
| 3664 | + | |
| 3665 | + | |
| 3666 | + | |
| 3667 | + | |
3660 | 3668 | | |
3661 | 3669 | | |
3662 | 3670 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
218 | 218 | | |
219 | 219 | | |
220 | 220 | | |
221 | | - | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
222 | 234 | | |
223 | | - | |
| 235 | + | |
224 | 236 | | |
225 | 237 | | |
226 | 238 | | |
| |||
2759 | 2771 | | |
2760 | 2772 | | |
2761 | 2773 | | |
2762 | | - | |
| 2774 | + | |
2763 | 2775 | | |
2764 | 2776 | | |
2765 | 2777 | | |
| |||
0 commit comments