一个查询块对应着一条基本的 SELECT 语句的语法结构
class Query_block : public Query_term {
/**
Intrusive linked list of all query blocks within the same
query expression.
*/
Query_block *next{nullptr};
/// The query expression containing this query block.
Query_expression *master{nullptr};
/// The first query expression contained within this query block.
Query_expression *slave{nullptr};
/// Intrusive double-linked global list of query blocks.
Query_block *link_next{nullptr};
Query_block **link_prev{nullptr};
Query_expression *master_query_expression() const { return master; }
Query_expression *first_inner_query_expression() const { return slave; }
Query_block *outer_query_block() const { return master->outer_query_block(); }
Query_block *next_query_block() const { return next; }
Query_block *next_select_in_list() const { return link_next; }
}
查询表达式中的查询块形成一个树形结构,表达了嵌套形式的查询操作
查询表达式由一个或多个查询块组成,多个查询块表示查询表达式有 UNION、INTERSECT、EXCEPT操作,或者利用查询块来描述子查询结构
class Query_expression {
/**
Intrusive double-linked list of all query expressions
immediately contained within the same query block.
*/
Query_expression *next;
Query_expression **prev;
/**
The query block wherein this query expression is contained,
NULL if the query block is the outer-most one.
*/
Query_block *master;
/// The first query block in this query expression.
Query_block *slave;
/// @return the query block this query expression belongs to as subquery
Query_block *outer_query_block() const { return master; }
/// @return the first query block inside this query expression
Query_block *first_query_block() const { return slave; }
/// @return the next query expression within same query block (next subquery)
Query_expression *next_query_expression() const { return next; }
}
从 LEX 可以定位到语法树中最外层的查询表达式和第一个查询块,也可以直接遍历所有的查询块
然后根据以上查询块和查询表达式的关系,从最外层的查询表达式的第一个查询块进行查询处理
struct LEX : public Query_tables_list {
Query_expression *unit; ///< Outer-most query expression
/// @todo: query_block can be replaced with unit->first-select()
Query_block *query_block; ///< First query block
Query_block *all_query_blocks_list; ///< List of all query blocks
private:
/* current Query_block in parsing */
Query_block *m_current_query_block;
}
Q1: union
+ order by
查询
select * from t1 union select * from t2 union select * from t3 order by 1;
Q2: union
+ intersect
+ except
+ order by
+ limit
查询
((
SELECT * FROM t1
UNION SELECT * FROM t2
UNION SELECT * FROM t3
ORDER BY c1 LIMIT 5
)
INTERSECT
(((
SELECT *
FROM t3
ORDER BY c1
LIMIT 1
)
)
EXCEPT
SELECT * FROM t4
)
ORDER BY c1
LIMIT 4
)
ORDER BY c1
LIMIT 3;
Q3: 带 view
和from
子句子查询的查询
(select * from t1) union (select tmp1.* from (select * from t2) as tmp1, (select * from t3 union select * from v1) as tmp2);
Q4:where
子句带子查询的查询
select * from t1 where c1 in (select c2 from t2 where t2.c1 < 20);
class Query_block {
SQL_I_List<Table_ref> m_table_list // FROM 字句中的所有表列表,使用 Table_ref::next_local 进行遍历
SQL_I_List<ORDER> order_list //ORDER BY 子句字段列表
QL_I_List<ORDER> group_list //GROUP BY 子句字段列表
table_map outer_join //outer join 查询中所有 inner tables 的 bitmap
mem_root_deque<Table_ref *> sj_nests // semi-join 的表 nests 列表
mem_root_deque<Item *> fields // join 和 filtering 之后所需的 fields,包括 select list(project所需字段)、group by list(分组所需字段)、having clause(having字句字段)、window clause(窗口函数字段)、order by clause(order by字段)
Item *select_limit // LIMIT 子句
Item *offset_limit // LIMIT .. OFFSET 子句
Item *m_where_cond // WHERE 子句
Item *m_having_cond // HAVING 子句
}
class Table_ref {
Table_ref *next_local //某一层 SELECT 的 FROM 中表的链表指针
const char *db
const char *table_name
Item *m_join_cond // JOIN 条件
List<String> *join_using_fields //JOIN ...USING 对应 USING 子句宏的 field 名称列表
/*嵌套连接
1.代表外连接中的内部表(inner tables);
2.代表内连接中括号内的表(resolve时被消除);
3.代表派生表或视图中引用的表;
4.代表semi-join嵌套中的表;
5.代表子查询中的表;
*/
NESTED_JOIN *nested_join
Table_ref *embedding //
mem_root_deque<Table_ref *> *join_list //
}
Q5: 普通JOIN
查询
select * from t3, (t1, t2) where t1.c1 = t2.c2;
Q6:
select * from t1 left outer join(t2, t3) on t1.c1 = t2.c1 and t1.c2 = t3.c2 where t1.c1 = t2.c2;
本文代码版本为:MySQL 8.1.0
示例中表和视图结构create table t1(c1 int, c2 int, c3 int); create table t2(c1 int, c2 int, c3 int); create table t3(c1 int, c2 int, c3 int); create table t4(c1 int, c2 int, c3 int); create table t5(c1 int, c2 int, c3 int); create view v1 as select * from t5;