暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

​PostgreSQL查询引擎——Restricted Expressions Grammar之表达式类型强转

肥叔菌 2023-02-07
331

General expressions语法规则定义在src/backend/parser/gram.y文件中,其是表达式语法的核心。有两种表达式类型:a_expr
是不受限制的类型,b_expr
是必须在某些地方使用的子集,以避免移位/减少冲突。例如,我们不能将BETWEEN
作为BETWEEN a_expr AND a_exp
,因为AND
的使用与AND
作为布尔运算符冲突。因此,b_expr
BETWEEN
中使用,我们从b_expr
中删除布尔关键字。请注意,( a_expr )
b_expr
,因此始终可以使用无限制表达式,方法是用括号将其括起来。c_expr
a_expr
b_expr
共同的所有乘积;它被分解出来只是为了消除冗余编码。注意涉及多个terminal token的产出productions。默认情况下,bison将为此类productions分配其最后一个terminal的优先级,但在几乎所有情况下,您都希望它是第一个terminal的优先权;否则你不会得到你期望的行为!因此,我们可以自由使用%prec
注释来设置优先级。

b_expr
代表Restricted expressions,它是复杂表达式a_expr
的子集,AND, NOT, IS, and IN是a_expr
的关键字,这些关键字在b_expr
使用会存在歧义。b_expr is a subset of the complete expression syntax defined by a_expr. Presently, AND, NOT, IS, and IN are the a_expr keywords that would cause trouble in the places where b_expr is used. For simplicity, we just eliminate all the boolean-keyword-operator productions from b_expr.

    b_expr:    c_expr
    { $$ = $1; }
    | b_expr TYPECAST Typename
    { $$ = makeTypeCast($1, $3, @2); }
    复制

    表达式强转

    b_expr TYPECAST Typename
    是表达式强转的规则,其中主要关注SimpleTypename所代表的规则。除了GenericType之外的规则和PostgreSQL查询引擎——General Expressions Grammar之AexprConst中介绍的常量类型强转类似,这里仅仅关注GenericType。

      SimpleTypename:
      GenericType { $$ = $1; }
      | Numeric { $$ = $1; }
      | Bit { $$ = $1; }
      | Character { $$ = $1; }
      | ConstDatetime { $$ = $1; }
      | ConstInterval opt_interval
      { $$ = $1; $$->typmods = $2; }
      | ConstInterval '(' Iconst ')'
      { $$ = $1; $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), makeIntConst($3, @3)); }
      ;
      复制

      GenericType涵盖所有没有标准规定的特殊语法的类型名称,包括限定名称。我们还允许类型修饰符。为了避免对函数调用的解析冲突,这里必须将修饰符显示为expr_list,但解析分析只接受它们的常量。GenericType covers all type names that don’t have special syntax mandated by the standard, including qualified names. We also allow type modifiers. To avoid parsing conflicts against function invocations, the modifiers have to be shown as expr_list here, but parse analysis will only accept constants for them.

        GenericType:
        type_function_name opt_type_modifiers
        { $$ = makeTypeName($1); $$->typmods = $2; $$->location = @1; }
        | type_function_name attrs opt_type_modifiers
        { $$ = makeTypeNameFromNameList(lcons(makeString($1), $2)); $$->typmods = $3; $$->location = @1; }
        opt_type_modifiers: '(' expr_list ')' { $$ = $2; }
        | /* EMPTY */ { $$ = NIL; }
        复制

        表达式强转的规则不同之处在于opt_array_bounds和ARRAY对于arrayBounds成员取值的影响,以及使用SETOF需要将setof成员设置为true。

          Typename:  SimpleTypename opt_array_bounds
          { $$ = $1; $$->arrayBounds = $2; }
          | SETOF SimpleTypename opt_array_bounds
          { $$ = $2; $$->arrayBounds = $3; $$->setof = true; }
          /* SQL standard syntax, currently only one-dimensional */
          | SimpleTypename ARRAY '[' Iconst ']'
          { $$ = $1; $$->arrayBounds = list_make1(makeInteger($4)); }
          | SETOF SimpleTypename ARRAY '[' Iconst ']'
          { $$ = $2; $$->arrayBounds = list_make1(makeInteger($5)); $$->setof = true; }
          | SimpleTypename ARRAY
          { $$ = $1; $$->arrayBounds = list_make1(makeInteger(-1)); }
          | SETOF SimpleTypename ARRAY
          { $$ = $2; $$->arrayBounds = list_make1(makeInteger(-1)); $$->setof = true; }
          opt_array_bounds:
          opt_array_bounds '[' ']'
          { $$ = lappend($1, makeInteger(-1)); }
          | opt_array_bounds '[' Iconst ']'
          { $$ = lappend($1, makeInteger($3)); }
          | /*EMPTY*/
          { $$ = NIL; }
          复制

          欢迎关注微信公众号肥叔菌PostgreSQL数据库专栏:



          文章转载自肥叔菌,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论