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

Commit72a070a

Browse files
committed
Teach find_nonnullable_rels to handle OR cases: if every arm of an OR
forces a particular relation nonnullable, then we can say that the OR does.This is worth a little extra trouble since it may allow reduction ofouter joins to plain joins.
1 parent46bd3bf commit72a070a

File tree

1 file changed

+71
-19
lines changed

1 file changed

+71
-19
lines changed

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

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.233 2007/02/02 00:02:55 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.234 2007/02/16 23:32:08 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -974,12 +974,13 @@ contain_nonstrict_functions_walker(Node *node, void *context)
974974
* the expression to have been AND/OR flattened and converted to implicit-AND
975975
* format.
976976
*
977-
* We don't use expression_tree_walker here because we don't want to
978-
* descend through very many kinds of nodes; only the ones we can be sure
979-
* are strict.We can descend through the top level of implicit AND'ing,
980-
* but not through any explicit ANDs (or ORs) below that, since those are not
981-
* strict constructs. The List case handles the top-level implicit AND list
982-
* as well as lists of arguments to strict operators/functions.
977+
* top_level is TRUE while scanning top-level AND/OR structure; here, showing
978+
* the result is either FALSE or NULL is good enough. top_level is FALSE when
979+
* we have descended below a NOT or a strict function: now we must be able to
980+
* prove that the subexpression goes to NULL.
981+
*
982+
* We don't use expression_tree_walker here because we don't want to descend
983+
* through very many kinds of nodes; only the ones we can be sure are strict.
983984
*/
984985
Relids
985986
find_nonnullable_rels(Node*clause)
@@ -991,6 +992,7 @@ static Relids
991992
find_nonnullable_rels_walker(Node*node,booltop_level)
992993
{
993994
Relidsresult=NULL;
995+
ListCell*l;
994996

995997
if (node==NULL)
996998
returnNULL;
@@ -1003,8 +1005,15 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
10031005
}
10041006
elseif (IsA(node,List))
10051007
{
1006-
ListCell*l;
1007-
1008+
/*
1009+
* At top level, we are examining an implicit-AND list: if any of
1010+
* the arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1011+
* If not at top level, we are examining the arguments of a strict
1012+
* function: if any of them produce NULL then the result of the
1013+
* function must be NULL. So in both cases, the set of nonnullable
1014+
* rels is the union of those found in the arms, and we pass down
1015+
* the top_level flag unmodified.
1016+
*/
10081017
foreach(l, (List*)node)
10091018
{
10101019
result=bms_join(result,
@@ -1037,9 +1046,57 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
10371046
{
10381047
BoolExpr*expr= (BoolExpr*)node;
10391048

1040-
/* NOT is strict, others are not */
1041-
if (expr->boolop==NOT_EXPR)
1042-
result=find_nonnullable_rels_walker((Node*)expr->args, false);
1049+
switch (expr->boolop)
1050+
{
1051+
caseAND_EXPR:
1052+
/* At top level we can just recurse (to the List case) */
1053+
if (top_level)
1054+
{
1055+
result=find_nonnullable_rels_walker((Node*)expr->args,
1056+
top_level);
1057+
break;
1058+
}
1059+
/*
1060+
* Below top level, even if one arm produces NULL, the result
1061+
* could be FALSE (hence not NULL). However, if *all* the
1062+
* arms produce NULL then the result is NULL, so we can
1063+
* take the intersection of the sets of nonnullable rels,
1064+
* just as for OR. Fall through to share code.
1065+
*/
1066+
/* FALL THRU */
1067+
caseOR_EXPR:
1068+
/*
1069+
* OR is strict if all of its arms are, so we can take the
1070+
* intersection of the sets of nonnullable rels for each arm.
1071+
* This works for both values of top_level.
1072+
*/
1073+
foreach(l,expr->args)
1074+
{
1075+
Relidssubresult;
1076+
1077+
subresult=find_nonnullable_rels_walker(lfirst(l),
1078+
top_level);
1079+
if (result==NULL)/* first subresult? */
1080+
result=subresult;
1081+
else
1082+
result=bms_int_members(result,subresult);
1083+
/*
1084+
* If the intersection is empty, we can stop looking.
1085+
* This also justifies the test for first-subresult above.
1086+
*/
1087+
if (bms_is_empty(result))
1088+
break;
1089+
}
1090+
break;
1091+
caseNOT_EXPR:
1092+
/* NOT will return null if its arg is null */
1093+
result=find_nonnullable_rels_walker((Node*)expr->args,
1094+
false);
1095+
break;
1096+
default:
1097+
elog(ERROR,"unrecognized boolop: %d", (int)expr->boolop);
1098+
break;
1099+
}
10431100
}
10441101
elseif (IsA(node,RelabelType))
10451102
{
@@ -1056,22 +1113,17 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
10561113
}
10571114
elseif (IsA(node,NullTest))
10581115
{
1116+
/* IS NOT NULL can be considered strict, but only at top level */
10591117
NullTest*expr= (NullTest*)node;
10601118

1061-
/*
1062-
* IS NOT NULL can be considered strict, but only at top level; else
1063-
* we might have something like NOT (x IS NOT NULL).
1064-
*/
10651119
if (top_level&&expr->nulltesttype==IS_NOT_NULL)
10661120
result=find_nonnullable_rels_walker((Node*)expr->arg, false);
10671121
}
10681122
elseif (IsA(node,BooleanTest))
10691123
{
1124+
/* Boolean tests that reject NULL are strict at top level */
10701125
BooleanTest*expr= (BooleanTest*)node;
10711126

1072-
/*
1073-
* Appropriate boolean tests are strict at top level.
1074-
*/
10751127
if (top_level&&
10761128
(expr->booltesttype==IS_TRUE||
10771129
expr->booltesttype==IS_FALSE||

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp