目录文档:MySQL 源码|源码剖析文档目录
源码位置(版本 = MySQL 8.0.37):sql/sql_yacc.yy
前置文档:
在继续梳理 SELECT
表达式、UPDATE
表达式和 DELETE
表达式之前,我们首先梳理 WITH 子句的规则。
本节涉及相关关系如下图所示:其中绿色节点为本章节梳理,蓝色节点为之前章节已梳理,红色节点为后续章节梳理。
opt_with_clause
规则
opt_with_clause
规则用于匹配可选的 WITH
子句,Bison 语法如下:
opt_with_clause:
%empty { $$= nullptr; }
| with_clause { $$= $1; }
;
with_clause
规则
with_clause
规则用于匹配 WITH
子句,对应的标准语法如下,详见 MySQL 参考手册 - 15.2.20 WITH (Common Table Expressions):
with_clause:
WITH [RECURSIVE]
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
with_clause
规则的 Bison 语法有如下两种备选方案,分别匹配包含和不包含 RECURSIVE
关键字的标准语法,Bison 语法如下:
with_clause:
WITH with_list
{
$$= NEW_PTN PT_with_clause(@$, $2, false);
}
| WITH RECURSIVE_SYM with_list
{
$$= NEW_PTN PT_with_clause(@$, $3, true);
}
;
with_list
规则
with_list
规则用于匹配 WITH
子句中的临时表的列表,对应的标准语法如下:
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
with_list
规则的 Bison 语法通过如下两种备选方案,实现了匹配任意数量是否逗号分隔的 WITH
子句临时表,Bison 语法如下:
with_list:
with_list ',' common_table_expr
{
if ($1->push_back($3))
MYSQL_YYABORT;
$$->m_pos = @$;
}
| common_table_expr
{
$$= NEW_PTN PT_with_list(@$, YYTHD->mem_root);
if ($$ == nullptr || $$->push_back($1))
MYSQL_YYABORT; /* purecov: inspected */
}
;
common_table_expr
规则
common_table_expr
规则用于匹配每一个 WITH
子句中的临时表,对应标准语法 cte_name [(col_name [, col_name] ...)] AS (subquery)
,只有依次匹配表名标识符(ident
规则)、表字段列表(opt_derived_column_list
规则)、AS
关键字和多行子查询(table_subquery
规则)这一种备选方案,Bison 语法如下:
common_table_expr:
ident opt_derived_column_list AS table_subquery
{
LEX_STRING subq_text;
subq_text.length= @4.cpp.length();
subq_text.str= YYTHD->strmake(@4.cpp.start, subq_text.length);
if (subq_text.str == nullptr)
MYSQL_YYABORT; /* purecov: inspected */
uint subq_text_offset= @4.cpp.start - YYLIP->get_cpp_buf();
$$= NEW_PTN PT_common_table_expr(@$, $1, subq_text, subq_text_offset,
$4, &$2, YYTHD->mem_root);
if ($$ == nullptr)
MYSQL_YYABORT; /* purecov: inspected */
}
;