MySQL 源码|50 - 语法解析:基础表达式(simple_expr)

目录文档:MySQL 源码|源码剖析文档目录

源码位置(版本 = MySQL 8.0.37):sql/sql_yacc.yy

前置文档:


在此之前,我们已经梳理的规则关系如下图所示。梳理基础表达式(simple_expr)规则的前置条件已经成熟,下面让我们开始梳理 simple_expr 规则。

在这里插入图片描述

simple_expr 规则相关关系如下图所示:其中绿色节点为本章节梳理,蓝色节点为之前章节已梳理,红色节点为后续章节梳理。

在这里插入图片描述

simple_expr 规则

simple_expr 规则用于匹配基础表达式,也可以理解为匹配一元表达式的结果,有如下备选方案:

  • 匹配 simple_ident 规则的结果:用于匹配 identident.identident.ident.ident
  • 匹配 function_call_keyword 规则匹配结果:用于匹配关键字函数,详见 MySQL 源码|43 - 语法解析:关键字函数
  • 匹配 function_call_nonkeyword 规则匹配结果:用于匹配非关键字函数,详见 MySQL 源码|44 - 语法解析:非关键字函数
  • 匹配 function_call_generic 规则匹配结果:用于匹配通用函数,详见 MySQL 源码|45 - 语法解析:通用函数
  • 匹配 function_call_conflict 规则匹配结果:用于匹配为避免语法冲突专门处理的函数,详见 MySQL 源码|46 - 语法解析:为避免语法冲突专门处理的函数
  • 依次匹配 simple_expr 规则匹配结果、COLLATE 关键字和 ident_or_text 规则匹配结果:用于在基础表达式的基础上指定排序规则
  • 匹配 literal_or_null 规则匹配结果:用于匹配字面值和 NULL 值,详见 MySQL 源码|48 - 语法解析:字面值
  • 匹配 param_marker 规则匹配结果:用于匹配参数值,详见 MySQL 源码|48 - 语法解析:字面值
  • 匹配 rvalue_system_or_user_variable 规则匹配结果:用于匹配系统变量或用户变量
  • 匹配 in_expression_user_variable_assignment 规则匹配结果:用于匹配用户变量赋值语句
  • 匹配 set_function_specification 规则匹配结果:用于匹配聚集函数,详见 MySQL 源码|37 - 语法解析:聚集函数
  • 匹配 window_func_call 规则匹配结果:用于匹配窗口函数,详见 MySQL 源码|38 - 语法解析:窗口函数
  • 依次匹配 simple_expr 规则匹配结果、||OR_OR_SYM)和 simple_expr 关键字:用于匹配使用逻辑或符号连接的基础表达式
  • 依次匹配 +simple_expr 规则匹配结果:用于匹配使用了 + 前缀一元表达式的基础表达式
  • 依次匹配 -simple_expr 规则匹配结果:用于匹配使用了 - 前缀一元表达式的基础表达式
  • 依次匹配 ~simple_expr 规则匹配结果:用于匹配使用了 ~ 前缀一元表达式的基础表达式
  • 依次匹配 not2 规则匹配结果和 simple_expr 规则用于:用于匹配使用了 ! 前缀一元表达式(或 SQL_MODE 为 MODE_HIGH_NOT_PRECEDENCE 时的 NOT 关键字)的基础表达式
  • 匹配 row_subquery 规则匹配结果:用于匹配单行子查询,详见 MySQL 源码|47 - 语法解析:子查询
  • 依次匹配 (expr 规则匹配结果和 ):用于匹配被括号框柱的一个更高级别表达式
  • 依次匹配 ROW 关键字、(expr 规则匹配结果、,expr_list):用于匹配 ROW 子句和其中被括号框柱的多个更高级别表达式
  • 依次匹配 EXISTS 关键字和 table_subquery 规则匹配结果:用于匹配 EXISTS 子句和其中的多行子查询,详见 详见 MySQL 源码|47 - 语法解析:子查询
  • 依次匹配 {ident 规则匹配结果、expr 规则匹配结果和 }:用于匹配 ODBC 日期
  • 依次匹配 MATCH 关键字、ident_list_arg 规则匹配结果、AGAINST 关键字、(bit_expr 规则匹配结果、fulltext_options 规则匹配结果和):用于匹配全文搜索子句,其中 ident_list_arg 规则匹配任意数量的逗号分隔的标识符,fulltext_options 规则匹配全文搜索的配置
  • 依次匹配 BINARY 关键字和 simple_expr:用于匹配 BINARY 关键字将字符串转换为二进制字符串
  • 依次匹配 CAST 关键字、(expr 规则匹配结果、AS 关键字、cast_type 规则匹配结果、opt_array_cast 规则匹配结果和 ):用于匹配 CAST 函数,详见 MySQL 源码|49 - 语法解析:CAST 函数、CONVERT 函数和 BINARY 关键字
  • 依次匹配 CAST 关键字、(expr 规则匹配结果、AT 关键字、LOCAL 关键字、AS 关键字、cast_type 规则匹配结果、opt_array_cast 规则匹配结果和 ):用于匹配 CAST 函数,详见 MySQL 源码|49 - 语法解析:CAST 函数、CONVERT 函数和 BINARY 关键字
  • 依次匹配 CAST 关键字、(expr 规则匹配结果、AT 关键字、TIME 关键字、ZONE 关键字、opt_interval 规则匹配结果、TEXT_STRING_literal 规则匹配结果、AS 关键字、DATETIME 关键字、type_datetime_precision 规则匹配结果和 ):用于匹配 CAST 函数,详见 MySQL 源码|49 - 语法解析:CAST 函数、CONVERT 函数和 BINARY 关键字
  • 依次匹配 CASE 关键字、opt_expr 规则匹配结果、when_list 规则匹配结果 opt_else 规则匹配结果和 END 关键字:用于匹配 CASE 子句,其中 opt_expr 规则匹配可选的一般表达式,when_list 规则匹配 CASE 子句中任意数量的 WHEN {expr} THEN {expr} 子句,opt_else 规则匹配可选的 ELSE {expr} 子句
  • 依次匹配 CONVERT 关键字、(expr 规则匹配结果,,cast_type 规则匹配结果和 ):用于匹配 CONVERT 函数,详见 MySQL 源码|49 - 语法解析:CAST 函数、CONVERT 函数和 BINARY 关键字依次匹配 CONVERT 关键字、(expr 规则匹配结果、USING 关键字、charset_name 关键字匹配结果和 ):用于匹配 CONVERT 函数,详见 MySQL 源码|49 - 语法解析:CAST 函数、CONVERT 函数和 BINARY 关键字
  • 依次匹配 DEFUALT 关键字、(simple_ident 规则匹配结果和 ):用于匹配 DEFAULT 函数
  • 依次匹配 VALUES 关键字、(simple_ident_nospvar 规则匹配结果和 ):用于匹配 VALUES 函数
  • 依次匹配 INTERVAL_SYM 关键字、expr 规则匹配结果、interval 规则匹配结果、+expr 规则匹配结果:用于匹配 INTERVAL 关键字引导的时间长度
  • 依次匹配 simple_ident 规则匹配结果、->JSON_SEPARATOR_SYM 规则)和 TEXT_STRING_literal 规则匹配结果:用于匹配 Json 数据提取语句
  • 依次匹配 simple_ident 规则匹配结果、->>JSON_UNQUOTED_SEPARATOR_SYM 规则)和 TEXT_STRING_literal 规则匹配结果:用于匹配 Json 数据提取语句

Bison 语法如下:

simple_expr:
          simple_ident
        | function_call_keyword
        | function_call_nonkeyword
        | function_call_generic
        | function_call_conflict
        | simple_expr COLLATE_SYM ident_or_text %prec NEG
          {
            warn_on_deprecated_user_defined_collation(YYTHD, $3);
            $$= NEW_PTN Item_func_set_collation(@$, $1, $3);
          }
        | literal_or_null
        | param_marker { $$= $1; }
        | rvalue_system_or_user_variable
        | in_expression_user_variable_assignment
        | set_function_specification
        | window_func_call
        | simple_expr OR_OR_SYM simple_expr
          {
            $$= NEW_PTN Item_func_concat(@$, $1, $3);
          }
        | '+' simple_expr %prec NEG
          {
            $$= $2; // TODO: do we really want to ignore unary '+' before any kind of literals?
            if ($$ != nullptr) $$->m_pos = @$;
          }
        | '-' simple_expr %prec NEG
          {
            $$= NEW_PTN Item_func_neg(@$, $2);
          }
        | '~' simple_expr %prec NEG
          {
            $$= NEW_PTN Item_func_bit_neg(@$, $2);
          }
        | not2 simple_expr %prec NEG
          {
            $$= NEW_PTN PTI_truth_transform(@$, $2, Item::BOOL_NEGATED);
          }
        | row_subquery
          {
            $$= NEW_PTN PTI_singlerow_subselect(@$, $1);
          }
        | '(' expr ')'
          {
            $$= $2;
            if ($$ != nullptr) $$->m_pos = @$;
          }
        | '(' expr ',' expr_list ')'
          {
            $$= NEW_PTN Item_row(@$, $2, $4->value);
          }
        | ROW_SYM '(' expr ',' expr_list ')'
          {
            $$= NEW_PTN Item_row(@$, $3, $5->value);
          }
        | EXISTS table_subquery
          {
            $$= NEW_PTN PTI_exists_subselect(@$, $2);
          }
        | '{' ident expr '}'
          {
            $$= NEW_PTN PTI_odbc_date(@$, $2, $3);
          }
        | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
          {
            $$= NEW_PTN Item_func_match(@$, $2, $5, $6);
          }
        | BINARY_SYM simple_expr %prec NEG
          {
            push_deprecated_warn(YYTHD, "BINARY expr", "CAST");
            $$= create_func_cast(YYTHD, @$, $2, ITEM_CAST_CHAR, &my_charset_bin);
            if ($$ == nullptr)
              MYSQL_YYABORT;
          }
        | CAST_SYM '(' expr AS cast_type opt_array_cast ')'
          {
            $$= create_func_cast(YYTHD, @$, $3, $5, $6);
            if ($$ == nullptr)
              MYSQL_YYABORT;
          }
        | CAST_SYM '(' expr AT_SYM LOCAL_SYM AS cast_type opt_array_cast ')'
          {
            my_error(ER_NOT_SUPPORTED_YET, MYF(0), "AT LOCAL");
          }
        | CAST_SYM '(' expr AT_SYM TIME_SYM ZONE_SYM opt_interval
          TEXT_STRING_literal AS DATETIME_SYM type_datetime_precision ')'
          {
            Cast_type cast_type{ITEM_CAST_DATETIME, nullptr, nullptr, $11};
            auto datetime_factor =
                NEW_PTN Item_func_at_time_zone(@3, $3, $8.str, $7);
            $$ = create_func_cast(YYTHD, @$, datetime_factor, cast_type, false);
            if ($$ == nullptr)
              MYSQL_YYABORT;
          }
        | CASE_SYM opt_expr when_list opt_else END
          {
            $$= NEW_PTN Item_func_case(@$, $3, $2, $4 );
          }
        | CONVERT_SYM '(' expr ',' cast_type ')'
          {
            $$= create_func_cast(YYTHD, @$, $3, $5, false);
            if ($$ == nullptr)
              MYSQL_YYABORT;
          }
        | CONVERT_SYM '(' expr USING charset_name ')'
          {
            $$= NEW_PTN Item_func_conv_charset(@$, $3,$5);
          }
        | DEFAULT_SYM '(' simple_ident ')'
          {
            $$= NEW_PTN Item_default_value(@$, $3);
          }
        | VALUES '(' simple_ident_nospvar ')'
          {
            $$= NEW_PTN Item_insert_value(@$, $3);
          }
        | INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM
          /* we cannot put interval before - */
          {
            $$= NEW_PTN Item_date_add_interval(@$, $5, $2, $3, 0);
          }
        | simple_ident JSON_SEPARATOR_SYM TEXT_STRING_literal
          {
            Item_string *path=
              NEW_PTN Item_string(@3, $3.str, $3.length,
                                  YYTHD->variables.collation_connection);
            $$= NEW_PTN Item_func_json_extract(YYTHD, @$, $1, path);
          }
         | simple_ident JSON_UNQUOTED_SEPARATOR_SYM TEXT_STRING_literal
          {
            Item_string *path=
              NEW_PTN Item_string(@3, $3.str, $3.length,
                                  YYTHD->variables.collation_connection);
            Item *extr= NEW_PTN Item_func_json_extract(YYTHD, @$, $1, path);
            $$= NEW_PTN Item_func_json_unquote(@$, extr);
          }
        ;
simple_ident 规则

simple_ident 规则用于匹配 identident.identident.ident.ident,包含如下两种备选方案,其中 simple_ident_q 规则用于匹配 ident.identident.ident.ident。Bison 语法如下:

simple_ident:
          ident
          {
            $$= NEW_PTN PTI_simple_ident_ident(@$, to_lex_cstring($1));
          }
        | simple_ident_q
        ;
simple_ident_q 规则

simple_ident_q 规则用于匹配 ident.identident.ident.ident,Bison 语法如下:

simple_ident_q:
          ident '.' ident
          {
            $$= NEW_PTN PTI_simple_ident_q_2d(@$, $1.str, $3.str);
          }
        | ident '.' ident '.' ident
          {
            if (check_and_convert_db_name(&$1, false) != Ident_name_check::OK)
              MYSQL_YYABORT;
            $$= NEW_PTN PTI_simple_ident_q_3d(@$, $1.str, $3.str, $5.str);
          }
        ;
rvalue_system_or_user_variable 规则

rvalue_system_or_user_variable 规则用于匹配系统变量和用户变量,包含如下 2 种备选方案:

  • 依次匹配 @ident_or_text 规则匹配结果。
  • 依次匹配 @@opt_rvalue_system_variable_type 规则匹配结果和 rvalue_system_variable 规则匹配结果,其中 opt_rvalue_system_variable_type 规则用于匹配 GLOBAL 关键字、LOCAL 关键字或 SESSION 关键字。

Bison 语法如下:

rvalue_system_or_user_variable:
          '@' ident_or_text
          {
            $$ = NEW_PTN PTI_user_variable(@$, $2);
          }
        | '@' '@' opt_rvalue_system_variable_type rvalue_system_variable
          {
            $$ = NEW_PTN PTI_get_system_variable(@$, $3,
                                                 @4, $4.prefix, $4.name);
          }
        ;
opt_rvalue_system_variable_type 规则

opt_rvalue_system_variable_type 规则用于匹配 GLOBAL 关键字、LOCAL 关键字或 SESSION 关键字,Bison 语法如下:

opt_rvalue_system_variable_type:
          %empty          { $$=OPT_DEFAULT; }
        | GLOBAL_SYM '.'  { $$=OPT_GLOBAL; }
        | LOCAL_SYM '.'   { $$=OPT_SESSION; }
        | SESSION_SYM '.' { $$=OPT_SESSION; }
        ;
rvalue_system_variable 规则

rvalue_system_variable 规则用于匹配 ident_or_text[.ident],Bison 语法如下:

rvalue_system_variable:
          ident_or_text
          {
            $$ = Bipartite_name{{}, to_lex_cstring($1)};
          }
        | ident_or_text '.' ident
          {
            // disallow "SELECT @@global.global.variable"
            if (check_reserved_words($1.str)) {
              YYTHD->syntax_error_at(@1);
              MYSQL_YYABORT;
            }
            $$ = Bipartite_name{to_lex_cstring($1), to_lex_cstring($3)};
          }
        ;
in_expression_user_variable_assignment 规则

in_expression_user_variable_assignment 规则用于匹配用户变量赋值语句,其中 SET_VAR 匹配 :=。Bison 语法如下:

in_expression_user_variable_assignment:
          '@' ident_or_text SET_VAR expr
          {
            push_warning(YYTHD, Sql_condition::SL_WARNING,
                         ER_WARN_DEPRECATED_SYNTAX,
                         ER_THD(YYTHD, ER_WARN_DEPRECATED_USER_SET_EXPR));
            $$ = NEW_PTN PTI_variable_aux_set_var(@$, $2, $4);
          }
        ;
not2 规则

not2 规则用于匹配 ! 运算符或 NOT2_SYM 关键字,其中 NOT2_SYM 关键字为 SQL_MODE 开启了 MODE_HIGH_NOT_PRECEDENCE 时的 NOT 关键字。Bison 语法如下:

not2:
          '!' { push_deprecated_warn(YYTHD, "!", "NOT"); }
        | NOT2_SYM
        ;
ident_list_arg 规则

ident_list_arg 规则用于匹配包含外层括号或不包含外层括号的标识符的、逗号分隔的、任意数量的标识符,Bison 语法如下:

ident_list_arg:
          ident_list          { $$= $1; }
        | '(' ident_list ')'  { $$= $2; }
        ;
ident_list 规则

ident_list 规则用于匹配使用逗号分隔的任意数量标识符,Bison 语法如下:

ident_list:
          simple_ident
          {
            $$= NEW_PTN PT_item_list(@$);
            if ($$ == nullptr || $$->push_back($1))
              MYSQL_YYABORT;
          }
        | ident_list ',' simple_ident
          {
            if ($1 == nullptr || $1->push_back($3))
              MYSQL_YYABORT;
            $$= $1;
            $$->m_pos = @$;
          }
        ;
fulltext_options 规则

fulltext_options 规则用于匹配全文搜索的配置,提供如下两种备选方案:

  • 依次匹配 opt_natural_language_mode 规则匹配结果和 opt_query_expansion 规则匹配结果,其中 opt_natural_language_mode 规则匹配可选的 IN NATURAL LANGUAGE MODEopt_query_expansion 规则匹配可选的 WITH QUERY EXPANSION
  • 依次匹配 IN 关键字、BOOLEAN 关键字和 MODE 关键字

Bison 语法如下:

fulltext_options:
          opt_natural_language_mode opt_query_expansion
          { $$= $1 | $2; }
        | IN_SYM BOOLEAN_SYM MODE_SYM
          {
            $$= FT_BOOL;
            DBUG_EXECUTE_IF("simulate_bug18831513",
                            {
                              THD *thd= YYTHD;
                              if (thd->sp_runtime_ctx)
                                YYTHD->syntax_error();
                            });
          }
        ;
opt_natural_language_mode 规则

opt_natural_language_mode 规则用于匹配可选的 IN NATURAL LANGUAGE MODE,Bison 语法如下:

opt_natural_language_mode:
          %empty { $$= FT_NL; }
        | IN_SYM NATURAL LANGUAGE_SYM MODE_SYM  { $$= FT_NL; }
        ;
opt_query_expansion 规则

opt_query_expansion 规则用于匹配可选的 WITH QUERY EXPANSION,Bison 语法如下:

opt_query_expansion:
          %empty { $$= 0;         }
        | WITH QUERY_SYM EXPANSION_SYM          { $$= FT_EXPAND; }
        ;
opt_expr 规则

opt_expr 规则用于匹配可选的一般表达式,Bison 语法如下:

opt_expr:
          %empty         { $$= nullptr; }
        | expr           { $$= $1; }
        ;
when_list 规则

when_list 规则用于匹配 CASE 子句中任意数量的 WHEN {expr} THEN {expr} 子句,Bison 语法如下:

when_list:
          WHEN_SYM expr THEN_SYM expr
          {
            $$= new (YYMEM_ROOT) mem_root_deque<Item *>(YYMEM_ROOT);
            if ($$ == nullptr)
              MYSQL_YYABORT;
            $$->push_back($2);
            $$->push_back($4);
          }
        | when_list WHEN_SYM expr THEN_SYM expr
          {
            $1->push_back($3);
            $1->push_back($5);
            $$= $1;
          }
        ;
opt_else 规则

opt_else 规则匹配可选的 ELSE {expr} 子句,Bison 语法如下:

opt_else:
          %empty       { $$= nullptr; }
        | ELSE expr    { $$= $2; }
        ;
  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长行

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

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

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

打赏作者

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

抵扣说明:

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

余额充值