On 6/7/2023 03:06, Alena Rybakina wrote:
I corrected this constant in the patch.
The patch don't apply cleanly: it contains some trailing spaces.
Also, quick glance into the code shows some weak points;
1. transformBoolExprOr should have input type BoolExpr.
2. You can avoid the switch operator at the beginning of the function,
because you only need one option.
3. Stale comments: RestrictIinfos definitely not exists at this point.
4. I don't know, you really need to copy the expr or not, but it is
better to do as late, as possible.
5. You assume, that leftop is non-constant and rightop - constant. Why?
6.I doubt about equivalence operator. Someone can invent a custom '='
operator with another semantics, than usual. May be better to check
mergejoinability?
7. I don't know how to confidently identify constant expressions at this
level. So, I guess, You can only merge here expressions like
"F(X)=Const", not an 'F(X)=ConstExpression'.
See delta.diff with mentioned changes in attachment.
--
regards,
Andrey Lepikhov
Postgres Professional
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index c9193d826f..26648b0876 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -107,41 +107,22 @@ typedef struct OrClauseGroupEntry
static int const_transform_or_limit = 500;
static Node *
-transformBoolExprOr(ParseState *pstate, Expr *expr_orig)
+transformBoolExprOr(ParseState *pstate, BoolExpr *expr_orig)
{
List *or_list = NIL;
List *groups_list = NIL;
ListCell *lc_eargs;
Node *result;
- BoolExpr *expr = (BoolExpr *)copyObject(expr_orig);
- const char *opname;
+ BoolExpr *expr;
bool change_apply = false;
- bool or_statement = false;
-
- Assert(IsA(expr, BoolExpr));
/* If this is not expression "Or", then will do it the old way. */
- switch (expr->boolop)
- {
- case AND_EXPR:
- opname = "AND";
- break;
- case OR_EXPR:
- opname = "OR";
- or_statement = true;
- break;
- case NOT_EXPR:
- opname = "NOT";
- break;
- default:
- elog(ERROR, "unrecognized boolop: %d", (int)
expr->boolop);
- opname = NULL; /* keep compiler quiet */
- break;
- }
-
- if (!or_statement || list_length(expr->args) < const_transform_or_limit)
+ if (expr_orig->boolop != OR_EXPR ||
+ list_length(expr_orig->args) < const_transform_or_limit)
return transformBoolExpr(pstate, (BoolExpr *)expr_orig);
+ expr = (BoolExpr *)copyObject(expr_orig);
+
/*
* NOTE:
* It is an OR-clause. So, rinfo->orclause is a BoolExpr node,
contains
@@ -176,15 +157,13 @@ transformBoolExprOr(ParseState *pstate, Expr *expr_orig)
if (!arg)
break;
- allow_transformation = (
- or_statement &&
- arg->type == T_A_Expr && (arg)->kind ==
AEXPR_OP &&
+ allow_transformation = (arg->type == T_A_Expr && (arg)->kind ==
AEXPR_OP &&
list_length((arg)->name) >=1 && strcmp(strVal(linitial((arg)->name)), "=") == 0
);
bare_orarg = transformExprRecurse(pstate, (Node *)arg);
- bare_orarg = coerce_to_boolean(pstate, bare_orarg, opname);
+ bare_orarg = coerce_to_boolean(pstate, bare_orarg, "OR");
/*
* The next step: transform all the inputs, and detect whether
any contain
@@ -357,14 +336,10 @@ transformBoolExprOr(ParseState *pstate, Expr *expr_orig)
}
}
- if (!change_apply)
- {
- or_statement = false;
- }
list_free_deep(groups_list);
}
- if (or_statement)
+ if (change_apply)
{
/* One more trick: assemble correct clause */
expr = list_length(or_list) > 1 ? makeBoolExpr(OR_EXPR,
list_copy(or_list), -1) : linitial(or_list);
@@ -376,9 +351,8 @@ transformBoolExprOr(ParseState *pstate, Expr *expr_orig)
* transformBoolExpr function
*/
else
- {
result = transformBoolExpr(pstate, (BoolExpr *)expr_orig);
- }
+
list_free(or_list);
return result;
@@ -496,7 +470,7 @@ transformExprRecurse(ParseState *pstate, Node *expr)
}
case T_BoolExpr:
- result = (Node *)transformBoolExprOr(pstate, (Expr
*)expr);
+ result = (Node *)transformBoolExprOr(pstate, (BoolExpr
*)expr);
break;
case T_FuncCall: