aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-02-25 18:00:22 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-02-25 18:00:22 +0000
commitf970cc9588fc0fe43c61f03e5fd4bd30f3d4d786 (patch)
tree648e50b1213c1002e9a2e6b2b8413a36abb2bb94 /src
parentebce90a1c2243d19d7ee0326ceb16220189405cd (diff)
downloadpostgresql-f970cc9588fc0fe43c61f03e5fd4bd30f3d4d786.tar.gz
postgresql-f970cc9588fc0fe43c61f03e5fd4bd30f3d4d786.zip
Fix an old problem in decompilation of CASE constructs: the ruleutils.c code
looks for a CaseTestExpr to figure out what the parser did, but it failed to consider the possibility that an implicit coercion might be inserted above the CaseTestExpr. This could result in an Assert failure in some cases (but correct results if Asserts weren't enabled), or an "unexpected CASE WHEN clause" error in other cases. Per report from Alan Li. Back-patch to 8.1; problem doesn't exist before that because CASE was implemented differently.
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/ruleutils.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 119a9c20db0..f1dd1d7dc5e 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207.2.9 2008/06/06 17:59:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207.2.10 2009/02/25 18:00:22 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -3556,33 +3556,38 @@ get_rule_expr(Node *node, deparse_context *context,
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". Also, depending on context
- * the original CaseTestExpr might have been reduced
- * to a Const (but we won't see "WHEN Const").
+ * 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". Also,
+ * depending on context the original CaseTestExpr
+ * might have been reduced to a Const (but we won't
+ * see "WHEN Const"). We have also to consider the
+ * possibility that an implicit coercion was inserted
+ * between the CaseTestExpr and the operator.
*/
if (IsA(w, OpExpr))
{
+ List *args = ((OpExpr *) w)->args;
+ Node *lhs;
Node *rhs;
- Assert(IsA(linitial(((OpExpr *) w)->args),
- CaseTestExpr) ||
- IsA(linitial(((OpExpr *) w)->args),
- Const));
- rhs = (Node *) lsecond(((OpExpr *) w)->args);
+ Assert(list_length(args) == 2);
+ lhs = strip_implicit_coercions(linitial(args));
+ Assert(IsA(lhs, CaseTestExpr) ||
+ IsA(lhs, Const));
+ rhs = (Node *) lsecond(args);
get_rule_expr(rhs, context, false);
}
- else if (IsA(w, CaseTestExpr))
+ else if (IsA(strip_implicit_coercions(w),
+ CaseTestExpr))
appendStringInfo(buf, "TRUE");
else if (not_clause(w))
{
- Assert(IsA(get_notclausearg((Expr *) w),
+ Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
CaseTestExpr));
appendStringInfo(buf, "FALSE");
}