我们都知道 SQL 语句经过词法分析器时,识别扫描输入的 SQL 语句,将关键词、标识符、常量等分解转换成独立的 tokens,进一步在语法分析阶段根据语法规则检查 tokens 序列的结构并不断 shift 、reduce 构建成 SQL 语法解析树。
在 MySQL 中,撇去解析树构建过程中的结构,最终生成语法树最重要的两个结构就是 Query_expression
和 Query_block
,
Query_expression
对应 <query expression>
用于描述查询表达式
(SELECT column1 FROM table1 WHERE condition1)
UNION
(SELECT column2 FROM table2 WHERE condition2);
Query_block
则对应 <query specification>
用以描述查询规范或定义,表示一个 SELECT
主体部分,通常包括查询的各个组成部分,例如要选择的列、查询的表、过滤条件等。
SELECT
[DISTINCT | ALL] select_list
FROM
table_reference
[WHERE
search_condition]
[GROUP BY
grouping_column_reference,...]
[HAVING
search_condition]
[ORDER BY
order_column_reference [ASC | DESC],...];
SQL 表达式可能是一条简单的 SELECT
:
select * from t1;
也可能是多条 SELECT
的代数运算,例如: UNION
、INTERSET
或者 EXCEPT
运算。
select * from t1 union select * from t2 union select * from t3 order by 1;
所以 Query_expression
的数据结构中主要维护的是表达式或者语句之间关系
class Query_expression {
Query_expression *next;
Query_expression **prev;
Query_block *master;
Query_block *slave;
}
而 Query_block
代表的是某条具体的 SQL,所以SELECT
语句中的所有 Clause
都在 Query_block
中
<select list>
<table expression>
、<from clause>
、<table reference>
<where clause>
<group by clause>
<having clause>
<order by clause>
<rollup clause>
class Query_block : public Query_term
mem_root_deque<Item*> fields;
SQL_I_List<Table_ref> m_table_list;
Item *m_where_cond;
Item *m_having_cond;
SQL_I_List<ORDER> order_list;
SQL_I_List<ORDER> group_list;
Item *select_limit;
Item *offset_limit;
Prealloced_array<Item_rollup_group_item*, 4> rollup_group_items;
Prealloced_array<Item_rollup_sum_switcher*, 4> rollup_sums;
LEX *parent_lex;
Query_block *next;
Query_expression *master;
Query_expression *slave;
Query_block *link_next;
Query_block **link_prev;
Query_result *m_query_result;
}
一些常见 SQL 语法树中
Query_expression
和Query_bloack
之间的关系可以阅读【MySQL·8.0·源码】MySQL 语法树结构
从上面的 Query_block
中的各个子句上看到大量的 Item
结构
MySQL 源码使用一个 Item 基类来表示在关系查询中出现的任意类型的 expression
(表达式)
从类的继承关系角度来看,下面一些常见的继承 Item
的子类
class Item
+--Item_row
+--Item_basic_constant
+--Item_num
+--Item_int
+--Item_decimal
+--Item_float
+--Item_null
+--Item_string
+--Item_json
+--..
+--Item_ident
+--Item_field
+--Item_ref
+--Item_param
+--Item_result_field
+--Item_subselect
+--Item_singlerow_subselect
+--Item_exists_subselect
+--Item_func
+--Item_str_func
+--Item_sum
+--Item_timeval_func
+--...
+--...
从 SQL 语句各表达式的角度来看
lieral(constant)values
字面值、常量值<column references>
列引用<variable references>
变量引用<predicates>
谓词表达式
<comparison predicate>
比较谓词<between predicate>
<in predicate>
<like predicate>
<exists predicate>
<match predicate>
<numeric value function>
和<string value function>
算术和字符串函数<row value expressiion>
行对象<mathod reference>
函数引用<subquery>
子查询<select list>
class Query_block : public Query_term
mem_root_deque<Item*> fields;
Q1:
select c1,c2,c3 from t1;
Q2:
select c1+3, "joy", max(c2) from t1;
<where clause>
select * from t1 where c1 > 20 and c1 <= 30 or c1 + c2 > c3;
<group by clause>
SELECT c1, c2, COUNT(*) AS count_rows
FROM t1
GROUP BY c1, c2;
<rollup clause>
select * from t1 group by c1 with rollup;
<having clause>
select c1, sum(c2) as total from t1 group by c1 having total < 5;
<order by clause>
select * from t1 order by c1, c2 desc;
<subquery>
select * from t1 where c1 in (select c2 from t2);
SELECT *
FROM t1
WHERE EXISTS (SELECT 1 FROM t2 WHERE t1.c1 = t2.c2);