Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3987e9e

Browse files
committed
Make decompilation of optimized CASE constructs more robust.
We had some hacks in ruleutils.c to cope with various odd transformations that the optimizer could do on a CASE foo WHEN "CaseTestExpr = RHS" clause. However, the fundamental impossibility of covering all cases was exposed by Heikki, who pointed out that the "=" operator could get replaced by an inlined SQL function, which could contain nearly anything at all. So give up on the hacks and just print the expression as-is if we fail to recognize it as "CaseTestExpr = RHS". (We must cover that case so that decompiled rules print correctly; but we are not under any obligation to make EXPLAIN output be 100% valid SQL in all cases, and already could not do so in some other cases.) This approach requires that we have some printable representation of the CaseTestExpr node type; I used "CASE_TEST_EXPR". Back-patch to all supported branches, since the problem case fails in all.
1 parent 44404f3 commit 3987e9e

File tree

1 file changed

+33
-34
lines changed

1 file changed

+33
-34
lines changed

src/backend/utils/adt/ruleutils.c

+33-34
Original file line numberDiff line numberDiff line change
@@ -5187,50 +5187,36 @@ get_rule_expr(Node *node, deparse_context *context,
51875187
CaseWhen *when = (CaseWhen *) lfirst(temp);
51885188
Node *w = (Node *) when->expr;
51895189

5190-
if (!PRETTY_INDENT(context))
5191-
appendStringInfoChar(buf, ' ');
5192-
appendContextKeyword(context, "WHEN ",
5193-
0, 0, 0);
51945190
if (caseexpr->arg)
51955191
{
51965192
/*
5197-
* The parser should have produced WHEN clauses of the
5198-
* form "CaseTestExpr = RHS"; we want to show just the
5199-
* RHS. If the user wrote something silly like "CASE
5200-
* boolexpr WHEN TRUE THEN ...", then the optimizer's
5201-
* simplify_boolean_equality() may have reduced this
5202-
* to just "CaseTestExpr" or "NOT CaseTestExpr", for
5203-
* which we have to show "TRUE" or "FALSE". We have
5204-
* also to consider the possibility that an implicit
5205-
* coercion was inserted between the CaseTestExpr and
5206-
* the operator.
5193+
* The parser should have produced WHEN clauses of
5194+
* the form "CaseTestExpr = RHS", possibly with an
5195+
* implicit coercion inserted above the CaseTestExpr.
5196+
* For accurate decompilation of rules it's essential
5197+
* that we show just the RHS. However in an
5198+
* expression that's been through the optimizer, the
5199+
* WHEN clause could be almost anything (since the
5200+
* equality operator could have been expanded into an
5201+
* inline function). If we don't recognize the form
5202+
* of the WHEN clause, just punt and display it as-is.
52075203
*/
52085204
if (IsA(w, OpExpr))
52095205
{
52105206
List *args = ((OpExpr *) w)->args;
5211-
Node *rhs;
52125207

5213-
Assert(list_length(args) == 2);
5214-
Assert(IsA(strip_implicit_coercions(linitial(args)),
5215-
CaseTestExpr));
5216-
rhs = (Node *) lsecond(args);
5217-
get_rule_expr(rhs, context, false);
5208+
if (list_length(args) == 2 &&
5209+
IsA(strip_implicit_coercions(linitial(args)),
5210+
CaseTestExpr))
5211+
w = (Node *) lsecond(args);
52185212
}
5219-
else if (IsA(strip_implicit_coercions(w),
5220-
CaseTestExpr))
5221-
appendStringInfo(buf, "TRUE");
5222-
else if (not_clause(w))
5223-
{
5224-
Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
5225-
CaseTestExpr));
5226-
appendStringInfo(buf, "FALSE");
5227-
}
5228-
else
5229-
elog(ERROR, "unexpected CASE WHEN clause: %d",
5230-
(int) nodeTag(w));
52315213
}
5232-
else
5233-
get_rule_expr(w, context, false);
5214+
5215+
if (!PRETTY_INDENT(context))
5216+
appendStringInfoChar(buf, ' ');
5217+
appendContextKeyword(context, "WHEN ",
5218+
0, 0, 0);
5219+
get_rule_expr(w, context, false);
52345220
appendStringInfo(buf, " THEN ");
52355221
get_rule_expr((Node *) when->result, context, true);
52365222
}
@@ -5246,6 +5232,19 @@ get_rule_expr(Node *node, deparse_context *context,
52465232
}
52475233
break;
52485234

5235+
case T_CaseTestExpr:
5236+
{
5237+
/*
5238+
* Normally we should never get here, since for expressions
5239+
* that can contain this node type we attempt to avoid
5240+
* recursing to it. But in an optimized expression we might
5241+
* be unable to avoid that (see comments for CaseExpr). If we
5242+
* do see one, print it as CASE_TEST_EXPR.
5243+
*/
5244+
appendStringInfo(buf, "CASE_TEST_EXPR");
5245+
}
5246+
break;
5247+
52495248
case T_ArrayExpr:
52505249
{
52515250
ArrayExpr *arrayexpr = (ArrayExpr *) node;

0 commit comments

Comments
 (0)