目录文档:MySQL 源码|源码剖析文档目录
源码位置(版本 = MySQL 8.0.37):sql/sql_yacc.yy
前置文档:
- MySQL 源码|39 - 语法解析:ORDER BY 子句
- MySQL 源码|40 - 语法解析:GROUP BY 子句
- MySQL 源码|52 - 语法解析:FROM 子句和 JOIN 子句
- MySQL 源码|53 - 语法解析:SELECT 语句的 INTO 子句
- MySQL 源码|54 - 语法解析:WINDOW 子句
在此之前,我们已经梳理了 query_specification
规则中涉及的 ORDER BY
子句、GROUP BY
子句、FROM
子句、JOIN
子句、INFO
子句和 WINDOW
子句,现在,我们来梳理 query_specification
规则。
本节涉及相关关系如下图所示:其中绿色节点为本章节梳理,蓝色节点为之前章节已梳理,红色节点为后续章节梳理。
query_specification
规则
query_specification
规则用于匹配基础查询语句,标准语法如下:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr] ...
[into_option]
[FROM table_references
[PARTITION partition_list]]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...]
这里不包含 ORDER BY
子句和 LIMIT
子句,是因为 MySQL 的查询树结构中,ORDER BY
子句和 LIMIT
子句的逻辑保存在 Query_block
之中,而这个规则解析的应该是不包含这部分的核心查询逻辑。这个逻辑我们会在后续继续梳理。
Bison 语法如下:
query_specification:
SELECT_SYM
select_options
select_item_list
into_clause
opt_from_clause
opt_where_clause
opt_group_clause
opt_having_clause
opt_window_clause
opt_qualify_clause
{
$$= NEW_PTN PT_query_specification(
@$,
$1, // SELECT_SYM
$2, // select_options
$3, // select_item_list
$4, // into_clause
$5, // from
$6, // where
$7, // group
$8, // having
$9, // windows
$10, // qualify
@5.raw.is_empty()); // implicit FROM
}
| SELECT_SYM
select_options
select_item_list
opt_from_clause
opt_where_clause
opt_group_clause
opt_having_clause
opt_window_clause
opt_qualify_clause
{
$$= NEW_PTN PT_query_specification(
@$,
$1, // SELECT_SYM
$2, // select_options
$3, // select_item_list
nullptr,// no INTO clause
$4, // from
$5, // where
$6, // group
$7, // having
$8, // windows
$9, // qualify
@4.raw.is_empty()); // implicit FROM
}
;
select_options
规则用于匹配可选的查询选项select_item_list
规则用于匹配查询的字段信息into_clause
规则用于匹配INTO
子句opt_from_clause
规则用于匹配可选的FROM
子句opt_where_clause
规则用于匹配可选的WHERE
子句opt_group_clause
规则用于匹配可选的GROUP BY
子句opt_having_clause
规则用于匹配可选的HAVING
子句opt_window_clause
规则用于匹配可选的WINDOW
子句opt_qualify_clause
规则用于匹配可选的QUALIFY
子句
select_options
规则
select_options
规则用于匹配可选的查询选项,对应标准语法如下:
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_options
规则有不匹配和匹配 select_option_list
规则匹配结果两种备选方案,Bison 语法如下:
select_options:
%empty
{
$$.query_spec_options= 0;
}
| select_option_list
;
select_option_list
规则
select_option_list
规则用于匹配大于等于一个、用空格分隔的查询选项,Bison 语法如下:
select_option_list:
select_option_list select_option
{
if ($$.merge($1, $2))
MYSQL_YYABORT;
}
| select_option
;
select_option
规则
select_option
规则用于匹配单个查询选项,标准语法如下:
ALL | DISTINCT | DISTINCTROW | HIGH_PRIORITY | STRAIGHT_JOIN | SQL_SMALL_RESULT | SQL_BIG_RESULT | SQL_BUFFER_RESULT | SQL_NO_CACHE | SQL_CALC_FOUND_ROWS
Bison 语法的第二个备选方案 SQL_NO_CACHE_SYM
用于实现标准语法 SQL_NO_CACHE
。Bison 语法如下:
select_option:
query_spec_option
{
$$.query_spec_options= $1;
}
| SQL_NO_CACHE_SYM
{
push_deprecated_warn_no_replacement(YYTHD, "SQL_NO_CACHE");
/* Ignored since MySQL 8.0. */
$$.query_spec_options= 0;
}
;
query_spec_option
规则
query_spec_option
规则用于匹配除 SQL_NO_CACHE
之外的其他单个查询选项,标准语法如下:
ALL | DISTINCT | DISTINCTROW | HIGH_PRIORITY | STRAIGHT_JOIN | SQL_SMALL_RESULT | SQL_BIG_RESULT | SQL_BUFFER_RESULT | SQL_CALC_FOUND_ROWS
Bison 语法中的每个备选方案,分别对应一个标准语法。Bison 语法如下:
query_spec_option:
STRAIGHT_JOIN { $$= SELECT_STRAIGHT_JOIN; }
| HIGH_PRIORITY { $$= SELECT_HIGH_PRIORITY; }
| DISTINCT { $$= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { $$= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { $$= SELECT_BIG_RESULT; }
| SQL_BUFFER_RESULT { $$= OPTION_BUFFER_RESULT; }
| SQL_CALC_FOUND_ROWS {
push_warning(YYTHD, Sql_condition::SL_WARNING,
ER_WARN_DEPRECATED_SYNTAX,
ER_THD(YYTHD, ER_WARN_DEPRECATED_SQL_CALC_FOUND_ROWS));
$$= OPTION_FOUND_ROWS;
}
| ALL { $$= SELECT_ALL; }
;
select_item_list
规则
select_item_list
规则用于匹配逗号分隔的多个查询字段或通配符 *
,Bison 语法如下:
select_item_list:
select_item_list ',' select_item
{
if ($1 == nullptr || $1->push_back($3))
MYSQL_YYABORT;
$$= $1;
$$->m_pos = @$;
}
| select_item
{
$$= NEW_PTN PT_select_item_list(@$);
if ($$ == nullptr || $$->push_back($1))
MYSQL_YYABORT;
}
| '*'
{
Item *item = NEW_PTN Item_asterisk(@$, nullptr, nullptr);
$$ = NEW_PTN PT_select_item_list(@$);
if ($$ == nullptr || item == nullptr || $$->push_back(item))
MYSQL_YYABORT;
}
;
select_item
规则
select_item
规则用于匹配单个查询字段,Bison 语法如下:
select_item:
table_wild { $$= $1; }
| expr select_alias
{
$$= NEW_PTN PTI_expr_with_alias(@$, $1, @1.cpp, to_lex_cstring($2));
}
;
table_wild
规则用于匹配ident.*
或ident.ident.*
的通配符名称expr
规则用于匹配一般表达式select_alias
规则用于匹配AS
子句指定别名
table_wild
规则
table_wild
规则用于匹配 ident.*
或 ident.ident.*
的通配符名称,Bison 语法如下:
table_wild:
ident '.' '*'
{
$$ = NEW_PTN Item_asterisk(@$, nullptr, $1.str);
}
| ident '.' ident '.' '*'
{
if (check_and_convert_db_name(&$1, false) != Ident_name_check::OK)
MYSQL_YYABORT;
auto schema_name = YYCLIENT_NO_SCHEMA ? nullptr : $1.str;
$$ = NEW_PTN Item_asterisk(@$, schema_name, $3.str);
}
;
opt_where_clause
规则
opt_where_clause
规则用于匹配可选的 WHERE
子句,对应标准语法 [WHERE where_condition]
,Bison 语法如下:
opt_where_clause:
%empty { $$ = nullptr; }
| where_clause
;
where_clause
规则
where_clause
规则用于匹配 WHERE
子句,对应标准语法 WHERE where_condition
,Bison 语法如下:
where_clause:
WHERE expr { $$ = NEW_PTN PTI_where(@2, $2); }
;
opt_having_clause
规则
opt_having_clause
规则用于匹配可选的 HAVING
子句,对应标准语法 [HAVING where_condition]
,Bison 语法如下:
opt_having_clause:
%empty { $$= nullptr; }
| HAVING expr
{
$$= new PTI_having(@$, $2);
}
;
opt_qualify_clause
规则
opt_qualify_clause
规则用于匹配可选的 QUALIFY_CLAUSE
子句,Bison 语法如下:
opt_qualify_clause:
%empty { $$= nullptr; }
| QUALIFY_SYM expr
{
$$= new PTI_qualify(@$, $2);
}
;