Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1b19e2c

Browse files
committed
Fix up handling of simple-form CASE with constant test expression.
eval_const_expressions() can replace CaseTestExprs with constants whenthe surrounding CASE's test expression is a constant. This confusesruleutils.c's heuristic for deparsing simple-form CASEs, leading toAssert failures or "unexpected CASE WHEN clause" errors. I had put ina hack solution for that years ago (see commit514ce7a of 2006-10-01), but bug #5794from Peter Speck shows that that solution failed to cover all cases.Fortunately, there's a much better way, which came to me upon reflectingthat Peter's "CASE TRUE WHEN" seemed pretty redundant: we can "simplify"the simple-form CASE to the general form of CASE, by simply omitting theconstant test expression from the rebuilt CASE construct. This isintuitively valid because there is no need for the executor to evaluatethe test expression at runtime; it will never be referenced, because anyCaseTestExprs that would have referenced it are now replaced by constants.This won't save a whole lot of cycles, since evaluating a Const is prettycheap, but a cycle saved is a cycle earned. In any case it beats klugingruleutils.c still further. So this patch improves const-simplificationand reverts the previous change in ruleutils.c.Back-patch to all supported branches. The bug exists in 8.1 too, but it'sout of warranty.
1 parentabc1026 commit1b19e2c

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

‎src/backend/optimizer/util/clauses.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2583,7 +2583,18 @@ eval_const_expressions_mutator(Node *node,
25832583
* placeholder nodes, so that we have the opportunity to reduce
25842584
* constant test conditions. For example this allows
25852585
*CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
2586-
* to reduce to 1 rather than drawing a divide-by-0 error.
2586+
* to reduce to 1 rather than drawing a divide-by-0 error. Note
2587+
* that when the test expression is constant, we don't have to
2588+
* include it in the resulting CASE; for example
2589+
*CASE 0 WHEN x THEN y ELSE z END
2590+
* is transformed by the parser to
2591+
*CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
2592+
* which we can simplify to
2593+
*CASE WHEN 0 = x THEN y ELSE z END
2594+
* It is not necessary for the executor to evaluate the "arg"
2595+
* expression when executing the CASE, since any contained
2596+
* CaseTestExprs that might have referred to it will have been
2597+
* replaced by the constant.
25872598
*----------
25882599
*/
25892600
CaseExpr*caseexpr= (CaseExpr*)node;
@@ -2602,7 +2613,10 @@ eval_const_expressions_mutator(Node *node,
26022613
/* Set up for contained CaseTestExpr nodes */
26032614
save_case_val=context->case_val;
26042615
if (newarg&&IsA(newarg,Const))
2616+
{
26052617
context->case_val=newarg;
2618+
newarg=NULL;/* not needed anymore, see comment above */
2619+
}
26062620
else
26072621
context->case_val=NULL;
26082622

‎src/backend/utils/adt/ruleutils.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5146,23 +5146,19 @@ get_rule_expr(Node *node, deparse_context *context,
51465146
* boolexpr WHEN TRUE THEN ...", then the optimizer's
51475147
* simplify_boolean_equality() may have reduced this
51485148
* to just "CaseTestExpr" or "NOT CaseTestExpr", for
5149-
* which we have to show "TRUE" or "FALSE". Also,
5150-
* depending on context the original CaseTestExpr
5151-
* might have been reduced to a Const (but we won't
5152-
* see "WHEN Const"). We have also to consider the
5153-
* possibility that an implicit coercion was inserted
5154-
* between the CaseTestExpr and the operator.
5149+
* which we have to show "TRUE" or "FALSE". We have
5150+
* also to consider the possibility that an implicit
5151+
* coercion was inserted between the CaseTestExpr and
5152+
* the operator.
51555153
*/
51565154
if (IsA(w,OpExpr))
51575155
{
51585156
List*args= ((OpExpr*)w)->args;
5159-
Node*lhs;
51605157
Node*rhs;
51615158

51625159
Assert(list_length(args)==2);
5163-
lhs=strip_implicit_coercions(linitial(args));
5164-
Assert(IsA(lhs,CaseTestExpr)||
5165-
IsA(lhs,Const));
5160+
Assert(IsA(strip_implicit_coercions(linitial(args)),
5161+
CaseTestExpr));
51665162
rhs= (Node*)lsecond(args);
51675163
get_rule_expr(rhs,context, false);
51685164
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp