MySQL 8.0.39
Source Code Documentation
Tables_in_user_order_iterator Class Reference

This is an iterator which emits leaf Table_ref nodes in an order suitable for expansion of 'table_name. More...

Public Member Functions

void init (Query_block *query_block, bool qualified)
 
 ~Tables_in_user_order_iterator ()
 
Table_refget_next ()
 

Private Member Functions

void fill_vec (const mem_root_deque< Table_ref * > &tables)
 Fills the vector. More...
 
void add_table (Table_ref *tr)
 

Private Attributes

Query_blockm_query_block {nullptr}
 
bool m_qualified
 True/false if we want to expand 'table_name.*' / '*'. More...
 
Table_refm_next
 If not using the vector: next table to emit. More...
 
std::vector< Table_ref * > * m_vec {nullptr}
 Vector for the complex case. More...
 
uint m_next_vec_pos {0}
 If using the vector: position in vector, of next table to emit. More...
 

Detailed Description

This is an iterator which emits leaf Table_ref nodes in an order suitable for expansion of 'table_name.

*' (qualified asterisk) or '*' (unqualified), fur use by insert_fields().

First here is some background.

1. SELECT T1.*, T2.* FROM T1 NATURAL JOIN T2; has to return all columns of T1 and then all of T2's; whereas SELECT * FROM T1 NATURAL JOIN T2; has to return all columns of T1 and then only those of T2's which are not common with T1. Thus, in the first case a NATURAL JOIN isn't considered a leaf (we have to see through it to find T1.* and T2.*), in the second case it is (we have to ask it for its column set). In the first case, the place to search for tables is thus the Table_ref::next_local list; in the second case it is Table_ref::next_name_resolution_table.

2. SELECT * FROM T1 RIGHT JOIN T2 ON < cond >; is converted, during contextualization, to: SELECT * FROM T2 LEFT JOIN T1 ON < cond >; however the former has to return columns of T1 then of T2, while the latter has to return T2's then T1's. The conversion has been complete: the lists 'next_local', 'next_name_resolution_table' and Query_block::m_current_table_nest are as if the user had typed the second query.

Now to the behaviour of this iterator.

A. If qualified asterisk, the emission order is irrelevant as the caller tests the table's name; and a NATURAL JOIN isn't a leaf. So, we just follow the Table_ref::next_local pointers.

B. If non-qualified asterisk, the order must be the left-to-right order as it was in the query entered by the user. And a NATURAL JOIN is a leaf. So:

B.i. if there was no RIGHT JOIN, then the user-input order is just that of the 'next_name_resolution' pointers.

B.ii. otherwise, then the order has to be found by a more complex procedure (function build_vec()):

  • first we traverse the join operators, taking into account operators which had a conversion from RIGHT to LEFT JOIN, we recreate the user-input order and store leaf TABLE_LISTs in that order in a vector.
  • then, in the emission phase, we just emit tables from the vector.

Sequence of calls: constructor, init(), [get_next() N times], destructor.

Constructor & Destructor Documentation

◆ ~Tables_in_user_order_iterator()

Tables_in_user_order_iterator::~Tables_in_user_order_iterator ( )
inline

Member Function Documentation

◆ add_table()

void Tables_in_user_order_iterator::add_table ( Table_ref tr)
inlineprivate

◆ fill_vec()

void Tables_in_user_order_iterator::fill_vec ( const mem_root_deque< Table_ref * > &  tables)
inlineprivate

Fills the vector.

Parameters
tableslist of tables and join operators

◆ get_next()

Table_ref * Tables_in_user_order_iterator::get_next ( )
inline

◆ init()

void Tables_in_user_order_iterator::init ( Query_block query_block,
bool  qualified 
)
inline

Member Data Documentation

◆ m_next

Table_ref* Tables_in_user_order_iterator::m_next
private

If not using the vector: next table to emit.

◆ m_next_vec_pos

uint Tables_in_user_order_iterator::m_next_vec_pos {0}
private

If using the vector: position in vector, of next table to emit.

◆ m_qualified

bool Tables_in_user_order_iterator::m_qualified
private

True/false if we want to expand 'table_name.*' / '*'.

◆ m_query_block

Query_block* Tables_in_user_order_iterator::m_query_block {nullptr}
private

◆ m_vec

std::vector<Table_ref *>* Tables_in_user_order_iterator::m_vec {nullptr}
private

Vector for the complex case.

As the complex case is expected to be rare, we allocate the vector only if needed. nullptr otherwise.


The documentation for this class was generated from the following file: