aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c168
1 files changed, 166 insertions, 2 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index cb31c025df2..e7c724c66ed 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.112 2002/12/01 20:27:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.113 2002/12/05 15:50:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1766,7 +1766,8 @@ ExecEvalExpr(Node *expression,
isNull, isDone);
break;
case SUBPLAN_EXPR:
- retDatum = ExecSubPlan((SubPlan *) expr->oper,
+ /* XXX temporary hack to find exec state node */
+ retDatum = ExecSubPlan(((SubPlan *) expr->oper)->pstate,
expr->args, econtext,
isNull);
break;
@@ -1850,6 +1851,169 @@ ExecEvalExprSwitchContext(Node *expression,
}
+/*
+ * ExecInitExpr: prepare an expression tree for execution
+ *
+ * 'node' is the root of the expression tree to examine
+ * 'parent' is the PlanState node that owns the expression,
+ * or NULL if we are preparing an expression that is not associated
+ * with a plan. (If so, it can't have Aggrefs or SubPlans.)
+ *
+ * Soon this will generate an expression state tree paralleling the given
+ * expression tree. Right now, it just searches the expression tree for
+ * Aggref and SubPlan nodes.
+ */
+Node *
+ExecInitExpr(Node *node, PlanState *parent)
+{
+ List *temp;
+
+ if (node == NULL)
+ return NULL;
+ switch (nodeTag(node))
+ {
+ case T_Var:
+ break;
+ case T_Const:
+ break;
+ case T_Param:
+ break;
+ case T_Aggref:
+ if (parent && IsA(parent, AggState))
+ {
+ AggState *aggstate = (AggState *) parent;
+ int naggs;
+
+ aggstate->aggs = lcons(node, aggstate->aggs);
+ naggs = ++aggstate->numaggs;
+
+ ExecInitExpr(((Aggref *) node)->target, parent);
+
+ /*
+ * Complain if the aggregate's argument contains any
+ * aggregates; nested agg functions are semantically
+ * nonsensical. (This probably was caught earlier,
+ * but we defend against it here anyway.)
+ */
+ if (naggs != aggstate->numaggs)
+ elog(ERROR, "Aggregate function calls may not be nested");
+ }
+ else
+ elog(ERROR, "ExecInitExpr: Aggref not expected here");
+ break;
+ case T_ArrayRef:
+ {
+ ArrayRef *aref = (ArrayRef *) node;
+
+ ExecInitExpr((Node *) aref->refupperindexpr, parent);
+ ExecInitExpr((Node *) aref->reflowerindexpr, parent);
+ ExecInitExpr(aref->refexpr, parent);
+ ExecInitExpr(aref->refassgnexpr, parent);
+ }
+ break;
+ case T_Expr:
+ {
+ Expr *expr = (Expr *) node;
+
+ switch (expr->opType)
+ {
+ case OP_EXPR:
+ break;
+ case FUNC_EXPR:
+ break;
+ case OR_EXPR:
+ break;
+ case AND_EXPR:
+ break;
+ case NOT_EXPR:
+ break;
+ case DISTINCT_EXPR:
+ break;
+ case SUBPLAN_EXPR:
+ if (parent)
+ {
+ SubLink *sublink = ((SubPlan *) expr->oper)->sublink;
+
+ /*
+ * Here we just add the SubPlan nodes to
+ * parent->subPlan. Later they will be expanded
+ * to SubPlanState nodes.
+ */
+ parent->subPlan = lcons(expr->oper,
+ parent->subPlan);
+
+ /* Must recurse into oper list too */
+ Assert(IsA(sublink, SubLink));
+ if (sublink->lefthand)
+ elog(ERROR, "ExecInitExpr: sublink has not been transformed");
+ ExecInitExpr((Node *) sublink->oper, parent);
+ }
+ else
+ elog(ERROR, "ExecInitExpr: SubPlan not expected here");
+ break;
+ default:
+ elog(ERROR, "ExecInitExpr: unknown expression type %d",
+ expr->opType);
+ break;
+ }
+ /* for all Expr node types, examine args list */
+ ExecInitExpr((Node *) expr->args, parent);
+ }
+ break;
+ case T_FieldSelect:
+ ExecInitExpr(((FieldSelect *) node)->arg, parent);
+ break;
+ case T_RelabelType:
+ ExecInitExpr(((RelabelType *) node)->arg, parent);
+ break;
+ case T_CaseExpr:
+ {
+ CaseExpr *caseexpr = (CaseExpr *) node;
+
+ foreach(temp, caseexpr->args)
+ {
+ CaseWhen *when = (CaseWhen *) lfirst(temp);
+
+ Assert(IsA(when, CaseWhen));
+ ExecInitExpr(when->expr, parent);
+ ExecInitExpr(when->result, parent);
+ }
+ /* caseexpr->arg should be null, but we'll check it anyway */
+ ExecInitExpr(caseexpr->arg, parent);
+ ExecInitExpr(caseexpr->defresult, parent);
+ }
+ break;
+ case T_NullTest:
+ ExecInitExpr(((NullTest *) node)->arg, parent);
+ break;
+ case T_BooleanTest:
+ ExecInitExpr(((BooleanTest *) node)->arg, parent);
+ break;
+ case T_ConstraintTest:
+ ExecInitExpr(((ConstraintTest *) node)->arg, parent);
+ ExecInitExpr(((ConstraintTest *) node)->check_expr, parent);
+ break;
+ case T_ConstraintTestValue:
+ break;
+ case T_List:
+ foreach(temp, (List *) node)
+ {
+ ExecInitExpr((Node *) lfirst(temp), parent);
+ }
+ break;
+ case T_TargetEntry:
+ ExecInitExpr(((TargetEntry *) node)->expr, parent);
+ break;
+ default:
+ elog(ERROR, "ExecInitExpr: unknown expression type %d",
+ nodeTag(node));
+ break;
+ }
+
+ return node;
+}
+
+
/* ----------------------------------------------------------------
* ExecQual / ExecTargetList / ExecProject
* ----------------------------------------------------------------