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

Commit40f6524

Browse files
committed
Implement constant-expression simplification per Bernard
Frankpitt, plus some improvements from yours truly. The simplifier dependson the proiscachable field of pg_proc to tell it whether a function issafe to pre-evaluate --- things like nextval() are not, for example.Update pg_proc.h to contain reasonable cacheability information; as of6.5.* hardly any functions were marked cacheable. I may have erred toofar in the other direction; see recent mail to pghackers for more info.This update does not force an initdb, exactly, but you won't see muchbenefit from the simplifier until you do one.
1 parent95d3d46 commit40f6524

File tree

7 files changed

+1358
-937
lines changed

7 files changed

+1358
-937
lines changed

‎src/backend/executor/execQual.c

Lines changed: 67 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.60 1999/09/24 00:24:23 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.61 1999/09/26 02:28:15 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -956,8 +956,8 @@ ExecEvalFunc(Expr *funcClause,
956956
staticDatum
957957
ExecEvalNot(Expr*notclause,ExprContext*econtext,bool*isNull)
958958
{
959-
Datumexpr_value;
960959
Node*clause;
960+
Datumexpr_value;
961961
boolisDone;
962962

963963
clause=lfirst(notclause->args);
@@ -995,67 +995,47 @@ ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
995995
List*clauses;
996996
List*clause;
997997
boolisDone;
998-
boolIsNull;
999-
Datumconst_value=0;
998+
boolAnyNull;
999+
Datumclause_value;
10001000

1001-
IsNull= false;
10021001
clauses=orExpr->args;
1002+
AnyNull= false;
10031003

10041004
/*
1005-
* we use three valued logic functions here... we evaluate each of the
1006-
* clauses in turn, as soon as one is true we return that value. If
1007-
* none is true and none of the clauses evaluate to NULL we return
1008-
* the value of the last clause evaluated (which should be false) with
1009-
* *isNull set to false else if none is true and at least one clause
1010-
* evaluated to NULL we set *isNull flag to true -
1005+
* If any of the clauses is TRUE, the OR result is TRUE regardless
1006+
* of the states of the rest of the clauses, so we can stop evaluating
1007+
* and return TRUE immediately. If none are TRUE and one or more is
1008+
* NULL, we return NULL; otherwise we return FALSE. This makes sense
1009+
* when you interpret NULL as "don't know": if we have a TRUE then the
1010+
* OR is TRUE even if we aren't sure about some of the other inputs.
1011+
* If all the known inputs are FALSE, but we have one or more "don't
1012+
* knows", then we have to report that we "don't know" what the OR's
1013+
* result should be --- perhaps one of the "don't knows" would have been
1014+
* TRUE if we'd known its value. Only when all the inputs are known
1015+
* to be FALSE can we state confidently that the OR's result is FALSE.
10111016
*/
10121017
foreach(clause,clauses)
10131018
{
1014-
10151019
/*
10161020
* We don't iterate over sets in the quals, so pass in an isDone
10171021
* flag, but ignore it.
10181022
*/
1019-
const_value=ExecEvalExpr((Node*)lfirst(clause),
1020-
econtext,
1021-
isNull,
1022-
&isDone);
1023-
1023+
clause_value=ExecEvalExpr((Node*)lfirst(clause),
1024+
econtext,
1025+
isNull,
1026+
&isDone);
10241027
/*
1025-
* if the expression evaluates to null, then we remember it in the
1026-
* local IsNull flag, if none of the clauses are true then we need
1027-
* to set *isNull to true again.
1028+
* if we have a non-null true result, then return it.
10281029
*/
10291030
if (*isNull)
1030-
{
1031-
IsNull=*isNull;
1032-
1033-
/*
1034-
* Many functions don't (or can't!) check if an argument is
1035-
* NULL or NOT_NULL and may return TRUE (1) with *isNull TRUE
1036-
* (an_int4_column <> 1: int4ne returns TRUE for NULLs). Not
1037-
* having time to fix the function manager I want to fix OR:
1038-
* if we had 'x <> 1 OR x isnull' then when x is NULL TRUE was
1039-
* returned by the 'x <> 1' clause ... but ExecQualClause says
1040-
* that the qualification should *fail* if isnull is TRUE for
1041-
* any value returned by ExecEvalExpr. So, force this rule
1042-
* here: if isnull is TRUE then the clause failed. Note:
1043-
* nullvalue() & nonnullvalue() always sets isnull to FALSE
1044-
* for NULLs. - vadim 09/22/97
1045-
*/
1046-
const_value=0;
1047-
}
1048-
1049-
/*
1050-
* if we have a true result, then we return it.
1051-
*/
1052-
if (DatumGetInt32(const_value)!=0)
1053-
returnconst_value;
1031+
AnyNull= true;/* remember we got a null */
1032+
elseif (DatumGetInt32(clause_value)!=0)
1033+
returnclause_value;
10541034
}
10551035

1056-
/*IsNull is true if at least one clause evaluated to NULL */
1057-
*isNull=IsNull;
1058-
returnconst_value;
1036+
/*AnyNull is true if at least one clause evaluated to NULL */
1037+
*isNull=AnyNull;
1038+
return(Datum) false;
10591039
}
10601040

10611041
/* ----------------------------------------------------------------
@@ -1067,49 +1047,43 @@ ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
10671047
{
10681048
List*clauses;
10691049
List*clause;
1070-
Datumconst_value=0;
10711050
boolisDone;
1072-
boolIsNull;
1073-
1074-
IsNull= false;
1051+
boolAnyNull;
1052+
Datumclause_value;
10751053

10761054
clauses=andExpr->args;
1055+
AnyNull= false;
10771056

10781057
/*
1079-
* we evaluate each of the clauses in turn, as soon as one is false we
1080-
* return that value. If none are false or NULL then we return the
1081-
* value of the last clause evaluated, which should be true.
1058+
* If any of the clauses is FALSE, the AND result is FALSE regardless
1059+
* of the states of the rest of the clauses, so we can stop evaluating
1060+
* and return FALSE immediately. If none are FALSE and one or more is
1061+
* NULL, we return NULL; otherwise we return TRUE. This makes sense
1062+
* when you interpret NULL as "don't know", using the same sort of
1063+
* reasoning as for OR, above.
10821064
*/
10831065
foreach(clause,clauses)
10841066
{
1085-
10861067
/*
10871068
* We don't iterate over sets in the quals, so pass in an isDone
10881069
* flag, but ignore it.
10891070
*/
1090-
const_value=ExecEvalExpr((Node*)lfirst(clause),
1091-
econtext,
1092-
isNull,
1093-
&isDone);
1094-
1071+
clause_value=ExecEvalExpr((Node*)lfirst(clause),
1072+
econtext,
1073+
isNull,
1074+
&isDone);
10951075
/*
1096-
* if the expression evaluates to null, then we remember it in
1097-
* IsNull, if none of the clauses after this evaluates to false we
1098-
* will have to set *isNull to true again.
1076+
* if we have a non-null false result, then return it.
10991077
*/
11001078
if (*isNull)
1101-
IsNull=*isNull;
1102-
1103-
/*
1104-
* if we have a false result, then we return it, since the
1105-
* conjunction must be false.
1106-
*/
1107-
if (DatumGetInt32(const_value)==0)
1108-
returnconst_value;
1079+
AnyNull= true;/* remember we got a null */
1080+
elseif (DatumGetInt32(clause_value)==0)
1081+
returnclause_value;
11091082
}
11101083

1111-
*isNull=IsNull;
1112-
returnconst_value;
1084+
/* AnyNull is true if at least one clause evaluated to NULL */
1085+
*isNull=AnyNull;
1086+
return (Datum) (!AnyNull);
11131087
}
11141088

11151089
/* ----------------------------------------------------------------
@@ -1126,7 +1100,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
11261100
{
11271101
List*clauses;
11281102
List*clause;
1129-
Datumconst_value=0;
1103+
Datumclause_value;
11301104
boolisDone;
11311105

11321106
clauses=caseExpr->args;
@@ -1144,37 +1118,35 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
11441118
* We don't iterate over sets in the quals, so pass in an isDone
11451119
* flag, but ignore it.
11461120
*/
1147-
const_value=ExecEvalExpr((Node*)wclause->expr,
1148-
econtext,
1149-
isNull,
1150-
&isDone);
1121+
clause_value=ExecEvalExpr(wclause->expr,
1122+
econtext,
1123+
isNull,
1124+
&isDone);
11511125

11521126
/*
11531127
* if we have a true test, then we return the result, since the
11541128
* case statement is satisfied. A NULL result from the test is
11551129
* not considered true.
11561130
*/
1157-
if (DatumGetInt32(const_value)!=0&& !*isNull)
1131+
if (DatumGetInt32(clause_value)!=0&& !*isNull)
11581132
{
1159-
const_value=ExecEvalExpr((Node*)wclause->result,
1160-
econtext,
1161-
isNull,
1162-
&isDone);
1163-
return (Datum)const_value;
1133+
returnExecEvalExpr(wclause->result,
1134+
econtext,
1135+
isNull,
1136+
&isDone);
11641137
}
11651138
}
11661139

11671140
if (caseExpr->defresult)
11681141
{
1169-
const_value=ExecEvalExpr((Node*)caseExpr->defresult,
1170-
econtext,
1171-
isNull,
1172-
&isDone);
1142+
returnExecEvalExpr(caseExpr->defresult,
1143+
econtext,
1144+
isNull,
1145+
&isDone);
11731146
}
1174-
else
1175-
*isNull= true;
11761147

1177-
returnconst_value;
1148+
*isNull= true;
1149+
return (Datum)0;
11781150
}
11791151

11801152
/* ----------------------------------------------------------------
@@ -1357,7 +1329,6 @@ bool
13571329
ExecQual(List*qual,ExprContext*econtext)
13581330
{
13591331
List*clause;
1360-
boolresult;
13611332

13621333
/*
13631334
* debugging stuff
@@ -1378,27 +1349,17 @@ ExecQual(List *qual, ExprContext *econtext)
13781349
* a "qual" is a list of clauses. To evaluate the qual, we evaluate
13791350
* each of the clauses in the list.
13801351
*
1381-
* ExecQualClause returns true when we know the qualification *failed* so
1382-
* we just pass each clause in qual to it until we know the qual
1352+
* ExecQualClause returns true when we know the qualification *failed*
1353+
*sowe just pass each clause in qual to it until we know the qual
13831354
* failed or there are no more clauses.
13841355
*/
1385-
result= false;
13861356

13871357
foreach(clause,qual)
13881358
{
1389-
result=ExecQualClause((Node*)lfirst(clause),econtext);
1390-
if (result== true)
1391-
break;
1359+
if (ExecQualClause((Node*)lfirst(clause),econtext))
1360+
return false;/* qual failed, so return false */
13921361
}
13931362

1394-
/*
1395-
* if result is true, then it means a clause failed so we return
1396-
* false. if result is false then it means no clause failed so we
1397-
* return true.
1398-
*/
1399-
if (result== true)
1400-
return false;
1401-
14021363
return true;
14031364
}
14041365

‎src/backend/nodes/equalfuncs.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.48 1999/08/21 03:48:57 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.49 1999/09/26 02:28:21 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -223,6 +223,22 @@ _equalAggref(Aggref *a, Aggref *b)
223223
return true;
224224
}
225225

226+
staticbool
227+
_equalSubLink(SubLink*a,SubLink*b)
228+
{
229+
if (a->subLinkType!=b->subLinkType)
230+
return false;
231+
if (a->useor!=b->useor)
232+
return false;
233+
if (!equal(a->lefthand,b->lefthand))
234+
return false;
235+
if (!equal(a->oper,b->oper))
236+
return false;
237+
if (!equal(a->subselect,b->subselect))
238+
return false;
239+
return true;
240+
}
241+
226242
staticbool
227243
_equalArray(Array*a,Array*b)
228244
{
@@ -393,7 +409,7 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
393409
if (a->plan_id!=b->plan_id)
394410
return false;
395411

396-
if (!equal(a->sublink->oper,b->sublink->oper))
412+
if (!equal(a->sublink,b->sublink))
397413
return false;
398414

399415
return true;
@@ -713,6 +729,9 @@ equal(void *a, void *b)
713729
caseT_Aggref:
714730
retval=_equalAggref(a,b);
715731
break;
732+
caseT_SubLink:
733+
retval=_equalSubLink(a,b);
734+
break;
716735
caseT_Func:
717736
retval=_equalFunc(a,b);
718737
break;

‎src/backend/optimizer/plan/planmain.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.44 1999/09/13 00:17:25 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.45 1999/09/26 02:28:27 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -66,24 +66,41 @@ query_planner(Query *root,
6666
List*level_tlist;
6767
Plan*subplan;
6868

69+
/*
70+
* Simplify constant expressions in both targetlist and qual.
71+
*
72+
* Note that at this point the qual has not yet been converted to
73+
* implicit-AND form, so we can apply eval_const_expressions directly.
74+
* Also note that we need to do this before SS_process_sublinks,
75+
* because that routine inserts bogus "Const" nodes.
76+
*/
77+
tlist= (List*)eval_const_expressions((Node*)tlist);
78+
qual= (List*)eval_const_expressions((Node*)qual);
79+
80+
/*
81+
* Canonicalize the qual, and convert it to implicit-AND format.
82+
*/
83+
qual=canonicalize_qual((Expr*)qual, true);
84+
#ifdefOPTIMIZER_DEBUG
85+
printf("After canonicalize_qual()\n");
86+
pprint(qual);
87+
#endif
88+
89+
/* Replace uplevel vars with Param nodes */
6990
if (PlannerQueryLevel>1)
7091
{
71-
/* should copy be made ? */
7292
tlist= (List*)SS_replace_correlation_vars((Node*)tlist);
7393
qual= (List*)SS_replace_correlation_vars((Node*)qual);
7494
}
95+
/* Expand SubLinks to SubPlans */
7596
if (root->hasSubLinks)
7697
qual= (List*)SS_process_sublinks((Node*)qual);
7798

78-
qual=canonicalize_qual((Expr*)qual, true);
79-
#ifdefOPTIMIZER_DEBUG
80-
printf("After canonicalize_qual()\n");
81-
pprint(qual);
82-
#endif
83-
8499
/*
85100
* Pull out any non-variable qualifications so these can be put in the
86-
* topmost result node.
101+
* topmost result node. (Any *really* non-variable quals will probably
102+
* have been optimized away by eval_const_expressions(). What we're
103+
* looking for here is quals that depend only on outer-level vars...)
87104
*/
88105
qual=pull_constant_clauses(qual,&constant_qual);
89106

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp