aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-05-26 19:25:19 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-05-26 19:25:19 -0400
commit3987e9e62046bd800d8d08566ed49fee1ae6cb86 (patch)
tree19734041040d9f718b48d60499b0e5a4b0732aa8 /src/backend/utils/adt/ruleutils.c
parent44404f394517f89a0bebb1aaace6e64ad79d2817 (diff)
downloadpostgresql-3987e9e62046bd800d8d08566ed49fee1ae6cb86.tar.gz
postgresql-3987e9e62046bd800d8d08566ed49fee1ae6cb86.zip
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.
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c67
1 files changed, 33 insertions, 34 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3ab90cb7d88..1595ef032d1 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -5187,50 +5187,36 @@ get_rule_expr(Node *node, deparse_context *context,
CaseWhen *when = (CaseWhen *) lfirst(temp);
Node *w = (Node *) when->expr;
- if (!PRETTY_INDENT(context))
- appendStringInfoChar(buf, ' ');
- appendContextKeyword(context, "WHEN ",
- 0, 0, 0);
if (caseexpr->arg)
{
/*
- * The parser should have produced WHEN clauses of the
- * form "CaseTestExpr = RHS"; we want to show just the
- * RHS. If the user wrote something silly like "CASE
- * boolexpr WHEN TRUE THEN ...", then the optimizer's
- * simplify_boolean_equality() may have reduced this
- * to just "CaseTestExpr" or "NOT CaseTestExpr", for
- * which we have to show "TRUE" or "FALSE". We have
- * also to consider the possibility that an implicit
- * coercion was inserted between the CaseTestExpr and
- * the operator.
+ * The parser should have produced WHEN clauses of
+ * the form "CaseTestExpr = RHS", possibly with an
+ * implicit coercion inserted above the CaseTestExpr.
+ * For accurate decompilation of rules it's essential
+ * that we show just the RHS. However in an
+ * expression that's been through the optimizer, the
+ * WHEN clause could be almost anything (since the
+ * equality operator could have been expanded into an
+ * inline function). If we don't recognize the form
+ * of the WHEN clause, just punt and display it as-is.
*/
if (IsA(w, OpExpr))
{
List *args = ((OpExpr *) w)->args;
- Node *rhs;
- Assert(list_length(args) == 2);
- Assert(IsA(strip_implicit_coercions(linitial(args)),
- CaseTestExpr));
- rhs = (Node *) lsecond(args);
- get_rule_expr(rhs, context, false);
+ if (list_length(args) == 2 &&
+ IsA(strip_implicit_coercions(linitial(args)),
+ CaseTestExpr))
+ w = (Node *) lsecond(args);
}
- else if (IsA(strip_implicit_coercions(w),
- CaseTestExpr))
- appendStringInfo(buf, "TRUE");
- else if (not_clause(w))
- {
- Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
- CaseTestExpr));
- appendStringInfo(buf, "FALSE");
- }
- else
- elog(ERROR, "unexpected CASE WHEN clause: %d",
- (int) nodeTag(w));
}
- else
- get_rule_expr(w, context, false);
+
+ if (!PRETTY_INDENT(context))
+ appendStringInfoChar(buf, ' ');
+ appendContextKeyword(context, "WHEN ",
+ 0, 0, 0);
+ get_rule_expr(w, context, false);
appendStringInfo(buf, " THEN ");
get_rule_expr((Node *) when->result, context, true);
}
@@ -5246,6 +5232,19 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
+ case T_CaseTestExpr:
+ {
+ /*
+ * Normally we should never get here, since for expressions
+ * that can contain this node type we attempt to avoid
+ * recursing to it. But in an optimized expression we might
+ * be unable to avoid that (see comments for CaseExpr). If we
+ * do see one, print it as CASE_TEST_EXPR.
+ */
+ appendStringInfo(buf, "CASE_TEST_EXPR");
+ }
+ break;
+
case T_ArrayExpr:
{
ArrayExpr *arrayexpr = (ArrayExpr *) node;