aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r--src/backend/optimizer/util/clauses.c521
1 files changed, 290 insertions, 231 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index d429db93a03..7ddbe4190cc 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.64 2000/04/04 01:21:46 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.65 2000/04/12 17:15:24 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -46,9 +46,9 @@ static bool pull_agg_clause_walker(Node *node, List **listptr);
static bool contain_subplans_walker(Node *node, void *context);
static bool pull_subplans_walker(Node *node, List **listptr);
static bool check_subplans_for_ungrouped_vars_walker(Node *node,
- Query *context);
-static int is_single_func(Node *node);
-static Node *eval_const_expressions_mutator (Node *node, void *context);
+ Query *context);
+static int is_single_func(Node *node);
+static Node *eval_const_expressions_mutator(Node *node, void *context);
static Expr *simplify_op_or_func(Expr *expr, List *args);
@@ -340,18 +340,19 @@ make_ands_explicit(List *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.
+ * 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 clause->args;
else if (IsA(clause, Const) &&
- ! ((Const *) clause)->constisnull &&
+ !((Const *) clause)->constisnull &&
DatumGetInt32(((Const *) clause)->constvalue))
return NIL; /* constant TRUE input -> NIL list */
else
@@ -381,7 +382,8 @@ contain_agg_clause_walker(Node *node, void *context)
if (node == NULL)
return false;
if (IsA(node, Aggref))
- return true; /* abort the tree traversal and return true */
+ return true; /* abort the tree traversal and return
+ * true */
return expression_tree_walker(node, contain_agg_clause_walker, context);
}
@@ -411,12 +413,14 @@ pull_agg_clause_walker(Node *node, List **listptr)
if (IsA(node, Aggref))
{
*listptr = lappend(*listptr, node);
+
/*
* Complain if the aggregate's argument contains any aggregates;
* nested agg functions are semantically nonsensical.
*/
if (contain_agg_clause(((Aggref *) node)->target))
elog(ERROR, "Aggregate function calls may not be nested");
+
/*
* Having checked that, we need not recurse into the argument.
*/
@@ -454,7 +458,8 @@ contain_subplans_walker(Node *node, void *context)
if (node == NULL)
return false;
if (is_subplan(node) || IsA(node, SubLink))
- return true; /* abort the tree traversal and return true */
+ return true; /* abort the tree traversal and return
+ * true */
return expression_tree_walker(node, contain_subplans_walker, context);
}
@@ -462,7 +467,7 @@ contain_subplans_walker(Node *node, void *context)
* pull_subplans
* Recursively pulls all subplans from an expression tree.
*
- * Returns list of subplan nodes found. Note the nodes themselves are not
+ * Returns list of subplan nodes found. Note the nodes themselves are not
* copied, only referenced.
*/
List *
@@ -507,7 +512,11 @@ void
check_subplans_for_ungrouped_vars(Node *clause,
Query *query)
{
- /* No special setup needed; context for walker is just the Query pointer */
+
+ /*
+ * No special setup needed; context for walker is just the Query
+ * pointer
+ */
check_subplans_for_ungrouped_vars_walker(clause, query);
}
@@ -517,17 +526,19 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
{
if (node == NULL)
return false;
+
/*
- * We can ignore Vars other than in subplan args lists,
- * since the parser already checked 'em.
+ * We can ignore Vars other than in subplan args lists, since the
+ * parser already checked 'em.
*/
if (is_subplan(node))
{
+
/*
* The args list of the subplan node represents attributes from
* outside passed into the sublink.
*/
- List *t;
+ List *t;
foreach(t, ((Expr *) node)->args)
{
@@ -539,10 +550,10 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
/*
* We do not care about args that are not local variables;
* params or outer-level vars are not our responsibility to
- * check. (The outer-level query passing them to us needs
- * to worry, instead.)
+ * check. (The outer-level query passing them to us needs to
+ * worry, instead.)
*/
- if (! IsA(thisarg, Var))
+ if (!IsA(thisarg, Var))
continue;
var = (Var *) thisarg;
if (var->varlevelsup > 0)
@@ -554,8 +565,8 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
contained_in_group_clause = false;
foreach(gl, context->groupClause)
{
- GroupClause *gcl = lfirst(gl);
- Node *groupexpr;
+ GroupClause *gcl = lfirst(gl);
+ Node *groupexpr;
groupexpr = get_sortgroupclause_expr(gcl,
context->targetList);
@@ -569,14 +580,14 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
if (!contained_in_group_clause)
{
/* Found an ungrouped argument. Complain. */
- RangeTblEntry *rte;
- char *attname;
+ RangeTblEntry *rte;
+ char *attname;
Assert(var->varno > 0 &&
var->varno <= length(context->rtable));
rte = rt_fetch(var->varno, context->rtable);
attname = get_attname(rte->relid, var->varattno);
- if (! attname)
+ if (!attname)
elog(ERROR, "cache lookup of attribute %d in relation %u failed",
var->varattno, rte->relid);
elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query",
@@ -585,7 +596,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
}
}
return expression_tree_walker(node,
- check_subplans_for_ungrouped_vars_walker,
+ check_subplans_for_ungrouped_vars_walker,
(void *) context);
}
@@ -697,7 +708,7 @@ NumRelids(Node *clause)
* is referenced in the clause). The routine checks that the
* expression is of the form (var op something) or (something op var)
* where the var is an attribute of the specified relation, or
- * a function of a var of the specified relation. If so, it
+ * a function of a var of the specified relation. If so, it
* returns the following info:
* the found relation number (same as targetrelid unless that is 0)
* the found var number (or InvalidAttrNumber if a function)
@@ -707,7 +718,7 @@ NumRelids(Node *clause)
* specifically 0 for the relid and attno, 0 for the constant value.
*
* Note that negative attno values are *not* invalid, but represent
- * system attributes such as OID. It's sufficient to check for relid=0
+ * system attributes such as OID. It's sufficient to check for relid=0
* to determine whether the routine succeeded.
*/
void
@@ -785,15 +796,13 @@ default_results:
*flag |= SEL_CONSTANT;
}
else
- {
*constval = 0;
- }
}
/*
* is_single_func
- * If the given expression is a function of a single relation,
- * return the relation number; else return 0
+ * If the given expression is a function of a single relation,
+ * return the relation number; else return 0
*/
static int
is_single_func(Node *node)
@@ -804,7 +813,7 @@ is_single_func(Node *node)
if (length(varnos) == 1)
{
- int funcvarno = lfirsti(varnos);
+ int funcvarno = lfirsti(varnos);
freeList(varnos);
return funcvarno;
@@ -922,7 +931,7 @@ CommuteClause(Expr *clause)
* expression tree, for example "2 + 2" => "4". More interestingly,
* we can reduce certain boolean expressions even when they contain
* non-constant subexpressions: "x OR true" => "true" no matter what
- * the subexpression x is. (XXX We assume that no such subexpression
+ * the subexpression x is. (XXX We assume that no such subexpression
* will have important side-effects, which is not necessarily a good
* assumption in the presence of user-defined functions; do we need a
* pg_proc flag that prevents discarding the execution of a function?)
@@ -954,7 +963,7 @@ eval_const_expressions(Node *node)
}
static Node *
-eval_const_expressions_mutator (Node *node, void *context)
+eval_const_expressions_mutator(Node *node, void *context)
{
if (node == NULL)
return NULL;
@@ -963,21 +972,22 @@ eval_const_expressions_mutator (Node *node, void *context)
Expr *expr = (Expr *) node;
List *args;
Const *const_input;
- Expr *newexpr;
+ Expr *newexpr;
/*
* Reduce constants in the Expr's arguments. We know args is
- * either NIL or a List node, so we can call expression_tree_mutator
- * directly rather than recursing to self.
+ * either NIL or a List node, so we can call
+ * expression_tree_mutator directly rather than recursing to self.
*/
args = (List *) expression_tree_mutator((Node *) expr->args,
- eval_const_expressions_mutator,
+ eval_const_expressions_mutator,
(void *) context);
switch (expr->opType)
{
case OP_EXPR:
case FUNC_EXPR:
+
/*
* Code for op/func case is pretty bulky, so split it out
* as a separate function.
@@ -985,123 +995,131 @@ eval_const_expressions_mutator (Node *node, void *context)
newexpr = simplify_op_or_func(expr, args);
if (newexpr) /* successfully simplified it */
return (Node *) newexpr;
- /* else fall out to build new Expr node with simplified args */
- break;
- case OR_EXPR:
- {
+
/*
- * OR arguments are handled as follows:
- * non constant: keep
- * FALSE: drop (does not affect result)
- * TRUE: force result to TRUE
- * NULL: keep only one
- * We keep one NULL input because ExecEvalOr returns
- * NULL when no input is TRUE and at least one is NULL.
+ * else fall out to build new Expr node with simplified
+ * args
*/
- List *newargs = NIL;
- List *arg;
- bool haveNull = false;
- bool forceTrue = false;
-
- foreach(arg, args)
+ break;
+ case OR_EXPR:
{
- if (! IsA(lfirst(arg), Const))
+
+ /*
+ * OR arguments are handled as follows: non constant:
+ * keep FALSE: drop (does not affect result) TRUE:
+ * force result to TRUE NULL: keep only one We keep
+ * one NULL input because ExecEvalOr returns NULL when
+ * no input is TRUE and at least one is NULL.
+ */
+ List *newargs = NIL;
+ List *arg;
+ bool haveNull = false;
+ bool forceTrue = false;
+
+ foreach(arg, args)
{
- newargs = lappend(newargs, lfirst(arg));
- continue;
+ if (!IsA(lfirst(arg), Const))
+ {
+ newargs = lappend(newargs, lfirst(arg));
+ continue;
+ }
+ const_input = (Const *) lfirst(arg);
+ if (const_input->constisnull)
+ haveNull = true;
+ else if (DatumGetInt32(const_input->constvalue))
+ forceTrue = true;
+ /* otherwise, we can drop the constant-false input */
}
- const_input = (Const *) lfirst(arg);
- if (const_input->constisnull)
- haveNull = true;
- else if (DatumGetInt32(const_input->constvalue))
- forceTrue = true;
- /* otherwise, we can drop the constant-false input */
+
+ /*
+ * We could return TRUE before falling out of the
+ * loop, but this coding method will be easier to
+ * adapt if we ever add a notion of non-removable
+ * functions. We'd need to check all the inputs for
+ * non-removability.
+ */
+ if (forceTrue)
+ return MAKEBOOLCONST(true, false);
+ if (haveNull)
+ newargs = lappend(newargs, MAKEBOOLCONST(false, true));
+ /* If all the inputs are FALSE, result is FALSE */
+ if (newargs == NIL)
+ return MAKEBOOLCONST(false, false);
+ /* If only one nonconst-or-NULL input, it's the result */
+ if (lnext(newargs) == NIL)
+ return (Node *) lfirst(newargs);
+ /* Else we still need an OR node */
+ return (Node *) make_orclause(newargs);
}
- /*
- * We could return TRUE before falling out of the loop,
- * but this coding method will be easier to adapt if
- * we ever add a notion of non-removable functions.
- * We'd need to check all the inputs for non-removability.
- */
- if (forceTrue)
- return MAKEBOOLCONST(true, false);
- if (haveNull)
- newargs = lappend(newargs, MAKEBOOLCONST(false, true));
- /* If all the inputs are FALSE, result is FALSE */
- if (newargs == NIL)
- return MAKEBOOLCONST(false, false);
- /* If only one nonconst-or-NULL input, it's the result */
- if (lnext(newargs) == NIL)
- return (Node *) lfirst(newargs);
- /* Else we still need an OR node */
- return (Node *) make_orclause(newargs);
- }
case AND_EXPR:
- {
- /*
- * AND arguments are handled as follows:
- * non constant: keep
- * TRUE: drop (does not affect result)
- * FALSE: force result to FALSE
- * NULL: keep only one
- * We keep one NULL input because ExecEvalAnd returns
- * NULL when no input is FALSE and at least one is NULL.
- */
- List *newargs = NIL;
- List *arg;
- bool haveNull = false;
- bool forceFalse = false;
-
- foreach(arg, args)
{
- if (! IsA(lfirst(arg), Const))
+
+ /*
+ * AND arguments are handled as follows: non constant:
+ * keep TRUE: drop (does not affect result) FALSE:
+ * force result to FALSE NULL: keep only one We keep
+ * one NULL input because ExecEvalAnd returns NULL
+ * when no input is FALSE and at least one is NULL.
+ */
+ List *newargs = NIL;
+ List *arg;
+ bool haveNull = false;
+ bool forceFalse = false;
+
+ foreach(arg, args)
{
- newargs = lappend(newargs, lfirst(arg));
- continue;
+ if (!IsA(lfirst(arg), Const))
+ {
+ newargs = lappend(newargs, lfirst(arg));
+ continue;
+ }
+ const_input = (Const *) lfirst(arg);
+ if (const_input->constisnull)
+ haveNull = true;
+ else if (!DatumGetInt32(const_input->constvalue))
+ forceFalse = true;
+ /* otherwise, we can drop the constant-true input */
}
- const_input = (Const *) lfirst(arg);
- if (const_input->constisnull)
- haveNull = true;
- else if (! DatumGetInt32(const_input->constvalue))
- forceFalse = true;
- /* otherwise, we can drop the constant-true input */
+
+ /*
+ * We could return FALSE before falling out of the
+ * loop, but this coding method will be easier to
+ * adapt if we ever add a notion of non-removable
+ * functions. We'd need to check all the inputs for
+ * non-removability.
+ */
+ if (forceFalse)
+ return MAKEBOOLCONST(false, false);
+ if (haveNull)
+ newargs = lappend(newargs, MAKEBOOLCONST(false, true));
+ /* If all the inputs are TRUE, result is TRUE */
+ if (newargs == NIL)
+ return MAKEBOOLCONST(true, false);
+ /* If only one nonconst-or-NULL input, it's the result */
+ if (lnext(newargs) == NIL)
+ return (Node *) lfirst(newargs);
+ /* Else we still need an AND node */
+ return (Node *) make_andclause(newargs);
}
- /*
- * We could return FALSE before falling out of the loop,
- * but this coding method will be easier to adapt if
- * we ever add a notion of non-removable functions.
- * We'd need to check all the inputs for non-removability.
- */
- if (forceFalse)
- return MAKEBOOLCONST(false, false);
- if (haveNull)
- newargs = lappend(newargs, MAKEBOOLCONST(false, true));
- /* If all the inputs are TRUE, result is TRUE */
- if (newargs == NIL)
- return MAKEBOOLCONST(true, false);
- /* If only one nonconst-or-NULL input, it's the result */
- if (lnext(newargs) == NIL)
- return (Node *) lfirst(newargs);
- /* Else we still need an AND node */
- return (Node *) make_andclause(newargs);
- }
case NOT_EXPR:
Assert(length(args) == 1);
- if (! IsA(lfirst(args), Const))
+ if (!IsA(lfirst(args), Const))
break;
const_input = (Const *) lfirst(args);
/* NOT NULL => NULL */
if (const_input->constisnull)
return MAKEBOOLCONST(false, true);
/* otherwise pretty easy */
- return MAKEBOOLCONST(! DatumGetInt32(const_input->constvalue),
+ return MAKEBOOLCONST(!DatumGetInt32(const_input->constvalue),
false);
case SUBPLAN_EXPR:
+
/*
* Safety measure per notes at head of this routine:
- * return a SubPlan unchanged. Too late to do anything
+ * return a SubPlan unchanged. Too late to do anything
* with it. The arglist simplification above was wasted
- * work (the list probably only contains Var nodes anyway).
+ * work (the list probably only contains Var nodes
+ * anyway).
*/
return (Node *) expr;
default:
@@ -1112,25 +1130,26 @@ eval_const_expressions_mutator (Node *node, void *context)
/*
* If we break out of the above switch on opType, then the
- * expression cannot be simplified any further, so build
- * and return a replacement Expr node using the
- * possibly-simplified arguments and the original oper node.
- * Can't use make_clause() here because we want to be sure
- * the typeOid field is preserved...
+ * expression cannot be simplified any further, so build and
+ * return a replacement Expr node using the possibly-simplified
+ * arguments and the original oper node. Can't use make_clause()
+ * here because we want to be sure the typeOid field is
+ * preserved...
*/
newexpr = makeNode(Expr);
- newexpr->typeOid = expr->typeOid;
- newexpr->opType = expr->opType;
- newexpr->oper = expr->oper;
- newexpr->args = args;
- return (Node *) newexpr;
+ newexpr->typeOid = expr->typeOid;
+ newexpr->opType = expr->opType;
+ newexpr->oper = expr->oper;
+ newexpr->args = args;
+ return (Node *) newexpr;
}
if (IsA(node, RelabelType))
{
+
/*
* If we can simplify the input to a constant, then we don't need
- * the RelabelType node anymore: just change the type field of
- * the Const node. Otherwise, copy the RelabelType node.
+ * the RelabelType node anymore: just change the type field of the
+ * Const node. Otherwise, copy the RelabelType node.
*/
RelabelType *relabel = (RelabelType *) node;
Node *arg;
@@ -1138,13 +1157,15 @@ eval_const_expressions_mutator (Node *node, void *context)
arg = eval_const_expressions_mutator(relabel->arg, context);
if (arg && IsA(arg, Const))
{
- Const *con = (Const *) arg;
+ Const *con = (Const *) arg;
con->consttype = relabel->resulttype;
+
/*
* relabel's resulttypmod is discarded, which is OK for now;
* if the type actually needs a runtime length coercion then
- * there should be a function call to do it just above this node.
+ * there should be a function call to do it just above this
+ * node.
*/
return (Node *) con;
}
@@ -1160,15 +1181,15 @@ eval_const_expressions_mutator (Node *node, void *context)
}
if (IsA(node, CaseExpr))
{
+
/*
- * CASE expressions can be simplified if there are constant condition
- * clauses:
- * FALSE (or NULL): drop the alternative
- * TRUE: drop all remaining alternatives
- * If the first non-FALSE alternative is a constant TRUE, we can
- * simplify the entire CASE to that alternative's expression.
- * If there are no non-FALSE alternatives, we simplify the entire
- * CASE to the default result (ELSE result).
+ * CASE expressions can be simplified if there are constant
+ * condition clauses: FALSE (or NULL): drop the alternative TRUE:
+ * drop all remaining alternatives If the first non-FALSE
+ * alternative is a constant TRUE, we can simplify the entire CASE
+ * to that alternative's expression. If there are no non-FALSE
+ * alternatives, we simplify the entire CASE to the default result
+ * (ELSE result).
*/
CaseExpr *caseexpr = (CaseExpr *) node;
CaseExpr *newcase;
@@ -1181,26 +1202,29 @@ eval_const_expressions_mutator (Node *node, void *context)
{
/* Simplify this alternative's condition and result */
CaseWhen *casewhen = (CaseWhen *)
- expression_tree_mutator((Node *) lfirst(arg),
- eval_const_expressions_mutator,
- (void *) context);
+ expression_tree_mutator((Node *) lfirst(arg),
+ eval_const_expressions_mutator,
+ (void *) context);
+
Assert(IsA(casewhen, CaseWhen));
if (casewhen->expr == NULL ||
- ! IsA(casewhen->expr, Const))
+ !IsA(casewhen->expr, Const))
{
newargs = lappend(newargs, casewhen);
continue;
}
const_input = (Const *) casewhen->expr;
if (const_input->constisnull ||
- ! DatumGetInt32(const_input->constvalue))
+ !DatumGetInt32(const_input->constvalue))
continue; /* drop alternative with FALSE condition */
+
/*
- * Found a TRUE condition. If it's the first (un-dropped)
+ * Found a TRUE condition. If it's the first (un-dropped)
* alternative, the CASE reduces to just this alternative.
*/
if (newargs == NIL)
return casewhen->result;
+
/*
* Otherwise, add it to the list, and drop all the rest.
*/
@@ -1211,7 +1235,11 @@ eval_const_expressions_mutator (Node *node, void *context)
/* Simplify the default result */
defresult = eval_const_expressions_mutator(caseexpr->defresult,
context);
- /* If no non-FALSE alternatives, CASE reduces to the default result */
+
+ /*
+ * If no non-FALSE alternatives, CASE reduces to the default
+ * result
+ */
if (newargs == NIL)
return defresult;
/* Otherwise we need a new CASE node */
@@ -1224,21 +1252,21 @@ eval_const_expressions_mutator (Node *node, void *context)
}
if (IsA(node, Iter))
{
+
/*
- * The argument of an Iter is normally a function call.
- * We must not try to eliminate the function, but we
- * can try to simplify its arguments. If, by chance,
- * the arg is NOT a function then we go ahead and try to
- * simplify it (by falling into expression_tree_mutator).
- * Is that the right thing?
+ * The argument of an Iter is normally a function call. We must
+ * not try to eliminate the function, but we can try to simplify
+ * its arguments. If, by chance, the arg is NOT a function then
+ * we go ahead and try to simplify it (by falling into
+ * expression_tree_mutator). Is that the right thing?
*/
Iter *iter = (Iter *) node;
if (is_funcclause(iter->iterexpr))
{
- Expr *func = (Expr *) iter->iterexpr;
- Expr *newfunc;
- Iter *newiter;
+ Expr *func = (Expr *) iter->iterexpr;
+ Expr *newfunc;
+ Iter *newiter;
newfunc = makeNode(Expr);
newfunc->typeOid = func->typeOid;
@@ -1254,12 +1282,13 @@ eval_const_expressions_mutator (Node *node, void *context)
return (Node *) newiter;
}
}
+
/*
* For any node type not handled above, we recurse using
- * expression_tree_mutator, which will copy the node unchanged
- * but try to simplify its arguments (if any) using this routine.
- * For example: we cannot eliminate an ArrayRef node, but we
- * might be able to simplify constant expressions in its subscripts.
+ * expression_tree_mutator, which will copy the node unchanged but try
+ * to simplify its arguments (if any) using this routine. For example:
+ * we cannot eliminate an ArrayRef node, but we might be able to
+ * simplify constant expressions in its subscripts.
*/
return expression_tree_mutator(node, eval_const_expressions_mutator,
(void *) context);
@@ -1289,31 +1318,32 @@ simplify_op_or_func(Expr *expr, List *args)
HeapTuple func_tuple;
Form_pg_proc funcform;
Type resultType;
- Expr *newexpr;
+ Expr *newexpr;
Datum const_val;
bool const_is_null;
bool isDone;
/*
- * For an operator or function, we cannot simplify unless all the inputs
- * are constants. (XXX possible future improvement: if the op/func is
- * strict and at least one input is NULL, we could simplify to NULL.
- * But we do not currently have any way to know if the op/func is strict
- * or not. For now, a NULL input is treated the same as any other
- * constant node.)
+ * For an operator or function, we cannot simplify unless all the
+ * inputs are constants. (XXX possible future improvement: if the
+ * op/func is strict and at least one input is NULL, we could simplify
+ * to NULL. But we do not currently have any way to know if the
+ * op/func is strict or not. For now, a NULL input is treated the
+ * same as any other constant node.)
*/
foreach(arg, args)
{
- if (! IsA(lfirst(arg), Const))
+ if (!IsA(lfirst(arg), Const))
return NULL;
}
+
/*
- * Get the function procedure's OID and look to see
- * whether it is marked proiscachable.
+ * Get the function procedure's OID and look to see whether it is
+ * marked proiscachable.
*/
if (expr->opType == OP_EXPR)
{
- Oper *oper = (Oper *) expr->oper;
+ Oper *oper = (Oper *) expr->oper;
replace_opid(oper); /* OK to scribble on input to this extent */
funcid = oper->opid;
@@ -1321,7 +1351,7 @@ simplify_op_or_func(Expr *expr, List *args)
}
else
{
- Func *func = (Func *) expr->oper;
+ Func *func = (Func *) expr->oper;
funcid = func->funcid;
result_typeid = func->functype;
@@ -1333,21 +1363,23 @@ simplify_op_or_func(Expr *expr, List *args)
if (!HeapTupleIsValid(func_tuple))
elog(ERROR, "Function OID %u does not exist", funcid);
funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
- if (! funcform->proiscachable)
+ if (!funcform->proiscachable)
return NULL;
+
/*
* Also check to make sure it doesn't return a set.
*/
if (funcform->proretset)
return NULL;
+
/*
* OK, looks like we can simplify this operator/function.
*
* We use the executor's routine ExecEvalExpr() to avoid duplication of
* code and ensure we get the same result as the executor would get.
*
- * Build a new Expr node containing the already-simplified arguments.
- * The only other setup needed here is the replace_opid() that we already
+ * Build a new Expr node containing the already-simplified arguments. The
+ * only other setup needed here is the replace_opid() that we already
* did for the OP_EXPR case.
*/
newexpr = makeNode(Expr);
@@ -1355,21 +1387,23 @@ simplify_op_or_func(Expr *expr, List *args)
newexpr->opType = expr->opType;
newexpr->oper = expr->oper;
newexpr->args = args;
+
/*
* It is OK to pass econtext = NULL because none of the ExecEvalExpr()
* code used in this situation will use econtext. That might seem
- * fortuitous, but it's not so unreasonable --- a constant expression does
- * not depend on context, by definition, n'est ce pas?
+ * fortuitous, but it's not so unreasonable --- a constant expression
+ * does not depend on context, by definition, n'est ce pas?
*/
const_val = ExecEvalExpr((Node *) newexpr, NULL,
&const_is_null, &isDone);
Assert(isDone); /* if this isn't set, we blew it... */
pfree(newexpr);
+
/*
* Make the constant result node.
*
- * XXX would it be better to take the result type from the
- * pg_proc tuple, rather than the Oper or Func node?
+ * XXX would it be better to take the result type from the pg_proc tuple,
+ * rather than the Oper or Func node?
*/
resultType = typeidType(result_typeid);
return (Expr *) makeConst(result_typeid, typeLen(resultType),
@@ -1426,8 +1460,8 @@ simplify_op_or_func(Expr *expr, List *args)
*
* The walker routine should return "false" to continue the tree walk, or
* "true" to abort the walk and immediately return "true" to the top-level
- * caller. This can be used to short-circuit the traversal if the walker
- * has found what it came for. "false" is returned to the top-level caller
+ * caller. This can be used to short-circuit the traversal if the walker
+ * has found what it came for. "false" is returned to the top-level caller
* iff no invocation of the walker returned "true".
*
* The node types handled by expression_tree_walker include all those
@@ -1454,16 +1488,16 @@ simplify_op_or_func(Expr *expr, List *args)
*/
bool
-expression_tree_walker(Node *node, bool (*walker) (), void *context)
+ expression_tree_walker(Node *node, bool (*walker) (), void *context)
{
List *temp;
/*
- * The walker has already visited the current node,
- * and so we need only recurse into any sub-nodes it has.
+ * The walker has already visited the current node, and so we need
+ * only recurse into any sub-nodes it has.
*
- * We assume that the walker is not interested in List nodes per se,
- * so when we expect a List we just recurse directly to self without
+ * We assume that the walker is not interested in List nodes per se, so
+ * when we expect a List we just recurse directly to self without
* bothering to call the walker.
*/
if (node == NULL)
@@ -1478,7 +1512,7 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context)
break;
case T_Expr:
{
- Expr *expr = (Expr *) node;
+ Expr *expr = (Expr *) node;
if (expr->opType == SUBPLAN_EXPR)
{
@@ -1500,6 +1534,7 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context)
case T_ArrayRef:
{
ArrayRef *aref = (ArrayRef *) node;
+
/* recurse directly for upper/lower array index lists */
if (expression_tree_walker((Node *) aref->refupperindexpr,
walker, context))
@@ -1519,10 +1554,12 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context)
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
+
/* we assume walker doesn't care about CaseWhens, either */
foreach(temp, caseexpr->args)
{
CaseWhen *when = (CaseWhen *) lfirst(temp);
+
Assert(IsA(when, CaseWhen));
if (walker(when->expr, context))
return true;
@@ -1538,12 +1575,14 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context)
break;
case T_SubLink:
{
- SubLink *sublink = (SubLink *) node;
+ SubLink *sublink = (SubLink *) node;
- /* If the SubLink has already been processed by subselect.c,
- * it will have lefthand=NIL, and we only need to look at
- * the oper list. Otherwise we only need to look at lefthand
- * (the Oper nodes in the oper list are deemed uninteresting).
+ /*
+ * If the SubLink has already been processed by
+ * subselect.c, it will have lefthand=NIL, and we only
+ * need to look at the oper list. Otherwise we only need
+ * to look at lefthand (the Oper nodes in the oper list
+ * are deemed uninteresting).
*/
if (sublink->lefthand)
return walker((Node *) sublink->lefthand, context);
@@ -1628,18 +1667,19 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context)
*/
Node *
-expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
+ expression_tree_mutator(Node *node, Node *(*mutator) (), void *context)
{
+
/*
- * The mutator has already decided not to modify the current node,
- * but we must call the mutator for any sub-nodes.
+ * The mutator has already decided not to modify the current node, but
+ * we must call the mutator for any sub-nodes.
*/
#define FLATCOPY(newnode, node, nodetype) \
( (newnode) = makeNode(nodetype), \
memcpy((newnode), (node), sizeof(nodetype)) )
-#define CHECKFLATCOPY(newnode, node, nodetype) \
+#define CHECKFLATCOPY(newnode, node, nodetype) \
( AssertMacro(IsA((node), nodetype)), \
(newnode) = makeNode(nodetype), \
memcpy((newnode), (node), sizeof(nodetype)) )
@@ -1659,31 +1699,41 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
return (Node *) copyObject(node);
case T_Expr:
{
- Expr *expr = (Expr *) node;
- Expr *newnode;
+ Expr *expr = (Expr *) node;
+ Expr *newnode;
FLATCOPY(newnode, expr, Expr);
if (expr->opType == SUBPLAN_EXPR)
{
- SubLink *oldsublink = ((SubPlan *) expr->oper)->sublink;
- SubPlan *newsubplan;
+ SubLink *oldsublink = ((SubPlan *) expr->oper)->sublink;
+ SubPlan *newsubplan;
/* flat-copy the oper node, which is a SubPlan */
CHECKFLATCOPY(newsubplan, expr->oper, SubPlan);
newnode->oper = (Node *) newsubplan;
/* likewise its SubLink node */
CHECKFLATCOPY(newsubplan->sublink, oldsublink, SubLink);
- /* transform args list (params to be passed to subplan) */
+
+ /*
+ * transform args list (params to be passed to
+ * subplan)
+ */
MUTATE(newnode->args, expr->args, List *);
/* transform sublink's oper list as well */
- MUTATE(newsubplan->sublink->oper, oldsublink->oper, List*);
- /* but not the subplan itself, which is referenced as-is */
+ MUTATE(newsubplan->sublink->oper, oldsublink->oper, List *);
+
+ /*
+ * but not the subplan itself, which is referenced
+ * as-is
+ */
}
else
{
- /* for other Expr node types, just transform args list,
- * linking to original oper node (OK?)
+
+ /*
+ * for other Expr node types, just transform args
+ * list, linking to original oper node (OK?)
*/
MUTATE(newnode->args, expr->args, List *);
}
@@ -1692,8 +1742,8 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
break;
case T_Aggref:
{
- Aggref *aggref = (Aggref *) node;
- Aggref *newnode;
+ Aggref *aggref = (Aggref *) node;
+ Aggref *newnode;
FLATCOPY(newnode, aggref, Aggref);
MUTATE(newnode->target, aggref->target, Node *);
@@ -1702,8 +1752,8 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
break;
case T_Iter:
{
- Iter *iter = (Iter *) node;
- Iter *newnode;
+ Iter *iter = (Iter *) node;
+ Iter *newnode;
FLATCOPY(newnode, iter, Iter);
MUTATE(newnode->iterexpr, iter->iterexpr, Node *);
@@ -1763,12 +1813,14 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
break;
case T_SubLink:
{
- /* A "bare" SubLink (note we will not come here if we found
- * a SUBPLAN_EXPR node above it). Transform the lefthand side,
- * but not the oper list nor the subquery.
+
+ /*
+ * A "bare" SubLink (note we will not come here if we
+ * found a SUBPLAN_EXPR node above it). Transform the
+ * lefthand side, but not the oper list nor the subquery.
*/
- SubLink *sublink = (SubLink *) node;
- SubLink *newnode;
+ SubLink *sublink = (SubLink *) node;
+ SubLink *newnode;
FLATCOPY(newnode, sublink, SubLink);
MUTATE(newnode->lefthand, sublink->lefthand, List *);
@@ -1777,9 +1829,12 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
break;
case T_List:
{
- /* We assume the mutator isn't interested in the list nodes
- * per se, so just invoke it on each list element.
- * NOTE: this would fail badly on a list with integer elements!
+
+ /*
+ * We assume the mutator isn't interested in the list
+ * nodes per se, so just invoke it on each list element.
+ * NOTE: this would fail badly on a list with integer
+ * elements!
*/
List *resultlist = NIL;
List *temp;
@@ -1795,9 +1850,13 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context)
break;
case T_TargetEntry:
{
- /* We mutate the expression, but not the resdom, by default. */
- TargetEntry *targetentry = (TargetEntry *) node;
- TargetEntry *newnode;
+
+ /*
+ * We mutate the expression, but not the resdom, by
+ * default.
+ */
+ TargetEntry *targetentry = (TargetEntry *) node;
+ TargetEntry *newnode;
FLATCOPY(newnode, targetentry, TargetEntry);
MUTATE(newnode->expr, targetentry->expr, Node *);