aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/clausesel.c23
-rw-r--r--src/backend/optimizer/path/costsize.c91
-rw-r--r--src/backend/optimizer/path/indxpath.c92
-rw-r--r--src/backend/optimizer/path/orindxpath.c4
-rw-r--r--src/backend/optimizer/path/pathkeys.c31
-rw-r--r--src/backend/optimizer/path/tidpath.c53
-rw-r--r--src/backend/optimizer/plan/createplan.c29
-rw-r--r--src/backend/optimizer/plan/initsplan.c29
-rw-r--r--src/backend/optimizer/plan/planner.c10
-rw-r--r--src/backend/optimizer/plan/setrefs.c62
-rw-r--r--src/backend/optimizer/plan/subselect.c44
-rw-r--r--src/backend/optimizer/prep/prepqual.c101
-rw-r--r--src/backend/optimizer/prep/preptlist.c6
-rw-r--r--src/backend/optimizer/prep/prepunion.c16
-rw-r--r--src/backend/optimizer/util/clauses.c1114
-rw-r--r--src/backend/optimizer/util/tlist.c6
-rw-r--r--src/backend/optimizer/util/var.c18
17 files changed, 869 insertions, 860 deletions
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index d0976ca4219..0294c828124 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.53 2002/11/25 21:29:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.54 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -141,7 +141,7 @@ clauselist_selectivity(Query *root,
if (is_opclause(clause) &&
(varRelid != 0 || NumRelids(clause) == 1))
{
- Expr *expr = (Expr *) clause;
+ OpExpr *expr = (OpExpr *) clause;
if (length(expr->args) == 2)
{
@@ -151,7 +151,7 @@ clauselist_selectivity(Query *root,
(varonleft = false,
is_pseudo_constant_clause(lfirst(expr->args))))
{
- Oid opno = ((Oper *) expr->oper)->opno;
+ Oid opno = expr->opno;
RegProcedure oprrest = get_oprrest(opno);
s2 = restriction_selectivity(root, opno,
@@ -430,7 +430,7 @@ clause_selectivity(Query *root,
{
/* share code with clauselist_selectivity() */
s1 = clauselist_selectivity(root,
- ((Expr *) clause)->args,
+ ((BoolExpr *) clause)->args,
varRelid);
}
else if (or_clause(clause))
@@ -443,7 +443,7 @@ clause_selectivity(Query *root,
List *arg;
s1 = 0.0;
- foreach(arg, ((Expr *) clause)->args)
+ foreach(arg, ((BoolExpr *) clause)->args)
{
Selectivity s2 = clause_selectivity(root,
(Node *) lfirst(arg),
@@ -454,7 +454,7 @@ clause_selectivity(Query *root,
}
else if (is_opclause(clause))
{
- Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
+ Oid opno = ((OpExpr *) clause)->opno;
bool is_join_clause;
if (varRelid != 0)
@@ -479,13 +479,14 @@ clause_selectivity(Query *root,
{
/* Estimate selectivity for a join clause. */
s1 = join_selectivity(root, opno,
- ((Expr *) clause)->args);
+ ((OpExpr *) clause)->args);
}
else
{
/* Estimate selectivity for a restriction clause. */
s1 = restriction_selectivity(root, opno,
- ((Expr *) clause)->args, varRelid);
+ ((OpExpr *) clause)->args,
+ varRelid);
}
}
else if (is_funcclause(clause))
@@ -509,7 +510,7 @@ clause_selectivity(Query *root,
/* Use node specific selectivity calculation function */
s1 = nulltestsel(root,
((NullTest *) clause)->nulltesttype,
- ((NullTest *) clause)->arg,
+ (Node *) ((NullTest *) clause)->arg,
varRelid);
}
else if (IsA(clause, BooleanTest))
@@ -517,14 +518,14 @@ clause_selectivity(Query *root,
/* Use node specific selectivity calculation function */
s1 = booltestsel(root,
((BooleanTest *) clause)->booltesttype,
- ((BooleanTest *) clause)->arg,
+ (Node *) ((BooleanTest *) clause)->arg,
varRelid);
}
else if (IsA(clause, RelabelType))
{
/* Not sure this case is needed, but it can't hurt */
s1 = clause_selectivity(root,
- ((RelabelType *) clause)->arg,
+ (Node *) ((RelabelType *) clause)->arg,
varRelid);
}
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 1db310fc52e..2125ff034f3 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.93 2002/11/30 05:21:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.94 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1220,63 +1220,48 @@ cost_qual_eval_walker(Node *node, Cost *total)
* Should we try to account for the possibility of short-circuit
* evaluation of AND/OR?
*/
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr) ||
+ IsA(node, OpExpr) ||
+ IsA(node, DistinctExpr))
+ *total += cpu_operator_cost;
+ else if (IsA(node, SubPlanExpr))
{
- Expr *expr = (Expr *) node;
+ /*
+ * A subplan node in an expression indicates that the
+ * subplan will be executed on each evaluation, so charge
+ * accordingly. (We assume that sub-selects that can be
+ * executed as InitPlans have already been removed from
+ * the expression.)
+ *
+ * NOTE: this logic should agree with the estimates used by
+ * make_subplan() in plan/subselect.c.
+ */
+ SubPlanExpr *subplan = (SubPlanExpr *) node;
+ Plan *plan = subplan->plan;
+ Cost subcost;
- switch (expr->opType)
+ if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
{
- case OP_EXPR:
- case DISTINCT_EXPR:
- case FUNC_EXPR:
- *total += cpu_operator_cost;
- break;
- case OR_EXPR:
- case AND_EXPR:
- case NOT_EXPR:
- break;
- case SUBPLAN_EXPR:
-
- /*
- * A subplan node in an expression indicates that the
- * subplan will be executed on each evaluation, so charge
- * accordingly. (We assume that sub-selects that can be
- * executed as InitPlans have already been removed from
- * the expression.)
- *
- * NOTE: this logic should agree with the estimates used by
- * make_subplan() in plan/subselect.c.
- */
- {
- SubPlan *subplan = (SubPlan *) expr->oper;
- Plan *plan = subplan->plan;
- Cost subcost;
-
- if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
- {
- /* we only need to fetch 1 tuple */
- subcost = plan->startup_cost +
- (plan->total_cost - plan->startup_cost) / plan->plan_rows;
- }
- else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
- subplan->sublink->subLinkType == ANY_SUBLINK)
- {
- /* assume we need 50% of the tuples */
- subcost = plan->startup_cost +
- 0.50 * (plan->total_cost - plan->startup_cost);
- /* XXX what if subplan has been materialized? */
- }
- else
- {
- /* assume we need all tuples */
- subcost = plan->total_cost;
- }
- *total += subcost;
- }
- break;
+ /* we only need to fetch 1 tuple */
+ subcost = plan->startup_cost +
+ (plan->total_cost - plan->startup_cost) / plan->plan_rows;
}
- /* fall through to examine args of Expr node */
+ else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
+ subplan->sublink->subLinkType == ANY_SUBLINK)
+ {
+ /* assume we need 50% of the tuples */
+ subcost = plan->startup_cost +
+ 0.50 * (plan->total_cost - plan->startup_cost);
+ /* XXX what if subplan has been materialized? */
+ }
+ else
+ {
+ /* assume we need all tuples */
+ subcost = plan->total_cost;
+ }
+ *total += subcost;
}
+
return expression_tree_walker(node, cost_qual_eval_walker,
(void *) total);
}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index c0241bb9ef3..7a20de8c1c1 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.126 2002/11/25 21:29:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.127 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -73,6 +73,8 @@ static bool match_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass, Expr *clause);
static bool match_join_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass, Expr *clause);
+static Oid indexable_operator(Expr *clause, Oid opclass,
+ bool indexkey_on_left);
static bool pred_test(List *predicate_list, List *restrictinfo_list,
List *joininfo_list, int relvarno);
static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list);
@@ -280,7 +282,7 @@ match_index_orclauses(RelOptInfo *rel,
*/
restrictinfo->subclauseindices =
match_index_orclause(rel, index,
- restrictinfo->clause->args,
+ ((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices);
}
}
@@ -377,7 +379,7 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
{
List *item;
- foreach(item, clause->args)
+ foreach(item, ((BoolExpr *) clause)->args)
{
if (match_clause_to_indexkey(rel, index, indexkey, opclass,
lfirst(item)))
@@ -443,7 +445,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
if (and_clause((Node *) orsubclause))
{
- foreach(item, orsubclause->args)
+ foreach(item, ((BoolExpr *) orsubclause)->args)
{
Expr *subsubclause = (Expr *) lfirst(item);
@@ -715,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
*rightop;
/* Clause must be a binary opclause. */
- if (!is_opclause((Node *) clause))
+ if (!is_opclause(clause))
return false;
leftop = get_leftop(clause);
rightop = get_rightop(clause);
@@ -803,7 +805,7 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
*rightop;
/* Clause must be a binary opclause. */
- if (!is_opclause((Node *) clause))
+ if (!is_opclause(clause))
return false;
leftop = get_leftop(clause);
rightop = get_rightop(clause);
@@ -857,10 +859,10 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
* (Formerly, this routine might return a binary-compatible operator
* rather than the original one, but that kluge is history.)
*/
-Oid
+static Oid
indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left)
{
- Oid expr_op = ((Oper *) clause->oper)->opno;
+ Oid expr_op = ((OpExpr *) clause)->opno;
Oid commuted_op;
/* Get the commuted operator if necessary */
@@ -985,7 +987,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause)
Assert(clause != NULL);
if (or_clause(clause))
{
- items = ((Expr *) clause)->args;
+ items = ((BoolExpr *) clause)->args;
foreach(item, items)
{
/* if any OR item doesn't imply the predicate, clause doesn't */
@@ -996,7 +998,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause)
}
else if (and_clause(clause))
{
- items = ((Expr *) clause)->args;
+ items = ((BoolExpr *) clause)->args;
foreach(item, items)
{
/*
@@ -1029,7 +1031,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
Assert(predicate != NULL);
if (or_clause((Node *) predicate))
{
- items = predicate->args;
+ items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/* if any item is implied, the whole predicate is implied */
@@ -1040,7 +1042,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
}
else if (and_clause((Node *) predicate))
{
- items = predicate->args;
+ items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/*
@@ -1121,7 +1123,6 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
StrategyNumber pred_strategy = 0,
clause_strategy,
test_strategy;
- Oper *test_oper;
Expr *test_expr;
Datum test_result;
bool isNull;
@@ -1140,7 +1141,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
* Can't do anything more unless they are both binary opclauses with a
* Var on the left and a Const on the right.
*/
- if (!is_opclause((Node *) predicate))
+ if (!is_opclause(predicate))
return false;
pred_var = (Var *) get_leftop(predicate);
pred_const = (Const *) get_rightop(predicate);
@@ -1167,8 +1168,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
return false;
/* Get the operators for the two clauses we're comparing */
- pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno;
- clause_op = ((Oper *) ((Expr *) clause)->oper)->opno;
+ pred_op = ((OpExpr *) predicate)->opno;
+ clause_op = ((OpExpr *) clause)->opno;
/*
* 1. Find a "btree" strategy number for the pred_op
@@ -1267,14 +1268,12 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
/*
* 5. Evaluate the test
*/
- test_oper = makeOper(test_op, /* opno */
- InvalidOid, /* opid */
- BOOLOID, /* opresulttype */
- false); /* opretset */
- replace_opid(test_oper);
- test_expr = make_opclause(test_oper,
- (Var *) clause_const,
- (Var *) pred_const);
+ test_expr = make_opclause(test_op,
+ BOOLOID,
+ false,
+ (Expr *) clause_const,
+ (Expr *) pred_const);
+ set_opfuncid((OpExpr *) test_expr);
econtext = MakeExprContext(NULL, TransactionCommandContext);
test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext,
@@ -1627,7 +1626,7 @@ static bool
function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
{
int relvarno = lfirsti(rel->relids);
- Func *function;
+ FuncExpr *function;
List *funcargs;
int *indexKeys = index->indexkeys;
List *arg;
@@ -1636,13 +1635,12 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
/*
* sanity check, make sure we know what we're dealing with here.
*/
- if (funcOpnd == NULL || !IsA(funcOpnd, Expr) ||
- funcOpnd->opType != FUNC_EXPR ||
- funcOpnd->oper == NULL || indexKeys == NULL)
+ if (funcOpnd == NULL || !IsA(funcOpnd, FuncExpr) ||
+ indexKeys == NULL)
return false;
- function = (Func *) funcOpnd->oper;
- funcargs = funcOpnd->args;
+ function = (FuncExpr *) funcOpnd;
+ funcargs = function->args;
if (function->funcid != index->indproc)
return false;
@@ -1752,7 +1750,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
/* we know these will succeed */
leftop = get_leftop(clause);
rightop = get_rightop(clause);
- expr_op = ((Oper *) clause->oper)->opno;
+ expr_op = ((OpExpr *) clause)->opno;
/* again, required for all current special ops: */
if (!IsA(rightop, Const) ||
@@ -1916,7 +1914,7 @@ expand_indexqual_conditions(List *indexquals)
/* we know these will succeed */
Var *leftop = get_leftop(clause);
Var *rightop = get_rightop(clause);
- Oid expr_op = ((Oper *) clause->oper)->opno;
+ Oid expr_op = ((OpExpr *) clause)->opno;
Const *patt = (Const *) rightop;
Const *prefix = NULL;
Const *rest = NULL;
@@ -2011,7 +2009,6 @@ prefix_quals(Var *leftop, Oid expr_op,
Oid oproid;
char *prefix;
Const *con;
- Oper *op;
Expr *expr;
Const *greaterstr = NULL;
@@ -2070,8 +2067,8 @@ prefix_quals(Var *leftop, Oid expr_op,
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
con = string_to_const(prefix, datatype);
- op = makeOper(oproid, InvalidOid, BOOLOID, false);
- expr = make_opclause(op, leftop, (Var *) con);
+ expr = make_opclause(oproid, BOOLOID, false,
+ (Expr *) leftop, (Expr *) con);
result = makeList1(expr);
return result;
}
@@ -2085,8 +2082,8 @@ prefix_quals(Var *leftop, Oid expr_op,
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
con = string_to_const(prefix, datatype);
- op = makeOper(oproid, InvalidOid, BOOLOID, false);
- expr = make_opclause(op, leftop, (Var *) con);
+ expr = make_opclause(oproid, BOOLOID, false,
+ (Expr *) leftop, (Expr *) con);
result = makeList1(expr);
/*-------
@@ -2100,8 +2097,8 @@ prefix_quals(Var *leftop, Oid expr_op,
oproid = find_operator("<", datatype);
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
- op = makeOper(oproid, InvalidOid, BOOLOID, false);
- expr = make_opclause(op, leftop, (Var *) greaterstr);
+ expr = make_opclause(oproid, BOOLOID, false,
+ (Expr *) leftop, (Expr *) greaterstr);
result = lappend(result, expr);
}
@@ -2124,7 +2121,6 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
Oid opr2oid;
List *result;
Oid datatype;
- Oper *op;
Expr *expr;
switch (expr_op)
@@ -2164,10 +2160,10 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
opr1right = network_scan_first(rightop);
- op = makeOper(opr1oid, InvalidOid, BOOLOID, false);
- expr = make_opclause(op, leftop,
- (Var *) makeConst(datatype, -1, opr1right,
- false, false));
+ expr = make_opclause(opr1oid, BOOLOID, false,
+ (Expr *) leftop,
+ (Expr *) makeConst(datatype, -1, opr1right,
+ false, false));
result = makeList1(expr);
/* create clause "key <= network_scan_last( rightop )" */
@@ -2179,10 +2175,10 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
opr2right = network_scan_last(rightop);
- op = makeOper(opr2oid, InvalidOid, BOOLOID, false);
- expr = make_opclause(op, leftop,
- (Var *) makeConst(datatype, -1, opr2right,
- false, false));
+ expr = make_opclause(opr2oid, BOOLOID, false,
+ (Expr *) leftop,
+ (Expr *) makeConst(datatype, -1, opr2right,
+ false, false));
result = lappend(result, expr);
return result;
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c
index 009afdff079..101866867b9 100644
--- a/src/backend/optimizer/path/orindxpath.c
+++ b/src/backend/optimizer/path/orindxpath.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.48 2002/11/24 21:52:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.49 2002/12/12 15:49:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -96,7 +96,7 @@ create_or_index_paths(Query *root, RelOptInfo *rel)
best_or_subclause_indices(root,
rel,
- restrictinfo->clause->args,
+ ((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices,
pathnode);
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 350c761165b..af0b61a4034 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.41 2002/09/18 21:35:21 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.42 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -514,14 +514,16 @@ build_index_pathkeys(Query *root,
if (index->indproc)
{
/* Functional index: build a representation of the function call */
- Func *funcnode = makeNode(Func);
+ Expr *funcnode;
List *funcargs = NIL;
- funcnode->funcid = index->indproc;
- funcnode->funcresulttype = get_func_rettype(index->indproc);
- funcnode->funcretset = false; /* can never be a set */
- funcnode->funcformat = COERCE_DONTCARE; /* to match any user expr */
- funcnode->func_fcache = NULL;
+ sortop = *ordering;
+ if (ScanDirectionIsBackward(scandir))
+ {
+ sortop = get_commutator(sortop);
+ if (sortop == InvalidOid)
+ return NIL; /* oops, no reverse sort operator? */
+ }
while (*indexkeys != 0)
{
@@ -530,17 +532,14 @@ build_index_pathkeys(Query *root,
indexkeys++;
}
- sortop = *ordering;
- if (ScanDirectionIsBackward(scandir))
- {
- sortop = get_commutator(sortop);
- if (sortop == InvalidOid)
- return NIL; /* oops, no reverse sort operator? */
- }
+ funcnode = make_funcclause(index->indproc,
+ get_func_rettype(index->indproc),
+ false, /* cannot be a set */
+ COERCE_DONTCARE, /* to match any user expr */
+ funcargs);
/* Make a one-sublist pathkeys list for the function expression */
- item = makePathKeyItem((Node *) make_funcclause(funcnode, funcargs),
- sortop);
+ item = makePathKeyItem((Node *) funcnode, sortop);
retval = makeList1(make_canonical_pathkey(root, item));
}
else
diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c
index 27fe9e281f3..f11ff81ea41 100644
--- a/src/backend/optimizer/path/tidpath.c
+++ b/src/backend/optimizer/path/tidpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.12 2002/11/24 21:52:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.13 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,15 +27,14 @@
static List *TidqualFromRestrictinfo(List *relids, List *restrictinfo);
static bool isEvaluable(int varno, Node *node);
-static Node *TidequalClause(int varno, Expr *node);
+static Node *TidequalClause(int varno, OpExpr *node);
static List *TidqualFromExpr(int varno, Expr *expr);
-static
-bool
+static bool
isEvaluable(int varno, Node *node)
{
List *lst;
- Expr *expr;
+ FuncExpr *expr;
if (IsA(node, Const))
return true;
@@ -51,7 +50,7 @@ isEvaluable(int varno, Node *node)
}
if (!is_funcclause(node))
return false;
- expr = (Expr *) node;
+ expr = (FuncExpr *) node;
foreach(lst, expr->args)
{
if (!isEvaluable(varno, lfirst(lst)))
@@ -66,33 +65,26 @@ isEvaluable(int varno, Node *node)
* Extract the right node if the opclause is CTID= ....
* or the left node if the opclause is ....=CTID
*/
-static
-Node *
-TidequalClause(int varno, Expr *node)
+static Node *
+TidequalClause(int varno, OpExpr *node)
{
- Node *rnode = 0,
+ Node *rnode = NULL,
*arg1,
*arg2,
*arg;
- Oper *oper;
Var *var;
Const *aconst;
Param *param;
- Expr *expr;
+ FuncExpr *expr;
- if (!node->oper)
- return rnode;
- if (!node->args)
+ if (node->opno != TIDEqualOperator)
return rnode;
if (length(node->args) != 2)
return rnode;
- oper = (Oper *) node->oper;
- if (oper->opno != TIDEqualOperator)
- return rnode;
arg1 = lfirst(node->args);
arg2 = lsecond(node->args);
- arg = (Node *) 0;
+ arg = NULL;
if (IsA(arg1, Var))
{
var = (Var *) arg1;
@@ -138,11 +130,9 @@ TidequalClause(int varno, Expr *node)
return rnode;
rnode = arg;
break;
- case T_Expr:
- expr = (Expr *) arg;
- if (expr->typeOid != TIDOID)
- return rnode;
- if (expr->opType != FUNC_EXPR)
+ case T_FuncExpr:
+ expr = (FuncExpr *) arg;
+ if (expr->funcresulttype != TIDOID)
return rnode;
if (isEvaluable(varno, (Node *) expr))
rnode = arg;
@@ -162,8 +152,7 @@ TidequalClause(int varno, Expr *node)
* CTID values if we could extract the CTID values from a member
* node.
*/
-static
-List *
+static List *
TidqualFromExpr(int varno, Expr *expr)
{
List *rlst = NIL,
@@ -174,17 +163,15 @@ TidqualFromExpr(int varno, Expr *expr)
if (is_opclause(node))
{
- rnode = TidequalClause(varno, expr);
+ rnode = TidequalClause(varno, (OpExpr *) expr);
if (rnode)
rlst = lcons(rnode, rlst);
}
else if (and_clause(node))
{
- foreach(lst, expr->args)
+ foreach(lst, ((BoolExpr *) expr)->args)
{
node = lfirst(lst);
- if (!IsA(node, Expr))
- continue;
rlst = TidqualFromExpr(varno, (Expr *) node);
if (rlst)
break;
@@ -192,11 +179,11 @@ TidqualFromExpr(int varno, Expr *expr)
}
else if (or_clause(node))
{
- foreach(lst, expr->args)
+ foreach(lst, ((BoolExpr *) expr)->args)
{
node = lfirst(lst);
- if (IsA(node, Expr) &&
- (frtn = TidqualFromExpr(varno, (Expr *) node)))
+ frtn = TidqualFromExpr(varno, (Expr *) node);
+ if (frtn)
rlst = nconc(rlst, frtn);
else
{
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 0414fdf2f3f..a67e23fbf20 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.127 2002/12/05 15:50:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.128 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1041,12 +1041,12 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
foreach(i, indexqual)
{
- Expr *clause = (Expr *) lfirst(i);
- Expr *newclause;
+ OpExpr *clause = (OpExpr *) lfirst(i);
+ OpExpr *newclause;
List *leftvarnos;
Oid opclass;
- if (!is_opclause((Node *) clause) || length(clause->args) != 2)
+ if (!IsA(clause, OpExpr) || length(clause->args) != 2)
elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause");
/*
@@ -1056,7 +1056,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
* is a subplan in the arguments of the opclause. So just do a
* full copy.
*/
- newclause = (Expr *) copyObject((Node *) clause);
+ newclause = (OpExpr *) copyObject((Node *) clause);
/*
* Check to see if the indexkey is on the right; if so, commute
@@ -1083,7 +1083,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
* Finally, check to see if index is lossy for this operator. If
* so, add (a copy of) original form of clause to recheck list.
*/
- if (op_requires_recheck(((Oper *) newclause->oper)->opno, opclass))
+ if (op_requires_recheck(newclause->opno, opclass))
recheck_qual = lappend(recheck_qual,
copyObject((Node *) clause));
}
@@ -1100,7 +1100,7 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
* Remove any binary-compatible relabeling of the indexkey
*/
if (IsA(node, RelabelType))
- node = ((RelabelType *) node)->arg;
+ node = (Node *) ((RelabelType *) node)->arg;
/*
* We represent index keys by Var nodes having the varno of the base
@@ -1168,11 +1168,11 @@ switch_outer(List *clauses)
foreach(i, clauses)
{
- Expr *clause = (Expr *) lfirst(i);
+ OpExpr *clause = (OpExpr *) lfirst(i);
Var *op;
- Assert(is_opclause((Node *) clause));
- op = get_rightop(clause);
+ Assert(is_opclause(clause));
+ op = get_rightop((Expr *) clause);
Assert(op && IsA(op, Var));
if (var_is_outer(op))
{
@@ -1181,10 +1181,13 @@ switch_outer(List *clauses)
* the clause without changing the original list. Could use
* copyObject, but a complete deep copy is overkill.
*/
- Expr *temp;
+ OpExpr *temp = makeNode(OpExpr);
- temp = make_clause(clause->opType, clause->oper,
- listCopy(clause->args));
+ temp->opno = clause->opno;
+ temp->opfuncid = InvalidOid;
+ temp->opresulttype = clause->opresulttype;
+ temp->opretset = clause->opretset;
+ temp->args = listCopy(clause->args);
/* Commute it --- note this modifies the temp node in-place. */
CommuteClause(temp);
t_list = lappend(t_list, temp);
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 529ba712f41..aca2c6f4f67 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.77 2002/11/24 21:52:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.78 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -761,14 +761,11 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
elog(ERROR, "Equality operator for types '%s' and '%s' should be mergejoinable, but isn't",
format_type_be(ltype), format_type_be(rtype));
- clause = makeNode(Expr);
- clause->typeOid = BOOLOID;
- clause->opType = OP_EXPR;
- clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */
- InvalidOid, /* opid */
- BOOLOID, /* opresulttype */
- false); /* opretset */
- clause->args = makeList2(item1, item2);
+ clause = make_opclause(oprid(eq_operator), /* opno */
+ BOOLOID, /* opresulttype */
+ false, /* opretset */
+ (Expr *) item1,
+ (Expr *) item2);
ReleaseSysCache(eq_operator);
@@ -969,7 +966,7 @@ check_mergejoinable(RestrictInfo *restrictinfo)
leftOp,
rightOp;
- if (!is_opclause((Node *) clause))
+ if (!is_opclause(clause))
return;
left = get_leftop(clause);
@@ -978,10 +975,11 @@ check_mergejoinable(RestrictInfo *restrictinfo)
/* caution: is_opclause accepts more than I do, so check it */
if (!right)
return; /* unary opclauses need not apply */
- if (!IsA(left, Var) ||!IsA(right, Var))
+ if (!IsA(left, Var) ||
+ !IsA(right, Var))
return;
- opno = ((Oper *) clause->oper)->opno;
+ opno = ((OpExpr *) clause)->opno;
if (op_mergejoinable(opno,
left->vartype,
@@ -1012,7 +1010,7 @@ check_hashjoinable(RestrictInfo *restrictinfo)
*right;
Oid opno;
- if (!is_opclause((Node *) clause))
+ if (!is_opclause(clause))
return;
left = get_leftop(clause);
@@ -1021,10 +1019,11 @@ check_hashjoinable(RestrictInfo *restrictinfo)
/* caution: is_opclause accepts more than I do, so check it */
if (!right)
return; /* unary opclauses need not apply */
- if (!IsA(left, Var) ||!IsA(right, Var))
+ if (!IsA(left, Var) ||
+ !IsA(right, Var))
return;
- opno = ((Oper *) clause->oper)->opno;
+ opno = ((OpExpr *) clause)->opno;
if (op_hashjoinable(opno,
left->vartype,
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index ebb9f3d2092..b3d7b5303c4 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.133 2002/12/05 21:46:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.134 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -91,7 +91,7 @@ planner(Query *parse)
* purpose is communication across multiple sub-Queries.
*
* Note we do NOT save and restore PlannerPlanId: it exists to assign
- * unique IDs to SubPlan nodes, and we want those IDs to be unique for
+ * unique IDs to SubPlanExpr nodes, and we want those IDs to be unique for
* the life of a backend. Also, PlannerInitPlan is saved/restored in
* subquery_planner, not here.
*/
@@ -278,7 +278,7 @@ subquery_planner(Query *parse, double tuple_fraction)
/* Must add the initPlans' extParams to the topmost node's, too */
foreach(lst, plan->initPlan)
{
- SubPlan *subplan = (SubPlan *) lfirst(lst);
+ SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
plan->extParam = set_unioni(plan->extParam,
subplan->plan->extParam);
@@ -1015,7 +1015,7 @@ grouping_planner(Query *parse, double tuple_fraction)
-1,
0);
- ctid = makeTargetEntry(resdom, (Node *) var);
+ ctid = makeTargetEntry(resdom, (Expr *) var);
tlist = lappend(tlist, ctid);
}
}
@@ -1707,7 +1707,7 @@ make_subplanTargetList(Query *parse,
exprTypmod(groupexpr),
NULL,
false),
- groupexpr);
+ (Expr *) groupexpr);
sub_tlist = lappend(sub_tlist, te);
}
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index b23843a030c..0d66c97964c 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.84 2002/12/05 15:50:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.85 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -52,7 +52,7 @@ static Node *replace_vars_with_subplan_refs(Node *node,
bool tlist_has_non_vars);
static Node *replace_vars_with_subplan_refs_mutator(Node *node,
replace_vars_with_subplan_refs_context *context);
-static bool fix_opids_walker(Node *node, void *context);
+static bool fix_opfuncids_walker(Node *node, void *context);
/*****************************************************************************
*
@@ -219,7 +219,7 @@ set_plan_references(Plan *plan, List *rtable)
* subplan references in this plan's tlist and quals. If we did the
* reference-adjustments bottom-up, then we would fail to match this
* plan's var nodes against the already-modified nodes of the
- * children. Fortunately, that consideration doesn't apply to SubPlan
+ * children. Fortunately, that consideration doesn't apply to SubPlanExpr
* nodes; else we'd need two passes over the expression trees.
*/
set_plan_references(plan->lefttree, rtable);
@@ -227,9 +227,9 @@ set_plan_references(Plan *plan, List *rtable)
foreach(pl, plan->initPlan)
{
- SubPlan *sp = (SubPlan *) lfirst(pl);
+ SubPlanExpr *sp = (SubPlanExpr *) lfirst(pl);
- Assert(IsA(sp, SubPlan));
+ Assert(IsA(sp, SubPlanExpr));
set_plan_references(sp->plan, sp->rtable);
}
}
@@ -238,8 +238,8 @@ set_plan_references(Plan *plan, List *rtable)
* fix_expr_references
* Do final cleanup on expressions (targetlists or quals).
*
- * This consists of looking up operator opcode info for Oper nodes
- * and recursively performing set_plan_references on SubPlans.
+ * This consists of looking up operator opcode info for OpExpr nodes
+ * and recursively performing set_plan_references on subplans.
*
* The Plan argument is currently unused, but might be needed again someday.
*/
@@ -255,20 +255,15 @@ fix_expr_references_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (IsA(node, Expr))
+ if (IsA(node, OpExpr))
+ set_opfuncid((OpExpr *) node);
+ else if (IsA(node, DistinctExpr))
+ set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
+ else if (IsA(node, SubPlanExpr))
{
- Expr *expr = (Expr *) node;
+ SubPlanExpr *sp = (SubPlanExpr *) node;
- if (expr->opType == OP_EXPR ||
- expr->opType == DISTINCT_EXPR)
- replace_opid((Oper *) expr->oper);
- else if (expr->opType == SUBPLAN_EXPR)
- {
- SubPlan *sp = (SubPlan *) expr->oper;
-
- Assert(IsA(sp, SubPlan));
- set_plan_references(sp->plan, sp->rtable);
- }
+ set_plan_references(sp->plan, sp->rtable);
}
return expression_tree_walker(node, fix_expr_references_walker, context);
}
@@ -362,12 +357,13 @@ set_uppernode_references(Plan *plan, Index subvarno)
TargetEntry *tle = (TargetEntry *) lfirst(l);
Node *newexpr;
- newexpr = replace_vars_with_subplan_refs(tle->expr,
+ newexpr = replace_vars_with_subplan_refs((Node *) tle->expr,
subvarno,
subplan_targetlist,
tlist_has_non_vars);
output_targetlist = lappend(output_targetlist,
- makeTargetEntry(tle->resdom, newexpr));
+ makeTargetEntry(tle->resdom,
+ (Expr *) newexpr));
}
plan->targetlist = output_targetlist;
@@ -570,8 +566,8 @@ replace_vars_with_subplan_refs_mutator(Node *node,
*****************************************************************************/
/*
- * fix_opids
- * Calculate opid field from opno for each Oper node in given tree.
+ * fix_opfuncids
+ * Calculate opfuncid field from opno for each OpExpr node in given tree.
* The given tree can be anything expression_tree_walker handles.
*
* The argument is modified in-place. (This is OK since we'd want the
@@ -579,24 +575,20 @@ replace_vars_with_subplan_refs_mutator(Node *node,
* shared structure.)
*/
void
-fix_opids(Node *node)
+fix_opfuncids(Node *node)
{
/* This tree walk requires no special setup, so away we go... */
- fix_opids_walker(node, NULL);
+ fix_opfuncids_walker(node, NULL);
}
static bool
-fix_opids_walker(Node *node, void *context)
+fix_opfuncids_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (IsA(node, Expr))
- {
- Expr *expr = (Expr *) node;
-
- if (expr->opType == OP_EXPR ||
- expr->opType == DISTINCT_EXPR)
- replace_opid((Oper *) expr->oper);
- }
- return expression_tree_walker(node, fix_opids_walker, context);
+ if (IsA(node, OpExpr))
+ set_opfuncid((OpExpr *) node);
+ else if (IsA(node, DistinctExpr))
+ set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
+ return expression_tree_walker(node, fix_opfuncids_walker, context);
}
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index a65de72c90b..fe17b8ebb01 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.59 2002/12/05 15:50:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.60 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -144,12 +144,12 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
}
/*
- * Convert a bare SubLink (as created by the parser) into a SubPlan.
+ * Convert a bare SubLink (as created by the parser) into a SubPlanExpr.
*/
static Node *
make_subplan(SubLink *slink)
{
- SubPlan *node = makeNode(SubPlan);
+ SubPlanExpr *node = makeNode(SubPlanExpr);
Query *subquery = (Query *) (slink->subselect);
Oid result_type = exprType((Node *) slink);
double tuple_fraction;
@@ -210,11 +210,13 @@ make_subplan(SubLink *slink)
node->plan = plan = subquery_planner(subquery, tuple_fraction);
node->plan_id = PlannerPlanId++; /* Assign unique ID to this
- * SubPlan */
+ * SubPlanExpr */
node->rtable = subquery->rtable;
node->sublink = slink;
+ node->typeOid = result_type;
+
slink->subselect = NULL; /* cool ?! see error check above! */
/*
@@ -270,7 +272,6 @@ make_subplan(SubLink *slink)
}
else
{
- Expr *expr = makeNode(Expr);
List *args = NIL;
/*
@@ -350,14 +351,7 @@ make_subplan(SubLink *slink)
convert_sublink_opers(slink, plan->targetlist, NULL);
/*
- * Make expression of SUBPLAN type
- */
- expr->typeOid = result_type;
- expr->opType = SUBPLAN_EXPR;
- expr->oper = (Node *) node;
-
- /*
- * Make expr->args from parParam.
+ * Make node->args from parParam.
*/
foreach(lst, node->parParam)
{
@@ -373,9 +367,9 @@ make_subplan(SubLink *slink)
var->varlevelsup = 0;
args = lappend(args, var);
}
- expr->args = args;
+ node->args = args;
- result = (Node *) expr;
+ result = (Node *) node;
}
return result;
@@ -385,7 +379,7 @@ make_subplan(SubLink *slink)
* convert_sublink_opers: convert a SubLink's oper list from the
* parser/rewriter format into the executor's format.
*
- * The oper list is initially just a list of Oper nodes. We replace it
+ * The oper list is initially just a list of OpExpr nodes. We replace it
* with a list of actually executable expressions, in which the specified
* operators are applied to corresponding elements of the lefthand list
* and Params representing the results of the subplan. lefthand is then
@@ -404,7 +398,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
foreach(lst, slink->oper)
{
- Oper *oper = (Oper *) lfirst(lst);
+ OpExpr *oper = (OpExpr *) lfirst(lst);
Node *lefthand = lfirst(leftlist);
TargetEntry *te = lfirst(targetlist);
Param *prm;
@@ -422,7 +416,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
*setParams = lappendi(*setParams, prm->paramid);
/* Look up the operator to check its declared input types */
- Assert(IsA(oper, Oper));
+ Assert(IsA(oper, OpExpr));
tup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oper->opno),
0, 0, 0);
@@ -439,9 +433,11 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
left = make_operand(lefthand, exprType(lefthand), opform->oprleft);
right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
newoper = lappend(newoper,
- make_opclause(oper,
- (Var *) left,
- (Var *) right));
+ make_opclause(oper->opno,
+ oper->opresulttype,
+ oper->opretset,
+ (Expr *) left,
+ (Expr *) right));
ReleaseSysCache(tup);
@@ -482,7 +478,7 @@ finalize_primnode(Node *node, finalize_primnode_results *results)
}
if (is_subplan(node))
{
- SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper;
+ SubPlanExpr *subplan = (SubPlanExpr *) node;
List *lst;
/* Check extParam list for params to add to paramids */
@@ -559,12 +555,12 @@ process_sublinks_mutator(Node *node, void *context)
*/
sublink->lefthand = (List *)
process_sublinks_mutator((Node *) sublink->lefthand, context);
- /* Now build the SubPlan node and make the expr to return */
+ /* Now build the SubPlanExpr node and make the expr to return */
return make_subplan(sublink);
}
/*
- * Note that we will never see a SubPlan expression in the input
+ * Note that we will never see a SubPlanExpr expression in the input
* (since this is the very routine that creates 'em to begin with). So
* the code in expression_tree_mutator() that might do inappropriate
* things with SubPlans or SubLinks will not be exercised.
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index bb00555f69d..4016ba476de 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.33 2002/09/02 02:47:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.34 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -294,7 +294,7 @@ flatten_andors(Expr *qual)
List *out_list = NIL;
List *arg;
- foreach(arg, qual->args)
+ foreach(arg, ((BoolExpr *) qual)->args)
{
Expr *subexpr = flatten_andors((Expr *) lfirst(arg));
@@ -305,7 +305,7 @@ flatten_andors(Expr *qual)
* with any other expr. Otherwise we'd need a listCopy here.
*/
if (and_clause((Node *) subexpr))
- out_list = nconc(out_list, subexpr->args);
+ out_list = nconc(out_list, ((BoolExpr *) subexpr)->args);
else
out_list = lappend(out_list, subexpr);
}
@@ -316,7 +316,7 @@ flatten_andors(Expr *qual)
List *out_list = NIL;
List *arg;
- foreach(arg, qual->args)
+ foreach(arg, ((BoolExpr *) qual)->args)
{
Expr *subexpr = flatten_andors((Expr *) lfirst(arg));
@@ -327,7 +327,7 @@ flatten_andors(Expr *qual)
* with any other expr. Otherwise we'd need a listCopy here.
*/
if (or_clause((Node *) subexpr))
- out_list = nconc(out_list, subexpr->args);
+ out_list = nconc(out_list, ((BoolExpr *) subexpr)->args);
else
out_list = lappend(out_list, subexpr);
}
@@ -335,20 +335,17 @@ flatten_andors(Expr *qual)
}
else if (not_clause((Node *) qual))
return make_notclause(flatten_andors(get_notclausearg(qual)));
- else if (is_opclause((Node *) qual))
+ else if (is_opclause(qual))
{
+ OpExpr *opexpr = (OpExpr *) qual;
Expr *left = (Expr *) get_leftop(qual);
Expr *right = (Expr *) get_rightop(qual);
- if (right)
- return make_clause(qual->opType, qual->oper,
- lcons(flatten_andors(left),
- lcons(flatten_andors(right),
- NIL)));
- else
- return make_clause(qual->opType, qual->oper,
- lcons(flatten_andors(left),
- NIL));
+ return make_opclause(opexpr->opno,
+ opexpr->opresulttype,
+ opexpr->opretset,
+ flatten_andors(left),
+ flatten_andors(right));
}
else
return qual;
@@ -379,7 +376,8 @@ pull_ors(List *orlist)
* we'd need a listCopy here.
*/
if (or_clause((Node *) subexpr))
- out_list = nconc(out_list, pull_ors(subexpr->args));
+ out_list = nconc(out_list,
+ pull_ors(((BoolExpr *) subexpr)->args));
else
out_list = lappend(out_list, subexpr);
}
@@ -410,7 +408,8 @@ pull_ands(List *andlist)
* we'd need a listCopy here.
*/
if (and_clause((Node *) subexpr))
- out_list = nconc(out_list, pull_ands(subexpr->args));
+ out_list = nconc(out_list,
+ pull_ands(((BoolExpr *) subexpr)->args));
else
out_list = lappend(out_list, subexpr);
}
@@ -433,20 +432,17 @@ find_nots(Expr *qual)
#ifdef NOT_USED
/* recursing into operator expressions is probably not worth it. */
- if (is_opclause((Node *) qual))
+ if (is_opclause(qual))
{
+ OpExpr *opexpr = (OpExpr *) qual;
Expr *left = (Expr *) get_leftop(qual);
Expr *right = (Expr *) get_rightop(qual);
- if (right)
- return make_clause(qual->opType, qual->oper,
- lcons(find_nots(left),
- lcons(find_nots(right),
- NIL)));
- else
- return make_clause(qual->opType, qual->oper,
- lcons(find_nots(left),
- NIL));
+ return make_opclause(opexpr->opno,
+ opexpr->opresulttype,
+ opexpr->opretset,
+ find_nots(left),
+ find_nots(right));
}
#endif
if (and_clause((Node *) qual))
@@ -454,7 +450,7 @@ find_nots(Expr *qual)
List *t_list = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, find_nots(lfirst(temp)));
return make_andclause(pull_ands(t_list));
}
@@ -463,7 +459,7 @@ find_nots(Expr *qual)
List *t_list = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, find_nots(lfirst(temp)));
return make_orclause(pull_ors(t_list));
}
@@ -492,20 +488,17 @@ push_nots(Expr *qual)
* Otherwise, retain the clause as it is (the 'not' can't be pushed
* down any farther).
*/
- if (is_opclause((Node *) qual))
+ if (is_opclause(qual))
{
- Oper *oper = (Oper *) ((Expr *) qual)->oper;
- Oid negator = get_negator(oper->opno);
+ OpExpr *opexpr = (OpExpr *) qual;
+ Oid negator = get_negator(opexpr->opno);
if (negator)
- {
- Oper *op = (Oper *) makeOper(negator,
- InvalidOid,
- oper->opresulttype,
- oper->opretset);
-
- return make_opclause(op, get_leftop(qual), get_rightop(qual));
- }
+ return make_opclause(negator,
+ opexpr->opresulttype,
+ opexpr->opretset,
+ (Expr *) get_leftop(qual),
+ (Expr *) get_rightop(qual));
else
return make_notclause(qual);
}
@@ -521,7 +514,7 @@ push_nots(Expr *qual)
List *t_list = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, push_nots(lfirst(temp)));
return make_orclause(pull_ors(t_list));
}
@@ -530,7 +523,7 @@ push_nots(Expr *qual)
List *t_list = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, push_nots(lfirst(temp)));
return make_andclause(pull_ands(t_list));
}
@@ -576,7 +569,7 @@ find_ors(Expr *qual)
List *andlist = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
andlist = lappend(andlist, find_ors(lfirst(temp)));
return make_andclause(pull_ands(andlist));
}
@@ -585,7 +578,7 @@ find_ors(Expr *qual)
List *orlist = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
orlist = lappend(orlist, find_ors(lfirst(temp)));
return or_normalize(pull_ors(orlist));
}
@@ -629,7 +622,7 @@ or_normalize(List *orlist)
if (and_clause((Node *) clause))
{
- int nclauses = length(clause->args);
+ int nclauses = length(((BoolExpr *) clause)->args);
if (nclauses > num_subclauses)
{
@@ -650,7 +643,7 @@ or_normalize(List *orlist)
*/
orlist = lremove(distributable, orlist);
- foreach(temp, distributable->args)
+ foreach(temp, ((BoolExpr *) distributable)->args)
{
Expr *andclause = lfirst(temp);
List *neworlist;
@@ -703,7 +696,7 @@ find_ands(Expr *qual)
List *orlist = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
orlist = lappend(orlist, find_ands(lfirst(temp)));
return make_orclause(pull_ors(orlist));
}
@@ -712,7 +705,7 @@ find_ands(Expr *qual)
List *andlist = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
andlist = lappend(andlist, find_ands(lfirst(temp)));
return and_normalize(pull_ands(andlist));
}
@@ -757,7 +750,7 @@ and_normalize(List *andlist)
if (or_clause((Node *) clause))
{
- int nclauses = length(clause->args);
+ int nclauses = length(((BoolExpr *) clause)->args);
if (nclauses > num_subclauses)
{
@@ -778,7 +771,7 @@ and_normalize(List *andlist)
*/
andlist = lremove(distributable, andlist);
- foreach(temp, distributable->args)
+ foreach(temp, ((BoolExpr *) distributable)->args)
{
Expr *orclause = lfirst(temp);
List *newandlist;
@@ -829,7 +822,7 @@ qual_cleanup(Expr *qual)
List *andlist = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
andlist = lappend(andlist, qual_cleanup(lfirst(temp)));
andlist = remove_duplicates(pull_ands(andlist));
@@ -844,7 +837,7 @@ qual_cleanup(Expr *qual)
List *orlist = NIL;
List *temp;
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
orlist = lappend(orlist, qual_cleanup(lfirst(temp)));
orlist = remove_duplicates(pull_ors(orlist));
@@ -910,7 +903,7 @@ count_bool_nodes(Expr *qual,
*nodes = *cnfnodes = 0.0;
*dnfnodes = 1.0; /* DNF nodes will be product of sub-counts */
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
{
count_bool_nodes(lfirst(temp),
&subnodes, &subcnfnodes, &subdnfnodes);
@@ -931,7 +924,7 @@ count_bool_nodes(Expr *qual,
*nodes = *dnfnodes = 0.0;
*cnfnodes = 1.0; /* CNF nodes will be product of sub-counts */
- foreach(temp, qual->args)
+ foreach(temp, ((BoolExpr *) qual)->args)
{
count_bool_nodes(lfirst(temp),
&subnodes, &subcnfnodes, &subdnfnodes);
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 68895143061..87d3c983a70 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.58 2002/11/25 21:29:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.59 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -96,7 +96,7 @@ preprocess_targetlist(List *tlist,
if (command_type == CMD_DELETE)
tlist = listCopy(tlist);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Node *) var));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var));
}
return tlist;
@@ -215,7 +215,7 @@ expand_targetlist(List *tlist, int command_type,
atttypmod,
pstrdup(NameStr(att_tup->attname)),
false),
- new_expr);
+ (Expr *) new_expr);
}
new_tlist = lappend(new_tlist, new_tle);
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 79063c02806..a55af2e2d06 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.81 2002/11/25 21:29:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.82 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -406,7 +406,7 @@ generate_setop_tlist(List *colTypes, int flag,
* the output tlists of upper-level nodes!
*/
if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
- expr = inputtle->expr;
+ expr = (Node *) inputtle->expr;
else
expr = (Node *) makeVar(0,
inputtle->resdom->resno,
@@ -430,7 +430,7 @@ generate_setop_tlist(List *colTypes, int flag,
colTypmod,
pstrdup(reftle->resdom->resname),
false);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
input_tlist = lnext(input_tlist);
refnames_tlist = lnext(refnames_tlist);
}
@@ -449,7 +449,7 @@ generate_setop_tlist(List *colTypes, int flag,
Int32GetDatum(flag),
false,
true);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
}
return tlist;
@@ -543,7 +543,7 @@ generate_append_tlist(List *colTypes, bool flag,
colTypmod,
pstrdup(reftle->resdom->resname),
false);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
refnames_tlist = lnext(refnames_tlist);
}
@@ -561,7 +561,7 @@ generate_append_tlist(List *colTypes, bool flag,
INT4OID,
-1,
0);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
}
pfree(colTypmods);
@@ -872,13 +872,13 @@ adjust_inherited_attrs_mutator(Node *node,
*/
if (is_subplan(node))
{
- SubPlan *subplan;
+ SubPlanExpr *subplan;
/* Copy the node and process subplan args */
node = expression_tree_mutator(node, adjust_inherited_attrs_mutator,
(void *) context);
/* Make sure we have separate copies of subplan and its rtable */
- subplan = (SubPlan *) ((Expr *) node)->oper;
+ subplan = (SubPlanExpr *) node;
subplan->plan = copyObject(subplan->plan);
subplan->rtable = copyObject(subplan->rtable);
return node;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index a0d1b752bc4..ef317c5b223 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.115 2002/12/01 21:05:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.116 2002/12/12 15:49:32 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -70,84 +70,41 @@ static bool contain_mutable_functions_walker(Node *node, void *context);
static bool contain_volatile_functions_walker(Node *node, void *context);
static bool contain_nonstrict_functions_walker(Node *node, void *context);
static Node *eval_const_expressions_mutator(Node *node, List *active_fns);
-static Expr *simplify_op_or_func(Expr *expr, List *args, bool allow_inline,
- List *active_fns);
-static Expr *evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple);
-static Expr *inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple,
+static Expr *simplify_function(Oid funcid, List *args, bool allow_inline,
List *active_fns);
+static Expr *evaluate_function(Oid funcid, List *args, HeapTuple func_tuple);
+static Expr *inline_function(Oid funcid, List *args, HeapTuple func_tuple,
+ List *active_fns);
static Node *substitute_actual_parameters(Node *expr, int nargs, List *args,
int *usecounts);
static Node *substitute_actual_parameters_mutator(Node *node,
substitute_actual_parameters_context *context);
-Expr *
-make_clause(int type, Node *oper, List *args)
-{
- Expr *expr = makeNode(Expr);
-
- switch (type)
- {
- case AND_EXPR:
- case OR_EXPR:
- case NOT_EXPR:
- expr->typeOid = BOOLOID;
- break;
- case OP_EXPR:
- case DISTINCT_EXPR:
- expr->typeOid = ((Oper *) oper)->opresulttype;
- break;
- case FUNC_EXPR:
- expr->typeOid = ((Func *) oper)->funcresulttype;
- break;
- default:
- elog(ERROR, "make_clause: unsupported type %d", type);
- break;
- }
- expr->opType = type;
- expr->oper = oper; /* ignored for AND, OR, NOT */
- expr->args = args;
- return expr;
-}
-
-
/*****************************************************************************
* OPERATOR clause functions
*****************************************************************************/
-
-/*
- * is_opclause
- *
- * Returns t iff the clause is an operator clause:
- * (op expr expr) or (op expr).
- */
-bool
-is_opclause(Node *clause)
-{
- return (clause != NULL &&
- IsA(clause, Expr) &&
- ((Expr *) clause)->opType == OP_EXPR);
-}
-
/*
* make_opclause
- * Creates a clause given its operator, left operand, and right
- * operand (pass NULL to create single-operand clause).
+ * Creates an operator clause given its operator info, left operand,
+ * and right operand (pass NULL to create single-operand clause).
*/
Expr *
-make_opclause(Oper *op, Var *leftop, Var *rightop)
+make_opclause(Oid opno, Oid opresulttype, bool opretset,
+ Expr *leftop, Expr *rightop)
{
- Expr *expr = makeNode(Expr);
+ OpExpr *expr = makeNode(OpExpr);
- expr->typeOid = op->opresulttype;
- expr->opType = OP_EXPR;
- expr->oper = (Node *) op;
+ expr->opno = opno;
+ expr->opfuncid = InvalidOid;
+ expr->opresulttype = opresulttype;
+ expr->opretset = opretset;
if (rightop)
expr->args = makeList2(leftop, rightop);
else
expr->args = makeList1(leftop);
- return expr;
+ return (Expr *) expr;
}
/*
@@ -163,8 +120,10 @@ make_opclause(Oper *op, Var *leftop, Var *rightop)
Var *
get_leftop(Expr *clause)
{
- if (clause->args != NULL)
- return lfirst(clause->args);
+ OpExpr *expr = (OpExpr *) clause;
+
+ if (expr->args != NULL)
+ return lfirst(expr->args);
else
return NULL;
}
@@ -178,124 +137,109 @@ get_leftop(Expr *clause)
Var *
get_rightop(Expr *clause)
{
- if (clause->args != NULL && lnext(clause->args) != NULL)
- return lfirst(lnext(clause->args));
+ OpExpr *expr = (OpExpr *) clause;
+
+ if (expr->args != NULL && lnext(expr->args) != NULL)
+ return lfirst(lnext(expr->args));
else
return NULL;
}
/*****************************************************************************
- * FUNC clause functions
+ * FUNCTION clause functions
*****************************************************************************/
/*
- * is_funcclause
- *
- * Returns t iff the clause is a function clause: (func { expr }).
- */
-bool
-is_funcclause(Node *clause)
-{
- return (clause != NULL &&
- IsA(clause, Expr) &&
- ((Expr *) clause)->opType == FUNC_EXPR);
-}
-
-/*
* make_funcclause
- *
- * Creates a function clause given the FUNC node and the functional
- * arguments.
+ * Creates a function clause given its function info and argument list.
*/
Expr *
-make_funcclause(Func *func, List *funcargs)
+make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset,
+ CoercionForm funcformat, List *funcargs)
{
- Expr *expr = makeNode(Expr);
+ FuncExpr *expr = makeNode(FuncExpr);
- expr->typeOid = func->funcresulttype;
- expr->opType = FUNC_EXPR;
- expr->oper = (Node *) func;
+ expr->funcid = funcid;
+ expr->funcresulttype = funcresulttype;
+ expr->funcretset = funcretset;
+ expr->funcformat = funcformat;
expr->args = funcargs;
- return expr;
+ return (Expr *) expr;
}
/*****************************************************************************
- * OR clause functions
+ * NOT clause functions
*****************************************************************************/
/*
- * or_clause
+ * not_clause
*
- * Returns t iff the clause is an 'or' clause: (OR { expr }).
+ * Returns t iff this is a 'not' clause: (NOT expr).
*/
bool
-or_clause(Node *clause)
+not_clause(Node *clause)
{
return (clause != NULL &&
- IsA(clause, Expr) &&
- ((Expr *) clause)->opType == OR_EXPR);
+ IsA(clause, BoolExpr) &&
+ ((BoolExpr *) clause)->boolop == NOT_EXPR);
}
/*
- * make_orclause
+ * make_notclause
*
- * Creates an 'or' clause given a list of its subclauses.
+ * Create a 'not' clause given the expression to be negated.
*/
Expr *
-make_orclause(List *orclauses)
+make_notclause(Expr *notclause)
{
- Expr *expr = makeNode(Expr);
+ BoolExpr *expr = makeNode(BoolExpr);
- expr->typeOid = BOOLOID;
- expr->opType = OR_EXPR;
- expr->oper = NULL;
- expr->args = orclauses;
- return expr;
+ expr->boolop = NOT_EXPR;
+ expr->args = makeList1(notclause);
+ return (Expr *) expr;
}
-/*****************************************************************************
- * NOT clause functions
- *****************************************************************************/
-
/*
- * not_clause
+ * get_notclausearg
*
- * Returns t iff this is a 'not' clause: (NOT expr).
+ * Retrieve the clause within a 'not' clause
*/
-bool
-not_clause(Node *clause)
+Expr *
+get_notclausearg(Expr *notclause)
{
- return (clause != NULL &&
- IsA(clause, Expr) &&
- ((Expr *) clause)->opType == NOT_EXPR);
+ return lfirst(((BoolExpr *) notclause)->args);
}
+/*****************************************************************************
+ * OR clause functions
+ *****************************************************************************/
+
/*
- * make_notclause
+ * or_clause
*
- * Create a 'not' clause given the expression to be negated.
+ * Returns t iff the clause is an 'or' clause: (OR { expr }).
*/
-Expr *
-make_notclause(Expr *notclause)
+bool
+or_clause(Node *clause)
{
- Expr *expr = makeNode(Expr);
-
- expr->typeOid = BOOLOID;
- expr->opType = NOT_EXPR;
- expr->oper = NULL;
- expr->args = makeList1(notclause);
- return expr;
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((BoolExpr *) clause)->boolop == OR_EXPR);
}
/*
- * get_notclausearg
+ * make_orclause
*
- * Retrieve the clause within a 'not' clause
+ * Creates an 'or' clause given a list of its subclauses.
*/
Expr *
-get_notclausearg(Expr *notclause)
+make_orclause(List *orclauses)
{
- return lfirst(notclause->args);
+ BoolExpr *expr = makeNode(BoolExpr);
+
+ expr->boolop = OR_EXPR;
+ expr->args = orclauses;
+ return (Expr *) expr;
}
/*****************************************************************************
@@ -312,25 +256,23 @@ bool
and_clause(Node *clause)
{
return (clause != NULL &&
- IsA(clause, Expr) &&
- ((Expr *) clause)->opType == AND_EXPR);
+ IsA(clause, BoolExpr) &&
+ ((BoolExpr *) clause)->boolop == AND_EXPR);
}
/*
* make_andclause
*
- * Create an 'and' clause given its arguments in a list.
+ * Creates an 'and' clause given a list of its subclauses.
*/
Expr *
make_andclause(List *andclauses)
{
- Expr *expr = makeNode(Expr);
+ BoolExpr *expr = makeNode(BoolExpr);
- expr->typeOid = BOOLOID;
- expr->opType = AND_EXPR;
- expr->oper = NULL;
+ expr->boolop = AND_EXPR;
expr->args = andclauses;
- return expr;
+ return (Expr *) expr;
}
/*
@@ -382,7 +324,7 @@ make_ands_implicit(Expr *clause)
if (clause == NULL)
return NIL; /* NULL -> NIL list == TRUE */
else if (and_clause((Node *) clause))
- return clause->args;
+ return ((BoolExpr *) clause)->args;
else if (IsA(clause, Const) &&
!((Const *) clause)->constisnull &&
DatumGetBool(((Const *) clause)->constvalue))
@@ -476,7 +418,7 @@ pull_agg_clause_walker(Node *node, List **listptr)
* Complain if the aggregate's argument contains any aggregates;
* nested agg functions are semantically nonsensical.
*/
- if (contain_agg_clause(((Aggref *) node)->target))
+ if (contain_agg_clause((Node *) ((Aggref *) node)->target))
elog(ERROR, "Aggregate function calls may not be nested");
/*
@@ -512,38 +454,41 @@ expression_returns_set_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr))
{
- Expr *expr = (Expr *) node;
+ FuncExpr *expr = (FuncExpr *) node;
- switch (expr->opType)
- {
- case OP_EXPR:
- case DISTINCT_EXPR:
- if (((Oper *) expr->oper)->opretset)
- return true;
- /* else fall through to check args */
- break;
- case FUNC_EXPR:
- if (((Func *) expr->oper)->funcretset)
- return true;
- /* else fall through to check args */
- break;
- case OR_EXPR:
- case AND_EXPR:
- case NOT_EXPR:
- /* Booleans can't return a set, so no need to recurse */
- return false;
- case SUBPLAN_EXPR:
- /* Subplans can't presently return sets either */
- return false;
- }
+ if (expr->funcretset)
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *expr = (OpExpr *) node;
+
+ if (expr->opretset)
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+
+ if (expr->opretset)
+ return true;
+ /* else fall through to check args */
}
- /* Avoid recursion for some other cases that can't return a set */
+
+ /* Avoid recursion for some cases that can't return a set */
+ if (IsA(node, BoolExpr))
+ return false;
if (IsA(node, Aggref))
return false;
if (IsA(node, SubLink))
return false;
+ if (IsA(node, SubPlanExpr))
+ return false;
+
return expression_tree_walker(node, expression_returns_set_walker,
context);
}
@@ -574,7 +519,8 @@ contain_subplans_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (is_subplan(node) || IsA(node, SubLink))
+ if (IsA(node, SubPlanExpr) ||
+ IsA(node, SubLink))
return true; /* abort the tree traversal and return
* true */
return expression_tree_walker(node, contain_subplans_walker, context);
@@ -584,8 +530,8 @@ 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
- * copied, only referenced.
+ * Returns list of SubPlanExpr nodes found. Note the nodes themselves
+ * are not copied, only referenced.
*/
List *
pull_subplans(Node *clause)
@@ -603,7 +549,7 @@ pull_subplans_walker(Node *node, List **listptr)
return false;
if (is_subplan(node))
{
- *listptr = lappend(*listptr, ((Expr *) node)->oper);
+ *listptr = lappend(*listptr, node);
/* fall through to check args to subplan */
}
return expression_tree_walker(node, pull_subplans_walker,
@@ -710,7 +656,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
*/
List *t;
- foreach(t, ((Expr *) node)->args)
+ foreach(t, ((SubPlanExpr *) node)->args)
{
Node *thisarg = lfirst(t);
Var *var;
@@ -789,24 +735,29 @@ contain_mutable_functions_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr))
{
- Expr *expr = (Expr *) node;
+ FuncExpr *expr = (FuncExpr *) node;
- switch (expr->opType)
- {
- case OP_EXPR:
- case DISTINCT_EXPR:
- if (op_volatile(((Oper *) expr->oper)->opno) != PROVOLATILE_IMMUTABLE)
- return true;
- break;
- case FUNC_EXPR:
- if (func_volatile(((Func *) expr->oper)->funcid) != PROVOLATILE_IMMUTABLE)
- return true;
- break;
- default:
- break;
- }
+ if (func_volatile(expr->funcid) != PROVOLATILE_IMMUTABLE)
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *expr = (OpExpr *) node;
+
+ if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+
+ if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)
+ return true;
+ /* else fall through to check args */
}
return expression_tree_walker(node, contain_mutable_functions_walker,
context);
@@ -839,24 +790,29 @@ contain_volatile_functions_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr))
{
- Expr *expr = (Expr *) node;
+ FuncExpr *expr = (FuncExpr *) node;
- switch (expr->opType)
- {
- case OP_EXPR:
- case DISTINCT_EXPR:
- if (op_volatile(((Oper *) expr->oper)->opno) == PROVOLATILE_VOLATILE)
- return true;
- break;
- case FUNC_EXPR:
- if (func_volatile(((Func *) expr->oper)->funcid) == PROVOLATILE_VOLATILE)
- return true;
- break;
- default:
- break;
- }
+ if (func_volatile(expr->funcid) == PROVOLATILE_VOLATILE)
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *expr = (OpExpr *) node;
+
+ if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+
+ if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)
+ return true;
+ /* else fall through to check args */
}
return expression_tree_walker(node, contain_volatile_functions_walker,
context);
@@ -876,7 +832,7 @@ contain_volatile_functions_walker(Node *node, void *context)
*
* XXX we do not examine sublinks/subplans to see if they contain uses of
* nonstrict functions. It's not real clear if that is correct or not...
- * for the current usage it does not matter, since inline_op_or_func()
+ * for the current usage it does not matter, since inline_function()
* rejects cases with sublinks.
*/
bool
@@ -890,23 +846,33 @@ contain_nonstrict_functions_walker(Node *node, void *context)
{
if (node == NULL)
return false;
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr))
+ {
+ FuncExpr *expr = (FuncExpr *) node;
+
+ if (!func_strict(expr->funcid))
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *expr = (OpExpr *) node;
+
+ if (!op_strict(expr->opno))
+ return true;
+ /* else fall through to check args */
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ /* IS DISTINCT FROM is inherently non-strict */
+ return true;
+ }
+ if (IsA(node, BoolExpr))
{
- Expr *expr = (Expr *) node;
+ BoolExpr *expr = (BoolExpr *) node;
- switch (expr->opType)
+ switch (expr->boolop)
{
- case OP_EXPR:
- if (!op_strict(((Oper *) expr->oper)->opno))
- return true;
- break;
- case DISTINCT_EXPR:
- /* IS DISTINCT FROM is inherently non-strict */
- return true;
- case FUNC_EXPR:
- if (!func_strict(((Func *) expr->oper)->funcid))
- return true;
- break;
case OR_EXPR:
case AND_EXPR:
/* OR, AND are inherently non-strict */
@@ -1147,39 +1113,28 @@ NumRelids(Node *clause)
* XXX the clause is destructively modified!
*/
void
-CommuteClause(Expr *clause)
+CommuteClause(OpExpr *clause)
{
Oid opoid;
- HeapTuple optup;
- Form_pg_operator commuTup;
- Oper *commu;
Node *temp;
- if (!is_opclause((Node *) clause) ||
+ if (!is_opclause(clause) ||
length(clause->args) != 2)
elog(ERROR, "CommuteClause: applied to non-binary-operator clause");
- opoid = ((Oper *) clause->oper)->opno;
-
- optup = SearchSysCache(OPEROID,
- ObjectIdGetDatum(get_commutator(opoid)),
- 0, 0, 0);
- if (!HeapTupleIsValid(optup))
- elog(ERROR, "CommuteClause: no commutator for operator %u", opoid);
-
- commuTup = (Form_pg_operator) GETSTRUCT(optup);
+ opoid = get_commutator(clause->opno);
- commu = makeOper(HeapTupleGetOid(optup),
- commuTup->oprcode,
- commuTup->oprresult,
- ((Oper *) clause->oper)->opretset);
-
- ReleaseSysCache(optup);
+ if (!OidIsValid(opoid))
+ elog(ERROR, "CommuteClause: no commutator for operator %u",
+ clause->opno);
/*
- * re-form the clause in-place!
+ * modify the clause in-place!
*/
- clause->oper = (Node *) commu;
+ clause->opno = opoid;
+ clause->opfuncid = InvalidOid;
+ /* opresulttype and opretset are assumed not to change */
+
temp = lfirst(clause->args);
lfirst(clause->args) = lsecond(clause->args);
lsecond(clause->args) = temp;
@@ -1223,15 +1178,94 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
{
if (node == NULL)
return NULL;
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr))
{
- Expr *expr = (Expr *) node;
+ FuncExpr *expr = (FuncExpr *) node;
List *args;
- Const *const_input;
- Expr *newexpr;
+ Expr *simple;
+ FuncExpr *newexpr;
+
+ /*
+ * Reduce constants in the FuncExpr'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.
+ */
+ args = (List *) expression_tree_mutator((Node *) expr->args,
+ eval_const_expressions_mutator,
+ (void *) active_fns);
+ /*
+ * Code for op/func reduction is pretty bulky, so split it out
+ * as a separate function.
+ */
+ simple = simplify_function(expr->funcid, args, true, active_fns);
+ if (simple) /* successfully simplified it */
+ return (Node *) simple;
+ /*
+ * The expression cannot be simplified any further, so build and
+ * return a replacement FuncExpr node using the possibly-simplified
+ * arguments.
+ */
+ newexpr = makeNode(FuncExpr);
+ newexpr->funcid = expr->funcid;
+ newexpr->funcresulttype = expr->funcresulttype;
+ newexpr->funcretset = expr->funcretset;
+ newexpr->funcformat = expr->funcformat;
+ newexpr->args = args;
+ return (Node *) newexpr;
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *expr = (OpExpr *) node;
+ List *args;
+ Expr *simple;
+ OpExpr *newexpr;
/*
- * Reduce constants in the Expr's arguments. We know args is
+ * Reduce constants in the OpExpr'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.
+ */
+ args = (List *) expression_tree_mutator((Node *) expr->args,
+ eval_const_expressions_mutator,
+ (void *) active_fns);
+ /*
+ * Need to get OID of underlying function. Okay to scribble on
+ * input to this extent.
+ */
+ set_opfuncid(expr);
+ /*
+ * Code for op/func reduction is pretty bulky, so split it out
+ * as a separate function.
+ */
+ simple = simplify_function(expr->opfuncid, args, true, active_fns);
+ if (simple) /* successfully simplified it */
+ return (Node *) simple;
+ /*
+ * The expression cannot be simplified any further, so build and
+ * return a replacement OpExpr node using the possibly-simplified
+ * arguments.
+ */
+ newexpr = makeNode(OpExpr);
+ newexpr->opno = expr->opno;
+ newexpr->opfuncid = expr->opfuncid;
+ newexpr->opresulttype = expr->opresulttype;
+ newexpr->opretset = expr->opretset;
+ newexpr->args = args;
+ return (Node *) newexpr;
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+ List *args;
+ List *arg;
+ bool has_null_input = false;
+ bool all_null_input = true;
+ bool has_nonconst_input = false;
+ Expr *simple;
+ DistinctExpr *newexpr;
+
+ /*
+ * Reduce constants in the DistinctExpr'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.
*/
@@ -1239,76 +1273,83 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
eval_const_expressions_mutator,
(void *) active_fns);
- switch (expr->opType)
+ /*
+ * We must do our own check for NULLs because
+ * DistinctExpr has different results for NULL input
+ * than the underlying operator does.
+ */
+ foreach(arg, args)
{
- case OP_EXPR:
- case FUNC_EXPR:
+ if (IsA(lfirst(arg), Const))
+ {
+ has_null_input |= ((Const *) lfirst(arg))->constisnull;
+ all_null_input &= ((Const *) lfirst(arg))->constisnull;
+ }
+ else
+ has_nonconst_input = true;
+ }
- /*
- * Code for op/func case is pretty bulky, so split it out
- * as a separate function.
- */
- newexpr = simplify_op_or_func(expr, args,
- true, active_fns);
- if (newexpr) /* successfully simplified it */
- return (Node *) newexpr;
+ /* all constants? then can optimize this out */
+ if (!has_nonconst_input)
+ {
+ /* all nulls? then not distinct */
+ if (all_null_input)
+ return MAKEBOOLCONST(false, false);
- /*
- * else fall out to build new Expr node with simplified
- * args
- */
- break;
- case DISTINCT_EXPR:
- {
- List *arg;
- bool has_null_input = false;
- bool all_null_input = true;
- bool has_nonconst_input = false;
+ /* one null? then distinct */
+ if (has_null_input)
+ return MAKEBOOLCONST(true, false);
- /*
- * We must do our own check for NULLs because
- * DISTINCT_EXPR has different results for NULL input
- * than the underlying operator does.
- */
- foreach(arg, args)
- {
- if (IsA(lfirst(arg), Const))
- {
- has_null_input |= ((Const *) lfirst(arg))->constisnull;
- all_null_input &= ((Const *) lfirst(arg))->constisnull;
- }
- else
- has_nonconst_input = true;
- }
+ /* otherwise try to evaluate the '=' operator */
+ /* (NOT okay to try to inline it, though!) */
- /* all constants? then can optimize this out */
- if (!has_nonconst_input)
- {
- /* all nulls? then not distinct */
- if (all_null_input)
- return MAKEBOOLCONST(false, false);
-
- /* one null? then distinct */
- if (has_null_input)
- return MAKEBOOLCONST(true, false);
-
- /* otherwise try to evaluate the '=' operator */
- /* (NOT okay to try to inline it, though!) */
- newexpr = simplify_op_or_func(expr, args,
- false, active_fns);
- if (newexpr) /* successfully simplified it */
- return (Node *) newexpr;
- }
+ /*
+ * Need to get OID of underlying function. Okay to scribble on
+ * input to this extent.
+ */
+ set_opfuncid((OpExpr *) expr); /* rely on struct equivalence */
+ /*
+ * Code for op/func reduction is pretty bulky, so split it out
+ * as a separate function.
+ */
+ simple = simplify_function(expr->opfuncid, args,
+ false, active_fns);
+ if (simple) /* successfully simplified it */
+ return (Node *) simple;
+ }
- /*
- * else fall out to build new Expr node with simplified
- * args
- */
- break;
- }
+ /*
+ * The expression cannot be simplified any further, so build and
+ * return a replacement DistinctExpr node using the
+ * possibly-simplified arguments.
+ */
+ newexpr = makeNode(DistinctExpr);
+ newexpr->opno = expr->opno;
+ newexpr->opfuncid = expr->opfuncid;
+ newexpr->opresulttype = expr->opresulttype;
+ newexpr->opretset = expr->opretset;
+ newexpr->args = args;
+ return (Node *) newexpr;
+ }
+ if (IsA(node, BoolExpr))
+ {
+ BoolExpr *expr = (BoolExpr *) node;
+ List *args;
+ Const *const_input;
+
+ /*
+ * Reduce constants in the BoolExpr'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.
+ */
+ args = (List *) expression_tree_mutator((Node *) expr->args,
+ eval_const_expressions_mutator,
+ (void *) active_fns);
+
+ switch (expr->boolop)
+ {
case OR_EXPR:
{
-
/*----------
* OR arguments are handled as follows:
* non constant: keep
@@ -1361,7 +1402,6 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
}
case AND_EXPR:
{
-
/*----------
* AND arguments are handled as follows:
* non constant: keep
@@ -1414,47 +1454,34 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
}
case NOT_EXPR:
Assert(length(args) == 1);
- 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(!DatumGetBool(const_input->constvalue),
- false);
- case SUBPLAN_EXPR:
-
- /*
- * 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).
- *
- * XXX should we elog() here instead? Probably this routine
- * should never be invoked after SubPlan creation.
- */
- return (Node *) expr;
+ if (IsA(lfirst(args), Const))
+ {
+ const_input = (Const *) lfirst(args);
+ /* NOT NULL => NULL */
+ if (const_input->constisnull)
+ return MAKEBOOLCONST(false, true);
+ /* otherwise pretty easy */
+ return MAKEBOOLCONST(!DatumGetBool(const_input->constvalue),
+ false);
+ }
+ /* Else we still need a NOT node */
+ return (Node *) make_notclause(lfirst(args));
default:
- elog(ERROR, "eval_const_expressions: unexpected opType %d",
- (int) expr->opType);
+ elog(ERROR, "eval_const_expressions: unexpected boolop %d",
+ (int) expr->boolop);
break;
}
-
+ }
+ if (IsA(node, SubPlanExpr))
+ {
/*
- * 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...
+ * Return a SubPlanExpr unchanged --- too late to do anything
+ * with it.
+ *
+ * XXX should we elog() here instead? Probably this routine
+ * should never be invoked after SubPlanExpr creation.
*/
- newexpr = makeNode(Expr);
- newexpr->typeOid = expr->typeOid;
- newexpr->opType = expr->opType;
- newexpr->oper = expr->oper;
- newexpr->args = args;
- return (Node *) newexpr;
+ return node;
}
if (IsA(node, RelabelType))
{
@@ -1466,14 +1493,15 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
RelabelType *relabel = (RelabelType *) node;
Node *arg;
- arg = eval_const_expressions_mutator(relabel->arg, active_fns);
+ arg = eval_const_expressions_mutator((Node *) relabel->arg,
+ active_fns);
/*
* If we find stacked RelabelTypes (eg, from foo :: int :: oid) we
* can discard all but the top one.
*/
while (arg && IsA(arg, RelabelType))
- arg = ((RelabelType *) arg)->arg;
+ arg = (Node *) ((RelabelType *) arg)->arg;
if (arg && IsA(arg, Const))
{
@@ -1493,7 +1521,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
{
RelabelType *newrelabel = makeNode(RelabelType);
- newrelabel->arg = arg;
+ newrelabel->arg = (Expr *) arg;
newrelabel->resulttype = relabel->resulttype;
newrelabel->resulttypmod = relabel->resulttypmod;
return (Node *) newrelabel;
@@ -1545,7 +1573,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
* alternative, the CASE reduces to just this alternative.
*/
if (newargs == NIL)
- return casewhen->result;
+ return (Node *) casewhen->result;
/*
* Otherwise, add it to the list, and drop all the rest.
@@ -1555,7 +1583,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
}
/* Simplify the default result */
- defresult = eval_const_expressions_mutator(caseexpr->defresult,
+ defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
active_fns);
/*
@@ -1569,7 +1597,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
newcase->casetype = caseexpr->casetype;
newcase->arg = NULL;
newcase->args = newargs;
- newcase->defresult = defresult;
+ newcase->defresult = (Expr *) defresult;
return (Node *) newcase;
}
@@ -1585,19 +1613,18 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
}
/*
- * Subroutine for eval_const_expressions: try to simplify an op or func
+ * Subroutine for eval_const_expressions: try to simplify a function call
+ * (which might originally have been an operator; we don't care)
*
- * Inputs are the op or func Expr node, and the pre-simplified argument list;
+ * Inputs are the function OID and the pre-simplified argument list;
* also a list of already-active inline function expansions.
*
* Returns a simplified expression if successful, or NULL if cannot
- * simplify the op/func.
+ * simplify the function call.
*/
static Expr *
-simplify_op_or_func(Expr *expr, List *args, bool allow_inline,
- List *active_fns)
+simplify_function(Oid funcid, List *args, bool allow_inline, List *active_fns)
{
- Oid funcid;
HeapTuple func_tuple;
Expr *newexpr;
@@ -1609,30 +1636,16 @@ simplify_op_or_func(Expr *expr, List *args, bool allow_inline,
* to the function's pg_proc tuple, so fetch it just once to use in both
* attempts.
*/
- if (expr->opType == FUNC_EXPR)
- {
- Func *func = (Func *) expr->oper;
-
- funcid = func->funcid;
- }
- else /* OP_EXPR or DISTINCT_EXPR */
- {
- Oper *oper = (Oper *) expr->oper;
-
- replace_opid(oper); /* OK to scribble on input to this extent */
- funcid = oper->opid;
- }
-
func_tuple = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcid),
0, 0, 0);
if (!HeapTupleIsValid(func_tuple))
elog(ERROR, "Function OID %u does not exist", funcid);
- newexpr = evaluate_op_or_func(expr, args, func_tuple);
+ newexpr = evaluate_function(funcid, args, func_tuple);
if (!newexpr && allow_inline)
- newexpr = inline_op_or_func(expr, args, func_tuple, active_fns);
+ newexpr = inline_function(funcid, args, func_tuple, active_fns);
ReleaseSysCache(func_tuple);
@@ -1640,17 +1653,17 @@ simplify_op_or_func(Expr *expr, List *args, bool allow_inline,
}
/*
- * evaluate_op_or_func: try to pre-evaluate an op or func
+ * evaluate_function: try to pre-evaluate a function call
*
* We can do this if the function is strict and has any constant-null inputs
* (just return a null constant), or if the function is immutable and has all
* constant inputs (call it and return the result as a Const node).
*
* Returns a simplified expression if successful, or NULL if cannot
- * simplify the op/func.
+ * simplify the function.
*/
static Expr *
-evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple)
+evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
{
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
Oid result_typeid = funcform->prorettype;
@@ -1658,7 +1671,7 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple)
bool resultTypByVal;
bool has_nonconst_input = false;
bool has_null_input = false;
- Expr *newexpr;
+ FuncExpr *newexpr;
ExprContext *econtext;
Datum const_val;
bool const_is_null;
@@ -1705,21 +1718,20 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple)
* 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
- * simplify_op_or_func already did for the OP_EXPR/DISTINCT_EXPR case.
+ * Build a new FuncExpr node containing the already-simplified arguments.
*/
- newexpr = makeNode(Expr);
- newexpr->typeOid = expr->typeOid;
- newexpr->opType = expr->opType;
- newexpr->oper = expr->oper;
+ newexpr = makeNode(FuncExpr);
+ newexpr->funcid = funcid;
+ newexpr->funcresulttype = result_typeid;
+ newexpr->funcretset = false;
+ newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
newexpr->args = args;
/* Get info needed about result datatype */
get_typlenbyval(result_typeid, &resultTypLen, &resultTypByVal);
/*
- * It is OK to pass a dummy econtext because none of the
+ * It is OK to use a dummy econtext 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?
@@ -1745,7 +1757,7 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple)
}
/*
- * inline_op_or_func: try to expand inline an op or func
+ * inline_function: try to expand a function call inline
*
* If the function is a sufficiently simple SQL-language function
* (just "SELECT expression"), then we can inline it and avoid the rather
@@ -1763,14 +1775,13 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple)
* functions by inlining them.
*
* Returns a simplified expression if successful, or NULL if cannot
- * simplify the op/func.
+ * simplify the function.
*/
static Expr *
-inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple,
- List *active_fns)
+inline_function(Oid funcid, List *args, HeapTuple func_tuple,
+ List *active_fns)
{
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
- Oid funcid = HeapTupleGetOid(func_tuple);
Oid result_typeid = funcform->prorettype;
char result_typtype;
char *src;
@@ -1816,7 +1827,7 @@ inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple,
* stuff that parsing might create.
*/
mycxt = AllocSetContextCreate(CurrentMemoryContext,
- "inline_op_or_func",
+ "inline_function",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1828,7 +1839,7 @@ inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple,
Anum_pg_proc_prosrc,
&isNull);
if (isNull)
- elog(ERROR, "inline_op_or_func: null prosrc for procedure %u",
+ elog(ERROR, "inline_function: null prosrc for procedure %u",
funcid);
src = DatumGetCString(DirectFunctionCall1(textout, tmp));
@@ -1877,7 +1888,7 @@ inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple,
length(querytree->targetList) != 1)
goto fail;
- newexpr = ((TargetEntry *) lfirst(querytree->targetList))->expr;
+ newexpr = (Node *) ((TargetEntry *) lfirst(querytree->targetList))->expr;
/*
* Additional validity checks on the expression. It mustn't return a
@@ -2065,17 +2076,17 @@ substitute_actual_parameters_mutator(Node *node,
* FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query
* jointrees and setOperation trees can be processed without additional code.
*
- * expression_tree_walker will handle SubLink and SubPlan nodes by recursing
- * normally into the "lefthand" arguments (which belong to the outer plan).
- * It will also call the walker on the sub-Query node; however, when
- * expression_tree_walker itself is called on a Query node, it does nothing
- * and returns "false". The net effect is that unless the walker does
- * something special at a Query node, sub-selects will not be visited
- * during an expression tree walk. This is exactly the behavior wanted
- * in many cases --- and for those walkers that do want to recurse into
- * sub-selects, special behavior is typically needed anyway at the entry
- * to a sub-select (such as incrementing a depth counter). A walker that
- * wants to examine sub-selects should include code along the lines of:
+ * expression_tree_walker will handle SubLink and SubPlanExpr nodes by
+ * recursing normally into the "lefthand" arguments (which are expressions
+ * belonging to the outer plan). It will also call the walker on the
+ * sub-Query node; however, when expression_tree_walker itself is called on a
+ * Query node, it does nothing and returns "false". The net effect is that
+ * unless the walker does something special at a Query node, sub-selects will
+ * not be visited during an expression tree walk. This is exactly the behavior
+ * wanted in many cases --- and for those walkers that do want to recurse into
+ * sub-selects, special behavior is typically needed anyway at the entry to a
+ * sub-select (such as incrementing a depth counter). A walker that wants to
+ * examine sub-selects should include code along the lines of:
*
* if (IsA(node, Query))
* {
@@ -2115,29 +2126,12 @@ expression_tree_walker(Node *node,
return false;
switch (nodeTag(node))
{
- case T_Const:
case T_Var:
+ case T_Const:
case T_Param:
case T_RangeTblRef:
/* primitive node types with no subnodes */
break;
- case T_Expr:
- {
- Expr *expr = (Expr *) node;
-
- if (expr->opType == SUBPLAN_EXPR)
- {
- /* recurse to the SubLink node (skipping SubPlan!) */
- if (walker((Node *) ((SubPlan *) expr->oper)->sublink,
- context))
- return true;
- }
- /* for all Expr node types, examine args list */
- if (expression_tree_walker((Node *) expr->args,
- walker, context))
- return true;
- }
- break;
case T_Aggref:
return walker(((Aggref *) node)->target, context);
case T_ArrayRef:
@@ -2158,41 +2152,41 @@ expression_tree_walker(Node *node,
return true;
}
break;
- case T_FieldSelect:
- return walker(((FieldSelect *) node)->arg, context);
- case T_RelabelType:
- return walker(((RelabelType *) node)->arg, context);
- case T_CaseExpr:
+ case T_FuncExpr:
{
- CaseExpr *caseexpr = (CaseExpr *) node;
+ FuncExpr *expr = (FuncExpr *) node;
- /* we assume walker doesn't care about CaseWhens, either */
- foreach(temp, caseexpr->args)
- {
- CaseWhen *when = (CaseWhen *) lfirst(temp);
+ if (expression_tree_walker((Node *) expr->args,
+ walker, context))
+ return true;
+ }
+ break;
+ case T_OpExpr:
+ {
+ OpExpr *expr = (OpExpr *) node;
- Assert(IsA(when, CaseWhen));
- if (walker(when->expr, context))
- return true;
- if (walker(when->result, context))
- return true;
- }
- /* caseexpr->arg should be null, but we'll check it anyway */
- if (walker(caseexpr->arg, context))
+ if (expression_tree_walker((Node *) expr->args,
+ walker, context))
return true;
- if (walker(caseexpr->defresult, context))
+ }
+ break;
+ case T_DistinctExpr:
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+
+ if (expression_tree_walker((Node *) expr->args,
+ walker, context))
return true;
}
break;
- case T_NullTest:
- return walker(((NullTest *) node)->arg, context);
- case T_BooleanTest:
- return walker(((BooleanTest *) node)->arg, context);
- case T_ConstraintTest:
- if (walker(((ConstraintTest *) node)->arg, context))
- return true;
- return walker(((ConstraintTest *) node)->check_expr, context);
- case T_ConstraintTestValue:
+ case T_BoolExpr:
+ {
+ BoolExpr *expr = (BoolExpr *) node;
+
+ if (expression_tree_walker((Node *) expr->args,
+ walker, context))
+ return true;
+ }
break;
case T_SubLink:
{
@@ -2202,7 +2196,7 @@ expression_tree_walker(Node *node,
* If the SubLink has already been processed by
* subselect.c, it will have lefthand=NIL, and we need to
* scan the oper list. Otherwise we only need to look at
- * the lefthand list (the incomplete Oper nodes in the
+ * the lefthand list (the incomplete OpExpr nodes in the
* oper list are deemed uninteresting, perhaps even
* confusing).
*/
@@ -2224,6 +2218,57 @@ expression_tree_walker(Node *node,
return walker(sublink->subselect, context);
}
break;
+ case T_SubPlanExpr:
+ {
+ SubPlanExpr *expr = (SubPlanExpr *) node;
+
+ /* recurse to the SubLink node, but not into the Plan */
+ if (walker((Node *) expr->sublink, context))
+ return true;
+ /* also examine args list */
+ if (expression_tree_walker((Node *) expr->args,
+ walker, context))
+ return true;
+ }
+ break;
+ case T_FieldSelect:
+ return walker(((FieldSelect *) node)->arg, context);
+ case T_RelabelType:
+ return walker(((RelabelType *) node)->arg, 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;
+ if (walker(when->result, context))
+ return true;
+ }
+ /* caseexpr->arg should be null, but we'll check it anyway */
+ if (walker(caseexpr->arg, context))
+ return true;
+ if (walker(caseexpr->defresult, context))
+ return true;
+ }
+ break;
+ case T_NullTest:
+ return walker(((NullTest *) node)->arg, context);
+ case T_BooleanTest:
+ return walker(((BooleanTest *) node)->arg, context);
+ case T_ConstraintTest:
+ if (walker(((ConstraintTest *) node)->arg, context))
+ return true;
+ return walker(((ConstraintTest *) node)->check_expr, context);
+ case T_ConstraintTestValue:
+ break;
+ case T_TargetEntry:
+ return walker(((TargetEntry *) node)->expr, context);
case T_Query:
/* Do nothing with a sub-Query, per discussion above */
break;
@@ -2234,8 +2279,6 @@ expression_tree_walker(Node *node,
return true;
}
break;
- case T_TargetEntry:
- return walker(((TargetEntry *) node)->expr, context);
case T_FromExpr:
{
FromExpr *from = (FromExpr *) node;
@@ -2387,14 +2430,14 @@ query_tree_walker(Query *query,
* expression_tree_mutator include all those normally found in target lists
* and qualifier clauses during the planning stage.
*
- * expression_tree_mutator will handle a SUBPLAN_EXPR node by recursing into
- * the args and slink->oper lists (which belong to the outer plan), but it
+ * expression_tree_mutator will handle a SubPlanExpr node by recursing into
+ * the args and sublink->oper lists (which belong to the outer plan), but it
* will simply copy the link to the inner plan, since that's typically what
* expression tree mutators want. A mutator that wants to modify the subplan
* can force appropriate behavior by recognizing subplan expression nodes
* and doing the right thing.
*
- * Bare SubLink nodes (without a SUBPLAN_EXPR) are handled by recursing into
+ * Bare SubLink nodes (without a SubPlanExpr) are handled by recursing into
* the "lefthand" argument list only. (A bare SubLink should be seen only if
* the tree has not yet been processed by subselect.c.) Again, this can be
* overridden by the mutator, but it seems to be the most useful default
@@ -2428,61 +2471,19 @@ expression_tree_mutator(Node *node,
return NULL;
switch (nodeTag(node))
{
- case T_Const:
case T_Var:
+ case T_Const:
case T_Param:
case T_RangeTblRef:
/* primitive node types with no subnodes */
return (Node *) copyObject(node);
- case T_Expr:
- {
- Expr *expr = (Expr *) node;
- Expr *newnode;
-
- FLATCOPY(newnode, expr, Expr);
-
- if (expr->opType == SUBPLAN_EXPR)
- {
- 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)
- */
- 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
- */
- }
- else
- {
- /*
- * for other Expr node types, just transform args
- * list, linking to original oper node (OK?)
- */
- MUTATE(newnode->args, expr->args, List *);
- }
- return (Node *) newnode;
- }
- break;
case T_Aggref:
{
Aggref *aggref = (Aggref *) node;
Aggref *newnode;
FLATCOPY(newnode, aggref, Aggref);
- MUTATE(newnode->target, aggref->target, Node *);
+ MUTATE(newnode->target, aggref->target, Expr *);
return (Node *) newnode;
}
break;
@@ -2497,9 +2498,81 @@ expression_tree_mutator(Node *node,
MUTATE(newnode->reflowerindexpr, arrayref->reflowerindexpr,
List *);
MUTATE(newnode->refexpr, arrayref->refexpr,
- Node *);
+ Expr *);
MUTATE(newnode->refassgnexpr, arrayref->refassgnexpr,
- Node *);
+ Expr *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_FuncExpr:
+ {
+ FuncExpr *expr = (FuncExpr *) node;
+ FuncExpr *newnode;
+
+ FLATCOPY(newnode, expr, FuncExpr);
+ MUTATE(newnode->args, expr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_OpExpr:
+ {
+ OpExpr *expr = (OpExpr *) node;
+ OpExpr *newnode;
+
+ FLATCOPY(newnode, expr, OpExpr);
+ MUTATE(newnode->args, expr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_DistinctExpr:
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+ DistinctExpr *newnode;
+
+ FLATCOPY(newnode, expr, DistinctExpr);
+ MUTATE(newnode->args, expr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_BoolExpr:
+ {
+ BoolExpr *expr = (BoolExpr *) node;
+ BoolExpr *newnode;
+
+ FLATCOPY(newnode, expr, BoolExpr);
+ MUTATE(newnode->args, expr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_SubLink:
+ {
+ /*
+ * A "bare" SubLink (note we will not come here if we
+ * found a SubPlanExpr node above it). Transform the
+ * lefthand side, but not the oper list nor the subquery.
+ */
+ SubLink *sublink = (SubLink *) node;
+ SubLink *newnode;
+
+ FLATCOPY(newnode, sublink, SubLink);
+ MUTATE(newnode->lefthand, sublink->lefthand, List *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_SubPlanExpr:
+ {
+ SubPlanExpr *expr = (SubPlanExpr *) node;
+ SubLink *oldsublink = expr->sublink;
+ SubPlanExpr *newnode;
+
+ FLATCOPY(newnode, expr, SubPlanExpr);
+ /* flat-copy the SubLink node */
+ CHECKFLATCOPY(newnode->sublink, oldsublink, SubLink);
+ /* transform args list (params to be passed to subplan) */
+ MUTATE(newnode->args, expr->args, List *);
+ /* transform sublink's oper list as well */
+ MUTATE(newnode->sublink->oper, oldsublink->oper, List *);
+ /* but not the subplan itself, which is referenced as-is */
return (Node *) newnode;
}
break;
@@ -2509,7 +2582,7 @@ expression_tree_mutator(Node *node,
FieldSelect *newnode;
FLATCOPY(newnode, fselect, FieldSelect);
- MUTATE(newnode->arg, fselect->arg, Node *);
+ MUTATE(newnode->arg, fselect->arg, Expr *);
return (Node *) newnode;
}
break;
@@ -2519,7 +2592,7 @@ expression_tree_mutator(Node *node,
RelabelType *newnode;
FLATCOPY(newnode, relabel, RelabelType);
- MUTATE(newnode->arg, relabel->arg, Node *);
+ MUTATE(newnode->arg, relabel->arg, Expr *);
return (Node *) newnode;
}
break;
@@ -2531,8 +2604,8 @@ expression_tree_mutator(Node *node,
FLATCOPY(newnode, caseexpr, CaseExpr);
MUTATE(newnode->args, caseexpr->args, List *);
/* caseexpr->arg should be null, but we'll check it anyway */
- MUTATE(newnode->arg, caseexpr->arg, Node *);
- MUTATE(newnode->defresult, caseexpr->defresult, Node *);
+ MUTATE(newnode->arg, caseexpr->arg, Expr *);
+ MUTATE(newnode->defresult, caseexpr->defresult, Expr *);
return (Node *) newnode;
}
break;
@@ -2542,8 +2615,8 @@ expression_tree_mutator(Node *node,
CaseWhen *newnode;
FLATCOPY(newnode, casewhen, CaseWhen);
- MUTATE(newnode->expr, casewhen->expr, Node *);
- MUTATE(newnode->result, casewhen->result, Node *);
+ MUTATE(newnode->expr, casewhen->expr, Expr *);
+ MUTATE(newnode->result, casewhen->result, Expr *);
return (Node *) newnode;
}
break;
@@ -2553,7 +2626,7 @@ expression_tree_mutator(Node *node,
NullTest *newnode;
FLATCOPY(newnode, ntest, NullTest);
- MUTATE(newnode->arg, ntest->arg, Node *);
+ MUTATE(newnode->arg, ntest->arg, Expr *);
return (Node *) newnode;
}
break;
@@ -2563,7 +2636,7 @@ expression_tree_mutator(Node *node,
BooleanTest *newnode;
FLATCOPY(newnode, btest, BooleanTest);
- MUTATE(newnode->arg, btest->arg, Node *);
+ MUTATE(newnode->arg, btest->arg, Expr *);
return (Node *) newnode;
}
break;
@@ -2573,8 +2646,8 @@ expression_tree_mutator(Node *node,
ConstraintTest *newnode;
FLATCOPY(newnode, ctest, ConstraintTest);
- MUTATE(newnode->arg, ctest->arg, Node *);
- MUTATE(newnode->check_expr, ctest->check_expr, Node *);
+ MUTATE(newnode->arg, ctest->arg, Expr *);
+ MUTATE(newnode->check_expr, ctest->check_expr, Expr *);
return (Node *) newnode;
}
break;
@@ -2587,18 +2660,17 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
- case T_SubLink:
+ case T_TargetEntry:
{
/*
- * 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.
+ * We mutate the expression, but not the resdom, by
+ * default.
*/
- SubLink *sublink = (SubLink *) node;
- SubLink *newnode;
+ TargetEntry *targetentry = (TargetEntry *) node;
+ TargetEntry *newnode;
- FLATCOPY(newnode, sublink, SubLink);
- MUTATE(newnode->lefthand, sublink->lefthand, List *);
+ FLATCOPY(newnode, targetentry, TargetEntry);
+ MUTATE(newnode->expr, targetentry->expr, Expr *);
return (Node *) newnode;
}
break;
@@ -2622,20 +2694,6 @@ expression_tree_mutator(Node *node,
return (Node *) resultlist;
}
break;
- case T_TargetEntry:
- {
- /*
- * 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 *);
- return (Node *) newnode;
- }
- break;
case T_FromExpr:
{
FromExpr *from = (FromExpr *) node;
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index fa8c89862f4..0d268b8e40c 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.52 2002/06/20 20:29:31 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.53 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -110,7 +110,7 @@ create_tl_element(Var *var, int resdomno)
var->vartypmod,
NULL,
false),
- (Node *) var);
+ (Expr *) var);
}
/*****************************************************************************
@@ -253,5 +253,5 @@ get_sortgroupclause_expr(SortClause *sortClause, List *targetList)
{
TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList);
- return tle->expr;
+ return (Node *) tle->expr;
}
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 23b824dbcb0..8d22aa26b91 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.40 2002/09/11 14:48:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.41 2002/12/12 15:49:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -65,7 +65,7 @@ static Node *flatten_join_alias_vars_mutator(Node *node,
* NOTE: this is used on not-yet-planned expressions. It may therefore find
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
* references to the desired rtable level! But when we find a completed
- * SubPlan, we only need to look at the parameters passed to the subplan.
+ * SubPlanExpr, we only need to look at the parameters passed to the subplan.
*/
List *
pull_varnos(Node *node)
@@ -111,12 +111,12 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
* executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort.
*/
- Expr *expr = (Expr *) node;
+ SubPlanExpr *subplan = (SubPlanExpr *) node;
- if (pull_varnos_walker((Node *) ((SubPlan *) expr->oper)->sublink->oper,
+ if (pull_varnos_walker((Node *) subplan->sublink->oper,
context))
return true;
- if (pull_varnos_walker((Node *) expr->args,
+ if (pull_varnos_walker((Node *) subplan->args,
context))
return true;
return false;
@@ -146,7 +146,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
* NOTE: this is used on not-yet-planned expressions. It may therefore find
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
* references to the desired rtable entry! But when we find a completed
- * SubPlan, we only need to look at the parameters passed to the subplan.
+ * SubPlanExpr, we only need to look at the parameters passed to the subplan.
*/
bool
contain_var_reference(Node *node, int varno, int varattno, int levelsup)
@@ -194,12 +194,12 @@ contain_var_reference_walker(Node *node,
* executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort.
*/
- Expr *expr = (Expr *) node;
+ SubPlanExpr *subplan = (SubPlanExpr *) node;
- if (contain_var_reference_walker((Node *) ((SubPlan *) expr->oper)->sublink->oper,
+ if (contain_var_reference_walker((Node *) subplan->sublink->oper,
context))
return true;
- if (contain_var_reference_walker((Node *) expr->args,
+ if (contain_var_reference_walker((Node *) subplan->args,
context))
return true;
return false;