![]() |
MySQL 8.4.4
Source Code Documentation
|
Query term tree structure. More...
#include <query_term.h>
Public Member Functions | |
Query_term * | pushdown_limit_order_by (Query_term_set_op *parent=nullptr) |
Called after contextualization to simplify query, c.f. More... | |
bool | validate_structure (const Query_term *parent, int depth=0) const |
Return true if structure is too deep, i.e. More... | |
std::pair< bool, bool > | redundant_order_by (Query_block *block, int level) |
Determine if we have a redundant ORDER BY in block. More... | |
virtual Query_term_type | term_type () const =0 |
Get the node tree type. More... | |
virtual const char * | operator_string () const =0 |
Get the node type description. More... | |
virtual | ~Query_term ()=default |
Node destructor. More... | |
virtual size_t | child_count () const |
Get the number of children this node has. More... | |
virtual void | label_children ()=0 |
Set the correct value of Query_term::m_sibling_idx recursively for set operations. More... | |
Query_term_set_op * | parent () const |
Getter for m_parent, q.v. More... | |
void | set_sibling_idx (uint idx) |
Setter for m_sibling_idx , q.v. More... | |
uint | sibling_idx () |
Getter for m_sibling_idx , q.v. More... | |
virtual void | cleanup (bool full) |
Reset resources used. More... | |
virtual void | destroy_tree ()=0 |
Destroy the query term tree structure. More... | |
virtual bool | open_result_tables (THD *thd, int level) |
Open tmp tables for the tree of set operation query results, by recursing. More... | |
virtual void | debugPrint (int level, std::ostringstream &buf) const =0 |
Print the tree rooted at this node to buf. More... | |
void | printPointers (std::ostringstream &buf) const |
Print the pointer of this node and its parent to buf. More... | |
virtual Query_block * | query_block () const =0 |
The query_block which holds the ORDER BY and LIMIT information for this set operation. More... | |
void | set_setop_query_result (Query_result *rs) |
Setter for m_setop_query_result, q.v. More... | |
Query_result * | setop_query_result () |
Getter for m_setop_query_result, q.v. More... | |
Query_result_union * | setop_query_result_union () |
Getter for m_setop_query_result, q.v. Use only if we can down cast. More... | |
void | cleanup_query_result (bool full) |
Cleanup m_setop_query_result, q.v. More... | |
void | set_owning_operand () |
Setter for m_owning_operand, q.v. More... | |
bool | owning_operand () |
Getter for m_owning_operand, q.v. More... | |
void | set_result_table (Table_ref *tl) |
Setter for m_result_table, q.v. More... | |
Table_ref & | result_table () |
Getter for m_result_table, q.v. More... | |
void | set_fields (mem_root_deque< Item * > *fields) |
mem_root_deque< Item * > * | fields () |
Static Public Member Functions | |
static void | indent (int level, std::ostringstream &buf) |
Print blank space indentation (unit: two) to buf according to level. More... | |
static void | print_order (const THD *thd, String *str, ORDER *ord, enum_query_type query_type) |
Print into str the order indicated in ord, using standard print_for_order Used by traditional explain. More... | |
Protected Attributes | |
Query_term_set_op * | m_parent {nullptr} |
Back pointer to the node whose child we are, or nullptr (root term). More... | |
uint | m_sibling_idx {0} |
If parent is non-null, this holds the index of the current sibling. More... | |
Query_result * | m_setop_query_result {nullptr} |
The query result for this term. More... | |
bool | m_owning_operand {false} |
The operand of a n-ary set operation (that owns the common query result) has this set to true. More... | |
Table_ref * | m_result_table {nullptr} |
Result temporary table for the set operation, if applicable. More... | |
mem_root_deque< Item * > * | m_fields {nullptr} |
Used only when streaming, i.e. More... | |
Query term tree structure.
There are five node types, cf. Query_term_type. Leaf nodes are Query_block objects. We have three kinds of n-ary set operation nodes corresponding to INTERSECT, UNION and EXCEPT. Finally, we have a "unary" node which essentially adds a ORDER BY/LIMIT over another node.
Query blocks serve a dual purpose: they represent the query specification and table constructors of the query. As such they are the leaf nodes of the query tree. But they also serve as a way to realize ORDER BY and LIMIT for non-leaf nodes, accessed via the function Query_term::query_block(). Therefore, every non-leaf node in the tree has a companion Query_block to hold ORDER BY and LIMIT information. For the leaf nodes, which are themselves query blocks, the query_block() function just returns a pointer to self, i.e. the leaf nodes handle ORDER BY and LIMIT themselves.
Example: ((SELECT * FROM t1 UNION SELECT * FROM t2 UNION ALL SELECT * FROM t3 ORDER BY a LIMIT 5) INTERSECT (((SELECT * FROM t3 ORDER BY a LIMIT 4) ) EXCEPT SELECT * FROM t4) ORDER BY a LIMIT 4) ORDER BY -a LIMIT 3; -> m_query_term +------------------+ slave(s) +--------------|-Query_expression |------------------+ | +------------------+ | V post_ | +-------------------+processing_ +----------------------+ | | Query_term_unary |block() |Query_block | | | |----------->|order by -(`a) limit 3| | +-------------------+ +----------------------+ | |m_children | | +-----------------------+ +----------------------+ | | |Query_term_intersect | |Query_block | | +>|last distinct index: 1 |-->|order by `a` limit 4 | | +-----------------------+ +----------------------+ | |m_children | | +-----------------------+ +----------------------+ | | |Query_term_union | |Query_block | | +->|last distinct index: 1 |-->|order by `a` limit 5 | | | +-----------------------+ +----------------------+ | | |m_children | | | +------------+ SELECT * FROM t1 / | +-->|Query_block | <---------------------------------+ | | +------------+ ----------------------------------+ next | | \ | | +------------+ SELECT * FROM t2 / | +-->|Query_block | <---------------------------------+ | | +------------+ ----------------------------------+ next | | \ | | +------------+ SELECT * FROM t3 / | +-->|Query_block | <---------------------------------+ | +------------+ ----------------------------------+ next | \ | +-----------------------+ +------------+ | | |Query_term_except |->|Query_block | | +->|last distinct index: 1 | +------------+ | +-----------------------+ | |m_children | | +----------------------+ | | |Query_block | SELECT * FROM t3 / +-->|order by `a` limit 4 | <------------------------+ | +----------------------+ -------------------------+ next | \ | +------------+ SELECT * FROM t4 | +-->|Query_block | <------------------------------------+ +------------+
Note that all leaf query blocks representing the query specifications are linked under Query_expression via their next pointers. The nesting is achieved by the arrows on the left side of the figure, via the nodes' m_children members. The four classes Query_term_unary and Query_term_{union, intersect, except} are modelled via the base class Query_term_set_op which contains a m_children member. Each of these also contain a Query_block which will handle its order by and/or limit clauses. These are similar to the old so-called "fake_query_block" (which is now gone), and are not linked in with "next" pointers.
The is also a back pointer from the children nodes to the parent Query_term object (not shown).
In the simple case of a single query specification (or table value constructor or explicit table), there is no super-structure over the Query_block linked from the Query_expression, i.e. Query_expression's m_query_term member is just a Query_block.
The query blocks (QT_QUERY_BLOCK nodes) corresponding to the query specification (or table value constructors) are prepared and optimized by running over them from the Query_expression via the slave/next pointers as before. There are separate methods which handle prepare and optimization for non-leaves, i.e. nodes of types QT_UNARY, QT_INTERSECT, QT_EXCEPT and QT_UNION.
We also define an iterator class (Query_terms) for iterating over all the nodes in the tree, see also Query_expression::query_terms() for its use. When possible, we access all nodes using iterators.
The built structure can be traced with the debug trace keyword "ast", e.g. as SET SESSION debug = 'd,ast:O,/tmp/mysqld.trace';
|
virtualdefault |
Node destructor.
|
inlinevirtual |
|
inlinevirtual |
Reset resources used.
full | do full cleanup. Same semantics as for Query_expression's cleanup |
Reimplemented in Query_term_set_op, and Query_block.
void Query_term::cleanup_query_result | ( | bool | full | ) |
Cleanup m_setop_query_result, q.v.
|
pure virtual |
Print the tree rooted at this node to buf.
Call on top level with level==0
level | level we are at in tree. |
buf | the buffer to format output into |
Implemented in Query_term_union, Query_term_intersect, Query_term_except, Query_term_unary, and Query_block.
|
pure virtual |
Destroy the query term tree structure.
Implemented in Query_term_set_op, and Query_block.
|
inline |
|
static |
Print blank space indentation (unit: two) to buf according to level.
Minion.
level | level we are at in tree. |
buf | the buffer to format output into |
|
pure virtual |
Set the correct value of Query_term::m_sibling_idx
recursively for set operations.
For Query_term_unary
, this is done in its constructor. A no-op for Query_block
. See also set_sibling_idx
.
Implemented in Query_term_set_op, and Query_block.
|
inlinevirtual |
Open tmp tables for the tree of set operation query results, by recursing.
thd | session context |
level | level in the tree, top should be called with 0. |
Reimplemented in Query_block, and Query_term_set_op.
|
pure virtual |
Get the node type description.
Implemented in Query_term_union, Query_term_intersect, Query_term_except, Query_term_unary, and Query_block.
|
inline |
Getter for m_owning_operand, q.v.
|
inline |
Getter for m_parent, q.v.
|
static |
Print into str the order indicated in ord, using standard print_for_order Used by traditional explain.
thd | session state |
str | string to accumulate formatted output into |
ord | the ORDER to be printed |
query_type | controls how printing happens |
void Query_term::printPointers | ( | std::ostringstream & | buf | ) | const |
Print the pointer of this node and its parent to buf.
Minion.
buf | the buffer to format output into |
Query_term * Query_term::pushdown_limit_order_by | ( | Query_term_set_op * | parent = nullptr | ) |
Called after contextualization to simplify query, c.f.
sql_yacc.yy CONTEXTUALIZE_VIEW. It also sets up the parent pointers.
parent | parent of this if any |
|
pure virtual |
The query_block which holds the ORDER BY and LIMIT information for this set operation.
Note that for the case where the root is a simple query block, this will return self.
Implemented in Query_term_set_op, and Query_block.
std::pair< bool, bool > Query_term::redundant_order_by | ( | Query_block * | block, |
int | level | ||
) |
Determine if we have a redundant ORDER BY in block.
Used during prepare.
block | the query block |
level | the current nesting level |
Not very object oriented with this switch, but nice to keep logic in one place.
Logic here presumes that query expressions that only add limit (not order by) will have been pushed down
|
inline |
Getter for m_result_table, q.v.
|
inline |
|
inline |
Setter for m_owning_operand, q.v.
|
inline |
Setter for m_result_table, q.v.
|
inline |
Setter for m_setop_query_result, q.v.
|
inline |
Setter for m_sibling_idx
, q.v.
|
inline |
Getter for m_setop_query_result, q.v.
|
inline |
Getter for m_setop_query_result, q.v. Use only if we can down cast.
|
inline |
Getter for m_sibling_idx
, q.v.
|
pure virtual |
Get the node tree type.
Implemented in Query_term_union, Query_term_intersect, Query_term_except, Query_term_unary, and Query_block.
bool Query_term::validate_structure | ( | const Query_term * | parent, |
int | depth = 0 |
||
) | const |
Return true if structure is too deep, i.e.
more than MAX_SELECT_NESTING. As a side effect is also gives the post processing block a select number, this is done late so as to get numbers higher the leaf blocks, and in inside out order, so that the top set operation block will have the highest number.
parent | the real parent in the tree as visited recursively |
depth | the current depth in the tree, starting at 0 at the top. It is increased with one for each time we recurse into a child. |
|
protected |
Used only when streaming, i.e.
not materialized result set
|
protected |
The operand of a n-ary set operation (that owns the common query result) has this set to true.
It is always the first one.
|
protected |
Back pointer to the node whose child we are, or nullptr (root term).
Result temporary table for the set operation, if applicable.
|
protected |
The query result for this term.
Shared between n-ary set operands, the first one holds it, cf. owning_operand. Except at top level, this is always a Query_result_union.
|
protected |
If parent is non-null, this holds the index of the current sibling.
Used for efficient iterator traversal up and down the tree.