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

Commit2f153dd

Browse files
committed
Refactor to reduce code duplication for function property checking.
As noted by Andres Freund, we'd accumulated quite a few similar functionsin clauses.c that examine all functions in an expression tree to see ifthey satisfy some boolean test. Reduce the duplication by inventing afunction check_functions_in_node() that applies a simple callback functionto each SQL function OID appearing in a given expression node. This alsofixes some arguable oversights; for example, contain_mutable_functions()did not check aggregate or window functions for mutability. I doubt thatthat represents a live bug at the moment, because we don't really considermutability for aggregates; but it might someday be one.I chose to put check_functions_in_node() in nodeFuncs.c because it seemedlike other modules might wish to use it in future. That in turn forcedmoving set_opfuncid() et al into nodeFuncs.c, as the alternative was fornodeFuncs.c to depend on optimizer/setrefs.c which didn't seem very clean.In passing, teach contain_leaked_vars_walker() about a few more expressionnode types it can safely look through, and improve the rather messy andundercommented code in has_parallel_hazard_walker().Discussion: <20160527185853.ziol2os2zskahl7v@alap3.anarazel.de>
1 parent13761bc commit2f153dd

File tree

7 files changed

+371
-575
lines changed

7 files changed

+371
-575
lines changed

‎src/backend/nodes/nodeFuncs.c

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
staticboolexpression_returns_set_walker(Node*node,void*context);
2929
staticintleftmostLoc(intloc1,intloc2);
30+
staticboolfix_opfuncids_walker(Node*node,void*context);
3031
staticboolplanstate_walk_subplans(List*plans,bool (*walker) (),
3132
void*context);
3233
staticboolplanstate_walk_members(List*plans,PlanState**planstates,
@@ -1559,6 +1560,183 @@ leftmostLoc(int loc1, int loc2)
15591560
}
15601561

15611562

1563+
/*
1564+
* fix_opfuncids
1565+
* Calculate opfuncid field from opno for each OpExpr node in given tree.
1566+
* The given tree can be anything expression_tree_walker handles.
1567+
*
1568+
* The argument is modified in-place. (This is OK since we'd want the
1569+
* same change for any node, even if it gets visited more than once due to
1570+
* shared structure.)
1571+
*/
1572+
void
1573+
fix_opfuncids(Node*node)
1574+
{
1575+
/* This tree walk requires no special setup, so away we go... */
1576+
fix_opfuncids_walker(node,NULL);
1577+
}
1578+
1579+
staticbool
1580+
fix_opfuncids_walker(Node*node,void*context)
1581+
{
1582+
if (node==NULL)
1583+
return false;
1584+
if (IsA(node,OpExpr))
1585+
set_opfuncid((OpExpr*)node);
1586+
elseif (IsA(node,DistinctExpr))
1587+
set_opfuncid((OpExpr*)node);/* rely on struct equivalence */
1588+
elseif (IsA(node,NullIfExpr))
1589+
set_opfuncid((OpExpr*)node);/* rely on struct equivalence */
1590+
elseif (IsA(node,ScalarArrayOpExpr))
1591+
set_sa_opfuncid((ScalarArrayOpExpr*)node);
1592+
returnexpression_tree_walker(node,fix_opfuncids_walker,context);
1593+
}
1594+
1595+
/*
1596+
* set_opfuncid
1597+
*Set the opfuncid (procedure OID) in an OpExpr node,
1598+
*if it hasn't been set already.
1599+
*
1600+
* Because of struct equivalence, this can also be used for
1601+
* DistinctExpr and NullIfExpr nodes.
1602+
*/
1603+
void
1604+
set_opfuncid(OpExpr*opexpr)
1605+
{
1606+
if (opexpr->opfuncid==InvalidOid)
1607+
opexpr->opfuncid=get_opcode(opexpr->opno);
1608+
}
1609+
1610+
/*
1611+
* set_sa_opfuncid
1612+
*As above, for ScalarArrayOpExpr nodes.
1613+
*/
1614+
void
1615+
set_sa_opfuncid(ScalarArrayOpExpr*opexpr)
1616+
{
1617+
if (opexpr->opfuncid==InvalidOid)
1618+
opexpr->opfuncid=get_opcode(opexpr->opno);
1619+
}
1620+
1621+
1622+
/*
1623+
*check_functions_in_node -
1624+
* apply checker() to each function OID contained in given expression node
1625+
*
1626+
* Returns TRUE if the checker() function does; for nodes representing more
1627+
* than one function call, returns TRUE if the checker() function does so
1628+
* for any of those functions. Returns FALSE if node does not invoke any
1629+
* SQL-visible function. Caller must not pass node == NULL.
1630+
*
1631+
* This function examines only the given node; it does not recurse into any
1632+
* sub-expressions. Callers typically prefer to keep control of the recursion
1633+
* for themselves, in case additional checks should be made, or because they
1634+
* have special rules about which parts of the tree need to be visited.
1635+
*
1636+
* Note: we ignore MinMaxExpr, XmlExpr, and CoerceToDomain nodes, because they
1637+
* do not contain SQL function OIDs. However, they can invoke SQL-visible
1638+
* functions, so callers should take thought about how to treat them.
1639+
*/
1640+
bool
1641+
check_functions_in_node(Node*node,check_function_callbackchecker,
1642+
void*context)
1643+
{
1644+
switch (nodeTag(node))
1645+
{
1646+
caseT_Aggref:
1647+
{
1648+
Aggref*expr= (Aggref*)node;
1649+
1650+
if (checker(expr->aggfnoid,context))
1651+
return true;
1652+
}
1653+
break;
1654+
caseT_WindowFunc:
1655+
{
1656+
WindowFunc*expr= (WindowFunc*)node;
1657+
1658+
if (checker(expr->winfnoid,context))
1659+
return true;
1660+
}
1661+
break;
1662+
caseT_FuncExpr:
1663+
{
1664+
FuncExpr*expr= (FuncExpr*)node;
1665+
1666+
if (checker(expr->funcid,context))
1667+
return true;
1668+
}
1669+
break;
1670+
caseT_OpExpr:
1671+
caseT_DistinctExpr:/* struct-equivalent to OpExpr */
1672+
caseT_NullIfExpr:/* struct-equivalent to OpExpr */
1673+
{
1674+
OpExpr*expr= (OpExpr*)node;
1675+
1676+
/* Set opfuncid if it wasn't set already */
1677+
set_opfuncid(expr);
1678+
if (checker(expr->opfuncid,context))
1679+
return true;
1680+
}
1681+
break;
1682+
caseT_ScalarArrayOpExpr:
1683+
{
1684+
ScalarArrayOpExpr*expr= (ScalarArrayOpExpr*)node;
1685+
1686+
set_sa_opfuncid(expr);
1687+
if (checker(expr->opfuncid,context))
1688+
return true;
1689+
}
1690+
break;
1691+
caseT_CoerceViaIO:
1692+
{
1693+
CoerceViaIO*expr= (CoerceViaIO*)node;
1694+
Oidiofunc;
1695+
Oidtypioparam;
1696+
booltypisvarlena;
1697+
1698+
/* check the result type's input function */
1699+
getTypeInputInfo(expr->resulttype,
1700+
&iofunc,&typioparam);
1701+
if (checker(iofunc,context))
1702+
return true;
1703+
/* check the input type's output function */
1704+
getTypeOutputInfo(exprType((Node*)expr->arg),
1705+
&iofunc,&typisvarlena);
1706+
if (checker(iofunc,context))
1707+
return true;
1708+
}
1709+
break;
1710+
caseT_ArrayCoerceExpr:
1711+
{
1712+
ArrayCoerceExpr*expr= (ArrayCoerceExpr*)node;
1713+
1714+
if (OidIsValid(expr->elemfuncid)&&
1715+
checker(expr->elemfuncid,context))
1716+
return true;
1717+
}
1718+
break;
1719+
caseT_RowCompareExpr:
1720+
{
1721+
RowCompareExpr*rcexpr= (RowCompareExpr*)node;
1722+
ListCell*opid;
1723+
1724+
foreach(opid,rcexpr->opnos)
1725+
{
1726+
Oidopfuncid=get_opcode(lfirst_oid(opid));
1727+
1728+
if (checker(opfuncid,context))
1729+
return true;
1730+
}
1731+
}
1732+
break;
1733+
default:
1734+
break;
1735+
}
1736+
return false;
1737+
}
1738+
1739+
15621740
/*
15631741
* Standard expression-tree walking support
15641742
*

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

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ static List *set_returning_clause_references(PlannerInfo *root,
147147
Plan*topplan,
148148
IndexresultRelation,
149149
intrtoffset);
150-
staticboolfix_opfuncids_walker(Node*node,void*context);
151150
staticboolextract_query_dependencies_walker(Node*node,
152151
PlannerInfo*context);
153152

@@ -2556,68 +2555,6 @@ set_returning_clause_references(PlannerInfo *root,
25562555
}
25572556

25582557

2559-
/*****************************************************************************
2560-
*OPERATOR REGPROC LOOKUP
2561-
*****************************************************************************/
2562-
2563-
/*
2564-
* fix_opfuncids
2565-
* Calculate opfuncid field from opno for each OpExpr node in given tree.
2566-
* The given tree can be anything expression_tree_walker handles.
2567-
*
2568-
* The argument is modified in-place. (This is OK since we'd want the
2569-
* same change for any node, even if it gets visited more than once due to
2570-
* shared structure.)
2571-
*/
2572-
void
2573-
fix_opfuncids(Node*node)
2574-
{
2575-
/* This tree walk requires no special setup, so away we go... */
2576-
fix_opfuncids_walker(node,NULL);
2577-
}
2578-
2579-
staticbool
2580-
fix_opfuncids_walker(Node*node,void*context)
2581-
{
2582-
if (node==NULL)
2583-
return false;
2584-
if (IsA(node,OpExpr))
2585-
set_opfuncid((OpExpr*)node);
2586-
elseif (IsA(node,DistinctExpr))
2587-
set_opfuncid((OpExpr*)node);/* rely on struct equivalence */
2588-
elseif (IsA(node,NullIfExpr))
2589-
set_opfuncid((OpExpr*)node);/* rely on struct equivalence */
2590-
elseif (IsA(node,ScalarArrayOpExpr))
2591-
set_sa_opfuncid((ScalarArrayOpExpr*)node);
2592-
returnexpression_tree_walker(node,fix_opfuncids_walker,context);
2593-
}
2594-
2595-
/*
2596-
* set_opfuncid
2597-
*Set the opfuncid (procedure OID) in an OpExpr node,
2598-
*if it hasn't been set already.
2599-
*
2600-
* Because of struct equivalence, this can also be used for
2601-
* DistinctExpr and NullIfExpr nodes.
2602-
*/
2603-
void
2604-
set_opfuncid(OpExpr*opexpr)
2605-
{
2606-
if (opexpr->opfuncid==InvalidOid)
2607-
opexpr->opfuncid=get_opcode(opexpr->opno);
2608-
}
2609-
2610-
/*
2611-
* set_sa_opfuncid
2612-
*As above, for ScalarArrayOpExpr nodes.
2613-
*/
2614-
void
2615-
set_sa_opfuncid(ScalarArrayOpExpr*opexpr)
2616-
{
2617-
if (opexpr->opfuncid==InvalidOid)
2618-
opexpr->opfuncid=get_opcode(opexpr->opno);
2619-
}
2620-
26212558
/*****************************************************************************
26222559
*QUERY DEPENDENCY MANAGEMENT
26232560
*****************************************************************************/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp