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

PostgreSQL查询引擎——General Expressions Grammar之AexprConst

肥叔菌 2023-02-05
328

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
注释来设置优先级。

productions expression

c_expr
a_expr
b_expr
所共有的规则,递归引用a_expr
b_expr
的productions通常不能出现在c_expr
规则中。但是,可以引用出现在括号内的a_exprs
,例如函数参数;这不会给b_expr
语法带来歧义。productions that refer recursively to a_expr or b_expr mostly cannot appear here. However, it’s OK to refer to a_exprs that occur inside parentheses, such as function arguments; that cannot introduce ambiguity to the b_expr syntax.

规则二:AexprConst { $$ = $1; }
 AexprConst代表的是表达式常量,下面8个规则就是使用字面值创建A_Const节点,该节点使用Value节点存储和标识数据类型。

    AexprConst: Iconst
    { $$ = makeIntConst($1, @1); }
    | FCONST
    { $$ = makeFloatConst($1, @1); }
    | Sconst
    { $$ = makeStringConst($1, @1); }
    | BCONST
    { $$ = makeBitStringConst($1, @1); }
    | XCONST
    { /* This is a bit constant per SQL99: Without Feature F511, "BIT data type", a <general literal> shall not be a <bit string literal> or a <hex string literal>. */
    $$ = makeBitStringConst($1, @1); }
    | TRUE_P
    { $$ = makeBoolAConst(true, @1); }
    | FALSE_P
    { $$ = makeBoolAConst(false, @1); }
    | NULL_P
    { $$ = makeNullAConst(@1); }


    下面的规则和常量类型强转相关,第一个规则指定了强制转换目标类型(ConstTypename规则包含了支持的类型),第二个规则是为了支持 interval Sconst opt_interval,第三个规则是为了支持ConstInterval ‘(’ Iconst ‘)’ Sconst。

            | ConstTypename Sconst  
      { $$ = makeStringConstCast($2, @2, $1); }
      | ConstInterval Sconst opt_interval
      {
      TypeName *t = $1; t->typmods = $3;
      $$ = makeStringConstCast($2, @2, t);
      }
      | ConstInterval '(' Iconst ')' Sconst
      {
      TypeName *t = $1; t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), makeIntConst($3, @3));
      $$ = makeStringConstCast($5, @5, t);
      }


      ;

      static Node *makeStringConstCast(char *str, int location, TypeName *typename){
      Node *s = makeStringConst(str, location);
      return makeTypeCast(s, typename, -1);
      }

      要学习下面的使用类型转换函数强制转换常量规则,需要先看一下func_name的生成:限定的func_name的生成必须与限定的columnref的生成完全匹配,因为在看到后面的内容之前,我们无法判断要解析的是哪一个(func_name为’(‘或Sconst,columnref为其他任何内容)。因此,我们允许包含下标的“indirection”,并在C代码中拒绝这种情况。(如果我们实现类似SQL99的方法,这样的语法实际上可能会变得合法!)The production for a qualified func_name has to exactly match the production for a qualified columnref, because we cannot tell which we are parsing until we see what comes after it (’(’ or Sconst for a func_name, anything else for a columnref). Therefore we allow ‘indirection’ which may contain subscripts, and reject that case in the C code. (If we ever implement SQL99-like methods, such syntax may actually become legal!)

      使用函数进行强制类型转换和类型强转类型,使用func_name规则生成的List填充TypeName的names成员。第二个规则支持函数使用参数列表。

              | func_name Sconst
        { /* generic type 'literal' syntax */
        TypeName *t = makeTypeNameFromNameList($1); t->location = @1;
        $$ = makeStringConstCast($2, @2, t);
        }
        | func_name '(' func_arg_list opt_sort_clause ')' Sconst
        { /* generic syntax with a type modifier */
        TypeName *t = makeTypeNameFromNameList($1);

        ListCell *lc;
        /* We must use func_arg_list and opt_sort_clause in the production to avoid reduce/reduce conflicts, but we don't actually wish to allow NamedArgExpr in this context, nor ORDER BY. */
        foreach(lc, $3){
        NamedArgExpr *arg = (NamedArgExpr *) lfirst(lc);
        if (IsA(arg, NamedArgExpr))
        ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR), errmsg("type modifier cannot have parameter name"), parser_errposition(arg->location)));
        }

        if ($4 != NIL) ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR), errmsg("type modifier cannot have ORDER BY"), parser_errposition(@4)));


        t->typmods = $3;
        t->location = @1;
        $$ = makeStringConstCast($6, @6, t);
        }

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




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

        评论