1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

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.
This commit is contained in:
Tom Lane
2009-02-25 18:00:22 +00:00
parent ebce90a1c2
commit f970cc9588

View File

@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -3556,33 +3556,38 @@ get_rule_expr(Node *node, deparse_context *context,
if (caseexpr->arg) if (caseexpr->arg)
{ {
/* /*
* The parser should have produced WHEN clauses of * The parser should have produced WHEN clauses of the
* the form "CaseTestExpr = RHS"; we want to show * form "CaseTestExpr = RHS"; we want to show just the
* just the RHS. If the user wrote something silly * RHS. If the user wrote something silly like "CASE
* like "CASE boolexpr WHEN TRUE THEN ...", then * boolexpr WHEN TRUE THEN ...", then the optimizer's
* the optimizer's simplify_boolean_equality() may * simplify_boolean_equality() may have reduced this
* have reduced this to just "CaseTestExpr" or * to just "CaseTestExpr" or "NOT CaseTestExpr", for
* "NOT CaseTestExpr", for which we have to show * which we have to show "TRUE" or "FALSE". Also,
* "TRUE" or "FALSE". Also, depending on context * depending on context the original CaseTestExpr
* the original CaseTestExpr might have been reduced * might have been reduced to a Const (but we won't
* to a Const (but we won't see "WHEN Const"). * 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)) if (IsA(w, OpExpr))
{ {
List *args = ((OpExpr *) w)->args;
Node *lhs;
Node *rhs; Node *rhs;
Assert(IsA(linitial(((OpExpr *) w)->args), Assert(list_length(args) == 2);
CaseTestExpr) || lhs = strip_implicit_coercions(linitial(args));
IsA(linitial(((OpExpr *) w)->args), Assert(IsA(lhs, CaseTestExpr) ||
Const)); IsA(lhs, Const));
rhs = (Node *) lsecond(((OpExpr *) w)->args); rhs = (Node *) lsecond(args);
get_rule_expr(rhs, context, false); get_rule_expr(rhs, context, false);
} }
else if (IsA(w, CaseTestExpr)) else if (IsA(strip_implicit_coercions(w),
CaseTestExpr))
appendStringInfo(buf, "TRUE"); appendStringInfo(buf, "TRUE");
else if (not_clause(w)) else if (not_clause(w))
{ {
Assert(IsA(get_notclausearg((Expr *) w), Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
CaseTestExpr)); CaseTestExpr));
appendStringInfo(buf, "FALSE"); appendStringInfo(buf, "FALSE");
} }