• Rex's avatar
    MDEV-31995 Bogus error executing PS for query using CTE with renaming of columns · eb8053b3
    Rex authored
    This commit addresses column naming issues with CTEs in the use of prepared
    statements and stored procedures. Usage of either prepared statements or
    procedures with Common Table Expressions and column renaming may be affected.
    
    There are three related but different issues addressed here.
    
    1) First execution issue. Consider the following
    
    prepare s from "with cte (col1, col2) as (select a as c1, b as c2 from t
    order by c1) select col1, col2 from cte";
    execute s;
    
    After parsing, items in the select are named (c1,c2), order by (and group by)
    resolution is performed, then item names are set to (col1, col2).
    When the statement is executed, context analysis is again performed, but
    resolution of elements in the order by statement will not be able to find c1,
    because it was renamed to col1 and remains this way.
    
    The solution is to save the names of these items during context resolution
    before they have been renamed. We can then reset item names back to those after
    parsing so first execution can resolve items referred to in order and group by
    clauses.
    
    2) Second Execution Issue
    
    When the derived table contains more than one select 'unioned' together we could
    reasonably think that dealing with only items in the first select (which
    determines names in the resultant table) would be sufficient.  This can lead to
    a different problem.  Consider
    
    prepare st from "with cte (c1,c2) as
      (select a as col1, sum(b) as col2 from t1 where a > 0 group by col1
        union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3)
      select * from cte where c1=1";
    
    When the optimizer (only run during the first execution) pushes the outside
    condition "c1=1" into every select in the derived table union, it renames the
    items to make the condition valid.  In this example, this leaves the first item
    in the second select named 'c1'.  The second execution will now fail 'group by'
    resolution.
    
    Again, the solution is to save the names during context analysis, resetting
    before subsequent resolution, but making sure that we save/reset the item
    names in all the selects in this union.
    
    3) Memory Leak
    
    During parsing Item::set_name() is used to allocate memory in the statement
    arena.  We cannot use this call during statement execution as this represents
    a memory leak.  We directly set the item list names to those in the column list
    of this CTE (also allocated during parsing).
    
    Approved by Igor Babaev <igor@mariadb.com>
    eb8053b3
cte_nonrecursive.test 49.4 KB