aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/util/clauses.c16
-rw-r--r--src/backend/utils/adt/ruleutils.c16
2 files changed, 21 insertions, 11 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index fa84164b068..ccf913b35cf 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -2583,7 +2583,18 @@ eval_const_expressions_mutator(Node *node,
* placeholder nodes, so that we have the opportunity to reduce
* constant test conditions. For example this allows
* CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
- * to reduce to 1 rather than drawing a divide-by-0 error.
+ * to reduce to 1 rather than drawing a divide-by-0 error. Note
+ * that when the test expression is constant, we don't have to
+ * include it in the resulting CASE; for example
+ * CASE 0 WHEN x THEN y ELSE z END
+ * is transformed by the parser to
+ * CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
+ * which we can simplify to
+ * CASE WHEN 0 = x THEN y ELSE z END
+ * It is not necessary for the executor to evaluate the "arg"
+ * expression when executing the CASE, since any contained
+ * CaseTestExprs that might have referred to it will have been
+ * replaced by the constant.
*----------
*/
CaseExpr *caseexpr = (CaseExpr *) node;
@@ -2602,7 +2613,10 @@ eval_const_expressions_mutator(Node *node,
/* Set up for contained CaseTestExpr nodes */
save_case_val = context->case_val;
if (newarg && IsA(newarg, Const))
+ {
context->case_val = newarg;
+ newarg = NULL; /* not needed anymore, see comment above */
+ }
else
context->case_val = NULL;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index dc17685563b..21aa6718c84 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -5146,23 +5146,19 @@ get_rule_expr(Node *node, deparse_context *context,
* 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.
+ * 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.
*/
if (IsA(w, OpExpr))
{
List *args = ((OpExpr *) w)->args;
- Node *lhs;
Node *rhs;
Assert(list_length(args) == 2);
- lhs = strip_implicit_coercions(linitial(args));
- Assert(IsA(lhs, CaseTestExpr) ||
- IsA(lhs, Const));
+ Assert(IsA(strip_implicit_coercions(linitial(args)),
+ CaseTestExpr));
rhs = (Node *) lsecond(args);
get_rule_expr(rhs, context, false);
}