On 7/7/2023 15:20, Alena Rybakina wrote:
because we will provide similar manipulation in this:
foreach(l, gentry->consts)
{
Node *rexpr = (Node *) lfirst(l);
rexpr = coerce_to_common_type(pstate, rexpr,
scalar_type,
"IN");
aexprs = lappend(aexprs, rexpr);
}
I'm not sure that it should be replaced.
In attachment - a bit more corrections to the patch.
The most important change - or_list contains already transformed
expression subtree. So, I think we don't need to free it at all.
--
regards,
Andrey Lepikhov
Postgres Professional
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 961ca3e482..f0fd63f05c 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -112,9 +112,6 @@ transformBoolExprOr(ParseState *pstate, BoolExpr *expr_orig)
List *or_list = NIL;
List *groups_list = NIL;
ListCell *lc;
- Node *result;
- BoolExpr *expr;
- bool change_apply = false;
/* If this is not an 'OR' expression, skip the transformation */
if (expr_orig->boolop != OR_EXPR ||
@@ -131,16 +128,7 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
OrClauseGroupEntry *gentry;
bool const_is_left = true;
- /*
- * The first step: checking that the expression consists only
of equality.
- * We can only do this here, while arg is still row data type,
namely A_Expr.
- * After applying transformExprRecurce, we already know that it
will be OpExr type,
- * but checking the expression for equality is already becoming
impossible for us.
- * Sometimes we have the chance to devide expression into the
groups on
- * equality and inequality. This is possible if all list items
are not at the
- * same level of a single BoolExpr expression, otherwise all of
them cannot be converted.
- */
-
+ /* At first, transform the arg and evaluate constant
expressions. */
orqual = transformExprRecurse(pstate, (Node *) arg);
orqual = coerce_to_boolean(pstate, orqual, "OR");
orqual = eval_const_expressions(NULL, orqual);
@@ -151,7 +139,13 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
continue;
}
- /* Detect constant side of the clause */
+ /*
+ * Detect the constant side of the clause. Recall non-constant
+ * expression can be made not only with Vars, but also with
Params,
+ * which is not bonded with any relation. Thus, we detect the
const
+ * side - if another side is constant too, the orqual couldn't
be
+ * an OpExpr.
+ */
if (IsA(get_leftop(orqual), Const))
const_is_left = true;
else if (IsA(get_rightop(orqual), Const))
@@ -175,26 +169,14 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
}
/*
- * The next step: transform all the inputs, and detect whether
- * any contain Vars.
- */
- if (!contain_vars_of_level(orqual, 0))
- {
- /* Again, it's not the expr we can transform */
- or_list = lappend(or_list, orqual);
- continue;
- }
-
- ;
-
- /*
- * At this point we definitely have a transformable
clause.
- * Classify it and add into specific group of clauses,
or create new
- * group.
- * TODO: to manage complexity in the case of many
different clauses
- * (X1=C1) OR (X2=C2 OR) ... (XN = CN) we could invent
something
- * like a hash table (htab key ???).
- */
+ * At this point we definitely have a transformable clause.
+ * Classify it and add into specific group of clauses, or create
new
+ * group.
+ * TODO: to manage complexity in the case of many different
clauses
+ * (X1=C1) OR (X2=C2 OR) ... (XN = CN) we could invent something
+ * like a hash table. But also we believe, that the case of many
+ * different variable sides is very rare.
+ */
foreach(lc_groups, groups_list)
{
OrClauseGroupEntry *v = (OrClauseGroupEntry *)
lfirst(lc_groups);
@@ -220,20 +202,18 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
gentry = palloc(sizeof(OrClauseGroupEntry));
gentry->node = nconst_expr;
gentry->consts = list_make1(const_expr);
- gentry->opno = ((OpExpr *)orqual)->opno;
- gentry->expr = (Expr *)orqual;
+ gentry->expr = (Expr *) orqual;
groups_list = lappend(groups_list, (void *) gentry);
}
if (groups_list == NIL)
{
/*
- * No any transformations possible with this rinfo, just add
itself
- * to the list and go further.
+ * No any transformations possible with this list of arguments.
Here we
+ * already made all underlying transformations. Thus, just
return the
+ * transformed bool expression.
*/
- list_free(or_list);
-
- return transformBoolExpr(pstate, (BoolExpr *)expr_orig);
+ return (Node *) makeBoolExpr(OR_EXPR, or_list,
expr_orig->location);
}
else
{
@@ -267,11 +247,12 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
}
/*
- * Do the transformation. It's been a long way ;)
+ * Do the transformation.
*
- * First of all, try to select a common type for the
array elements. Note that
- * since the LHS' type is first in the list, it will be
preferred when
- * there is doubt (eg, when all the RHS items are
unknown literals).
+ * First of all, try to select a common type for the
array elements.
+ * Note that since the LHS' type is first in the list,
it will be
+ * preferred when there is doubt (eg, when all the RHS
items are
+ * unknown literals).
*
* Note: use list_concat here not lcons, to avoid
damaging rnonvars.
*
@@ -288,8 +269,8 @@ transformBoolExprOr(ParseState *pstate, BoolExpr *expr_orig)
if (array_type != InvalidOid)
{
/*
- * OK: coerce all the right-hand non-Var inputs
to the common type
- * and build an ArrayExpr for them.
+ * OK: coerce all the right-hand non-Var inputs
to the common
+ * type and build an ArrayExpr for them.
*/
List *aexprs;
ArrayExpr *newa;
@@ -314,24 +295,18 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
newa->array_typeid =
get_array_type(scalar_type);
newa->multidims = false;
newa->elements = aexprs;
- newa->location = -1; /* Position of the new
clause is undefined */
+ newa->location = -1;
- saopexpr = (ScalarArrayOpExpr
*)make_scalar_array_op(pstate,
-
list_make1(makeString((char *) "=")),
-
true,
-
gentry->node,
-
(Node *) newa,
-
-1); /* Position of the new clause is undefined */
-
- /*
- * TODO: here we can try to coerce the array to
a Const and find
- * hash func instead of linear search (see
50e17ad281b).
- * convert_saop_to_hashed_saop((Node *)
saopexpr);
- * We don't have to do this anymore, do we?
- */
+ saopexpr =
+ (ScalarArrayOpExpr *)
+ make_scalar_array_op(pstate,
+
list_make1(makeString((char *) "=")),
+
true,
+
gentry->node,
+
(Node *) newa,
+
-1);
or_list = lappend(or_list, (void *) saopexpr);
- change_apply = true;
}
else
{
@@ -344,23 +319,10 @@ transformBoolExprOr(ParseState *pstate, BoolExpr
*expr_orig)
list_free_deep(groups_list);
}
- 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);
- result = (Node *)expr;
- }
- /*
- * There was no reasons to create a new expresion, so
- * run the original BoolExpr conversion with using
- * transformBoolExpr function
- */
- else
- result = transformBoolExpr(pstate, (BoolExpr *)expr_orig);
-
- list_free(or_list);
-
- return result;
+ /* One more trick: assemble correct clause */
+ return (Node *) ((list_length(or_list) > 1) ?
+ makeBoolExpr(OR_EXPR, or_list,
expr_orig->location) :
+ linitial(or_list));
}
/*
@@ -475,7 +437,7 @@ transformExprRecurse(ParseState *pstate, Node *expr)
}
case T_BoolExpr:
- result = (Node *)transformBoolExprOr(pstate, (BoolExpr
*)expr);
+ result = (Node *)transformBoolExprOr(pstate, (BoolExpr
*) expr);
break;
case T_FuncCall: