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

Commit5590be0

Browse files
committed
Preserve AND/OR flatness during eval_const_expressions(). This seems a
useful improvement in any case, and it keeps the new logic for restrictinfostructures happy. Per report from Kris Jurka.
1 parent1c15812 commit5590be0

File tree

1 file changed

+154
-84
lines changed

1 file changed

+154
-84
lines changed

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

Lines changed: 154 additions & 84 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.161 2004/01/10 18:13:53 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.162 2004/01/12 20:48:15 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -61,6 +61,10 @@ static bool contain_mutable_functions_walker(Node *node, void *context);
6161
staticboolcontain_volatile_functions_walker(Node*node,void*context);
6262
staticboolcontain_nonstrict_functions_walker(Node*node,void*context);
6363
staticNode*eval_const_expressions_mutator(Node*node,List*active_fns);
64+
staticList*simplify_or_arguments(List*args,
65+
bool*haveNull,bool*forceTrue);
66+
staticList*simplify_and_arguments(List*args,
67+
bool*haveNull,bool*forceFalse);
6468
staticExpr*simplify_function(Oidfuncid,Oidresult_type,List*args,
6569
boolallow_inline,List*active_fns);
6670
staticExpr*evaluate_function(Oidfuncid,Oidresult_type,List*args,
@@ -249,6 +253,9 @@ make_andclause(List *andclauses)
249253
* Variant of make_andclause for ANDing two qual conditions together.
250254
* Qual conditions have the property that a NULL nodetree is interpreted
251255
* as 'true'.
256+
*
257+
* NB: this makes no attempt to preserve AND/OR flatness; so it should not
258+
* be used on a qual that has already been run through prepqual.c.
252259
*/
253260
Node*
254261
make_and_qual(Node*qual1,Node*qual2)
@@ -1210,7 +1217,6 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
12101217
{
12111218
BoolExpr*expr= (BoolExpr*)node;
12121219
List*args;
1213-
Const*const_input;
12141220

12151221
/*
12161222
* Reduce constants in the BoolExpr's arguments. We know args is
@@ -1225,124 +1231,66 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
12251231
{
12261232
caseOR_EXPR:
12271233
{
1228-
/*----------
1229-
* OR arguments are handled as follows:
1230-
*non constant: keep
1231-
*FALSE: drop (does not affect result)
1232-
*TRUE: force result to TRUE
1233-
*NULL: keep only one
1234-
* We keep one NULL input because ExecEvalOr returns NULL
1235-
* when no input is TRUE and at least one is NULL.
1236-
*----------
1237-
*/
1238-
FastListnewargs;
1239-
List*arg;
1234+
List*newargs;
12401235
boolhaveNull= false;
12411236
boolforceTrue= false;
12421237

1243-
FastListInit(&newargs);
1244-
foreach(arg,args)
1245-
{
1246-
if (!IsA(lfirst(arg),Const))
1247-
{
1248-
FastAppend(&newargs,lfirst(arg));
1249-
continue;
1250-
}
1251-
const_input= (Const*)lfirst(arg);
1252-
if (const_input->constisnull)
1253-
haveNull= true;
1254-
elseif (DatumGetBool(const_input->constvalue))
1255-
forceTrue= true;
1256-
/* otherwise, we can drop the constant-false input */
1257-
}
1258-
1259-
/*
1260-
* We could return TRUE before falling out of the
1261-
* loop, but this coding method will be easier to
1262-
* adapt if we ever add a notion of non-removable
1263-
* functions. We'd need to check all the inputs for
1264-
* non-removability.
1265-
*/
1238+
newargs=simplify_or_arguments(args,
1239+
&haveNull,&forceTrue);
12661240
if (forceTrue)
12671241
returnMAKEBOOLCONST(true, false);
12681242
if (haveNull)
1269-
FastAppend(&newargs,MAKEBOOLCONST(false, true));
1243+
newargs=lappend(newargs,MAKEBOOLCONST(false, true));
12701244
/* If all the inputs are FALSE, result is FALSE */
1271-
if (FastListValue(&newargs)==NIL)
1245+
if (newargs==NIL)
12721246
returnMAKEBOOLCONST(false, false);
12731247
/* If only one nonconst-or-NULL input, it's the result */
1274-
if (lnext(FastListValue(&newargs))==NIL)
1275-
return (Node*)lfirst(FastListValue(&newargs));
1248+
if (lnext(newargs)==NIL)
1249+
return (Node*)lfirst(newargs);
12761250
/* Else we still need an OR node */
1277-
return (Node*)make_orclause(FastListValue(&newargs));
1251+
return (Node*)make_orclause(newargs);
12781252
}
12791253
caseAND_EXPR:
12801254
{
1281-
/*----------
1282-
* AND arguments are handled as follows:
1283-
*non constant: keep
1284-
*TRUE: drop (does not affect result)
1285-
*FALSE: force result to FALSE
1286-
*NULL: keep only one
1287-
* We keep one NULL input because ExecEvalAnd returns NULL
1288-
* when no input is FALSE and at least one is NULL.
1289-
*----------
1290-
*/
1291-
FastListnewargs;
1292-
List*arg;
1255+
List*newargs;
12931256
boolhaveNull= false;
12941257
boolforceFalse= false;
12951258

1296-
FastListInit(&newargs);
1297-
foreach(arg,args)
1298-
{
1299-
if (!IsA(lfirst(arg),Const))
1300-
{
1301-
FastAppend(&newargs,lfirst(arg));
1302-
continue;
1303-
}
1304-
const_input= (Const*)lfirst(arg);
1305-
if (const_input->constisnull)
1306-
haveNull= true;
1307-
elseif (!DatumGetBool(const_input->constvalue))
1308-
forceFalse= true;
1309-
/* otherwise, we can drop the constant-true input */
1310-
}
1311-
1312-
/*
1313-
* We could return FALSE before falling out of the
1314-
* loop, but this coding method will be easier to
1315-
* adapt if we ever add a notion of non-removable
1316-
* functions. We'd need to check all the inputs for
1317-
* non-removability.
1318-
*/
1259+
newargs=simplify_and_arguments(args,
1260+
&haveNull,&forceFalse);
13191261
if (forceFalse)
13201262
returnMAKEBOOLCONST(false, false);
13211263
if (haveNull)
1322-
FastAppend(&newargs,MAKEBOOLCONST(false, true));
1264+
newargs=lappend(newargs,MAKEBOOLCONST(false, true));
13231265
/* If all the inputs are TRUE, result is TRUE */
1324-
if (FastListValue(&newargs)==NIL)
1266+
if (newargs==NIL)
13251267
returnMAKEBOOLCONST(true, false);
13261268
/* If only one nonconst-or-NULL input, it's the result */
1327-
if (lnext(FastListValue(&newargs))==NIL)
1328-
return (Node*)lfirst(FastListValue(&newargs));
1269+
if (lnext(newargs)==NIL)
1270+
return (Node*)lfirst(newargs);
13291271
/* Else we still need an AND node */
1330-
return (Node*)make_andclause(FastListValue(&newargs));
1272+
return (Node*)make_andclause(newargs);
13311273
}
13321274
caseNOT_EXPR:
13331275
Assert(length(args)==1);
13341276
if (IsA(lfirst(args),Const))
13351277
{
1336-
const_input= (Const*)lfirst(args);
1278+
Const*const_input= (Const*)lfirst(args);
1279+
13371280
/* NOT NULL => NULL */
13381281
if (const_input->constisnull)
13391282
returnMAKEBOOLCONST(false, true);
13401283
/* otherwise pretty easy */
13411284
returnMAKEBOOLCONST(!DatumGetBool(const_input->constvalue),
13421285
false);
13431286
}
1287+
elseif (not_clause((Node*)lfirst(args)))
1288+
{
1289+
/* Cancel NOT/NOT */
1290+
return (Node*)get_notclausearg((Expr*)lfirst(args));
1291+
}
13441292
/* Else we still need a NOT node */
1345-
return (Node*)make_notclause(lfirst(args));
1293+
return (Node*)make_notclause((Expr*)lfirst(args));
13461294
default:
13471295
elog(ERROR,"unrecognized boolop: %d",
13481296
(int)expr->boolop);
@@ -1579,6 +1527,128 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
15791527
(void*)active_fns);
15801528
}
15811529

1530+
/*
1531+
* Subroutine for eval_const_expressions: scan the arguments of an OR clause
1532+
*
1533+
* OR arguments are handled as follows:
1534+
*non constant: keep
1535+
*FALSE: drop (does not affect result)
1536+
*TRUE: force result to TRUE
1537+
*NULL: keep only one
1538+
* We must keep one NULL input because ExecEvalOr returns NULL when no input
1539+
* is TRUE and at least one is NULL.
1540+
*
1541+
* This is split out as a subroutine so that we can recurse to fold sub-ORs
1542+
* into the upper OR clause, thereby preserving AND/OR flatness.
1543+
*
1544+
* The output arguments *haveNull and *forceTrue must be initialized FALSE
1545+
* by the caller. They will be set TRUE if a null constant or true constant,
1546+
* respectively, is detected anywhere in the argument list.
1547+
*/
1548+
staticList*
1549+
simplify_or_arguments(List*args,bool*haveNull,bool*forceTrue)
1550+
{
1551+
List*newargs=NIL;
1552+
List*larg;
1553+
1554+
foreach(larg,args)
1555+
{
1556+
Node*arg= (Node*)lfirst(larg);
1557+
1558+
if (IsA(arg,Const))
1559+
{
1560+
Const*const_input= (Const*)arg;
1561+
1562+
if (const_input->constisnull)
1563+
*haveNull= true;
1564+
elseif (DatumGetBool(const_input->constvalue))
1565+
{
1566+
*forceTrue= true;
1567+
/*
1568+
* Once we detect a TRUE result we can just exit the loop
1569+
* immediately. However, if we ever add a notion of
1570+
* non-removable functions, we'd need to keep scanning.
1571+
*/
1572+
returnNIL;
1573+
}
1574+
/* otherwise, we can drop the constant-false input */
1575+
}
1576+
elseif (or_clause(arg))
1577+
{
1578+
newargs=nconc(newargs,
1579+
simplify_or_arguments(((BoolExpr*)arg)->args,
1580+
haveNull,forceTrue));
1581+
}
1582+
else
1583+
{
1584+
newargs=lappend(newargs,arg);
1585+
}
1586+
}
1587+
1588+
returnnewargs;
1589+
}
1590+
1591+
/*
1592+
* Subroutine for eval_const_expressions: scan the arguments of an AND clause
1593+
*
1594+
* AND arguments are handled as follows:
1595+
*non constant: keep
1596+
*TRUE: drop (does not affect result)
1597+
*FALSE: force result to FALSE
1598+
*NULL: keep only one
1599+
* We must keep one NULL input because ExecEvalAnd returns NULL when no input
1600+
* is FALSE and at least one is NULL.
1601+
*
1602+
* This is split out as a subroutine so that we can recurse to fold sub-ANDs
1603+
* into the upper AND clause, thereby preserving AND/OR flatness.
1604+
*
1605+
* The output arguments *haveNull and *forceFalse must be initialized FALSE
1606+
* by the caller. They will be set TRUE if a null constant or false constant,
1607+
* respectively, is detected anywhere in the argument list.
1608+
*/
1609+
staticList*
1610+
simplify_and_arguments(List*args,bool*haveNull,bool*forceFalse)
1611+
{
1612+
List*newargs=NIL;
1613+
List*larg;
1614+
1615+
foreach(larg,args)
1616+
{
1617+
Node*arg= (Node*)lfirst(larg);
1618+
1619+
if (IsA(arg,Const))
1620+
{
1621+
Const*const_input= (Const*)arg;
1622+
1623+
if (const_input->constisnull)
1624+
*haveNull= true;
1625+
elseif (!DatumGetBool(const_input->constvalue))
1626+
{
1627+
*forceFalse= true;
1628+
/*
1629+
* Once we detect a FALSE result we can just exit the loop
1630+
* immediately. However, if we ever add a notion of
1631+
* non-removable functions, we'd need to keep scanning.
1632+
*/
1633+
returnNIL;
1634+
}
1635+
/* otherwise, we can drop the constant-true input */
1636+
}
1637+
elseif (and_clause(arg))
1638+
{
1639+
newargs=nconc(newargs,
1640+
simplify_and_arguments(((BoolExpr*)arg)->args,
1641+
haveNull,forceFalse));
1642+
}
1643+
else
1644+
{
1645+
newargs=lappend(newargs,arg);
1646+
}
1647+
}
1648+
1649+
returnnewargs;
1650+
}
1651+
15821652
/*
15831653
* Subroutine for eval_const_expressions: try to simplify a function call
15841654
* (which might originally have been an operator; we don't care)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp