diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 1b07d572c1..e9ab204aa9 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -2570,7 +2570,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; @@ -2589,7 +2600,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 4b564362ca..75ecf2af41 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -4682,23 +4682,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); }