Skip to content

Conversation

@Olernov
Copy link
Contributor

@Olernov Olernov commented Dec 14, 2025

  • The Jira issue number for this PR is: MDEV-38045

Description

This PR follows #4463.

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

How can this PR be tested?

./mtr opt_hints_qb_name_path

Basing the PR against the correct MariaDB version

  • This is a new feature or a refactoring, and the PR is based against the main branch.
  • This is a bug fix, and the PR is based against the earliest maintained branch in which the bug can be reproduced.

PR quality check

  • I checked the CODING_STANDARDS.md file and my PR conforms to this where appropriate.
  • For any trivial modifications to the PR, I am ok with the reviewer making the changes themselves.

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;

Key changes:

1. Two-stage hint resolution
   - Introduced hint_resolution_stage enum (EARLY/LATE) to control
     when different hint types are resolved:
     - EARLY stage: before opening tables (QB_NAME, MERGE hints)
     - LATE stage: after opening tables (all other hints)

2. Implicit QB name support
   - Derived table/view/CTE aliases can now be used as implicit query
     block names in hint syntax: @alias, table@alias
   - Derived tables inside views can be addressed from outer queries
     using their aliases
@Olernov Olernov force-pushed the 12.3-MDEV-38045-qb-tidb branch from 0135586 to 3818d14 Compare December 14, 2025 10:10
…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`
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.

3 participants