Details
-
Type:
Bug
-
Status: Closed
-
Priority:
Minor
-
Resolution: Cannot Reproduce
-
Affects Version/s: 10.0.9
-
Fix Version/s: N/A
-
Component/s: None
-
Labels:None
Description
The following revision doesn't seem to be merged into 10.0. Found while analyzing result difference in ps_ddl1.test:
revno: 4591.1.70
committer: Guilhem Bichot <guilhem.bichot@oracle.com>
branch nick: 5.6-3
timestamp: Sat 2012-11-24 15:45:56 +0100
message:
fix for Bug#13996639 CRASH IN ITEM_REF::FIX_FIELDS ON EXEC OF STORED
FUNCTION WITH ONLY_FULL_GROUP_BY. See per-file comments.
mysql-test/r/ps_ddl1.result:
side affect of the bugfix; this is a good change, as the removed comment says.
sql/sql_lex.cc:
LEX starts clean
sql/sql_optimizer.cc:
If optimize () fails, tag the Lex as "broken"
sql/sql_parse.cc:
At first execution of:
SELECT stored_func()
this happens:
1) body of stored_func is read from mysql.proc
2) body is parsed (sp_compile()) (for each substatement a LEX and some
Items are created)
3) parsing went ok so parse trees are cached (sp_cache_insert())
4) substatement starts executing (SELECT with a NOT IN (subq))
4.1) Item_in_subselect::fix_fields():
if (!(res= engine->prepare()))
{
(*ref)= substitution;
engine->prepare() calls JOIN::prepare() on subq, which calls
resolve_subquery() which starts IN2EXISTS transformation: adds
conditions (using some new Item_ref) to the subquery's WHERE, creates
Item_in_optimizer and puts it in 'substitution'. After
resolve_subquery(), JOIN::prepare() of subq fails in:
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
DBUG_RETURN(-1);
So far, so good.
Thus engine->prepare() fails. Thus we don't do:
(*ref)= substitution;
i.e. the parent of the subquery continues to have its WHERE point to
Item_in_subselect. At this stage we have a broken parse tree, because
subq has been transformed but parent query points to pre-transform
subq. This mess is not rolled back (IN2EXISTS is a complex transform
which does not use change_item_tree()).
ER_MIX_OF_GROUP_FUNC_AND_FIELDS is sent to client.
So far, so good.
At 2nd execution of:
SELECT stored_func()
this happens:
1) cached parse trees of stored_func is read from cache
2) but this is the broken parse tree!
3) as the Item_ref depends on Item_in_optimizer::fix_fields() to set
its '*ref', and as Item_in_optimizer was not stored in parent query,
Item_in_optimizer::fix_fields() is not called, so
Item_ref::fix_fields() crashes.
Summary: first execution broke Item_in_subselect/LEX, 2nd execution reused it.
Solution: first execution marks the fact that it
broke LEX; 2nd execution sees the mark and asks for a
reprepare, which creates new parse trees, and thus works as the first
execution.
A new member m_broken is added to class LEX. It is set to "true" when
JOIN:: prepare () or JOIN:: optimize () fail, because it is possible
that those functions were doing transformations. It is set to "false"
when the Lex is initialized.
sql/sql_resolver.cc:
If prepare () fails, tag the Lex as "broken"
Gliffy Diagrams
Attachments
Issue Links
- is part of
-
MDEV-4784 merge test cases from 5.6
-
- Stalled
-
Activity
- All
- Comments
- Work Log
- History
- Activity
- Transitions
MariaDB doesn't seem to be vulnerable, I mean, there's no crash in this case.