aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-01-29 15:26:44 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-01-29 15:26:44 -0500
commita1b8c41e990ec0f083e9b684700a07640d5a356a (patch)
treedaa26b95223c1e2a09507973853aa77b91df7644 /src/backend
parente77cfa54d700557ea700d47454c9e570f20f1841 (diff)
downloadpostgresql-a1b8c41e990ec0f083e9b684700a07640d5a356a.tar.gz
postgresql-a1b8c41e990ec0f083e9b684700a07640d5a356a.zip
Make some small planner API cleanups.
Move a few very simple node-creation and node-type-testing functions from the planner's clauses.c to nodes/makefuncs and nodes/nodeFuncs. There's nothing planner-specific about them, as evidenced by the number of other places that were using them. While at it, rename and_clause() etc to is_andclause() etc, to clarify that they are node-type-testing functions not node-creation functions. And use "static inline" implementations for the shortest ones. Also, modify flatten_join_alias_vars() and some subsidiary functions to take a Query not a PlannerInfo to define the join structure that Vars should be translated according to. They were only using the "parse" field of the PlannerInfo anyway, so this just requires removing one level of indirection. The advantage is that now parse_agg.c can use flatten_join_alias_vars() without the horrid kluge of creating an incomplete PlannerInfo, which will allow that file to be decoupled from relation.h in a subsequent patch. Discussion: https://postgr.es/m/11460.1548706639@sss.pgh.pa.us
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/commands/explain.c1
-rw-r--r--src/backend/executor/nodeSubplan.c4
-rw-r--r--src/backend/executor/nodeTidscan.c2
-rw-r--r--src/backend/nodes/makefuncs.c135
-rw-r--r--src/backend/nodes/print.c3
-rw-r--r--src/backend/optimizer/path/clausesel.c7
-rw-r--r--src/backend/optimizer/path/costsize.c1
-rw-r--r--src/backend/optimizer/path/indxpath.c6
-rw-r--r--src/backend/optimizer/path/joinrels.c4
-rw-r--r--src/backend/optimizer/path/tidpath.c2
-rw-r--r--src/backend/optimizer/plan/initsplan.c1
-rw-r--r--src/backend/optimizer/plan/planner.c5
-rw-r--r--src/backend/optimizer/plan/subselect.c10
-rw-r--r--src/backend/optimizer/prep/prepjointree.c10
-rw-r--r--src/backend/optimizer/prep/prepqual.c15
-rw-r--r--src/backend/optimizer/util/clauses.c246
-rw-r--r--src/backend/optimizer/util/orclauses.c8
-rw-r--r--src/backend/optimizer/util/predtest.c5
-rw-r--r--src/backend/optimizer/util/restrictinfo.c10
-rw-r--r--src/backend/optimizer/util/var.c22
-rw-r--r--src/backend/parser/parse_agg.c36
-rw-r--r--src/backend/partitioning/partprune.c6
-rw-r--r--src/backend/statistics/dependencies.c3
-rw-r--r--src/backend/utils/cache/relcache.c1
24 files changed, 222 insertions, 321 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index ae7f0382031..5d859b7c99e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -22,6 +22,7 @@
#include "foreign/fdwapi.h"
#include "jit/jit.h"
#include "nodes/extensible.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 574e7bc4fa0..152696035cd 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -33,8 +33,8 @@
#include "executor/executor.h"
#include "executor/nodeSubplan.h"
#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "miscadmin.h"
-#include "optimizer/clauses.h"
#include "utils/array.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
@@ -888,7 +888,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
/* single combining operator */
oplist = list_make1(subplan->testexpr);
}
- else if (and_clause((Node *) subplan->testexpr))
+ else if (is_andclause(subplan->testexpr))
{
/* multiple combining operators */
oplist = castNode(BoolExpr, subplan->testexpr)->args;
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index b7a8725e2dc..8daf09c785a 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -28,7 +28,7 @@
#include "executor/execdebug.h"
#include "executor/nodeTidscan.h"
#include "miscadmin.h"
-#include "optimizer/clauses.h"
+#include "nodes/nodeFuncs.h"
#include "storage/bufmgr.h"
#include "utils/array.h"
#include "utils/rel.h"
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 079d0160a8b..7085ed2c4c8 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -599,6 +599,141 @@ makeFuncCall(List *name, List *args, int location)
}
/*
+ * make_opclause
+ * Creates an operator clause given its operator info, left operand
+ * and right operand (pass NULL to create single-operand clause),
+ * and collation info.
+ */
+Expr *
+make_opclause(Oid opno, Oid opresulttype, bool opretset,
+ Expr *leftop, Expr *rightop,
+ Oid opcollid, Oid inputcollid)
+{
+ OpExpr *expr = makeNode(OpExpr);
+
+ expr->opno = opno;
+ expr->opfuncid = InvalidOid;
+ expr->opresulttype = opresulttype;
+ expr->opretset = opretset;
+ expr->opcollid = opcollid;
+ expr->inputcollid = inputcollid;
+ if (rightop)
+ expr->args = list_make2(leftop, rightop);
+ else
+ expr->args = list_make1(leftop);
+ expr->location = -1;
+ return (Expr *) expr;
+}
+
+/*
+ * make_andclause
+ *
+ * Creates an 'and' clause given a list of its subclauses.
+ */
+Expr *
+make_andclause(List *andclauses)
+{
+ BoolExpr *expr = makeNode(BoolExpr);
+
+ expr->boolop = AND_EXPR;
+ expr->args = andclauses;
+ expr->location = -1;
+ return (Expr *) expr;
+}
+
+/*
+ * make_orclause
+ *
+ * Creates an 'or' clause given a list of its subclauses.
+ */
+Expr *
+make_orclause(List *orclauses)
+{
+ BoolExpr *expr = makeNode(BoolExpr);
+
+ expr->boolop = OR_EXPR;
+ expr->args = orclauses;
+ expr->location = -1;
+ return (Expr *) expr;
+}
+
+/*
+ * make_notclause
+ *
+ * Create a 'not' clause given the expression to be negated.
+ */
+Expr *
+make_notclause(Expr *notclause)
+{
+ BoolExpr *expr = makeNode(BoolExpr);
+
+ expr->boolop = NOT_EXPR;
+ expr->args = list_make1(notclause);
+ expr->location = -1;
+ return (Expr *) expr;
+}
+
+/*
+ * make_and_qual
+ *
+ * Variant of make_andclause for ANDing two qual conditions together.
+ * Qual conditions have the property that a NULL nodetree is interpreted
+ * as 'true'.
+ *
+ * NB: this makes no attempt to preserve AND/OR flatness; so it should not
+ * be used on a qual that has already been run through prepqual.c.
+ */
+Node *
+make_and_qual(Node *qual1, Node *qual2)
+{
+ if (qual1 == NULL)
+ return qual2;
+ if (qual2 == NULL)
+ return qual1;
+ return (Node *) make_andclause(list_make2(qual1, qual2));
+}
+
+/*
+ * The planner and executor usually represent qualification expressions
+ * as lists of boolean expressions with implicit AND semantics.
+ *
+ * These functions convert between an AND-semantics expression list and the
+ * ordinary representation of a boolean expression.
+ *
+ * Note that an empty list is considered equivalent to TRUE.
+ */
+Expr *
+make_ands_explicit(List *andclauses)
+{
+ if (andclauses == NIL)
+ return (Expr *) makeBoolConst(true, false);
+ else if (list_length(andclauses) == 1)
+ return (Expr *) linitial(andclauses);
+ else
+ return make_andclause(andclauses);
+}
+
+List *
+make_ands_implicit(Expr *clause)
+{
+ /*
+ * NB: because the parser sets the qual field to NULL in a query that has
+ * no WHERE clause, we must consider a NULL input clause as TRUE, even
+ * though one might more reasonably think it FALSE.
+ */
+ if (clause == NULL)
+ return NIL; /* NULL -> NIL list == TRUE */
+ else if (is_andclause(clause))
+ return ((BoolExpr *) clause)->args;
+ else if (IsA(clause, Const) &&
+ !((Const *) clause)->constisnull &&
+ DatumGetBool(((Const *) clause)->constvalue))
+ return NIL; /* constant TRUE input -> NIL list */
+ else
+ return list_make1(clause);
+}
+
+/*
* makeGroupingSet
*
*/
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index b9fa3f4842a..6d6da5299fa 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -21,8 +21,9 @@
#include "access/printtup.h"
#include "lib/stringinfo.h"
+#include "nodes/nodeFuncs.h"
#include "nodes/print.h"
-#include "optimizer/clauses.h"
+#include "nodes/relation.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index 3739b9817a0..50452706ed1 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
@@ -688,7 +689,7 @@ clause_selectivity(PlannerInfo *root,
/* XXX any way to do better than default? */
}
}
- else if (not_clause(clause))
+ else if (is_notclause(clause))
{
/* inverse of the selectivity of the underlying clause */
s1 = 1.0 - clause_selectivity(root,
@@ -697,7 +698,7 @@ clause_selectivity(PlannerInfo *root,
jointype,
sjinfo);
}
- else if (and_clause(clause))
+ else if (is_andclause(clause))
{
/* share code with clauselist_selectivity() */
s1 = clauselist_selectivity(root,
@@ -706,7 +707,7 @@ clause_selectivity(PlannerInfo *root,
jointype,
sjinfo);
}
- else if (or_clause(clause))
+ else if (is_orclause(clause))
{
/*
* Selectivities for an OR clause are computed as s1+s2 - s1*s2 to
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 30b0e925d3c..19be1f375c5 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -79,6 +79,7 @@
#include "executor/executor.h"
#include "executor/nodeHash.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index f8e674c9c4e..be50d56b5a9 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1297,7 +1297,7 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
List *indlist;
/* OR arguments should be ANDs or sub-RestrictInfos */
- if (and_clause(orarg))
+ if (is_andclause(orarg))
{
List *andargs = ((BoolExpr *) orarg)->args;
@@ -3368,7 +3368,7 @@ match_boolean_index_clause(Node *clause,
if (match_index_to_operand(clause, indexcol, index))
return true;
/* NOT clause? */
- if (not_clause(clause))
+ if (is_notclause(clause))
{
if (match_index_to_operand((Node *) get_notclausearg((Expr *) clause),
indexcol, index))
@@ -3680,7 +3680,7 @@ expand_boolean_index_clause(Node *clause,
InvalidOid, InvalidOid);
}
/* NOT clause? */
- if (not_clause(clause))
+ if (is_notclause(clause))
{
Node *arg = (Node *) get_notclausearg((Expr *) clause);
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 8bfe9c3ff74..dfbbfdac6d7 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "miscadmin.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/appendinfo.h"
#include "optimizer/clauses.h"
#include "optimizer/joininfo.h"
@@ -1554,8 +1555,7 @@ have_partkey_equi_join(RelOptInfo *joinrel,
if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
continue;
- opexpr = (OpExpr *) rinfo->clause;
- Assert(is_opclause(opexpr));
+ opexpr = castNode(OpExpr, rinfo->clause);
/*
* The equi-join between partition keys is strict if equi-join between
diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c
index 74b5a151350..94c88bd6622 100644
--- a/src/backend/optimizer/path/tidpath.c
+++ b/src/backend/optimizer/path/tidpath.c
@@ -250,7 +250,7 @@ TidQualFromRestrictInfoList(List *rlist, RelOptInfo *rel)
List *sublist;
/* OR arguments should be ANDs or sub-RestrictInfos */
- if (and_clause(orarg))
+ if (is_andclause(orarg))
{
List *andargs = ((BoolExpr *) orarg)->args;
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 1c78852a881..a2376d2ed7e 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -16,6 +16,7 @@
#include "catalog/pg_type.h"
#include "catalog/pg_class.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 272710eed2d..5db88afd893 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -849,7 +849,8 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
*/
if (rte->lateral && root->hasJoinRTEs)
rte->subquery = (Query *)
- flatten_join_alias_vars(root, (Node *) rte->subquery);
+ flatten_join_alias_vars(root->parse,
+ (Node *) rte->subquery);
}
else if (rte->rtekind == RTE_FUNCTION)
{
@@ -1054,7 +1055,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
kind == EXPRKIND_VALUES ||
kind == EXPRKIND_TABLESAMPLE ||
kind == EXPRKIND_TABLEFUNC))
- expr = flatten_join_alias_vars(root, expr);
+ expr = flatten_join_alias_vars(root->parse, expr);
/*
* Simplify constant expressions.
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index fd19d0acf1c..60403eef913 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -739,7 +739,7 @@ testexpr_is_hashable(Node *testexpr)
if (hash_ok_operator((OpExpr *) testexpr))
return true;
}
- else if (and_clause(testexpr))
+ else if (is_andclause(testexpr))
{
ListCell *l;
@@ -1693,7 +1693,7 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
* propagates down in both cases. (Note that this is unlike the meaning
* of "top level qual" used in most other places in Postgres.)
*/
- if (and_clause(node))
+ if (is_andclause(node))
{
List *newargs = NIL;
ListCell *l;
@@ -1706,7 +1706,7 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
Node *newarg;
newarg = process_sublinks_mutator(lfirst(l), &locContext);
- if (and_clause(newarg))
+ if (is_andclause(newarg))
newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
else
newargs = lappend(newargs, newarg);
@@ -1714,7 +1714,7 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
return (Node *) make_andclause(newargs);
}
- if (or_clause(node))
+ if (is_orclause(node))
{
List *newargs = NIL;
ListCell *l;
@@ -1727,7 +1727,7 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
Node *newarg;
newarg = process_sublinks_mutator(lfirst(l), &locContext);
- if (or_clause(newarg))
+ if (is_orclause(newarg))
newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
else
newargs = lappend(newargs, newarg);
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index bcbca1a0f50..1f64004cf61 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -497,7 +497,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
/* Else return it unmodified */
return node;
}
- if (not_clause(node))
+ if (is_notclause(node))
{
/* If the immediate argument of NOT is EXISTS, try to convert */
SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
@@ -564,7 +564,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
/* Else return it unmodified */
return node;
}
- if (and_clause(node))
+ if (is_andclause(node))
{
/* Recurse into AND clause */
List *newclauses = NIL;
@@ -968,7 +968,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
* maybe even in the rewriter; but for now let's just fix this case here.)
*/
subquery->targetList = (List *)
- flatten_join_alias_vars(subroot, (Node *) subquery->targetList);
+ flatten_join_alias_vars(subroot->parse, (Node *) subquery->targetList);
/*
* Adjust level-0 varnos in subquery so that we can append its rangetable
@@ -3317,11 +3317,11 @@ get_relids_in_jointree(Node *jtnode, bool include_joins)
* get_relids_for_join: get set of base RT indexes making up a join
*/
Relids
-get_relids_for_join(PlannerInfo *root, int joinrelid)
+get_relids_for_join(Query *query, int joinrelid)
{
Node *jtnode;
- jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
+ jtnode = find_jointree_node_for_rel((Node *) query->jointree,
joinrelid);
if (!jtnode)
elog(ERROR, "could not find join node %d", joinrelid);
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index 234dc5b3e7f..2bd6c200cfa 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -32,6 +32,7 @@
#include "postgres.h"
#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/prep.h"
#include "utils/lsyscache.h"
@@ -333,7 +334,7 @@ pull_ands(List *andlist)
* built a new arglist not shared with any other expr. Otherwise we'd
* need a list_copy here.
*/
- if (and_clause(subexpr))
+ if (is_andclause(subexpr))
out_list = list_concat(out_list,
pull_ands(((BoolExpr *) subexpr)->args));
else
@@ -365,7 +366,7 @@ pull_ors(List *orlist)
* built a new arglist not shared with any other expr. Otherwise we'd
* need a list_copy here.
*/
- if (or_clause(subexpr))
+ if (is_orclause(subexpr))
out_list = list_concat(out_list,
pull_ors(((BoolExpr *) subexpr)->args));
else
@@ -415,7 +416,7 @@ pull_ors(List *orlist)
static Expr *
find_duplicate_ors(Expr *qual, bool is_check)
{
- if (or_clause((Node *) qual))
+ if (is_orclause(qual))
{
List *orlist = NIL;
ListCell *temp;
@@ -459,7 +460,7 @@ find_duplicate_ors(Expr *qual, bool is_check)
/* Now we can look for duplicate ORs */
return process_duplicate_ors(orlist);
}
- else if (and_clause((Node *) qual))
+ else if (is_andclause(qual))
{
List *andlist = NIL;
ListCell *temp;
@@ -550,7 +551,7 @@ process_duplicate_ors(List *orlist)
{
Expr *clause = (Expr *) lfirst(temp);
- if (and_clause((Node *) clause))
+ if (is_andclause(clause))
{
List *subclauses = ((BoolExpr *) clause)->args;
int nclauses = list_length(subclauses);
@@ -588,7 +589,7 @@ process_duplicate_ors(List *orlist)
{
Expr *clause = (Expr *) lfirst(temp2);
- if (and_clause((Node *) clause))
+ if (is_andclause(clause))
{
if (!list_member(((BoolExpr *) clause)->args, refclause))
{
@@ -631,7 +632,7 @@ process_duplicate_ors(List *orlist)
{
Expr *clause = (Expr *) lfirst(temp);
- if (and_clause((Node *) clause))
+ if (is_andclause(clause))
{
List *subclauses = ((BoolExpr *) clause)->args;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index ea11dbb67c3..99616063f45 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -158,244 +158,6 @@ static bool tlist_matches_coltypelist(List *tlist, List *coltypelist);
/*****************************************************************************
- * OPERATOR clause functions
- *****************************************************************************/
-
-/*
- * make_opclause
- * Creates an operator clause given its operator info, left operand
- * and right operand (pass NULL to create single-operand clause),
- * and collation info.
- */
-Expr *
-make_opclause(Oid opno, Oid opresulttype, bool opretset,
- Expr *leftop, Expr *rightop,
- Oid opcollid, Oid inputcollid)
-{
- OpExpr *expr = makeNode(OpExpr);
-
- expr->opno = opno;
- expr->opfuncid = InvalidOid;
- expr->opresulttype = opresulttype;
- expr->opretset = opretset;
- expr->opcollid = opcollid;
- expr->inputcollid = inputcollid;
- if (rightop)
- expr->args = list_make2(leftop, rightop);
- else
- expr->args = list_make1(leftop);
- expr->location = -1;
- return (Expr *) expr;
-}
-
-/*
- * get_leftop
- *
- * Returns the left operand of a clause of the form (op expr expr)
- * or (op expr)
- */
-Node *
-get_leftop(const Expr *clause)
-{
- const OpExpr *expr = (const OpExpr *) clause;
-
- if (expr->args != NIL)
- return linitial(expr->args);
- else
- return NULL;
-}
-
-/*
- * get_rightop
- *
- * Returns the right operand in a clause of the form (op expr expr).
- * NB: result will be NULL if applied to a unary op clause.
- */
-Node *
-get_rightop(const Expr *clause)
-{
- const OpExpr *expr = (const OpExpr *) clause;
-
- if (list_length(expr->args) >= 2)
- return lsecond(expr->args);
- else
- return NULL;
-}
-
-/*****************************************************************************
- * NOT clause functions
- *****************************************************************************/
-
-/*
- * not_clause
- *
- * Returns t iff this is a 'not' clause: (NOT expr).
- */
-bool
-not_clause(Node *clause)
-{
- return (clause != NULL &&
- IsA(clause, BoolExpr) &&
- ((BoolExpr *) clause)->boolop == NOT_EXPR);
-}
-
-/*
- * make_notclause
- *
- * Create a 'not' clause given the expression to be negated.
- */
-Expr *
-make_notclause(Expr *notclause)
-{
- BoolExpr *expr = makeNode(BoolExpr);
-
- expr->boolop = NOT_EXPR;
- expr->args = list_make1(notclause);
- expr->location = -1;
- return (Expr *) expr;
-}
-
-/*
- * get_notclausearg
- *
- * Retrieve the clause within a 'not' clause
- */
-Expr *
-get_notclausearg(Expr *notclause)
-{
- return linitial(((BoolExpr *) notclause)->args);
-}
-
-/*****************************************************************************
- * OR clause functions
- *****************************************************************************/
-
-/*
- * or_clause
- *
- * Returns t iff the clause is an 'or' clause: (OR { expr }).
- */
-bool
-or_clause(Node *clause)
-{
- return (clause != NULL &&
- IsA(clause, BoolExpr) &&
- ((BoolExpr *) clause)->boolop == OR_EXPR);
-}
-
-/*
- * make_orclause
- *
- * Creates an 'or' clause given a list of its subclauses.
- */
-Expr *
-make_orclause(List *orclauses)
-{
- BoolExpr *expr = makeNode(BoolExpr);
-
- expr->boolop = OR_EXPR;
- expr->args = orclauses;
- expr->location = -1;
- return (Expr *) expr;
-}
-
-/*****************************************************************************
- * AND clause functions
- *****************************************************************************/
-
-
-/*
- * and_clause
- *
- * Returns t iff its argument is an 'and' clause: (AND { expr }).
- */
-bool
-and_clause(Node *clause)
-{
- return (clause != NULL &&
- IsA(clause, BoolExpr) &&
- ((BoolExpr *) clause)->boolop == AND_EXPR);
-}
-
-/*
- * make_andclause
- *
- * Creates an 'and' clause given a list of its subclauses.
- */
-Expr *
-make_andclause(List *andclauses)
-{
- BoolExpr *expr = makeNode(BoolExpr);
-
- expr->boolop = AND_EXPR;
- expr->args = andclauses;
- expr->location = -1;
- return (Expr *) expr;
-}
-
-/*
- * make_and_qual
- *
- * Variant of make_andclause for ANDing two qual conditions together.
- * Qual conditions have the property that a NULL nodetree is interpreted
- * as 'true'.
- *
- * NB: this makes no attempt to preserve AND/OR flatness; so it should not
- * be used on a qual that has already been run through prepqual.c.
- */
-Node *
-make_and_qual(Node *qual1, Node *qual2)
-{
- if (qual1 == NULL)
- return qual2;
- if (qual2 == NULL)
- return qual1;
- return (Node *) make_andclause(list_make2(qual1, qual2));
-}
-
-/*
- * The planner frequently prefers to represent qualification expressions
- * as lists of boolean expressions with implicit AND semantics.
- *
- * These functions convert between an AND-semantics expression list and the
- * ordinary representation of a boolean expression.
- *
- * Note that an empty list is considered equivalent to TRUE.
- */
-Expr *
-make_ands_explicit(List *andclauses)
-{
- if (andclauses == NIL)
- return (Expr *) makeBoolConst(true, false);
- else if (list_length(andclauses) == 1)
- return (Expr *) linitial(andclauses);
- else
- return make_andclause(andclauses);
-}
-
-List *
-make_ands_implicit(Expr *clause)
-{
- /*
- * NB: because the parser sets the qual field to NULL in a query that has
- * no WHERE clause, we must consider a NULL input clause as TRUE, even
- * though one might more reasonably think it FALSE. Grumble. If this
- * causes trouble, consider changing the parser's behavior.
- */
- if (clause == NULL)
- return NIL; /* NULL -> NIL list == TRUE */
- else if (and_clause((Node *) clause))
- return ((BoolExpr *) clause)->args;
- else if (IsA(clause, Const) &&
- !((Const *) clause)->constisnull &&
- DatumGetBool(((Const *) clause)->constvalue))
- return NIL; /* constant TRUE input -> NIL list */
- else
- return list_make1(clause);
-}
-
-
-/*****************************************************************************
* Aggregate-function clause manipulation
*****************************************************************************/
@@ -3979,7 +3741,7 @@ simplify_or_arguments(List *args,
unprocessed_args = list_delete_first(unprocessed_args);
/* flatten nested ORs as per above comment */
- if (or_clause(arg))
+ if (is_orclause(arg))
{
List *subargs = list_copy(((BoolExpr *) arg)->args);
@@ -4005,7 +3767,7 @@ simplify_or_arguments(List *args,
* since it's not a mainstream case. In particular we don't worry
* about const-simplifying the input twice.
*/
- if (or_clause(arg))
+ if (is_orclause(arg))
{
List *subargs = list_copy(((BoolExpr *) arg)->args);
@@ -4081,7 +3843,7 @@ simplify_and_arguments(List *args,
unprocessed_args = list_delete_first(unprocessed_args);
/* flatten nested ANDs as per above comment */
- if (and_clause(arg))
+ if (is_andclause(arg))
{
List *subargs = list_copy(((BoolExpr *) arg)->args);
@@ -4107,7 +3869,7 @@ simplify_and_arguments(List *args,
* since it's not a mainstream case. In particular we don't worry
* about const-simplifying the input twice.
*/
- if (and_clause(arg))
+ if (is_andclause(arg))
{
List *subargs = list_copy(((BoolExpr *) arg)->args);
diff --git a/src/backend/optimizer/util/orclauses.c b/src/backend/optimizer/util/orclauses.c
index 9420f1347ae..c62ba88d1b2 100644
--- a/src/backend/optimizer/util/orclauses.c
+++ b/src/backend/optimizer/util/orclauses.c
@@ -15,6 +15,8 @@
#include "postgres.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/orclauses.h"
@@ -173,7 +175,7 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
* selectivity and other cached data is computed exactly the same way for
* a restriction clause as for a join clause, which seems undesirable.
*/
- Assert(or_clause((Node *) or_rinfo->orclause));
+ Assert(is_orclause(or_rinfo->orclause));
foreach(lc, ((BoolExpr *) or_rinfo->orclause)->args)
{
Node *orarg = (Node *) lfirst(lc);
@@ -181,7 +183,7 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
Node *subclause;
/* OR arguments should be ANDs or sub-RestrictInfos */
- if (and_clause(orarg))
+ if (is_andclause(orarg))
{
List *andargs = ((BoolExpr *) orarg)->args;
ListCell *lc2;
@@ -231,7 +233,7 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
* to preserve AND/OR flatness (ie, no OR directly underneath OR).
*/
subclause = (Node *) make_ands_explicit(subclauses);
- if (or_clause(subclause))
+ if (is_orclause(subclause))
clauselist = list_concat(clauselist,
list_copy(((BoolExpr *) subclause)->args));
else
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 3d5ef6922ca..ecbb0db18c3 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -19,6 +19,7 @@
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/predtest.h"
@@ -839,14 +840,14 @@ predicate_classify(Node *clause, PredIterInfo info)
}
/* Handle normal AND and OR boolean clauses */
- if (and_clause(clause))
+ if (is_andclause(clause))
{
info->startup_fn = boolexpr_startup_fn;
info->next_fn = list_next_fn;
info->cleanup_fn = list_cleanup_fn;
return CLASS_AND;
}
- if (or_clause(clause))
+ if (is_orclause(clause))
{
info->startup_fn = boolexpr_startup_fn;
info->next_fn = list_next_fn;
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index e633881d8a6..c1bda812c70 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -14,6 +14,8 @@
*/
#include "postgres.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/var.h"
@@ -67,7 +69,7 @@ make_restrictinfo(Expr *clause,
* If it's an OR clause, build a modified copy with RestrictInfos inserted
* above each subclause of the top-level AND/OR structure.
*/
- if (or_clause((Node *) clause))
+ if (is_orclause(clause))
return (RestrictInfo *) make_sub_restrictinfos(clause,
is_pushed_down,
outerjoin_delayed,
@@ -78,7 +80,7 @@ make_restrictinfo(Expr *clause,
nullable_relids);
/* Shouldn't be an AND clause, else AND/OR flattening messed up */
- Assert(!and_clause((Node *) clause));
+ Assert(!is_andclause(clause));
return make_restrictinfo_internal(clause,
NULL,
@@ -232,7 +234,7 @@ make_sub_restrictinfos(Expr *clause,
Relids outer_relids,
Relids nullable_relids)
{
- if (or_clause((Node *) clause))
+ if (is_orclause(clause))
{
List *orlist = NIL;
ListCell *temp;
@@ -257,7 +259,7 @@ make_sub_restrictinfos(Expr *clause,
outer_relids,
nullable_relids);
}
- else if (and_clause((Node *) clause))
+ else if (is_andclause(clause))
{
List *andlist = NIL;
ListCell *temp;
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 48175b746b8..5116d7f3490 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -60,7 +60,7 @@ typedef struct
typedef struct
{
- PlannerInfo *root;
+ Query *query; /* outer Query */
int sublevels_up;
bool possible_sublink; /* could aliases include a SubLink? */
bool inserted_sublink; /* have we inserted a SubLink? */
@@ -78,7 +78,7 @@ static bool pull_var_clause_walker(Node *node,
pull_var_clause_context *context);
static Node *flatten_join_alias_vars_mutator(Node *node,
flatten_join_alias_vars_context *context);
-static Relids alias_relid_set(PlannerInfo *root, Relids relids);
+static Relids alias_relid_set(Query *query, Relids relids);
/*
@@ -667,16 +667,16 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
* subqueries).
*/
Node *
-flatten_join_alias_vars(PlannerInfo *root, Node *node)
+flatten_join_alias_vars(Query *query, Node *node)
{
flatten_join_alias_vars_context context;
- context.root = root;
+ context.query = query;
context.sublevels_up = 0;
/* flag whether join aliases could possibly contain SubLinks */
- context.possible_sublink = root->parse->hasSubLinks;
+ context.possible_sublink = query->hasSubLinks;
/* if hasSubLinks is already true, no need to work hard */
- context.inserted_sublink = root->parse->hasSubLinks;
+ context.inserted_sublink = query->hasSubLinks;
return flatten_join_alias_vars_mutator(node, &context);
}
@@ -696,7 +696,7 @@ flatten_join_alias_vars_mutator(Node *node,
/* No change unless Var belongs to a JOIN of the target level */
if (var->varlevelsup != context->sublevels_up)
return node; /* no need to copy, really */
- rte = rt_fetch(var->varno, context->root->parse->rtable);
+ rte = rt_fetch(var->varno, context->query->rtable);
if (rte->rtekind != RTE_JOIN)
return node;
if (var->varattno == InvalidAttrNumber)
@@ -783,7 +783,7 @@ flatten_join_alias_vars_mutator(Node *node,
/* now fix PlaceHolderVar's relid sets */
if (phv->phlevelsup == context->sublevels_up)
{
- phv->phrels = alias_relid_set(context->root,
+ phv->phrels = alias_relid_set(context->query,
phv->phrels);
}
return (Node *) phv;
@@ -823,7 +823,7 @@ flatten_join_alias_vars_mutator(Node *node,
* underlying base relids
*/
static Relids
-alias_relid_set(PlannerInfo *root, Relids relids)
+alias_relid_set(Query *query, Relids relids)
{
Relids result = NULL;
int rtindex;
@@ -831,10 +831,10 @@ alias_relid_set(PlannerInfo *root, Relids relids)
rtindex = -1;
while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
{
- RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
+ RangeTblEntry *rte = rt_fetch(rtindex, query->rtable);
if (rte->rtekind == RTE_JOIN)
- result = bms_join(result, get_relids_for_join(root, rtindex));
+ result = bms_join(result, get_relids_for_join(query, rtindex));
else
result = bms_add_member(result, rtindex);
}
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 8ed38168667..5b73378a19c 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -43,7 +43,7 @@ typedef struct
{
ParseState *pstate;
Query *qry;
- PlannerInfo *root;
+ bool hasJoinRTEs;
List *groupClauses;
List *groupClauseCommonVars;
bool have_non_var_grouping;
@@ -65,7 +65,7 @@ static void check_ungrouped_columns(Node *node, ParseState *pstate, Query *qry,
static bool check_ungrouped_columns_walker(Node *node,
check_ungrouped_columns_context *context);
static void finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
- List *groupClauses, PlannerInfo *root,
+ List *groupClauses, bool hasJoinRTEs,
bool have_non_var_grouping);
static bool finalize_grouping_exprs_walker(Node *node,
check_ungrouped_columns_context *context);
@@ -1039,7 +1039,6 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
ListCell *l;
bool hasJoinRTEs;
bool hasSelfRefRTEs;
- PlannerInfo *root = NULL;
Node *clause;
/* This should only be called if we found aggregates or grouping */
@@ -1130,20 +1129,11 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
* If there are join alias vars involved, we have to flatten them to the
* underlying vars, so that aliased and unaliased vars will be correctly
* taken as equal. We can skip the expense of doing this if no rangetable
- * entries are RTE_JOIN kind. We use the planner's flatten_join_alias_vars
- * routine to do the flattening; it wants a PlannerInfo root node, which
- * fortunately can be mostly dummy.
+ * entries are RTE_JOIN kind.
*/
if (hasJoinRTEs)
- {
- root = makeNode(PlannerInfo);
- root->parse = qry;
- root->planner_cxt = CurrentMemoryContext;
- root->hasJoinRTEs = true;
-
- groupClauses = (List *) flatten_join_alias_vars(root,
+ groupClauses = (List *) flatten_join_alias_vars(qry,
(Node *) groupClauses);
- }
/*
* Detect whether any of the grouping expressions aren't simple Vars; if
@@ -1183,10 +1173,10 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
*/
clause = (Node *) qry->targetList;
finalize_grouping_exprs(clause, pstate, qry,
- groupClauses, root,
+ groupClauses, hasJoinRTEs,
have_non_var_grouping);
if (hasJoinRTEs)
- clause = flatten_join_alias_vars(root, clause);
+ clause = flatten_join_alias_vars(qry, clause);
check_ungrouped_columns(clause, pstate, qry,
groupClauses, groupClauseCommonVars,
have_non_var_grouping,
@@ -1194,10 +1184,10 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
clause = (Node *) qry->havingQual;
finalize_grouping_exprs(clause, pstate, qry,
- groupClauses, root,
+ groupClauses, hasJoinRTEs,
have_non_var_grouping);
if (hasJoinRTEs)
- clause = flatten_join_alias_vars(root, clause);
+ clause = flatten_join_alias_vars(qry, clause);
check_ungrouped_columns(clause, pstate, qry,
groupClauses, groupClauseCommonVars,
have_non_var_grouping,
@@ -1245,7 +1235,7 @@ check_ungrouped_columns(Node *node, ParseState *pstate, Query *qry,
context.pstate = pstate;
context.qry = qry;
- context.root = NULL;
+ context.hasJoinRTEs = false; /* assume caller flattened join Vars */
context.groupClauses = groupClauses;
context.groupClauseCommonVars = groupClauseCommonVars;
context.have_non_var_grouping = have_non_var_grouping;
@@ -1445,14 +1435,14 @@ check_ungrouped_columns_walker(Node *node,
*/
static void
finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
- List *groupClauses, PlannerInfo *root,
+ List *groupClauses, bool hasJoinRTEs,
bool have_non_var_grouping)
{
check_ungrouped_columns_context context;
context.pstate = pstate;
context.qry = qry;
- context.root = root;
+ context.hasJoinRTEs = hasJoinRTEs;
context.groupClauses = groupClauses;
context.groupClauseCommonVars = NIL;
context.have_non_var_grouping = have_non_var_grouping;
@@ -1525,8 +1515,8 @@ finalize_grouping_exprs_walker(Node *node,
Node *expr = lfirst(lc);
Index ref = 0;
- if (context->root)
- expr = flatten_join_alias_vars(context->root, expr);
+ if (context->hasJoinRTEs)
+ expr = flatten_join_alias_vars(context->qry, expr);
/*
* Each expression must match a grouping entry at the current
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 901433c68c7..f5155fe062e 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -775,7 +775,7 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
* independently, collect their step IDs to be stored in the
* combine step we'll be creating.
*/
- if (or_clause((Node *) clause))
+ if (is_orclause(clause))
{
List *arg_stepids = NIL;
bool all_args_contradictory = true;
@@ -865,7 +865,7 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
}
continue;
}
- else if (and_clause((Node *) clause))
+ else if (is_andclause(clause))
{
List *args = ((BoolExpr *) clause)->args;
List *argsteps,
@@ -3262,7 +3262,7 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
}
else
{
- bool is_not_clause = not_clause((Node *) clause);
+ bool is_not_clause = is_notclause(clause);
leftop = is_not_clause ? get_notclausearg(clause) : clause;
diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c
index 1d7e028874b..a8e9f722140 100644
--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -18,6 +18,7 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_statistic_ext.h"
#include "lib/stringinfo.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/var.h"
@@ -802,7 +803,7 @@ dependency_is_compatible_clause(Node *clause, Index relid, AttrNumber *attnum)
/* OK to proceed with checking "var" */
}
- else if (not_clause((Node *) rinfo->clause))
+ else if (is_notclause(rinfo->clause))
{
/*
* "NOT x" can be interpreted as "x = false", so get the argument and
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index bcf4f104cf6..12bba1b63a0 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -69,6 +69,7 @@
#include "commands/policy.h"
#include "commands/trigger.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/prep.h"