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

PostgreSQL查询引擎——Restricted Expressions Grammar之运算符

肥叔菌 2023-02-10
487

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.

运算符

如下规则所示,makeSimpleA_Expr函数创建A_Expr节点,makeXmlExpr函数创建XmlExpr节点,makeNotExpr函数创建BoolExpr节点。

    b_expr:    
           '+' b_expr          %prec UMINUS
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }
    | '-' b_expr %prec UMINUS
    { $$ = doNegate($2, @1); }
    | b_expr '+' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }
    | b_expr '-' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }
    | b_expr '*' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }
    | b_expr '/' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }
    | b_expr '%' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }
    | b_expr '^' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }
    | b_expr '<' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }
    | b_expr '>' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
    | b_expr '=' b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
    | b_expr LESS_EQUALS b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $3, @2); }
    | b_expr GREATER_EQUALS b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $3, @2); }
    | b_expr NOT_EQUALS b_expr
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<>", $1, $3, @2); }
    | b_expr qual_Op b_expr %prec Op
    { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }
    | qual_Op b_expr %prec Op
    { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }
    | b_expr qual_Op %prec POSTFIXOP
    { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }
    | b_expr IS DISTINCT FROM b_expr %prec IS
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2); }
    | b_expr IS NOT DISTINCT FROM b_expr %prec IS
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_NOT_DISTINCT, "=", $1, $6, @2); }
    | b_expr IS OF '(' type_list ')' %prec IS
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); }
    | b_expr IS NOT OF '(' type_list ')' %prec IS
    { $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); }
    | b_expr IS DOCUMENT_P %prec IS
    { $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1), @2); }
    | b_expr IS NOT DOCUMENT_P %prec IS
    { $$ = makeNotExpr(makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1), @2), @2); }

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


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

    评论