#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"
#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"
/* 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;
#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"
return n;
}
+/*
+ * 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
*
#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"
#include "postgres.h"
#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
/* 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,
jointype,
sjinfo);
}
- else if (and_clause(clause))
+ else if (is_andclause(clause))
{
/* share code with clauselist_selectivity() */
s1 = clauselist_selectivity(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
#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"
List *indlist;
/* OR arguments should be ANDs or sub-RestrictInfos */
- if (and_clause(orarg))
+ if (is_andclause(orarg))
{
List *andargs = ((BoolExpr *) orarg)->args;
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))
InvalidOid, InvalidOid);
}
/* NOT clause? */
- if (not_clause(clause))
+ if (is_notclause(clause))
{
Node *arg = (Node *) get_notclausearg((Expr *) clause);
#include "postgres.h"
#include "miscadmin.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/appendinfo.h"
#include "optimizer/clauses.h"
#include "optimizer/joininfo.h"
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
List *sublist;
/* OR arguments should be ANDs or sub-RestrictInfos */
- if (and_clause(orarg))
+ if (is_andclause(orarg))
{
List *andargs = ((BoolExpr *) orarg)->args;
#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"
*/
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)
{
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.
if (hash_ok_operator((OpExpr *) testexpr))
return true;
}
- else if (and_clause(testexpr))
+ else if (is_andclause(testexpr))
{
ListCell *l;
* 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;
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);
return (Node *) make_andclause(newargs);
}
- if (or_clause(node))
+ if (is_orclause(node))
{
List *newargs = NIL;
ListCell *l;
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);
/* 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);
/* Else return it unmodified */
return node;
}
- if (and_clause(node))
+ if (is_andclause(node))
{
/* Recurse into AND clause */
List *newclauses = NIL;
* 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
* 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);
#include "postgres.h"
#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/prep.h"
#include "utils/lsyscache.h"
* 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
* 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
static Expr *
find_duplicate_ors(Expr *qual, bool is_check)
{
- if (or_clause((Node *) qual))
+ if (is_orclause(qual))
{
List *orlist = NIL;
ListCell *temp;
/* 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;
{
Expr *clause = (Expr *) lfirst(temp);
- if (and_clause((Node *) clause))
+ if (is_andclause(clause))
{
List *subclauses = ((BoolExpr *) clause)->args;
int nclauses = list_length(subclauses);
{
Expr *clause = (Expr *) lfirst(temp2);
- if (and_clause((Node *) clause))
+ if (is_andclause(clause))
{
if (!list_member(((BoolExpr *) clause)->args, refclause))
{
{
Expr *clause = (Expr *) lfirst(temp);
- if (and_clause((Node *) clause))
+ if (is_andclause(clause))
{
List *subclauses = ((BoolExpr *) clause)->args;
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
*****************************************************************************/
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);
* 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);
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);
* 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);
#include "postgres.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/orclauses.h"
* 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);
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;
* 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
#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"
}
/* 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;
*/
#include "postgres.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/var.h"
* 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,
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,
Relids outer_relids,
Relids nullable_relids)
{
- if (or_clause((Node *) clause))
+ if (is_orclause(clause))
{
List *orlist = NIL;
ListCell *temp;
outer_relids,
nullable_relids);
}
- else if (and_clause((Node *) clause))
+ else if (is_andclause(clause))
{
List *andlist = NIL;
ListCell *temp;
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? */
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);
/*
* 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);
}
/* 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)
/* 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;
* underlying base relids
*/
static Relids
-alias_relid_set(PlannerInfo *root, Relids relids)
+alias_relid_set(Query *query, Relids relids)
{
Relids result = NULL;
int rtindex;
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);
}
{
ParseState *pstate;
Query *qry;
- PlannerInfo *root;
+ bool hasJoinRTEs;
List *groupClauses;
List *groupClauseCommonVars;
bool have_non_var_grouping;
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);
ListCell *l;
bool hasJoinRTEs;
bool hasSelfRefRTEs;
- PlannerInfo *root = NULL;
Node *clause;
/* This should only be called if we found aggregates or grouping */
* 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
*/
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,
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,
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;
*/
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;
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
* 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;
}
continue;
}
- else if (and_clause((Node *) clause))
+ else if (is_andclause(clause))
{
List *args = ((BoolExpr *) clause)->args;
List *argsteps,
}
else
{
- bool is_not_clause = not_clause((Node *) clause);
+ bool is_not_clause = is_notclause(clause);
leftop = is_not_clause ? get_notclausearg(clause) : clause;
#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"
/* 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
#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"
extern FuncCall *makeFuncCall(List *name, List *args, int location);
+extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
+ Expr *leftop, Expr *rightop,
+ Oid opcollid, Oid inputcollid);
+
+extern Expr *make_andclause(List *andclauses);
+extern Expr *make_orclause(List *orclauses);
+extern Expr *make_notclause(Expr *notclause);
+
+extern Node *make_and_qual(Node *qual1, Node *qual2);
+extern Expr *make_ands_explicit(List *andclauses);
+extern List *make_ands_implicit(Expr *clause);
+
extern DefElem *makeDefElem(char *name, Node *arg, int location);
extern DefElem *makeDefElemExtended(char *nameSpace, char *name, Node *arg,
DefElemAction defaction, int location);
extern void set_opfuncid(OpExpr *opexpr);
extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
+/* Is clause a FuncExpr clause? */
+static inline bool
+is_funcclause(const void *clause)
+{
+ return clause != NULL && IsA(clause, FuncExpr);
+}
+
+/* Is clause an OpExpr clause? */
+static inline bool
+is_opclause(const void *clause)
+{
+ return clause != NULL && IsA(clause, OpExpr);
+}
+
+/* Extract left arg of a binary opclause, or only arg of a unary opclause */
+static inline Node *
+get_leftop(const void *clause)
+{
+ const OpExpr *expr = (const OpExpr *) clause;
+
+ if (expr->args != NIL)
+ return (Node *) linitial(expr->args);
+ else
+ return NULL;
+}
+
+/* Extract right arg of a binary opclause (NULL if it's a unary opclause) */
+static inline Node *
+get_rightop(const void *clause)
+{
+ const OpExpr *expr = (const OpExpr *) clause;
+
+ if (list_length(expr->args) >= 2)
+ return (Node *) lsecond(expr->args);
+ else
+ return NULL;
+}
+
+/* Is clause an AND clause? */
+static inline bool
+is_andclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == AND_EXPR);
+}
+
+/* Is clause an OR clause? */
+static inline bool
+is_orclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == OR_EXPR);
+}
+
+/* Is clause a NOT clause? */
+static inline bool
+is_notclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == NOT_EXPR);
+}
+
+/* Extract argument from a clause known to be a NOT clause */
+static inline Expr *
+get_notclausearg(const void *notclause)
+{
+ return (Expr *) linitial(((const BoolExpr *) notclause)->args);
+}
+
extern bool check_functions_in_node(Node *node, check_function_callback checker,
void *context);
#include "access/htup.h"
#include "nodes/relation.h"
-#define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr))
-#define is_funcclause(clause) ((clause) != NULL && IsA(clause, FuncExpr))
-
typedef struct
{
int numWindowFuncs; /* total number of WindowFuncs found */
List **windowFuncs; /* lists of WindowFuncs for each winref */
} WindowFuncLists;
-extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
- Expr *leftop, Expr *rightop,
- Oid opcollid, Oid inputcollid);
-extern Node *get_leftop(const Expr *clause);
-extern Node *get_rightop(const Expr *clause);
-
-extern bool not_clause(Node *clause);
-extern Expr *make_notclause(Expr *notclause);
-extern Expr *get_notclausearg(Expr *notclause);
-
-extern bool or_clause(Node *clause);
-extern Expr *make_orclause(List *orclauses);
-
-extern bool and_clause(Node *clause);
-extern Expr *make_andclause(List *andclauses);
-extern Node *make_and_qual(Node *qual1, Node *qual2);
-extern Expr *make_ands_explicit(List *andclauses);
-extern List *make_ands_implicit(Expr *clause);
-
extern bool contain_agg_clause(Node *clause);
extern void get_agg_clause_costs(PlannerInfo *root, Node *clause,
AggSplit aggsplit, AggClauseCosts *costs);
extern void reduce_outer_joins(PlannerInfo *root);
extern void remove_useless_result_rtes(PlannerInfo *root);
extern Relids get_relids_in_jointree(Node *jtnode, bool include_joins);
-extern Relids get_relids_for_join(PlannerInfo *root, int joinrelid);
+extern Relids get_relids_for_join(Query *query, int joinrelid);
/*
* prototypes for prepqual.c
extern bool contain_vars_of_level(Node *node, int levelsup);
extern int locate_var_of_level(Node *node, int levelsup);
extern List *pull_var_clause(Node *node, int flags);
-extern Node *flatten_join_alias_vars(PlannerInfo *root, Node *node);
+extern Node *flatten_join_alias_vars(Query *query, Node *node);
#endif /* VAR_H */
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "funcapi.h"
+#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/predtest.h"
#include "utils/builtins.h"