@@ -1663,72 +1663,107 @@ static int subq_sj_candidate_cmp(Item_exists_subselect* const *el1,
1663
1663
1664
1664
/* *
1665
1665
Update table reference information for conditions and expressions due to
1666
- query blocks having been merged in from derived tables and due to
1666
+ query blocks having been merged in from derived tables/views and due to
1667
1667
semi-join transformation.
1668
1668
1669
1669
This is needed for two reasons:
1670
1670
1671
1671
1. Since table numbers are changed, we need to update used_tables
1672
1672
information for all conditions and expressions that are possibly touched.
1673
- Notice that requirements are different for the two transforms:
1674
- semi-join only changes table numbers for tables from the subquery,
1675
- while derived tables may also change table numbers from the query block
1676
- being merged into.
1677
1673
1678
1674
2. For semi-join, some column references are changed from outer references
1679
1675
to local references.
1680
1676
1681
- Notice that function needs to recursively walk down into join nests,
1677
+ The function needs to recursively walk down into join nests,
1682
1678
in order to cover all conditions and expressions.
1683
1679
1680
+ For a semi-join, tables from the subquery are added last in the query block.
1681
+ This means that conditions and expressions from the outer query block
1682
+ are unaffected. But all conditions inside the semi-join nest, including
1683
+ join conditions, must have their table numbers changed.
1684
+
1685
+ For a derived table/view, tables from the subquery are merged into the
1686
+ outer query, and this function is called for every derived table that is
1687
+ merged in. This algorithm only works when derived tables are merged in
1688
+ the order of their original table numbers.
1689
+
1690
+ A hypothetical example with a triple self-join over a mergeable view:
1691
+
1692
+ CREATE VIEW v AS SELECT t1.a, t2.b FROM t1 JOIN t2 USING (a);
1693
+ SELECT v1.a, v1.b, v2.b, v3.b
1694
+ FROM v AS v1 JOIN v AS v2 ON ... JOIN v AS v3 ON ...;
1695
+
1696
+ The analysis starts with three tables v1, v2 and v3 having numbers 0, 1, 2.
1697
+ First we merge in v1, so we get (t1, t2, v2, v3). v2 and v3 are shifted up.
1698
+ Tables from v1 need to have their table numbers altered (actually they do not
1699
+ since both old and new numbers are 0 and 1, but this is a special case).
1700
+ v2 and v3 are not merged in yet, so we delay pullout on them until they
1701
+ are merged. Conditions and expressions from the outer query are not resolved
1702
+ yet, so regular resolving will take of them later.
1703
+ Then we merge in v2, so we get (t1, t2, t1, t2, v3). The tables from this
1704
+ view gets numbers 2 and 3, and v3 gets number 4.
1705
+ Because v2 had a higher number than the tables from v1, the join nest
1706
+ representing v1 is unaffected. And v3 is still not merged, so the only
1707
+ join nest we need to consider is v2.
1708
+ Finally we merge in v3, and then we have tables (t1, t2, t1, t2, t1, t2),
1709
+ with numbers 0 through 5.
1710
+ Again, since v3 has higher number than any of the already merged in views,
1711
+ only this join nest needs the pullout.
1712
+
1684
1713
@param parent_select Query block being merged into
1685
1714
@param removed_select Query block that is removed (subquery)
1686
- @param tlist List of tables to be checked, given as
1687
- semi_join: List of tables from subquery
1688
- derived table: List of tables from outer query
1689
- recursive call: List of tables from join nest
1690
- @param table_adjust Number of positions that a derived table nest is
1691
- adjusted, used to fix up semi-join related fields.
1692
- Tables are adjusted from position N to N+table_adjust
1715
+ @param tr Table object this pullout is applied to
1716
+ @param table_adjust Number of positions that a derived table nest is
1717
+ adjusted, used to fix up semi-join related fields.
1718
+ Tables are adjusted from position N to N+table_adjust
1693
1719
*/
1694
1720
1695
1721
static void fix_tables_after_pullout (st_select_lex *parent_select,
1696
1722
st_select_lex *removed_select,
1697
- List< TABLE_LIST> *tlist ,
1723
+ TABLE_LIST *tr ,
1698
1724
uint table_adjust)
1699
1725
{
1700
- List_iterator<TABLE_LIST> it (*tlist);
1701
- TABLE_LIST *table;
1702
- while ((table= it++))
1726
+ if (tr->is_merged ())
1703
1727
{
1704
- if (table->is_merged ())
1728
+ // Update select list of merged derived tables:
1729
+ for (Field_translator *transl= tr->field_translation ;
1730
+ transl < tr->field_translation_end ;
1731
+ transl++)
1705
1732
{
1706
- // Update select list of merged derived tables:
1707
- for (Field_translator *transl= table->field_translation ;
1708
- transl < table->field_translation_end ;
1709
- transl++)
1710
- {
1711
- DBUG_ASSERT (transl->item ->fixed );
1712
- transl->item ->fix_after_pullout (parent_select, removed_select);
1713
- }
1714
- // Update used table info for the WHERE clause of the derived table
1715
- DBUG_ASSERT (!table->derived_where_cond ||
1716
- table->derived_where_cond ->fixed );
1717
- if (table->derived_where_cond )
1718
- table->derived_where_cond ->fix_after_pullout (parent_select,
1719
- removed_select);
1733
+ DBUG_ASSERT (transl->item ->fixed );
1734
+ transl->item ->fix_after_pullout (parent_select, removed_select);
1720
1735
}
1721
- if ( table-> join_cond () && table-> join_cond ()-> fixed )
1722
- table-> join_cond ()-> fix_after_pullout (parent_select, removed_select);
1723
- if (table-> nested_join )
1724
- {
1725
- // In case a derived table is merged-in, these fields need adjustment:
1726
- table-> nested_join -> sj_corr_tables <<= table_adjust ;
1727
- table-> nested_join -> sj_depends_on <<= table_adjust;
1736
+ // Update used table info for the WHERE clause of the derived table
1737
+ DBUG_ASSERT (!tr-> derived_where_cond ||
1738
+ tr-> derived_where_cond -> fixed );
1739
+ if (tr-> derived_where_cond )
1740
+ tr-> derived_where_cond -> fix_after_pullout (parent_select,
1741
+ removed_select) ;
1742
+ }
1728
1743
1729
- fix_tables_after_pullout (parent_select, removed_select,
1730
- &table->nested_join ->join_list , table_adjust);
1731
- }
1744
+ /*
1745
+ If join_cond() is fixed, it contains a join condition from a subquery
1746
+ that has already been resolved. Call fix_after_pullout() to update
1747
+ used table information since table numbers may have changed.
1748
+ If join_cond() is not fixed, it contains a condition that was generated
1749
+ in the derived table merge operation, which will be fixed later.
1750
+ This condition may also contain a fixed part, but this is saved as
1751
+ derived_where_cond and is pulled out explicitly.
1752
+ */
1753
+ if (tr->join_cond () && tr->join_cond ()->fixed )
1754
+ tr->join_cond ()->fix_after_pullout (parent_select, removed_select);
1755
+
1756
+ if (tr->nested_join )
1757
+ {
1758
+ // In case a derived table is merged-in, these fields need adjustment:
1759
+ tr->nested_join ->sj_corr_tables <<= table_adjust;
1760
+ tr->nested_join ->sj_depends_on <<= table_adjust;
1761
+
1762
+ List_iterator<TABLE_LIST> it (tr->nested_join ->join_list );
1763
+ TABLE_LIST *child;
1764
+ while ((child= it++))
1765
+ fix_tables_after_pullout (parent_select, removed_select, child,
1766
+ table_adjust);
1732
1767
}
1733
1768
}
1734
1769
@@ -2123,8 +2158,7 @@ SELECT_LEX::convert_subquery_to_semijoin(Item_exists_subselect *subq_pred)
2123
2158
sj_nest->sj_cond ()->fix_after_pullout (this , subq_select);
2124
2159
2125
2160
// Update table map for semi-join nest's WHERE condition and join conditions
2126
- fix_tables_after_pullout (this , subq_select,
2127
- &sj_nest->nested_join ->join_list , 0 );
2161
+ fix_tables_after_pullout (this , subq_select, sj_nest, 0 );
2128
2162
2129
2163
// TODO fix QT_
2130
2164
DBUG_EXECUTE (" where" ,
@@ -2331,7 +2365,7 @@ bool SELECT_LEX::merge_derived(THD *thd, TABLE_LIST *derived_table)
2331
2365
remap_tables (thd);
2332
2366
2333
2367
// Update table info of referenced expressions after query block is merged
2334
- fix_tables_after_pullout (this , derived_select, &top_join_list , table_adjust);
2368
+ fix_tables_after_pullout (this , derived_select, derived_table , table_adjust);
2335
2369
2336
2370
if (derived_select->is_ordered ())
2337
2371
{
0 commit comments