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

Commit554b00c

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 parentaebddf0 commit554b00c

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
@@ -2595,7 +2595,18 @@ eval_const_expressions_mutator(Node *node,
25952595
* placeholder nodes, so that we have the opportunity to reduce
25962596
* constant test conditions. For example this allows
25972597
*CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
2598-
* to reduce to 1 rather than drawing a divide-by-0 error.
2598+
* to reduce to 1 rather than drawing a divide-by-0 error. Note
2599+
* that when the test expression is constant, we don't have to
2600+
* include it in the resulting CASE; for example
2601+
*CASE 0 WHEN x THEN y ELSE z END
2602+
* is transformed by the parser to
2603+
*CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
2604+
* which we can simplify to
2605+
*CASE WHEN 0 = x THEN y ELSE z END
2606+
* It is not necessary for the executor to evaluate the "arg"
2607+
* expression when executing the CASE, since any contained
2608+
* CaseTestExprs that might have referred to it will have been
2609+
* replaced by the constant.
25992610
*----------
26002611
*/
26012612
CaseExpr*caseexpr= (CaseExpr*)node;
@@ -2614,7 +2625,10 @@ eval_const_expressions_mutator(Node *node,
26142625
/* Set up for contained CaseTestExpr nodes */
26152626
save_case_val=context->case_val;
26162627
if (newarg&&IsA(newarg,Const))
2628+
{
26172629
context->case_val=newarg;
2630+
newarg=NULL;/* not needed anymore, see comment above */
2631+
}
26182632
else
26192633
context->case_val=NULL;
26202634

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4906,23 +4906,19 @@ get_rule_expr(Node *node, deparse_context *context,
49064906
* boolexpr WHEN TRUE THEN ...", then the optimizer's
49074907
* simplify_boolean_equality() may have reduced this
49084908
* to just "CaseTestExpr" or "NOT CaseTestExpr", for
4909-
* which we have to show "TRUE" or "FALSE". Also,
4910-
* depending on context the original CaseTestExpr
4911-
* might have been reduced to a Const (but we won't
4912-
* see "WHEN Const"). We have also to consider the
4913-
* possibility that an implicit coercion was inserted
4914-
* between the CaseTestExpr and the operator.
4909+
* which we have to show "TRUE" or "FALSE". We have
4910+
* also to consider the possibility that an implicit
4911+
* coercion was inserted between the CaseTestExpr and
4912+
* the operator.
49154913
*/
49164914
if (IsA(w,OpExpr))
49174915
{
49184916
List*args= ((OpExpr*)w)->args;
4919-
Node*lhs;
49204917
Node*rhs;
49214918

49224919
Assert(list_length(args)==2);
4923-
lhs=strip_implicit_coercions(linitial(args));
4924-
Assert(IsA(lhs,CaseTestExpr)||
4925-
IsA(lhs,Const));
4920+
Assert(IsA(strip_implicit_coercions(linitial(args)),
4921+
CaseTestExpr));
49264922
rhs= (Node*)lsecond(args);
49274923
get_rule_expr(rhs,context, false);
49284924
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp