Skip to content
/ server Public

MDEV-38045 support implicit names and paths to query blocks in QB_NAME hints#4777

Open
Olernov wants to merge 3 commits intomainfrom
13.0-MDEV-38045
Open

MDEV-38045 support implicit names and paths to query blocks in QB_NAME hints#4777
Olernov wants to merge 3 commits intomainfrom
13.0-MDEV-38045

Conversation

@Olernov
Copy link
Contributor

@Olernov Olernov commented Mar 10, 2026

  1. This patch implements support for implicit query block (QB) names in
    optimizer hints, allowing hints to reference query blocks and tables
    within derived tables, views and CTEs without requiring explicit
    QB_NAME hints.

  2. Extended QB_NAME hint to support path-based addressing of query blocks
    nested within views, derived tables, and CTEs, following TiDB's syntax.
    New syntax:

      QB_NAME(name, query_block_path), where
        query_block_path ::= query_block_path_element
                              [ {. query_block_path_element }... ]
        query_block_path_element ::= @ qb_path_element_select_num |
                                        qb_path_element_view_sel
        qb_path_element_view_sel ::= qb_path_element_view_name
                                      [ @ qb_path_element_select_num ]

Olernov added 3 commits March 10, 2026 20:49
1. `TABLE_LIST::init_derived` is called twice during derived tables
processing: first time from `mysql_derived_init` and the second
time from `mysql_derived_prepare`. Both times there is a check
for whether an optimizer hint or switch setting allows a derived
table to be merged.
However, it is not necessary to restrict merging during the
initialization call, it is enough to apply hints/switch setting
during the preparation phase.

2. `open_normal_and_derived_tables()` runs processing of all phases
of derived tables handling with a single call. But for future
commits it is required to separate DT initialization from other
phases. This commit implements the separation.
This patch implements support for implicit query block (QB) names in
optimizer hints, allowing hints to reference query blocks and tables
within derived tables, views and CTEs without requiring explicit
QB_NAME hints.

Examples.
-- Addressing a table inside a derived table using implicit QB name
select /*+ no_index(t1@dt) */ *
  from (select * from t1 where a > 10) as DT;
-- this is an equivalent to:
select /*+ no_index(t1@dt) */ * from
  (select /*+ qb_name(dt)*/ * from t1 where a > 10) as DT;
-- Addressing a query block corresponding to the derived table
select /*+ no_bnl(@dt) */ *
  from (select * from t1, t2 where t.1.a > t2.a) as DT;

-- View
create view v1 as select * from t1 where a > 10 and b > 100;
-- referencing a table inside a view by implicit QB name:
select /*+ index_merge(t1@v1 idx_a, idx_b) */ *
  from v1, t2 where v1.a = t2.a;
-- equivalent to:
create view v1 as select /*+ qb_name(qb_v1) */ *
  from t1 where a > 10 and b > 100;
select /*+ index_merge(t1@qb_v1 idx_a, idx_b) */ *
  from v1, t2 where v1.a = t2.a;

-- CTE
with aless100 as (select a from t1 where b <100)
  select /*+ index(t1@aless100) */ * from aless100;
-- equivalent to:
with aless100 as (select /*+ qb_name(aless100) */ a from t1 where b <100)
  select /*+ index(t1@aless100) */ * from aless100;

Limitations:
  - Only SELECT statements support implicit QB names. DML operations
    (UPDATE, DELETE, INSERT) only support explicit QB names
…blocks

Extended QB_NAME hint to support path-based addressing of query blocks
nested within views, derived tables, and CTEs, following TiDB's syntax.

New syntax:
  QB_NAME(name, query_block_path), where
    query_block_path ::= query_block_path_element
                          [ {. query_block_path_element }... ]
    query_block_path_element ::= @ qb_path_element_select_num |
                                    qb_path_element_view_sel
    qb_path_element_view_sel ::= qb_path_element_view_name
                                  [ @ qb_path_element_select_num ]

For example,
  `SELECT /*+ qb_name(qb_v1, v1) */* FROM v1`
The name `qb_v1` is assigned to the inner query block of the view `v1`.

  `SELECT /*+ qb_name(qb_v1, v1@sel_1) */* FROM v1`
Means the same but specifies that `v1` is present in SELECT#1 of the current
query block.

  `SELECT /*+ qb_name(qb_v1, v1@sel_1 .@sel_2) */* FROM v1`
This means SELECT#2 of view `v1`, which is present in SELECT#1 of
the current query block, gets the name `qb_v1`.

It is possible to specify not only view names but also derived tables
and CTE's in the path.

Views and derived tables may be nested on multiple levels, for example:
  `SELECT /*+ qb_name(dt2_dt1_v1_1, dt1 .dt2 .v2 .@SEL_2)
              no_index(t1@dt2_dt1_v1_1)*/ v1.*
  FROM v1 JOIN (SELECT v1.* FROM v1 JOIN (SELECT * FROM v2) dt2) dt1`

Limitations:
  - Only SELECT statements support QB names with path. DML operations
    (UPDATE, DELETE, INSERT) only support explicitly defined QB names
@Olernov
Copy link
Contributor Author

Olernov commented Mar 10, 2026

This is a compilation of #4692 and #4700. Both PRs were reviewed and approved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant