MySQL 源码|37 - 语法解析:聚集函数

MySQL 源码|37 - 语法解析:聚集函数

源码位置(版本 = MySQL 8.0.37):

前置文档:

MySQL 语法解析的核心规则是 simple_exprexpr,分别对应基础表达式和表达式。但是它们引用的其他规则很多,逻辑相对复杂,于是,我们先从一些相对独立的语法单元开始梳理,从而简化 simple_exprexpr 的引用关系。

不妨从聚集函数(aggregate function)的语法逻辑开始梳理,已知聚集函数的语法逻辑一定涉及 AVG 关键字,在 sql_yacc.yy 文件中搜索 AVG_SYM,找到仅 sum_expr 规则包含此关键字。sum_expr 的关系图如下:

在这里插入图片描述

sum_expr 规则

sum_expr 中,涉及备选方案如下:

AVG 函数

标准语法:AVG([DISTINCT] expr) [over_clause]

用于计算 in_sum_expr 的平均值。有 AVG(in_sum_expr)AVG(DISTINCT in_sum_expr) 两种备选语法,可以作为窗口函数。Bison 语法如下:

sum_expr:
          AVG_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_avg(@$, $3, false, $5);
          }
        | AVG_SYM '(' DISTINCT in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_avg(@$, $4, true, $6);
          }
BIT_AND 函数

标准语法:BIT_AND(expr) [over_clause]

用于计算 in_sum_expr 的按位与。只有 BIT_AND(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | BIT_AND_SYM  '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_and(@$, $3, $5);
          }
BIT_OR 函数

标准语法:BIT_OR(expr) [over_clause]

用于计算 in_sum_expr 的按位或。只有 BIT_OR(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | BIT_OR_SYM  '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_or(@$, $3, $5);
          }
JSON_ARRAYAGG 函数

标准语法:JSON_ARRAYAGG(col_or_expr) [over_clause]

用于将 in_sum_expr 中的值聚合为 Json 数组,详见 MySQL 8.0 官方手册:14.19.1 Aggregate Function Descriptions。只有 JSON_ARRAYAGG(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | JSON_ARRAYAGG '(' in_sum_expr ')' opt_windowing_clause
          {
            auto wrapper = make_unique_destroy_only<Json_wrapper>(YYMEM_ROOT);
            if (wrapper == nullptr) YYABORT;
            unique_ptr_destroy_only<Json_array> array{::new (YYMEM_ROOT)
                                                          Json_array};
            if (array == nullptr) YYABORT;
            $$ = NEW_PTN Item_sum_json_array(@$, $3, $5, std::move(wrapper),
                                             std::move(array));
          }
JSON_OBJECTAGG 函数

标准语法:JSON_OBJECTAGG(key, value) [over_clause]

用于以第 1 个 in_sum_expr 中的值为键,以第 2 个 in_sum_expr 中的值为值构造 Json 对象,详见 MySQL 8.0 官方手册:14.19.1 Aggregate Function Descriptions。只有 JSON_OBJECTAGG(in_sum_expr, in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | JSON_OBJECTAGG '(' in_sum_expr ',' in_sum_expr ')' opt_windowing_clause
          {
            auto wrapper = make_unique_destroy_only<Json_wrapper>(YYMEM_ROOT);
            if (wrapper == nullptr) YYABORT;
            unique_ptr_destroy_only<Json_object> object{::new (YYMEM_ROOT)
                                                            Json_object};
            if (object == nullptr) YYABORT;
            $$ = NEW_PTN Item_sum_json_object(
                @$, $3, $5, $7, std::move(wrapper), std::move(object));
          }
ST_COLLECT 函数

用于将 in_sum_expr 中的空间元素构造为数据集,详见 MySQL 8.0 官方手册:14.16.12 Spatial Aggregate Functions。有 ST_COLLECT(in_sum_expr)ST_COLLECT(DISTINCT in_sum_expr) 两种备选语法, 可以作为窗口函数。Bison 语法如下:

        | ST_COLLECT_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_collect(@$, $3, $5, false);
          }
        | ST_COLLECT_SYM '(' DISTINCT in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_collect(@$, $4, $6, true );
          }
BIT_XOR 函数

标准语法:BIT_XOR(expr) [over_clause]

用于计算 in_sum_expr 的按位异或。只有 BIT_XOR(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | BIT_XOR_SYM  '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_xor(@$, $3, $5);
          }
COUNT 函数

标准语法:

  • COUNT(expr) [over_clause]
  • COUNT(DISTINCT expr,[expr...])

COUNT 函数有如下三种语法结构:

  • COUNT(ALL *)COUNT(*) 语法:计算所有记录数,可以作为窗口函数。Bison 语法如下:
        | COUNT_SYM '(' opt_all '*' ')' opt_windowing_clause
          {
            $$= NEW_PTN PTI_count_sym(@$, $6);
          }
  • COUNT(in_sum_expr) 语法:计算 in_sum_expr 非空的记录数,可以作为窗口函数。Bison 语法如下:
        | COUNT_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_count(@$, $3, $5);
          }
  • COUNT(DISTINCT expr_list) 语法:计算 expr_list 字段均不同的记录数,可以作为窗口函数。Bison 语法如下:
        | COUNT_SYM '(' DISTINCT expr_list ')' opt_windowing_clause
          {
            $$= new Item_sum_count(@$, $4, $6);
          }
MIN 函数

标准语法:MIN([DISTINCT] expr) [over_clause]

用于计算 in_sum_expr 的最小值。有 MIN(in_sum_expr)MIN(DISTINCT in_sum_expr) 两种备选语法,可以作为窗口函数。根据 ANSI SQL 的标准,允许在 minmax 分组函数中使用 DISTINCT 关键字,但实际上不会改变函数的行为和结果,即 MIN|MAX(DISTINCT ...) 的处理方式与普通的 MIN|MAX() 没有区别。Bison 语法如下:

        | MIN_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_min(@$, $3, $5);
          }
        | MIN_SYM '(' DISTINCT in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_min(@$, $4, $6);
          }
MAX 函数

标准语法:MAX([DISTINCT] expr) [over_clause]

用于计算 in_sum_expr 的最大值。有 MAX(in_sum_expr)MAX(DISTINCT in_sum_expr) 两种备选语法,可以作为窗口函数。根据 ANSI SQL 的标准,允许在 minmax 分组函数中使用 DISTINCT 关键字,但实际上不会改变函数的行为和结果,即 MIN|MAX(DISTINCT ...) 的处理方式与普通的 MIN|MAX() 没有区别。Bison 语法如下:

        | MAX_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_max(@$, $3, $5);
          }
        | MAX_SYM '(' DISTINCT in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_max(@$, $4, $6);
          }
STD 函数

标准语法:STD(expr) [over_clause]

用于计算 in_sum_expr 的总体标准差。只有 STD(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | STD_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_std(@$, $3, 0, $5);
          }
VARIANCE 函数

标准语法:VARIANCE(expr) [over_clause]

用于计算 in_sum_expr 的总体平方差。只有 VARIANCE(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | VARIANCE_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_variance(@$, $3, 0, $5);
          }
STDDEV_SAMP 函数

标准语法:STDDEV_SAMP(expr) [over_clause]

用于计算 in_sum_expr 的样本标准差。只有 STDDEV_SAMP(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | STDDEV_SAMP_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_std(@$, $3, 1, $5);
          }
VAR_SAMP 函数

标准语法:VAR_SAMP(expr) [over_clause]

用于计算 in_sum_expr 的样本平方差。只有 VAR_SAMP(in_sum_expr) 一种备选语法,可以作为窗口函数。Bison 语法如下:

        | VAR_SAMP_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_variance(@$, $3, 1, $5);
          }
SUM 函数

标准语法:SUM([DISTINCT] expr) [over_clause]

用于计算 in_sum_expr 中元素之和。有 SUM(in_sum_expr)SUM(DISTINCT in_sum_expr) 两种备选语法,可以作为窗口函数。Bison 语法如下:

        | SUM_SYM '(' in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_sum(@$, $3, false, $5);
          }
        | SUM_SYM '(' DISTINCT in_sum_expr ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_sum_sum(@$, $4, true, $6);
          }
GROUP_CONCAT 函数

标准语法:

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

用于将 expr_list 中的值拼接为字符串。在 expr_list 之前允许使用 opt_distinct 规则添加可选的 DISTINCT 关键字用于去重,在 expr_lsit 之后允许使用 opt_gorder_clause 关键字添加可选的 ORDER BY 子句用于排序,在可选的 ORDER BY 子句后允许使用 opt_gconcat_separator 规则添加可选的分隔符子句。Bison 语法如下:

        | GROUP_CONCAT_SYM '(' opt_distinct
          expr_list opt_gorder_clause
          opt_gconcat_separator
          ')' opt_windowing_clause
          {
            $$= NEW_PTN Item_func_group_concat(@$, $3, $4, $5, $6, $8);
          }
        ;

sum_expr 规则中,涉及了 in_sum_expropt_windowing_clauseopt_allexpr_listopt_distinctopt_gorder_clauseopt_gconcat_separator 规则,其中:expr_listexpr 的列表,我们在梳理 expr 规则时梳理;opt_windowing_clause 是可选的窗口函数,我们在梳理窗口函数时梳理;opt_gorder_clauseORDER BY 子句的延伸,我们在梳理 ORDER BY 规则时梳理。下面我们来看其他涉及的规则:

in_sum_expr 规则

sum_expr 规则中,几乎每个函数中的元素都是 in_sum_expr 规则。

in_sum_expr 规则对应标准语法 [ALL] expr,包含一个可选的 ALL 关键字和一个普通表达式。Bison 语法如下:

in_sum_expr:
          opt_all expr
          {
            $$= NEW_PTN PTI_in_sum_expr(@1, $2);
          }
        ;
opt_all 规则

查看在 sum_expr 规则的 COUNT 函数备选方案以及在 in_sum_expr 规则中使用的 opt_all 规则。

opt_all 规则对应标准语法 [ALL],可以为空或为关键字 ALL。Bison 语法如下:

opt_all:
          %empty
        | ALL
        ;
opt_distinct 规则

查看在 sum_expr 规则的 GROUP_CONCAT 函数备选方案中使用的 opt_distinct 规则。

opt_all 规则对应标准语法 [DISTINCT],可以为空或为关键字 DISTINCT。Bison 语法如下:

opt_distinct:
          %empty      { $$ = 0; }
        | DISTINCT    { $$ = 1; }
        ;
opt_gconcat_separator 规则

查看在 sum_expr 规则的 GROUP_CONCAT 函数备选方案中使用的 opt_gconcat_separator 规则。

opt_gconcat_separator 规则对应标准语法 [SEPARATOR str_val],可以为空或为 SEPARATOR text_string 的语法形式。当为 SEPARATOR text_string 时,表示使用 text_string 作为分隔符。Bison 语法如下:

opt_gconcat_separator:
          %empty
          {
            $$= NEW_PTN String(",", 1, &my_charset_latin1);
            if ($$ == nullptr)
              MYSQL_YYABORT;
          }
        | SEPARATOR_SYM text_string { $$ = $2; }
        ;
  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值