* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.17 2002/12/06 05:00:10 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.18 2002/12/12 15:49:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
return false;
}
- if (IsA(node, Expr))
+ if (IsA(node, FuncExpr))
{
- Expr *expr = (Expr *) node;
+ FuncExpr *funcexpr = (FuncExpr *) node;
- if (expr->opType == OP_EXPR ||
- expr->opType == DISTINCT_EXPR)
- {
- Oper *oper = (Oper *) expr->oper;
+ add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
+ &context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *opexpr = (OpExpr *) node;
- add_object_address(OCLASS_OPERATOR, oper->opno, 0,
- &context->addrs);
- }
- else if (expr->opType == FUNC_EXPR)
- {
- Func *func = (Func *) expr->oper;
+ add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
+ &context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *distinctexpr = (DistinctExpr *) node;
- add_object_address(OCLASS_PROC, func->funcid, 0,
- &context->addrs);
- }
+ add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
+ &context->addrs);
/* fall through to examine arguments */
}
if (IsA(node, Aggref))
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.235 2002/11/15 02:50:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.236 2002/12/12 15:49:23 tgl Exp $
*
*
* INTERFACE ROUTINES
*/
expr = (Node *) make_ands_implicit((Expr *) expr);
- /*
- * Must fix opids in operator clauses.
- */
- fix_opids(expr);
-
/*
* OK, store it.
*/
*/
expr = eval_const_expressions(expr);
- /*
- * Must fix opids, in case any operators remain...
- */
- fix_opids(expr);
-
return (expr);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.205 2002/11/13 00:39:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.206 2002/12/12 15:49:24 tgl Exp $
*
*
* INTERFACE ROUTINES
#include "executor/executor.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
+#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "parser/parse_func.h"
#include "storage/sinval.h"
predString = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(&indexStruct->indpred)));
ii->ii_Predicate = stringToNode(predString);
+ fix_opfuncids((Node *) ii->ii_Predicate);
pfree(predString);
}
else
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.94 2002/09/18 21:35:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.95 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
} while (attr->attisdropped);
rellogcols++;
- tletype = exprType(tle->expr);
+ tletype = exprType((Node *) tle->expr);
atttype = attr->atttypid;
if (!IsBinaryCoercible(tletype, atttype))
elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.184 2002/12/01 18:14:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.185 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
+#include "optimizer/planmain.h"
#include "parser/parse_coerce.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteHandler.h"
defexprs[num_defaults] = build_column_default(rel, i + 1);
if (defexprs[num_defaults] != NULL)
{
+ fix_opfuncids(defexprs[num_defaults]);
defmap[num_defaults] = i;
num_defaults++;
}
/* check whether any constraints actually found */
if (node != (Node *) prm)
{
+ fix_opfuncids(node);
constraintexprs[i] = node;
hasConstraints = true;
}
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.95 2002/12/06 19:28:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.96 2002/12/12 15:49:24 tgl Exp $
*
*/
{
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
es->rtable);
- Expr *expr;
- Func *funcnode;
- Oid funcid;
char *proname;
/* Assert it's on a RangeFunction */
Assert(rte->rtekind == RTE_FUNCTION);
- expr = (Expr *) rte->funcexpr;
- funcnode = (Func *) expr->oper;
- funcid = funcnode->funcid;
-
- /* We only show the func name, not schema name */
- proname = get_func_name(funcid);
+ /*
+ * If the expression is still a function call, we can get
+ * the real name of the function. Otherwise, punt (this
+ * can happen if the optimizer simplified away the function
+ * call, for example).
+ */
+ if (rte->funcexpr && IsA(rte->funcexpr, FuncExpr))
+ {
+ FuncExpr *funcexpr = (FuncExpr *) rte->funcexpr;
+ Oid funcid = funcexpr->funcid;
+
+ /* We only show the func name, not schema name */
+ proname = get_func_name(funcid);
+ }
+ else
+ proname = rte->eref->aliasname;
appendStringInfo(str, " on %s",
quote_identifier(proname));
appendStringInfo(str, " InitPlan\n");
foreach(lst, plan->initPlan)
{
- SubPlan *subplan = (SubPlan *) lfirst(lst);
+ SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist);
es->rtable = subplan->rtable;
foreach(lst, planstate->subPlan)
{
SubPlanState *sps = (SubPlanState *) lfirst(lst);
- SubPlan *sp = (SubPlan *) sps->ps.plan;
+ SubPlanExpr *sp = (SubPlanExpr *) sps->ps.plan;
es->rtable = sp->rtable;
for (i = 0; i < indent; i++)
if (target->resdom->reskey == keyno)
{
/* Deparse the expression, showing any top-level cast */
- exprstr = deparse_expression(target->expr, context,
+ exprstr = deparse_expression((Node *) target->expr, context,
useprefix, true);
/* And add to str */
if (keyno > 1)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.92 2002/10/21 22:06:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.93 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* While we are at it, we reduce it to a canonical (CNF or DNF) form
* to simplify the task of proving implications.
*/
- if (predicate != NULL && rangetable != NIL)
+ if (predicate)
{
cnfPred = canonicalize_qual((Expr *) copyObject(predicate), true);
- fix_opids((Node *) cnfPred);
+ fix_opfuncids((Node *) cnfPred);
CheckPredicate(cnfPred, rangetable, relationId);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.57 2002/11/23 18:26:45 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.58 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* We need to make a parse state and range
* table to allow us to transformExpr and
- * fix_opids to get a version of the
+ * fix_opfuncids to get a version of the
* expression we can pass to ExecQual
*/
pstate = make_parsestate(NULL);
*/
expr = eval_const_expressions(expr);
- /* And fix the opids */
- fix_opids(expr);
+ /* And fix the opfuncids */
+ fix_opfuncids(expr);
qual = makeList1(expr);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.21 2002/12/09 20:31:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.22 2002/12/12 15:49:24 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
* the constraint is being added to.
*/
expr = stringToNode(ccbin);
+ fix_opfuncids(expr);
rels = get_rels_with_domain(domainoid);
+
foreach (rt, rels)
{
Relation typrel;
/*
- *
+ * domainAddConstraint
*/
char *
domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
expr = eval_const_expressions(expr);
/*
- * Must fix opids in operator clauses.
+ * Convert to string form for storage.
*/
- fix_opids(expr);
-
ccbin = nodeToString(expr);
/*
- * Deparse it. Since VARNOs aren't allowed in domain
- * constraints, relation context isn't required as anything
- * other than a shell.
+ * Deparse it to produce text for consrc.
+ *
+ * Since VARNOs aren't allowed in domain constraints, relation context
+ * isn't required as anything other than a shell.
*/
ccsrc = deparse_expression(expr,
- deparse_context_for(domainName,
- InvalidOid),
- false, false);
+ deparse_context_for(domainName,
+ InvalidOid),
+ false, false);
/* Write the constraint */
CreateConstraintEntry(constr->name, /* Constraint Name */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.32 2002/09/04 20:31:17 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.33 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
bool resjunk;
AttrNumber cleanResno;
AttrNumber *cleanMap;
- Node *expr;
+ Expr *expr;
/*
* Make a memory context that will hold the JunkFilter as well as all
{
TargetEntry *rtarget = lfirst(t);
- if (rtarget->resdom != NULL)
- {
- resdom = rtarget->resdom;
- expr = rtarget->expr;
- resjunk = resdom->resjunk;
- if (!resjunk)
- {
- /*
- * make a copy of the resdom node, changing its resno.
- */
- cleanResdom = (Resdom *) copyObject(resdom);
- cleanResdom->resno = cleanResno;
- cleanResno++;
-
- /*
- * create a new target list entry
- */
- tle = makeTargetEntry(cleanResdom, expr);
- cleanTargetList = lappend(cleanTargetList, tle);
- }
- }
- else
+ resdom = rtarget->resdom;
+ expr = rtarget->expr;
+ resjunk = resdom->resjunk;
+ if (!resjunk)
{
-#ifdef SETS_FIXED
- List *fjListP;
- Fjoin *cleanFjoin;
- List *cleanFjList;
- List *fjList = lfirst(t);
- Fjoin *fjNode = (Fjoin *) tl_node(fjList);
-
- cleanFjoin = (Fjoin) copyObject((Node) fjNode);
- cleanFjList = makeList1(cleanFjoin);
-
- resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
- expr = lsecond(get_fj_innerNode(fjNode));
- cleanResdom = (Resdom) copyObject((Node) resdom);
- set_resno(cleanResdom, cleanResno);
+ /*
+ * make a copy of the resdom node, changing its resno.
+ */
+ cleanResdom = (Resdom *) copyObject(resdom);
+ cleanResdom->resno = cleanResno;
cleanResno++;
- tle = (List) makeTargetEntry(cleanResdom, (Node *) expr);
- set_fj_innerNode(cleanFjoin, tle);
-
- foreach(fjListP, lnext(fjList))
- {
- TargetEntry *tle = lfirst(fjListP);
- resdom = tle->resdom;
- expr = tle->expr;
- cleanResdom = (Resdom *) copyObject((Node) resdom);
- cleanResno++;
- cleanResdom->Resno = cleanResno;
-
- /*
- * create a new target list entry
- */
- tle = (List) makeTargetEntry(cleanResdom, (Node *) expr);
- cleanFjList = lappend(cleanFjList, tle);
- }
- lappend(cleanTargetList, cleanFjList);
-#endif
+ /*
+ * create a new target list entry
+ */
+ tle = makeTargetEntry(cleanResdom, expr);
+ cleanTargetList = lappend(cleanTargetList, tle);
}
}
{
TargetEntry *tle = lfirst(t);
- if (tle->resdom != NULL)
- {
- resdom = tle->resdom;
- expr = tle->expr;
- resjunk = resdom->resjunk;
- if (!resjunk)
- {
- cleanMap[cleanResno - 1] = resdom->resno;
- cleanResno++;
- }
- }
- else
+ resdom = tle->resdom;
+ resjunk = resdom->resjunk;
+ if (!resjunk)
{
-#ifdef SETS_FIXED
- List fjListP;
- List fjList = lfirst(t);
- Fjoin fjNode = (Fjoin) lfirst(fjList);
-
- /* what the hell is this????? */
- resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
-#endif
-
- cleanMap[cleanResno - 1] = tle->resdom->resno;
+ cleanMap[cleanResno - 1] = resdom->resno;
cleanResno++;
-
-#ifdef SETS_FIXED
- foreach(fjListP, lnext(fjList))
- {
- TargetEntry *tle = lfirst(fjListP);
-
- resdom = tle->resdom;
- cleanMap[cleanResno - 1] = resdom->resno;
- cleanResno++;
- }
-#endif
}
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.190 2002/12/05 15:50:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.191 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "executor/execdebug.h"
#include "executor/execdefs.h"
#include "miscadmin.h"
+#include "optimizer/planmain.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
#include "utils/acl.h"
for (i = 0; i < ncheck; i++)
{
qual = (List *) stringToNode(check[i].ccbin);
+ fix_opfuncids((Node *) qual);
resultRelInfo->ri_ConstraintExprs[i] = qual;
}
MemoryContextSwitchTo(oldContext);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.31 2002/12/05 15:50:31 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.32 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
subps = NIL;
foreach(subp, node->initPlan)
{
- SubPlan *subplan = (SubPlan *) lfirst(subp);
+ SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
- Assert(IsA(subplan, SubPlan));
+ Assert(IsA(subplan, SubPlanExpr));
subps = lappend(subps, ExecInitSubPlan(subplan, estate));
}
result->initPlan = subps;
subps = NIL;
foreach(subp, result->subPlan)
{
- SubPlan *subplan = (SubPlan *) lfirst(subp);
+ SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
- Assert(IsA(subplan, SubPlan));
+ Assert(IsA(subplan, SubPlanExpr));
subps = lappend(subps, ExecInitSubPlan(subplan, estate));
}
result->subPlan = subps;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.116 2002/12/06 05:00:16 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.117 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
-static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
+static Datum ExecEvalOper(OpExpr *op, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalDistinct(Expr *opClause, ExprContext *econtext,
+static Datum ExecEvalDistinct(DistinctExpr *op, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
+static Datum ExecEvalFunc(FuncExpr *func, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
List *argList, ExprContext *econtext);
-static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
-static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
-static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
+static Datum ExecEvalNot(BoolExpr *notclause, ExprContext *econtext,
+ bool *isNull);
+static Datum ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext,
+ bool *isNull);
+static Datum ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext,
+ bool *isNull);
static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
if (arrayRef->refexpr != NULL)
{
array_source = (ArrayType *)
- DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
+ DatumGetPointer(ExecEvalExpr((Node *) arrayRef->refexpr,
econtext,
isNull,
isDone));
if (isAssignment)
{
- Datum sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
+ Datum sourceData = ExecEvalExpr((Node *) arrayRef->refassgnexpr,
econtext,
isNull,
NULL);
bool returnsTuple = false;
/*
- * Normally the passed expression tree will be a FUNC_EXPR, since the
+ * Normally the passed expression tree will be a FuncExpr, since the
* grammar only allows a function call at the top level of a table
* function reference. However, if the function doesn't return set then
* the planner might have replaced the function call via constant-folding
* we don't get a chance to pass a special ReturnSetInfo to any functions
* buried in the expression.
*/
- if (funcexpr &&
- IsA(funcexpr, Expr) &&
- ((Expr *) funcexpr)->opType == FUNC_EXPR)
+ if (funcexpr && IsA(funcexpr, FuncExpr))
{
- Func *func;
+ FuncExpr *func = (FuncExpr *) funcexpr;
List *argList;
FunctionCachePtr fcache;
ExprDoneCond argDone;
*/
direct_function_call = true;
- funcrettype = ((Expr *) funcexpr)->typeOid;
- func = (Func *) ((Expr *) funcexpr)->oper;
- argList = ((Expr *) funcexpr)->args;
+ funcrettype = func->funcresulttype;
+ argList = func->args;
/*
- * get the fcache from the Func node. If it is NULL, then initialize
- * it
+ * get the fcache from the FuncExpr node. If it is NULL, then
+ * initialize it
*/
fcache = func->func_fcache;
if (fcache == NULL)
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalOper(Expr *opClause,
+ExecEvalOper(OpExpr *op,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
- Oper *op;
List *argList;
FunctionCachePtr fcache;
* arguments and returns the result of calling the function on the
* evaluated arguments.
*/
- op = (Oper *) opClause->oper;
- argList = opClause->args;
+ argList = op->args;
/*
- * get the fcache from the Oper node. If it is NULL, then initialize
+ * get the fcache from the OpExpr node. If it is NULL, then initialize
* it
*/
fcache = op->op_fcache;
if (fcache == NULL)
{
- fcache = init_fcache(op->opid, length(argList),
+ fcache = init_fcache(op->opfuncid, length(argList),
econtext->ecxt_per_query_memory);
op->op_fcache = fcache;
}
*/
static Datum
-ExecEvalFunc(Expr *funcClause,
+ExecEvalFunc(FuncExpr *func,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
- Func *func;
List *argList;
FunctionCachePtr fcache;
*
* this is nearly identical to the ExecEvalOper code.
*/
- func = (Func *) funcClause->oper;
- argList = funcClause->args;
+ argList = func->args;
/*
- * get the fcache from the Func node. If it is NULL, then initialize
+ * get the fcache from the FuncExpr node. If it is NULL, then initialize
* it
*/
fcache = func->func_fcache;
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalDistinct(Expr *opClause,
+ExecEvalDistinct(DistinctExpr *op,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
FunctionCachePtr fcache;
FunctionCallInfoData fcinfo;
ExprDoneCond argDone;
- Oper *op;
List *argList;
/*
- * extract info from opClause
+ * extract info from op
*/
- op = (Oper *) opClause->oper;
- argList = opClause->args;
+ argList = op->args;
/*
- * get the fcache from the Oper node. If it is NULL, then initialize
- * it
+ * get the fcache from the DistinctExpr node. If it is NULL, then
+ * initialize it
*/
fcache = op->op_fcache;
if (fcache == NULL)
{
- fcache = init_fcache(op->opid, length(argList),
+ fcache = init_fcache(op->opfuncid, length(argList),
econtext->ecxt_per_query_memory);
op->op_fcache = fcache;
}
* ExecEvalOr
* ExecEvalAnd
*
- * Evaluate boolean expressions. Evaluation of 'or' is
- * short-circuited when the first true (or null) value is found.
+ * Evaluate boolean expressions, with appropriate short-circuiting.
*
* The query planner reformulates clause expressions in the
* qualification to conjunctive normal form. If we ever get
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
+ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull)
{
Node *clause;
Datum expr_value;
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
+ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull)
{
List *clauses;
List *clause;
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
+ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull)
{
List *clauses;
List *clause;
{
CaseWhen *wclause = lfirst(clause);
- clause_value = ExecEvalExpr(wclause->expr,
+ clause_value = ExecEvalExpr((Node *) wclause->expr,
econtext,
isNull,
NULL);
*/
if (DatumGetBool(clause_value) && !*isNull)
{
- return ExecEvalExpr(wclause->result,
+ return ExecEvalExpr((Node *) wclause->result,
econtext,
isNull,
isDone);
if (caseExpr->defresult)
{
- return ExecEvalExpr(caseExpr->defresult,
+ return ExecEvalExpr((Node *) caseExpr->defresult,
econtext,
isNull,
isDone);
{
Datum result;
- result = ExecEvalExpr(ntest->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr((Node *) ntest->arg, econtext, isNull, isDone);
switch (ntest->nulltesttype)
{
case IS_NULL:
{
Datum result;
- result = ExecEvalExpr(btest->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr((Node *) btest->arg, econtext, isNull, isDone);
switch (btest->booltesttype)
{
case IS_TRUE:
{
Datum result;
- result = ExecEvalExpr(constraint->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr((Node *) constraint->arg, econtext, isNull, isDone);
switch (constraint->testtype)
{
econtext->domainValue_datum = result;
econtext->domainValue_isNull = *isNull;
- conResult = ExecEvalExpr(constraint->check_expr, econtext, isNull, isDone);
+ conResult = ExecEvalExpr((Node *) constraint->check_expr, econtext, isNull, isDone);
if (!DatumGetBool(conResult))
elog(ERROR, "ExecEvalConstraintTest: Domain %s constraint %s failed",
Datum result;
TupleTableSlot *resSlot;
- result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr((Node *) fselect->arg, econtext, isNull, isDone);
if (*isNull)
return result;
resSlot = (TupleTableSlot *) DatumGetPointer(result);
isNull,
isDone);
break;
- case T_Expr:
+ case T_FuncExpr:
+ retDatum = ExecEvalFunc((FuncExpr *) expression, econtext,
+ isNull, isDone);
+ break;
+ case T_OpExpr:
+ retDatum = ExecEvalOper((OpExpr *) expression, econtext,
+ isNull, isDone);
+ break;
+ case T_DistinctExpr:
+ retDatum = ExecEvalDistinct((DistinctExpr *) expression, econtext,
+ isNull, isDone);
+ break;
+ case T_BoolExpr:
{
- Expr *expr = (Expr *) expression;
+ BoolExpr *expr = (BoolExpr *) expression;
- switch (expr->opType)
+ switch (expr->boolop)
{
- case OP_EXPR:
- retDatum = ExecEvalOper(expr, econtext,
- isNull, isDone);
- break;
- case FUNC_EXPR:
- retDatum = ExecEvalFunc(expr, econtext,
- isNull, isDone);
+ case AND_EXPR:
+ retDatum = ExecEvalAnd(expr, econtext, isNull);
break;
case OR_EXPR:
retDatum = ExecEvalOr(expr, econtext, isNull);
break;
- case AND_EXPR:
- retDatum = ExecEvalAnd(expr, econtext, isNull);
- break;
case NOT_EXPR:
retDatum = ExecEvalNot(expr, econtext, isNull);
break;
- case DISTINCT_EXPR:
- retDatum = ExecEvalDistinct(expr, econtext,
- isNull, isDone);
- break;
- case SUBPLAN_EXPR:
- /* XXX temporary hack to find exec state node */
- retDatum = ExecSubPlan(((SubPlan *) expr->oper)->pstate,
- expr->args, econtext,
- isNull);
- break;
default:
- elog(ERROR, "ExecEvalExpr: unknown expression type %d",
- expr->opType);
+ elog(ERROR, "ExecEvalExpr: unknown boolop %d",
+ expr->boolop);
retDatum = 0; /* keep compiler quiet */
break;
}
break;
}
+ case T_SubPlanExpr:
+ /* XXX temporary hack to find exec state node */
+ retDatum = ExecSubPlan(((SubPlanExpr *) expression)->pstate,
+ ((SubPlanExpr *) expression)->args,
+ econtext,
+ isNull);
+ break;
case T_FieldSelect:
retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
econtext,
isDone);
break;
case T_RelabelType:
- retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
+ retDatum = ExecEvalExpr((Node *) ((RelabelType *) expression)->arg,
econtext,
isNull,
isDone);
*
* 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.
+ * Aggref and SubPlanExpr nodes.
*/
Node *
ExecInitExpr(Node *node, PlanState *parent)
aggstate->aggs = lcons(node, aggstate->aggs);
naggs = ++aggstate->numaggs;
- ExecInitExpr(((Aggref *) node)->target, parent);
+ ExecInitExpr((Node *) ((Aggref *) node)->target, parent);
/*
* Complain if the aggregate's argument contains any
ExecInitExpr((Node *) aref->refupperindexpr, parent);
ExecInitExpr((Node *) aref->reflowerindexpr, parent);
- ExecInitExpr(aref->refexpr, parent);
- ExecInitExpr(aref->refassgnexpr, parent);
+ ExecInitExpr((Node *) aref->refexpr, parent);
+ ExecInitExpr((Node *) aref->refassgnexpr, parent);
}
break;
- case T_Expr:
+ case T_FuncExpr:
{
- Expr *expr = (Expr *) node;
+ FuncExpr *funcexpr = (FuncExpr *) 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;
+ ExecInitExpr((Node *) funcexpr->args, parent);
+ }
+ break;
+ case T_OpExpr:
+ {
+ OpExpr *opexpr = (OpExpr *) node;
- /*
- * 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);
+ ExecInitExpr((Node *) opexpr->args, parent);
+ }
+ break;
+ case T_DistinctExpr:
+ {
+ DistinctExpr *distinctexpr = (DistinctExpr *) node;
+
+ ExecInitExpr((Node *) distinctexpr->args, parent);
+ }
+ break;
+ case T_BoolExpr:
+ {
+ BoolExpr *boolexpr = (BoolExpr *) node;
+
+ ExecInitExpr((Node *) boolexpr->args, parent);
+ }
+ break;
+ case T_SubPlanExpr:
+ {
+ SubPlanExpr *subplanexpr = (SubPlanExpr *) node;
+ SubLink *sublink = subplanexpr->sublink;
+
+ Assert(IsA(sublink, SubLink));
+ if (!parent)
+ elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
+
+ /*
+ * Here we just add the SubPlanExpr nodes to
+ * parent->subPlan. Later they will be expanded
+ * to SubPlanState nodes.
+ */
+ parent->subPlan = lcons(subplanexpr, parent->subPlan);
+
+ /* Must recurse into oper list too */
+ if (sublink->lefthand)
+ elog(ERROR, "ExecInitExpr: sublink has not been transformed");
+ ExecInitExpr((Node *) sublink->oper, parent);
+
+ ExecInitExpr((Node *) subplanexpr->args, parent);
}
break;
case T_FieldSelect:
- ExecInitExpr(((FieldSelect *) node)->arg, parent);
+ ExecInitExpr((Node *) ((FieldSelect *) node)->arg, parent);
break;
case T_RelabelType:
- ExecInitExpr(((RelabelType *) node)->arg, parent);
+ ExecInitExpr((Node *) ((RelabelType *) node)->arg, parent);
break;
case T_CaseExpr:
{
CaseWhen *when = (CaseWhen *) lfirst(temp);
Assert(IsA(when, CaseWhen));
- ExecInitExpr(when->expr, parent);
- ExecInitExpr(when->result, parent);
+ ExecInitExpr((Node *) when->expr, parent);
+ ExecInitExpr((Node *) when->result, parent);
}
/* caseexpr->arg should be null, but we'll check it anyway */
- ExecInitExpr(caseexpr->arg, parent);
- ExecInitExpr(caseexpr->defresult, parent);
+ ExecInitExpr((Node *) caseexpr->arg, parent);
+ ExecInitExpr((Node *) caseexpr->defresult, parent);
}
break;
case T_NullTest:
- ExecInitExpr(((NullTest *) node)->arg, parent);
+ ExecInitExpr((Node *) ((NullTest *) node)->arg, parent);
break;
case T_BooleanTest:
- ExecInitExpr(((BooleanTest *) node)->arg, parent);
+ ExecInitExpr((Node *) ((BooleanTest *) node)->arg, parent);
break;
case T_ConstraintTest:
- ExecInitExpr(((ConstraintTest *) node)->arg, parent);
- ExecInitExpr(((ConstraintTest *) node)->check_expr, parent);
+ ExecInitExpr((Node *) ((ConstraintTest *) node)->arg, parent);
+ ExecInitExpr((Node *) ((ConstraintTest *) node)->check_expr, parent);
break;
case T_ConstraintTestValue:
break;
+ case T_TargetEntry:
+ ExecInitExpr((Node *) ((TargetEntry *) node)->expr, parent);
+ 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));
int
ExecTargetListLength(List *targetlist)
{
- int len = 0;
- List *tl;
-
- foreach(tl, targetlist)
- {
- TargetEntry *curTle = (TargetEntry *) lfirst(tl);
-
- if (curTle->resdom != NULL)
- len++;
- else
- len += curTle->fjoin->fj_nNodes;
- }
- return len;
+ /* This used to be more complex, but fjoins are dead */
+ return length(targetlist);
}
/*
{
TargetEntry *curTle = (TargetEntry *) lfirst(tl);
- if (curTle->resdom != NULL)
- {
- if (!curTle->resdom->resjunk)
- len++;
- }
- else
- len += curTle->fjoin->fj_nNodes;
+ if (!curTle->resdom->resjunk)
+ len++;
}
return len;
}
#define NPREALLOCDOMAINS 64
char nullsArray[NPREALLOCDOMAINS];
- bool fjIsNullArray[NPREALLOCDOMAINS];
ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS];
char *nulls;
- bool *fjIsNull;
ExprDoneCond *itemIsDone;
List *tl;
TargetEntry *tle;
* allocate an array of char's to hold the "null" information only if
* we have a really large targetlist. otherwise we use the stack.
*
- * We also allocate a bool array that is used to hold fjoin result state,
- * and another array that holds the isDone status for each targetlist
- * item. The isDone status is needed so that we can iterate,
+ * We also allocate another array that holds the isDone status for each
+ * targetlist item. The isDone status is needed so that we can iterate,
* generating multiple tuples, when one or more tlist items return
- * sets. (We expect the caller to call us again if we return:
- *
+ * sets. (We expect the caller to call us again if we return
* isDone = ExprMultipleResult.)
*/
if (nodomains > NPREALLOCDOMAINS)
{
nulls = (char *) palloc(nodomains * sizeof(char));
- fjIsNull = (bool *) palloc(nodomains * sizeof(bool));
itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond));
}
else
{
nulls = nullsArray;
- fjIsNull = fjIsNullArray;
itemIsDone = itemIsDoneArray;
}
{
tle = lfirst(tl);
- if (tle->resdom != NULL)
- {
- resind = tle->resdom->resno - 1;
+ resind = tle->resdom->resno - 1;
- values[resind] = ExecEvalExpr(tle->expr,
- econtext,
- &isNull,
- &itemIsDone[resind]);
- nulls[resind] = isNull ? 'n' : ' ';
+ values[resind] = ExecEvalExpr((Node *) tle->expr,
+ econtext,
+ &isNull,
+ &itemIsDone[resind]);
+ nulls[resind] = isNull ? 'n' : ' ';
- if (itemIsDone[resind] != ExprSingleResult)
- {
- /* We have a set-valued expression in the tlist */
- if (isDone == NULL)
- elog(ERROR, "Set-valued function called in context that cannot accept a set");
- if (itemIsDone[resind] == ExprMultipleResult)
- {
- /* we have undone sets in the tlist, set flag */
- *isDone = ExprMultipleResult;
- }
- else
- {
- /* we have done sets in the tlist, set flag for that */
- haveDoneSets = true;
- }
- }
- }
- else
+ if (itemIsDone[resind] != ExprSingleResult)
{
-#ifdef SETS_FIXED
- int curNode;
- Resdom *fjRes;
- List *fjTlist = (List *) tle->expr;
- Fjoin *fjNode = tle->fjoin;
- int nNodes = fjNode->fj_nNodes;
- DatumPtr results = fjNode->fj_results;
-
- ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
-
- /*
- * XXX this is wrong, but since fjoin code is completely
- * broken anyway, I'm not going to worry about it now --- tgl
- * 8/23/00
- */
- if (isDone && *isDone == ExprEndResult)
+ /* We have a set-valued expression in the tlist */
+ if (isDone == NULL)
+ elog(ERROR, "Set-valued function called in context that cannot accept a set");
+ if (itemIsDone[resind] == ExprMultipleResult)
{
- MemoryContextSwitchTo(oldContext);
- newTuple = NULL;
- goto exit;
+ /* we have undone sets in the tlist, set flag */
+ *isDone = ExprMultipleResult;
}
-
- /*
- * get the result from the inner node
- */
- fjRes = (Resdom *) fjNode->fj_innerNode;
- resind = fjRes->resno - 1;
- values[resind] = results[0];
- nulls[resind] = fjIsNull[0] ? 'n' : ' ';
-
- /*
- * Get results from all of the outer nodes
- */
- for (curNode = 1;
- curNode < nNodes;
- curNode++, fjTlist = lnext(fjTlist))
+ else
{
- Node *outernode = lfirst(fjTlist);
-
- fjRes = (Resdom *) outernode->iterexpr;
- resind = fjRes->resno - 1;
- values[resind] = results[curNode];
- nulls[resind] = fjIsNull[curNode] ? 'n' : ' ';
+ /* we have done sets in the tlist, set flag for that */
+ haveDoneSets = true;
}
-#else
- elog(ERROR, "ExecTargetList: fjoin nodes not currently supported");
-#endif
}
}
if (itemIsDone[resind] == ExprEndResult)
{
- values[resind] = ExecEvalExpr(tle->expr,
+ values[resind] = ExecEvalExpr((Node *) tle->expr,
econtext,
&isNull,
&itemIsDone[resind]);
while (itemIsDone[resind] == ExprMultipleResult)
{
- (void) ExecEvalExpr(tle->expr,
+ (void) ExecEvalExpr((Node *) tle->expr,
econtext,
&isNull,
&itemIsDone[resind]);
if (nodomains > NPREALLOCDOMAINS)
{
pfree(nulls);
- pfree(fjIsNull);
pfree(itemIsDone);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.61 2002/12/05 15:50:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.62 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
foreach(tlitem, targetList)
{
TargetEntry *tle = lfirst(tlitem);
- Resdom *resdom;
- Oid restype;
-
- if (tle->resdom != NULL)
- {
- resdom = tle->resdom;
- restype = resdom->restype;
-
- TupleDescInitEntry(typeInfo,
- resdom->resno,
- resdom->resname,
- restype,
- resdom->restypmod,
- 0,
- false);
-
-#ifdef NOT_USED
- ExecSetTypeInfo(resdom->resno - 1,
- typeInfo,
- (Oid) restype,
- resdom->resno,
- resdom->reslen,
- NameStr(*resdom->resname),
- get_typbyval(restype),
- get_typalign(restype));
-#endif
- }
- else
- {
- /* XXX this branch looks fairly broken ... tgl 12/2000 */
- Resdom *fjRes;
- List *fjTlistP;
- List *fjList = lfirst(tlitem);
-
-#ifdef SETS_FIXED
- TargetEntry *tle;
- Fjoin *fjNode = ((TargetEntry *) lfirst(fjList))->fjoin;
-
- tle = fjNode->fj_innerNode; /* ??? */
-#endif
- fjRes = tle->resdom;
- restype = fjRes->restype;
-
- TupleDescInitEntry(typeInfo,
- fjRes->resno,
- fjRes->resname,
- restype,
- fjRes->restypmod,
- 0,
- false);
-#ifdef NOT_USED
- ExecSetTypeInfo(fjRes->resno - 1,
- typeInfo,
- (Oid) restype,
- fjRes->resno,
- fjRes->reslen,
- (char *) fjRes->resname,
- get_typbyval(restype),
- get_typalign(restype));
-#endif
-
- foreach(fjTlistP, lnext(fjList))
- {
- TargetEntry *fjTle = lfirst(fjTlistP);
-
- fjRes = fjTle->resdom;
-
- TupleDescInitEntry(typeInfo,
- fjRes->resno,
- fjRes->resname,
- restype,
- fjRes->restypmod,
- 0,
- false);
-
-#ifdef NOT_USED
- ExecSetTypeInfo(fjRes->resno - 1,
- typeInfo,
- (Oid) fjRes->restype,
- fjRes->resno,
- fjRes->reslen,
- (char *) fjRes->resname,
- get_typbyval(fjRes->restype),
- get_typalign(fjRes->restype));
-#endif
- }
- }
+ Resdom *resdom = tle->resdom;
+
+ TupleDescInitEntry(typeInfo,
+ resdom->resno,
+ resdom->resname,
+ resdom->restype,
+ resdom->restypmod,
+ 0,
+ false);
}
return typeInfo;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.98 2002/12/05 15:50:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.99 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Datum newVal;
bool isNull;
- newVal = ExecEvalExprSwitchContext(aggref->target, econtext,
+ newVal = ExecEvalExprSwitchContext((Node *) aggref->target, econtext,
&isNull, NULL);
if (aggref->aggdistinct)
* pg_proc.proargtypes, because the latter might be 0.
* (Consider COUNT(*).)
*/
- Oid inputType = exprType(aggref->target);
+ Oid inputType = exprType((Node *) aggref->target);
if (!IsBinaryCoercible(inputType, aggform->aggtranstype))
elog(ERROR, "Aggregate %u needs to have compatible input type and transition type",
* pg_proc.proargtypes, because the latter might be a pseudotype.
* (Consider COUNT(*).)
*/
- Oid inputType = exprType(aggref->target);
+ Oid inputType = exprType((Node *) aggref->target);
Oid eq_function;
/* We don't implement DISTINCT aggs in the HASHED case */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.72 2002/12/05 15:50:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.73 2002/12/12 15:49:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
listscan = qual;
for (j = 0; j < n_keys; j++)
{
- Expr *clause; /* one clause of index qual */
- Oper *op; /* operator used in clause */
+ OpExpr *clause; /* one clause of index qual */
Node *leftop; /* expr on lhs of operator */
Node *rightop; /* expr on rhs ... */
bits16 flags = 0;
int scanvar; /* which var identifies varattno */
AttrNumber varattno = 0; /* att number used in scan */
- Oid opid; /* operator id used in scan */
+ Oid opfuncid; /* operator id used in scan */
Datum scanvalue = 0; /* value used in scan (if const) */
/*
* extract clause information from the qualification
*/
- clause = lfirst(listscan);
+ clause = (OpExpr *) lfirst(listscan);
listscan = lnext(listscan);
- op = (Oper *) clause->oper;
- if (!IsA(clause, Expr) ||!IsA(op, Oper))
+ if (!IsA(clause, OpExpr))
elog(ERROR, "ExecInitIndexScan: indxqual not an opclause!");
- opid = op->opid;
+ opfuncid = clause->opfuncid;
/*
* Here we figure out the contents of the index qual. The
/*
* determine information in leftop
*/
- leftop = (Node *) get_leftop(clause);
+ leftop = (Node *) get_leftop((Expr *) clause);
if (leftop && IsA(leftop, RelabelType))
- leftop = ((RelabelType *) leftop)->arg;
+ leftop = (Node *) ((RelabelType *) leftop)->arg;
Assert(leftop != NULL);
/*
* now determine information in rightop
*/
- rightop = (Node *) get_rightop(clause);
+ rightop = (Node *) get_rightop((Expr *) clause);
if (rightop && IsA(rightop, RelabelType))
- rightop = ((RelabelType *) rightop)->arg;
+ rightop = (Node *) ((RelabelType *) rightop)->arg;
Assert(rightop != NULL);
flags,
varattno, /* attribute number to
* scan */
- (RegProcedure) opid, /* reg proc to use */
+ opfuncid, /* reg proc to use */
scanvalue); /* constant */
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.52 2002/12/05 15:50:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.53 2002/12/12 15:49:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ltcdr = *ltQuals;
foreach(gtcdr, *gtQuals)
{
- Expr *ltqual = (Expr *) lfirst(ltcdr);
- Expr *gtqual = (Expr *) lfirst(gtcdr);
- Oper *ltop = (Oper *) ltqual->oper;
- Oper *gtop = (Oper *) gtqual->oper;
+ OpExpr *ltop = (OpExpr *) lfirst(ltcdr);
+ OpExpr *gtop = (OpExpr *) lfirst(gtcdr);
/*
* The two ops should be identical, so use either one for lookup.
*/
- if (!IsA(ltop, Oper))
- elog(ERROR, "MJFormSkipQuals: op not an Oper!");
+ if (!IsA(ltop, OpExpr))
+ elog(ERROR, "MJFormSkipQuals: op not an OpExpr!");
/*
* Lookup the operators, and replace the data in the copied
op_mergejoin_crossops(ltop->opno,
<op->opno,
>op->opno,
- <op->opid,
- >op->opid);
+ <op->opfuncid,
+ >op->opfuncid);
ltop->op_fcache = NULL;
gtop->op_fcache = NULL;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.35 2002/12/05 15:50:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.36 2002/12/12 15:49:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ExprContext *econtext, bool *isNull)
{
PlanState *planstate = node->planstate;
- SubPlan *subplan = (SubPlan *) node->ps.plan;
+ SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
SubLink *sublink = subplan->sublink;
SubLinkType subLinkType = sublink->subLinkType;
bool useor = sublink->useor;
*/
foreach(lst, sublink->oper)
{
- Expr *expr = (Expr *) lfirst(lst);
+ OpExpr *expr = (OpExpr *) lfirst(lst);
Param *prm = lsecond(expr->args);
ParamExecData *prmdata;
Datum expresult;
{
switch (nodeTag(prm))
{
- case T_Expr:
- prm = lfirst(((Expr *) prm)->args);
+ case T_FuncExpr:
+ prm = lfirst(((FuncExpr *) prm)->args);
break;
case T_RelabelType:
prm = (Param *) (((RelabelType *) prm)->arg);
* ----------------------------------------------------------------
*/
SubPlanState *
-ExecInitSubPlan(SubPlan *node, EState *estate)
+ExecInitSubPlan(SubPlanExpr *node, EState *estate)
{
SubPlanState *subplanstate;
EState *sp_estate;
ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
PlanState *planstate = node->planstate;
- SubPlan *subplan = (SubPlan *) node->ps.plan;
+ SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
SubLink *sublink = subplan->sublink;
EState *estate = node->ps.state;
MemoryContext oldcontext;
ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
{
PlanState *planstate = node->planstate;
- SubPlan *subplan = (SubPlan *) node->ps.plan;
+ SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
EState *estate = node->ps.state;
List *lst;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.229 2002/12/06 05:00:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.230 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
return newnode;
}
-static SubPlan *
-_copySubPlan(SubPlan *from)
-{
- SubPlan *newnode = makeNode(SubPlan);
-
- COPY_NODE_FIELD(plan);
- COPY_SCALAR_FIELD(plan_id);
- COPY_NODE_FIELD(rtable);
- COPY_INTLIST_FIELD(setParam);
- COPY_INTLIST_FIELD(parParam);
- COPY_NODE_FIELD(sublink);
-
- return newnode;
-}
-
/* ****************************************************************
* primnodes.h copy functions
* ****************************************************************
return newnode;
}
-static Fjoin *
-_copyFjoin(Fjoin *from)
-{
- Fjoin *newnode = makeNode(Fjoin);
-
- COPY_SCALAR_FIELD(fj_initialized);
- COPY_SCALAR_FIELD(fj_nNodes);
- COPY_NODE_FIELD(fj_innerNode);
- COPY_POINTER_FIELD(fj_results, from->fj_nNodes * sizeof(Datum));
- COPY_POINTER_FIELD(fj_alwaysDone, from->fj_nNodes * sizeof(bool));
-
- return newnode;
-}
-
+/*
+ * _copyAlias
+ */
static Alias *
_copyAlias(Alias *from)
{
return newnode;
}
+/*
+ * _copyRangeVar
+ */
static RangeVar *
_copyRangeVar(RangeVar *from)
{
}
/*
- * _copyExpr
+ * We don't need a _copyExpr because Expr is an abstract supertype which
+ * should never actually get instantiated. Also, since it has no common
+ * fields except NodeTag, there's no need for a helper routine to factor
+ * out copying the common fields...
*/
-static Expr *
-_copyExpr(Expr *from)
-{
- Expr *newnode = makeNode(Expr);
-
- COPY_SCALAR_FIELD(typeOid);
- COPY_SCALAR_FIELD(opType);
- COPY_NODE_FIELD(oper);
- COPY_NODE_FIELD(args);
-
- return newnode;
-}
/*
* _copyVar
return newnode;
}
-/*
- * _copyOper
- */
-static Oper *
-_copyOper(Oper *from)
-{
- Oper *newnode = makeNode(Oper);
-
- COPY_SCALAR_FIELD(opno);
- COPY_SCALAR_FIELD(opid);
- COPY_SCALAR_FIELD(opresulttype);
- COPY_SCALAR_FIELD(opretset);
-
- /* Do not copy the run-time state, if any */
- newnode->op_fcache = NULL;
-
- return newnode;
-}
-
/*
* _copyConst
*/
}
/*
- * _copyFunc
+ * _copyAggref
*/
-static Func *
-_copyFunc(Func *from)
+static Aggref *
+_copyAggref(Aggref *from)
{
- Func *newnode = makeNode(Func);
+ Aggref *newnode = makeNode(Aggref);
+
+ COPY_SCALAR_FIELD(aggfnoid);
+ COPY_SCALAR_FIELD(aggtype);
+ COPY_NODE_FIELD(target);
+ COPY_SCALAR_FIELD(aggstar);
+ COPY_SCALAR_FIELD(aggdistinct);
+ COPY_SCALAR_FIELD(aggno); /* will go away soon */
+
+ return newnode;
+}
+
+/*
+ * _copyArrayRef
+ */
+static ArrayRef *
+_copyArrayRef(ArrayRef *from)
+{
+ ArrayRef *newnode = makeNode(ArrayRef);
+
+ COPY_SCALAR_FIELD(refrestype);
+ COPY_SCALAR_FIELD(refattrlength);
+ COPY_SCALAR_FIELD(refelemlength);
+ COPY_SCALAR_FIELD(refelembyval);
+ COPY_SCALAR_FIELD(refelemalign);
+ COPY_NODE_FIELD(refupperindexpr);
+ COPY_NODE_FIELD(reflowerindexpr);
+ COPY_NODE_FIELD(refexpr);
+ COPY_NODE_FIELD(refassgnexpr);
+
+ return newnode;
+}
+
+/*
+ * _copyFuncExpr
+ */
+static FuncExpr *
+_copyFuncExpr(FuncExpr *from)
+{
+ FuncExpr *newnode = makeNode(FuncExpr);
COPY_SCALAR_FIELD(funcid);
COPY_SCALAR_FIELD(funcresulttype);
COPY_SCALAR_FIELD(funcretset);
COPY_SCALAR_FIELD(funcformat);
+ COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->func_fcache = NULL;
}
/*
- * _copyAggref
+ * _copyOpExpr
*/
-static Aggref *
-_copyAggref(Aggref *from)
+static OpExpr *
+_copyOpExpr(OpExpr *from)
{
- Aggref *newnode = makeNode(Aggref);
+ OpExpr *newnode = makeNode(OpExpr);
- COPY_SCALAR_FIELD(aggfnoid);
- COPY_SCALAR_FIELD(aggtype);
- COPY_NODE_FIELD(target);
- COPY_SCALAR_FIELD(aggstar);
- COPY_SCALAR_FIELD(aggdistinct);
- COPY_SCALAR_FIELD(aggno); /* probably not necessary */
+ COPY_SCALAR_FIELD(opno);
+ COPY_SCALAR_FIELD(opfuncid);
+ COPY_SCALAR_FIELD(opresulttype);
+ COPY_SCALAR_FIELD(opretset);
+ COPY_NODE_FIELD(args);
+
+ /* Do not copy the run-time state, if any */
+ newnode->op_fcache = NULL;
+
+ return newnode;
+}
+
+/*
+ * _copyDistinctExpr
+ */
+static DistinctExpr *
+_copyDistinctExpr(DistinctExpr *from)
+{
+ DistinctExpr *newnode = makeNode(DistinctExpr);
+
+ COPY_SCALAR_FIELD(opno);
+ COPY_SCALAR_FIELD(opfuncid);
+ COPY_SCALAR_FIELD(opresulttype);
+ COPY_SCALAR_FIELD(opretset);
+ COPY_NODE_FIELD(args);
+
+ /* Do not copy the run-time state, if any */
+ newnode->op_fcache = NULL;
+
+ return newnode;
+}
+
+/*
+ * _copyBoolExpr
+ */
+static BoolExpr *
+_copyBoolExpr(BoolExpr *from)
+{
+ BoolExpr *newnode = makeNode(BoolExpr);
+
+ COPY_SCALAR_FIELD(boolop);
+ COPY_NODE_FIELD(args);
return newnode;
}
return newnode;
}
+/*
+ * _copySubPlanExpr
+ */
+static SubPlanExpr *
+_copySubPlanExpr(SubPlanExpr *from)
+{
+ SubPlanExpr *newnode = makeNode(SubPlanExpr);
+
+ COPY_SCALAR_FIELD(typeOid);
+ COPY_NODE_FIELD(plan);
+ COPY_SCALAR_FIELD(plan_id);
+ COPY_NODE_FIELD(rtable);
+ COPY_INTLIST_FIELD(setParam);
+ COPY_INTLIST_FIELD(parParam);
+ COPY_NODE_FIELD(args);
+ COPY_NODE_FIELD(sublink);
+
+ return newnode;
+}
+
/*
* _copyFieldSelect
*/
return newnode;
}
+/*
+ * _copyCaseExpr
+ */
+static CaseExpr *
+_copyCaseExpr(CaseExpr *from)
+{
+ CaseExpr *newnode = makeNode(CaseExpr);
+
+ COPY_SCALAR_FIELD(casetype);
+ COPY_NODE_FIELD(arg);
+ COPY_NODE_FIELD(args);
+ COPY_NODE_FIELD(defresult);
+
+ return newnode;
+}
+
+/*
+ * _copyCaseWhen
+ */
+static CaseWhen *
+_copyCaseWhen(CaseWhen *from)
+{
+ CaseWhen *newnode = makeNode(CaseWhen);
+
+ COPY_NODE_FIELD(expr);
+ COPY_NODE_FIELD(result);
+
+ return newnode;
+}
+
+/*
+ * _copyNullTest
+ */
+static NullTest *
+_copyNullTest(NullTest *from)
+{
+ NullTest *newnode = makeNode(NullTest);
+
+ COPY_NODE_FIELD(arg);
+ COPY_SCALAR_FIELD(nulltesttype);
+
+ return newnode;
+}
+
+/*
+ * _copyBooleanTest
+ */
+static BooleanTest *
+_copyBooleanTest(BooleanTest *from)
+{
+ BooleanTest *newnode = makeNode(BooleanTest);
+
+ COPY_NODE_FIELD(arg);
+ COPY_SCALAR_FIELD(booltesttype);
+
+ return newnode;
+}
+
+/*
+ * _copyConstraintTest
+ */
+static ConstraintTest *
+_copyConstraintTest(ConstraintTest *from)
+{
+ ConstraintTest *newnode = makeNode(ConstraintTest);
+
+ COPY_NODE_FIELD(arg);
+ COPY_SCALAR_FIELD(testtype);
+ COPY_STRING_FIELD(name);
+ COPY_STRING_FIELD(domname);
+ COPY_NODE_FIELD(check_expr);
+
+ return newnode;
+}
+
+/*
+ * _copyConstraintTestValue
+ */
+static ConstraintTestValue *
+_copyConstraintTestValue(ConstraintTestValue *from)
+{
+ ConstraintTestValue *newnode = makeNode(ConstraintTestValue);
+
+ COPY_SCALAR_FIELD(typeId);
+ COPY_SCALAR_FIELD(typeMod);
+
+ return newnode;
+}
+
+/*
+ * _copyTargetEntry
+ */
+static TargetEntry *
+_copyTargetEntry(TargetEntry *from)
+{
+ TargetEntry *newnode = makeNode(TargetEntry);
+
+ COPY_NODE_FIELD(resdom);
+ COPY_NODE_FIELD(expr);
+
+ return newnode;
+}
+
+/*
+ * _copyRangeTblRef
+ */
static RangeTblRef *
_copyRangeTblRef(RangeTblRef *from)
{
return newnode;
}
+/*
+ * _copyJoinExpr
+ */
static JoinExpr *
_copyJoinExpr(JoinExpr *from)
{
return newnode;
}
+/*
+ * _copyFromExpr
+ */
static FromExpr *
_copyFromExpr(FromExpr *from)
{
return newnode;
}
-static ArrayRef *
-_copyArrayRef(ArrayRef *from)
-{
- ArrayRef *newnode = makeNode(ArrayRef);
-
- COPY_SCALAR_FIELD(refrestype);
- COPY_SCALAR_FIELD(refattrlength);
- COPY_SCALAR_FIELD(refelemlength);
- COPY_SCALAR_FIELD(refelembyval);
- COPY_SCALAR_FIELD(refelemalign);
- COPY_NODE_FIELD(refupperindexpr);
- COPY_NODE_FIELD(reflowerindexpr);
- COPY_NODE_FIELD(refexpr);
- COPY_NODE_FIELD(refassgnexpr);
-
- return newnode;
-}
-
/* ****************************************************************
* relation.h copy functions
*
* ****************************************************************
*/
-static TargetEntry *
-_copyTargetEntry(TargetEntry *from)
-{
- TargetEntry *newnode = makeNode(TargetEntry);
-
- COPY_NODE_FIELD(resdom);
- COPY_NODE_FIELD(fjoin);
- COPY_NODE_FIELD(expr);
-
- return newnode;
-}
-
static RangeTblEntry *
_copyRangeTblEntry(RangeTblEntry *from)
{
return newnode;
}
+static DomainConstraintValue *
+_copyDomainConstraintValue(DomainConstraintValue *from)
+{
+ DomainConstraintValue *newnode = makeNode(DomainConstraintValue);
+
+ return newnode;
+}
+
static SortGroupBy *
_copySortGroupBy(SortGroupBy *from)
{
return newnode;
}
-static CaseExpr *
-_copyCaseExpr(CaseExpr *from)
-{
- CaseExpr *newnode = makeNode(CaseExpr);
-
- COPY_SCALAR_FIELD(casetype);
- COPY_NODE_FIELD(arg);
- COPY_NODE_FIELD(args);
- COPY_NODE_FIELD(defresult);
-
- return newnode;
-}
-
-static CaseWhen *
-_copyCaseWhen(CaseWhen *from)
-{
- CaseWhen *newnode = makeNode(CaseWhen);
-
- COPY_NODE_FIELD(expr);
- COPY_NODE_FIELD(result);
-
- return newnode;
-}
-
-static NullTest *
-_copyNullTest(NullTest *from)
-{
- NullTest *newnode = makeNode(NullTest);
-
- COPY_NODE_FIELD(arg);
- COPY_SCALAR_FIELD(nulltesttype);
-
- return newnode;
-}
-
-static BooleanTest *
-_copyBooleanTest(BooleanTest *from)
-{
- BooleanTest *newnode = makeNode(BooleanTest);
-
- COPY_NODE_FIELD(arg);
- COPY_SCALAR_FIELD(booltesttype);
-
- return newnode;
-}
-
-static ConstraintTest *
-_copyConstraintTest(ConstraintTest *from)
-{
- ConstraintTest *newnode = makeNode(ConstraintTest);
-
- COPY_NODE_FIELD(arg);
- COPY_SCALAR_FIELD(testtype);
- COPY_STRING_FIELD(name);
- COPY_STRING_FIELD(domname);
- COPY_NODE_FIELD(check_expr);
-
- return newnode;
-}
-
-static DomainConstraintValue *
-_copyDomainConstraintValue(DomainConstraintValue *from)
-{
- DomainConstraintValue *newnode = makeNode(DomainConstraintValue);
-
- return newnode;
-}
-
-static ConstraintTestValue *
-_copyConstraintTestValue(ConstraintTestValue *from)
-{
- ConstraintTestValue *newnode = makeNode(ConstraintTestValue);
-
- COPY_SCALAR_FIELD(typeId);
- COPY_SCALAR_FIELD(typeMod);
-
- return newnode;
-}
-
static DefElem *
_copyDefElem(DefElem *from)
{
case T_Limit:
retval = _copyLimit(from);
break;
- case T_SubPlan:
- retval = _copySubPlan(from);
- break;
/*
* PRIMITIVE NODES
case T_Resdom:
retval = _copyResdom(from);
break;
- case T_Fjoin:
- retval = _copyFjoin(from);
- break;
case T_Alias:
retval = _copyAlias(from);
break;
case T_RangeVar:
retval = _copyRangeVar(from);
break;
- case T_Expr:
- retval = _copyExpr(from);
- break;
case T_Var:
retval = _copyVar(from);
break;
- case T_Oper:
- retval = _copyOper(from);
- break;
case T_Const:
retval = _copyConst(from);
break;
case T_Param:
retval = _copyParam(from);
break;
- case T_Func:
- retval = _copyFunc(from);
- break;
case T_Aggref:
retval = _copyAggref(from);
break;
+ case T_ArrayRef:
+ retval = _copyArrayRef(from);
+ break;
+ case T_FuncExpr:
+ retval = _copyFuncExpr(from);
+ break;
+ case T_OpExpr:
+ retval = _copyOpExpr(from);
+ break;
+ case T_DistinctExpr:
+ retval = _copyDistinctExpr(from);
+ break;
+ case T_BoolExpr:
+ retval = _copyBoolExpr(from);
+ break;
case T_SubLink:
retval = _copySubLink(from);
break;
+ case T_SubPlanExpr:
+ retval = _copySubPlanExpr(from);
+ break;
case T_FieldSelect:
retval = _copyFieldSelect(from);
break;
case T_RelabelType:
retval = _copyRelabelType(from);
break;
+ case T_CaseExpr:
+ retval = _copyCaseExpr(from);
+ break;
+ case T_CaseWhen:
+ retval = _copyCaseWhen(from);
+ break;
+ case T_NullTest:
+ retval = _copyNullTest(from);
+ break;
+ case T_BooleanTest:
+ retval = _copyBooleanTest(from);
+ break;
+ case T_ConstraintTest:
+ retval = _copyConstraintTest(from);
+ break;
+ case T_ConstraintTestValue:
+ retval = _copyConstraintTestValue(from);
+ break;
+ case T_TargetEntry:
+ retval = _copyTargetEntry(from);
+ break;
case T_RangeTblRef:
retval = _copyRangeTblRef(from);
break;
case T_FromExpr:
retval = _copyFromExpr(from);
break;
- case T_ArrayRef:
- retval = _copyArrayRef(from);
- break;
/*
* RELATION NODES
case T_TypeCast:
retval = _copyTypeCast(from);
break;
+ case T_DomainConstraintValue:
+ retval = _copyDomainConstraintValue(from);
+ break;
case T_SortGroupBy:
retval = _copySortGroupBy(from);
break;
case T_DefElem:
retval = _copyDefElem(from);
break;
- case T_TargetEntry:
- retval = _copyTargetEntry(from);
- break;
case T_RangeTblEntry:
retval = _copyRangeTblEntry(from);
break;
case T_GroupClause:
retval = _copyGroupClause(from);
break;
- case T_CaseExpr:
- retval = _copyCaseExpr(from);
- break;
- case T_CaseWhen:
- retval = _copyCaseWhen(from);
- break;
- case T_NullTest:
- retval = _copyNullTest(from);
- break;
- case T_BooleanTest:
- retval = _copyBooleanTest(from);
- break;
- case T_ConstraintTest:
- retval = _copyConstraintTest(from);
- break;
- case T_ConstraintTestValue:
- retval = _copyConstraintTestValue(from);
- break;
case T_FkConstraint:
retval = _copyFkConstraint(from);
break;
case T_InsertDefault:
retval = _copyInsertDefault(from);
break;
- case T_DomainConstraintValue:
- retval = _copyDomainConstraintValue(from);
- break;
default:
elog(ERROR, "copyObject: don't know how to copy node type %d",
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.174 2002/12/06 05:00:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.175 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/params.h"
#include "nodes/parsenodes.h"
-#include "nodes/plannodes.h"
#include "nodes/relation.h"
#include "utils/datum.h"
return true;
}
-static bool
-_equalFjoin(Fjoin *a, Fjoin *b)
-{
- COMPARE_SCALAR_FIELD(fj_initialized);
- COMPARE_SCALAR_FIELD(fj_nNodes);
- COMPARE_NODE_FIELD(fj_innerNode);
- COMPARE_POINTER_FIELD(fj_results, a->fj_nNodes * sizeof(Datum));
- COMPARE_POINTER_FIELD(fj_alwaysDone, a->fj_nNodes * sizeof(bool));
-
- return true;
-}
-
static bool
_equalAlias(Alias *a, Alias *b)
{
return true;
}
-static bool
-_equalExpr(Expr *a, Expr *b)
-{
- /*
- * We do not examine typeOid, since the optimizer often doesn't bother
- * to set it in created nodes, and it is logically a derivative of the
- * oper field anyway.
- */
- COMPARE_SCALAR_FIELD(opType);
- COMPARE_NODE_FIELD(oper);
- COMPARE_NODE_FIELD(args);
-
- return true;
-}
+/*
+ * We don't need an _equalExpr because Expr is an abstract supertype which
+ * should never actually get instantiated. Also, since it has no common
+ * fields except NodeTag, there's no need for a helper routine to factor
+ * out comparing the common fields...
+ */
static bool
_equalVar(Var *a, Var *b)
return true;
}
-static bool
-_equalOper(Oper *a, Oper *b)
-{
- COMPARE_SCALAR_FIELD(opno);
- COMPARE_SCALAR_FIELD(opresulttype);
- COMPARE_SCALAR_FIELD(opretset);
-
- /*
- * We do not examine opid or op_fcache, since these are logically
- * derived from opno, and they may not be set yet depending on how far
- * along the node is in the parse/plan pipeline.
- *
- * (Besides, op_fcache is executor state, which we don't check --- see
- * notes at head of file.)
- *
- * It's probably not really necessary to check opresulttype or opretset,
- * either...
- */
-
- return true;
-}
-
static bool
_equalConst(Const *a, Const *b)
{
}
static bool
-_equalFunc(Func *a, Func *b)
+_equalAggref(Aggref *a, Aggref *b)
+{
+ COMPARE_SCALAR_FIELD(aggfnoid);
+ COMPARE_SCALAR_FIELD(aggtype);
+ COMPARE_NODE_FIELD(target);
+ COMPARE_SCALAR_FIELD(aggstar);
+ COMPARE_SCALAR_FIELD(aggdistinct);
+
+ return true;
+}
+
+static bool
+_equalArrayRef(ArrayRef *a, ArrayRef *b)
+{
+ COMPARE_SCALAR_FIELD(refrestype);
+ COMPARE_SCALAR_FIELD(refattrlength);
+ COMPARE_SCALAR_FIELD(refelemlength);
+ COMPARE_SCALAR_FIELD(refelembyval);
+ COMPARE_SCALAR_FIELD(refelemalign);
+ COMPARE_NODE_FIELD(refupperindexpr);
+ COMPARE_NODE_FIELD(reflowerindexpr);
+ COMPARE_NODE_FIELD(refexpr);
+ COMPARE_NODE_FIELD(refassgnexpr);
+
+ return true;
+}
+
+static bool
+_equalFuncExpr(FuncExpr *a, FuncExpr *b)
{
COMPARE_SCALAR_FIELD(funcid);
COMPARE_SCALAR_FIELD(funcresulttype);
b->funcformat != COERCE_DONTCARE)
return false;
- /* Note we do not look at func_fcache; see notes for _equalOper */
+ COMPARE_NODE_FIELD(args);
return true;
}
static bool
-_equalAggref(Aggref *a, Aggref *b)
+_equalOpExpr(OpExpr *a, OpExpr *b)
{
- COMPARE_SCALAR_FIELD(aggfnoid);
- COMPARE_SCALAR_FIELD(aggtype);
- COMPARE_NODE_FIELD(target);
- COMPARE_SCALAR_FIELD(aggstar);
- COMPARE_SCALAR_FIELD(aggdistinct);
- /* ignore aggno, which is only a private field for the executor */
+ COMPARE_SCALAR_FIELD(opno);
+ /*
+ * Special-case opfuncid: it is allowable for it to differ if one
+ * node contains zero and the other doesn't. This just means that the
+ * one node isn't as far along in the parse/plan pipeline and hasn't
+ * had the opfuncid cache filled yet.
+ */
+ if (a->opfuncid != b->opfuncid &&
+ a->opfuncid != 0 &&
+ b->opfuncid != 0)
+ return false;
+
+ COMPARE_SCALAR_FIELD(opresulttype);
+ COMPARE_SCALAR_FIELD(opretset);
+ COMPARE_NODE_FIELD(args);
+
+ return true;
+}
+
+static bool
+_equalDistinctExpr(DistinctExpr *a, DistinctExpr *b)
+{
+ COMPARE_SCALAR_FIELD(opno);
+ /*
+ * Special-case opfuncid: it is allowable for it to differ if one
+ * node contains zero and the other doesn't. This just means that the
+ * one node isn't as far along in the parse/plan pipeline and hasn't
+ * had the opfuncid cache filled yet.
+ */
+ if (a->opfuncid != b->opfuncid &&
+ a->opfuncid != 0 &&
+ b->opfuncid != 0)
+ return false;
+
+ COMPARE_SCALAR_FIELD(opresulttype);
+ COMPARE_SCALAR_FIELD(opretset);
+ COMPARE_NODE_FIELD(args);
+
+ return true;
+}
+
+static bool
+_equalBoolExpr(BoolExpr *a, BoolExpr *b)
+{
+ COMPARE_SCALAR_FIELD(boolop);
+ COMPARE_NODE_FIELD(args);
return true;
}
return true;
}
+static bool
+_equalSubPlanExpr(SubPlanExpr *a, SubPlanExpr *b)
+{
+ COMPARE_SCALAR_FIELD(typeOid);
+ /* should compare plans, but have to settle for comparing plan IDs */
+ COMPARE_SCALAR_FIELD(plan_id);
+ COMPARE_NODE_FIELD(rtable);
+ COMPARE_INTLIST_FIELD(setParam);
+ COMPARE_INTLIST_FIELD(parParam);
+ COMPARE_NODE_FIELD(args);
+ COMPARE_NODE_FIELD(sublink);
+
+ return true;
+}
+
static bool
_equalFieldSelect(FieldSelect *a, FieldSelect *b)
{
}
static bool
-_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
+_equalCaseExpr(CaseExpr *a, CaseExpr *b)
{
- COMPARE_SCALAR_FIELD(rtindex);
+ COMPARE_SCALAR_FIELD(casetype);
+ COMPARE_NODE_FIELD(arg);
+ COMPARE_NODE_FIELD(args);
+ COMPARE_NODE_FIELD(defresult);
return true;
}
static bool
-_equalJoinExpr(JoinExpr *a, JoinExpr *b)
+_equalCaseWhen(CaseWhen *a, CaseWhen *b)
{
- COMPARE_SCALAR_FIELD(jointype);
- COMPARE_SCALAR_FIELD(isNatural);
- COMPARE_NODE_FIELD(larg);
- COMPARE_NODE_FIELD(rarg);
- COMPARE_NODE_FIELD(using);
- COMPARE_NODE_FIELD(quals);
- COMPARE_NODE_FIELD(alias);
- COMPARE_SCALAR_FIELD(rtindex);
+ COMPARE_NODE_FIELD(expr);
+ COMPARE_NODE_FIELD(result);
return true;
}
static bool
-_equalFromExpr(FromExpr *a, FromExpr *b)
+_equalNullTest(NullTest *a, NullTest *b)
{
- COMPARE_NODE_FIELD(fromlist);
- COMPARE_NODE_FIELD(quals);
+ COMPARE_NODE_FIELD(arg);
+ COMPARE_SCALAR_FIELD(nulltesttype);
return true;
}
static bool
-_equalArrayRef(ArrayRef *a, ArrayRef *b)
+_equalBooleanTest(BooleanTest *a, BooleanTest *b)
{
- COMPARE_SCALAR_FIELD(refrestype);
- COMPARE_SCALAR_FIELD(refattrlength);
- COMPARE_SCALAR_FIELD(refelemlength);
- COMPARE_SCALAR_FIELD(refelembyval);
- COMPARE_SCALAR_FIELD(refelemalign);
- COMPARE_NODE_FIELD(refupperindexpr);
- COMPARE_NODE_FIELD(reflowerindexpr);
- COMPARE_NODE_FIELD(refexpr);
- COMPARE_NODE_FIELD(refassgnexpr);
+ COMPARE_NODE_FIELD(arg);
+ COMPARE_SCALAR_FIELD(booltesttype);
return true;
}
+static bool
+_equalConstraintTest(ConstraintTest *a, ConstraintTest *b)
+{
+ COMPARE_NODE_FIELD(arg);
+ COMPARE_SCALAR_FIELD(testtype);
+ COMPARE_STRING_FIELD(name);
+ COMPARE_STRING_FIELD(domname);
+ COMPARE_NODE_FIELD(check_expr);
-/*
- * Stuff from plannodes.h
- */
+ return true;
+}
static bool
-_equalSubPlan(SubPlan *a, SubPlan *b)
+_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b)
{
- /* should compare plans, but have to settle for comparing plan IDs */
- COMPARE_SCALAR_FIELD(plan_id);
+ COMPARE_SCALAR_FIELD(typeId);
+ COMPARE_SCALAR_FIELD(typeMod);
- COMPARE_NODE_FIELD(rtable);
- COMPARE_NODE_FIELD(sublink);
+ return true;
+}
+
+static bool
+_equalTargetEntry(TargetEntry *a, TargetEntry *b)
+{
+ COMPARE_NODE_FIELD(resdom);
+ COMPARE_NODE_FIELD(expr);
+
+ return true;
+}
+
+static bool
+_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
+{
+ COMPARE_SCALAR_FIELD(rtindex);
+
+ return true;
+}
+
+static bool
+_equalJoinExpr(JoinExpr *a, JoinExpr *b)
+{
+ COMPARE_SCALAR_FIELD(jointype);
+ COMPARE_SCALAR_FIELD(isNatural);
+ COMPARE_NODE_FIELD(larg);
+ COMPARE_NODE_FIELD(rarg);
+ COMPARE_NODE_FIELD(using);
+ COMPARE_NODE_FIELD(quals);
+ COMPARE_NODE_FIELD(alias);
+ COMPARE_SCALAR_FIELD(rtindex);
+
+ return true;
+}
+
+static bool
+_equalFromExpr(FromExpr *a, FromExpr *b)
+{
+ COMPARE_NODE_FIELD(fromlist);
+ COMPARE_NODE_FIELD(quals);
return true;
}
return true;
}
+static bool
+_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b)
+{
+ return true;
+}
+
static bool
_equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
{
return true;
}
-static bool
-_equalTargetEntry(TargetEntry *a, TargetEntry *b)
-{
- COMPARE_NODE_FIELD(resdom);
- COMPARE_NODE_FIELD(fjoin);
- COMPARE_NODE_FIELD(expr);
-
- return true;
-}
-
static bool
_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
{
return true;
}
-static bool
-_equalCaseExpr(CaseExpr *a, CaseExpr *b)
-{
- COMPARE_SCALAR_FIELD(casetype);
- COMPARE_NODE_FIELD(arg);
- COMPARE_NODE_FIELD(args);
- COMPARE_NODE_FIELD(defresult);
-
- return true;
-}
-
-static bool
-_equalCaseWhen(CaseWhen *a, CaseWhen *b)
-{
- COMPARE_NODE_FIELD(expr);
- COMPARE_NODE_FIELD(result);
-
- return true;
-}
-
-static bool
-_equalNullTest(NullTest *a, NullTest *b)
-{
- COMPARE_NODE_FIELD(arg);
- COMPARE_SCALAR_FIELD(nulltesttype);
-
- return true;
-}
-
-static bool
-_equalBooleanTest(BooleanTest *a, BooleanTest *b)
-{
- COMPARE_NODE_FIELD(arg);
- COMPARE_SCALAR_FIELD(booltesttype);
-
- return true;
-}
-
-static bool
-_equalConstraintTest(ConstraintTest *a, ConstraintTest *b)
-{
- COMPARE_NODE_FIELD(arg);
- COMPARE_SCALAR_FIELD(testtype);
- COMPARE_STRING_FIELD(name);
- COMPARE_STRING_FIELD(domname);
- COMPARE_NODE_FIELD(check_expr);
-
- return true;
-}
-
-static bool
-_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b)
-{
- return true;
-}
-
-static bool
-_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b)
-{
- COMPARE_SCALAR_FIELD(typeId);
- COMPARE_SCALAR_FIELD(typeMod);
-
- return true;
-}
-
/*
* Stuff from pg_list.h
switch (nodeTag(a))
{
- case T_SubPlan:
- retval = _equalSubPlan(a, b);
- break;
-
+ /*
+ * PRIMITIVE NODES
+ */
case T_Resdom:
retval = _equalResdom(a, b);
break;
- case T_Fjoin:
- retval = _equalFjoin(a, b);
+ case T_Alias:
+ retval = _equalAlias(a, b);
break;
- case T_Expr:
- retval = _equalExpr(a, b);
+ case T_RangeVar:
+ retval = _equalRangeVar(a, b);
break;
case T_Var:
retval = _equalVar(a, b);
break;
- case T_Oper:
- retval = _equalOper(a, b);
- break;
case T_Const:
retval = _equalConst(a, b);
break;
case T_Aggref:
retval = _equalAggref(a, b);
break;
+ case T_ArrayRef:
+ retval = _equalArrayRef(a, b);
+ break;
+ case T_FuncExpr:
+ retval = _equalFuncExpr(a, b);
+ break;
+ case T_OpExpr:
+ retval = _equalOpExpr(a, b);
+ break;
+ case T_DistinctExpr:
+ retval = _equalDistinctExpr(a, b);
+ break;
+ case T_BoolExpr:
+ retval = _equalBoolExpr(a, b);
+ break;
case T_SubLink:
retval = _equalSubLink(a, b);
break;
- case T_Func:
- retval = _equalFunc(a, b);
+ case T_SubPlanExpr:
+ retval = _equalSubPlanExpr(a, b);
break;
case T_FieldSelect:
retval = _equalFieldSelect(a, b);
break;
- case T_ArrayRef:
- retval = _equalArrayRef(a, b);
- break;
case T_RelabelType:
retval = _equalRelabelType(a, b);
break;
+ case T_CaseExpr:
+ retval = _equalCaseExpr(a, b);
+ break;
+ case T_CaseWhen:
+ retval = _equalCaseWhen(a, b);
+ break;
+ case T_NullTest:
+ retval = _equalNullTest(a, b);
+ break;
+ case T_BooleanTest:
+ retval = _equalBooleanTest(a, b);
+ break;
+ case T_ConstraintTest:
+ retval = _equalConstraintTest(a, b);
+ break;
+ case T_ConstraintTestValue:
+ retval = _equalConstraintTestValue(a, b);
+ break;
+ case T_TargetEntry:
+ retval = _equalTargetEntry(a, b);
+ break;
case T_RangeTblRef:
retval = _equalRangeTblRef(a, b);
break;
retval = _equalJoinExpr(a, b);
break;
+ /*
+ * RELATION NODES
+ */
case T_PathKeyItem:
retval = _equalPathKeyItem(a, b);
break;
retval = _equalJoinInfo(a, b);
break;
+ /*
+ * LIST NODES
+ */
case T_List:
{
List *la = (List *) a;
retval = _equalValue(a, b);
break;
+ /*
+ * PARSE NODES
+ */
case T_Query:
retval = _equalQuery(a, b);
break;
case T_SortGroupBy:
retval = _equalSortGroupBy(a, b);
break;
- case T_Alias:
- retval = _equalAlias(a, b);
- break;
- case T_RangeVar:
- retval = _equalRangeVar(a, b);
- break;
case T_RangeSubselect:
retval = _equalRangeSubselect(a, b);
break;
case T_DefElem:
retval = _equalDefElem(a, b);
break;
- case T_TargetEntry:
- retval = _equalTargetEntry(a, b);
- break;
case T_RangeTblEntry:
retval = _equalRangeTblEntry(a, b);
break;
/* GroupClause is equivalent to SortClause */
retval = _equalSortClause(a, b);
break;
- case T_CaseExpr:
- retval = _equalCaseExpr(a, b);
- break;
- case T_CaseWhen:
- retval = _equalCaseWhen(a, b);
- break;
- case T_NullTest:
- retval = _equalNullTest(a, b);
- break;
- case T_BooleanTest:
- retval = _equalBooleanTest(a, b);
- break;
- case T_ConstraintTest:
- retval = _equalConstraintTest(a, b);
- break;
- case T_ConstraintTestValue:
- retval = _equalConstraintTestValue(a, b);
- break;
case T_FkConstraint:
retval = _equalFkConstraint(a, b);
break;
-/*
+/*-------------------------------------------------------------------------
+ *
* makefuncs.c
* creator functions for primitive nodes. The functions here are for
* the most frequently created nodes.
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.36 2002/11/25 21:29:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.37 2002/12/12 15:49:28 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
*/
#include "postgres.h"
return a;
}
-/*
- * makeOper -
- * creates an Oper node
- */
-Oper *
-makeOper(Oid opno,
- Oid opid,
- Oid opresulttype,
- bool opretset)
-{
- Oper *oper = makeNode(Oper);
-
- oper->opno = opno;
- oper->opid = opid;
- oper->opresulttype = opresulttype;
- oper->opretset = opretset;
- oper->op_fcache = NULL;
- return oper;
-}
-
/*
* makeVar -
* creates a Var node
- *
*/
Var *
makeVar(Index varno,
/*
* makeTargetEntry -
- * creates a TargetEntry node(contains a Resdom)
+ * creates a TargetEntry node (contains a Resdom)
*/
TargetEntry *
-makeTargetEntry(Resdom *resdom, Node *expr)
+makeTargetEntry(Resdom *resdom, Expr *expr)
{
TargetEntry *rt = makeNode(TargetEntry);
typByVal);
}
+/*
+ * makeBoolExpr -
+ * creates a BoolExpr node
+ */
+Expr *
+makeBoolExpr(BoolExprType boolop, List *args)
+{
+ BoolExpr *b = makeNode(BoolExpr);
+
+ b->boolop = boolop;
+ b->args = args;
+
+ return (Expr *) b;
+}
+
/*
* makeAlias -
* creates an Alias node
* creates a RelabelType node
*/
RelabelType *
-makeRelabelType(Node *arg, Oid rtype, int32 rtypmod, CoercionForm rformat)
+makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat)
{
RelabelType *r = makeNode(RelabelType);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.19 2002/09/02 02:47:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.20 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-
-
#include "postgres.h"
#include "nodes/nodeFuncs.h"
static bool var_is_inner(Var *var);
+
/*
* single_node -
* Returns t if node corresponds to a single-noded expression
*****************************************************************************/
/*
- * replace_opid -
- *
- * Given a oper node, resets the opfid field with the
- * procedure OID (regproc id).
- *
- * Returns the modified oper node.
+ * set_opfuncid -
*
+ * Set the opfuncid (procedure OID) in an OpExpr node,
+ * if it hasn't been set already.
*/
-Oper *
-replace_opid(Oper *oper)
+void
+set_opfuncid(OpExpr *opexpr)
{
- oper->opid = get_opcode(oper->opno);
- oper->op_fcache = NULL;
- return oper;
+ if (opexpr->opfuncid == InvalidOid)
+ opexpr->opfuncid = get_opcode(opexpr->opno);
+ opexpr->op_fcache = NULL; /* XXX will go away soon */
}
-
-/*****************************************************************************
- * constant (CONST, PARAM) nodes
- *****************************************************************************/
-
-#ifdef NOT_USED
-/*
- * non_null -
- * Returns t if the node is a non-null constant, e.g., if the node has a
- * valid `constvalue' field.
- */
-bool
-non_null(Expr *c)
-{
-
- if (IsA(c, Const) &&
- !((Const *) c)->constisnull)
- return true;
- else
- return false;
-}
-
-#endif
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.186 2002/12/05 15:50:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.187 2002/12/12 15:49:28 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
#define booltostr(x) ((x) ? "true" : "false")
-static void _outDatum(StringInfo str, Datum value, int typlen, bool typbyval);
static void _outNode(StringInfo str, void *obj);
+
/*
* _outToken
* Convert an ordinary string (eg, an identifier) into a form that
appendStringInfoChar(str, ')');
}
+/*
+ * Print the value of a Datum given its type.
+ */
static void
-_outCreateStmt(StringInfo str, CreateStmt *node)
-{
- WRITE_NODE_TYPE("CREATE");
-
- WRITE_NODE_FIELD(relation);
- WRITE_NODE_FIELD(tableElts);
- WRITE_NODE_FIELD(inhRelations);
- WRITE_NODE_FIELD(constraints);
- WRITE_BOOL_FIELD(hasoids);
- WRITE_ENUM_FIELD(oncommit, OnCommitAction);
-}
-
-static void
-_outIndexStmt(StringInfo str, IndexStmt *node)
-{
- WRITE_NODE_TYPE("INDEX");
-
- WRITE_STRING_FIELD(idxname);
- WRITE_NODE_FIELD(relation);
- WRITE_STRING_FIELD(accessMethod);
- WRITE_NODE_FIELD(indexParams);
- WRITE_NODE_FIELD(whereClause);
- WRITE_NODE_FIELD(rangetable);
- WRITE_BOOL_FIELD(unique);
- WRITE_BOOL_FIELD(primary);
- WRITE_BOOL_FIELD(isconstraint);
-}
-
-static void
-_outNotifyStmt(StringInfo str, NotifyStmt *node)
-{
- WRITE_NODE_TYPE("NOTIFY");
-
- WRITE_NODE_FIELD(relation);
-}
-
-static void
-_outSelectStmt(StringInfo str, SelectStmt *node)
-{
- WRITE_NODE_TYPE("SELECT");
-
- /* XXX this is pretty durn incomplete */
- WRITE_NODE_FIELD(whereClause);
-}
-
-static void
-_outFuncCall(StringInfo str, FuncCall *node)
-{
- WRITE_NODE_TYPE("FUNCCALL");
-
- WRITE_NODE_FIELD(funcname);
- WRITE_NODE_FIELD(args);
- WRITE_BOOL_FIELD(agg_star);
- WRITE_BOOL_FIELD(agg_distinct);
-}
-
-static void
-_outColumnDef(StringInfo str, ColumnDef *node)
-{
- WRITE_NODE_TYPE("COLUMNDEF");
-
- WRITE_STRING_FIELD(colname);
- WRITE_NODE_FIELD(typename);
- WRITE_INT_FIELD(inhcount);
- WRITE_BOOL_FIELD(is_local);
- WRITE_BOOL_FIELD(is_not_null);
- WRITE_NODE_FIELD(raw_default);
- WRITE_STRING_FIELD(cooked_default);
- WRITE_NODE_FIELD(constraints);
- WRITE_NODE_FIELD(support);
-}
-
-static void
-_outTypeName(StringInfo str, TypeName *node)
-{
- WRITE_NODE_TYPE("TYPENAME");
-
- WRITE_NODE_FIELD(names);
- WRITE_OID_FIELD(typeid);
- WRITE_BOOL_FIELD(timezone);
- WRITE_BOOL_FIELD(setof);
- WRITE_BOOL_FIELD(pct_type);
- WRITE_INT_FIELD(typmod);
- WRITE_NODE_FIELD(arrayBounds);
-}
-
-static void
-_outTypeCast(StringInfo str, TypeCast *node)
-{
- WRITE_NODE_TYPE("TYPECAST");
-
- WRITE_NODE_FIELD(arg);
- WRITE_NODE_FIELD(typename);
-}
-
-static void
-_outIndexElem(StringInfo str, IndexElem *node)
-{
- WRITE_NODE_TYPE("INDEXELEM");
-
- WRITE_STRING_FIELD(name);
- WRITE_NODE_FIELD(funcname);
- WRITE_NODE_FIELD(args);
- WRITE_NODE_FIELD(opclass);
-}
-
-static void
-_outQuery(StringInfo str, Query *node)
+_outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
{
- WRITE_NODE_TYPE("QUERY");
+ Size length,
+ i;
+ char *s;
- WRITE_ENUM_FIELD(commandType, CmdType);
- WRITE_ENUM_FIELD(querySource, QuerySource);
+ length = datumGetSize(value, typbyval, typlen);
- /*
- * Hack to work around missing outfuncs routines for a lot of the
- * utility-statement node types. (The only one we actually *need* for
- * rules support is NotifyStmt.) Someday we ought to support 'em all,
- * but for the meantime do this to avoid getting lots of warnings when
- * running with debug_print_parse on.
- */
- if (node->utilityStmt)
+ if (typbyval)
{
- switch (nodeTag(node->utilityStmt))
+ s = (char *) (&value);
+ appendStringInfo(str, "%u [ ", (unsigned int) length);
+ for (i = 0; i < (Size) sizeof(Datum); i++)
+ appendStringInfo(str, "%d ", (int) (s[i]));
+ appendStringInfo(str, "]");
+ }
+ else
+ {
+ s = (char *) DatumGetPointer(value);
+ if (!PointerIsValid(s))
+ appendStringInfo(str, "0 [ ]");
+ else
{
- case T_CreateStmt:
- case T_IndexStmt:
- case T_NotifyStmt:
- WRITE_NODE_FIELD(utilityStmt);
- break;
- default:
- appendStringInfo(str, " :utilityStmt ?");
- break;
+ appendStringInfo(str, "%u [ ", (unsigned int) length);
+ for (i = 0; i < length; i++)
+ appendStringInfo(str, "%d ", (int) (s[i]));
+ appendStringInfo(str, "]");
}
}
- else
- appendStringInfo(str, " :utilityStmt <>");
-
- WRITE_INT_FIELD(resultRelation);
- WRITE_NODE_FIELD(into);
- WRITE_BOOL_FIELD(isPortal);
- WRITE_BOOL_FIELD(isBinary);
- WRITE_BOOL_FIELD(hasAggs);
- WRITE_BOOL_FIELD(hasSubLinks);
- WRITE_NODE_FIELD(rtable);
- WRITE_NODE_FIELD(jointree);
- WRITE_INTLIST_FIELD(rowMarks);
- WRITE_NODE_FIELD(targetList);
- WRITE_NODE_FIELD(groupClause);
- WRITE_NODE_FIELD(havingQual);
- WRITE_NODE_FIELD(distinctClause);
- WRITE_NODE_FIELD(sortClause);
- WRITE_NODE_FIELD(limitOffset);
- WRITE_NODE_FIELD(limitCount);
- WRITE_NODE_FIELD(setOperations);
- WRITE_INTLIST_FIELD(resultRelations);
-
- /* planner-internal fields are not written out */
-}
-
-static void
-_outSortClause(StringInfo str, SortClause *node)
-{
- WRITE_NODE_TYPE("SORTCLAUSE");
-
- WRITE_UINT_FIELD(tleSortGroupRef);
- WRITE_OID_FIELD(sortop);
-}
-
-static void
-_outGroupClause(StringInfo str, GroupClause *node)
-{
- WRITE_NODE_TYPE("GROUPCLAUSE");
-
- WRITE_UINT_FIELD(tleSortGroupRef);
- WRITE_OID_FIELD(sortop);
}
-static void
-_outSetOperationStmt(StringInfo str, SetOperationStmt *node)
-{
- WRITE_NODE_TYPE("SETOPERATIONSTMT");
-
- WRITE_ENUM_FIELD(op, SetOperation);
- WRITE_BOOL_FIELD(all);
- WRITE_NODE_FIELD(larg);
- WRITE_NODE_FIELD(rarg);
- WRITE_OIDLIST_FIELD(colTypes);
-}
/*
* Stuff from plannodes.h
WRITE_NODE_FIELD(hashkeys);
}
-static void
-_outSubPlan(StringInfo str, SubPlan *node)
-{
- WRITE_NODE_TYPE("SUBPLAN");
-
- WRITE_NODE_FIELD(plan);
- WRITE_INT_FIELD(plan_id);
- WRITE_NODE_FIELD(rtable);
- WRITE_INTLIST_FIELD(setParam);
- WRITE_INTLIST_FIELD(parParam);
- WRITE_NODE_FIELD(sublink);
-}
-
/*****************************************************************************
*
* Stuff from primnodes.h.
}
static void
-_outExpr(StringInfo str, Expr *node)
+_outAlias(StringInfo str, Alias *node)
{
- char *opstr = NULL;
-
- WRITE_NODE_TYPE("EXPR");
-
- WRITE_OID_FIELD(typeOid);
-
- /* do-it-yourself enum representation */
- switch (node->opType)
- {
- case OP_EXPR:
- opstr = "op";
- break;
- case DISTINCT_EXPR:
- opstr = "distinct";
- break;
- case FUNC_EXPR:
- opstr = "func";
- break;
- case OR_EXPR:
- opstr = "or";
- break;
- case AND_EXPR:
- opstr = "and";
- break;
- case NOT_EXPR:
- opstr = "not";
- break;
- case SUBPLAN_EXPR:
- opstr = "subp";
- break;
- }
- appendStringInfo(str, " :opType ");
- _outToken(str, opstr);
+ WRITE_NODE_TYPE("ALIAS");
- WRITE_NODE_FIELD(oper);
- WRITE_NODE_FIELD(args);
+ WRITE_STRING_FIELD(aliasname);
+ WRITE_NODE_FIELD(colnames);
}
static void
-_outVar(StringInfo str, Var *node)
+_outRangeVar(StringInfo str, RangeVar *node)
{
- WRITE_NODE_TYPE("VAR");
+ WRITE_NODE_TYPE("RANGEVAR");
- WRITE_UINT_FIELD(varno);
- WRITE_INT_FIELD(varattno);
- WRITE_OID_FIELD(vartype);
- WRITE_INT_FIELD(vartypmod);
- WRITE_UINT_FIELD(varlevelsup);
- WRITE_UINT_FIELD(varnoold);
- WRITE_INT_FIELD(varoattno);
+ /*
+ * we deliberately ignore catalogname here, since it is presently not
+ * semantically meaningful
+ */
+ WRITE_STRING_FIELD(schemaname);
+ WRITE_STRING_FIELD(relname);
+ WRITE_ENUM_FIELD(inhOpt, InhOption);
+ WRITE_BOOL_FIELD(istemp);
+ WRITE_NODE_FIELD(alias);
+}
+
+static void
+_outVar(StringInfo str, Var *node)
+{
+ WRITE_NODE_TYPE("VAR");
+
+ WRITE_UINT_FIELD(varno);
+ WRITE_INT_FIELD(varattno);
+ WRITE_OID_FIELD(vartype);
+ WRITE_INT_FIELD(vartypmod);
+ WRITE_UINT_FIELD(varlevelsup);
+ WRITE_UINT_FIELD(varnoold);
+ WRITE_INT_FIELD(varoattno);
}
static void
_outDatum(str, node->constvalue, node->constlen, node->constbyval);
}
+static void
+_outParam(StringInfo str, Param *node)
+{
+ WRITE_NODE_TYPE("PARAM");
+
+ WRITE_INT_FIELD(paramkind);
+ WRITE_INT_FIELD(paramid);
+ WRITE_STRING_FIELD(paramname);
+ WRITE_OID_FIELD(paramtype);
+}
+
static void
_outAggref(StringInfo str, Aggref *node)
{
WRITE_NODE_FIELD(target);
WRITE_BOOL_FIELD(aggstar);
WRITE_BOOL_FIELD(aggdistinct);
- /* aggno is not saved since it is just executor state */
-}
-
-static void
-_outSubLink(StringInfo str, SubLink *node)
-{
- WRITE_NODE_TYPE("SUBLINK");
-
- WRITE_ENUM_FIELD(subLinkType, SubLinkType);
- WRITE_BOOL_FIELD(useor);
- WRITE_NODE_FIELD(lefthand);
- WRITE_NODE_FIELD(oper);
- WRITE_NODE_FIELD(subselect);
}
static void
}
static void
-_outFunc(StringInfo str, Func *node)
+_outFuncExpr(StringInfo str, FuncExpr *node)
{
- WRITE_NODE_TYPE("FUNC");
+ WRITE_NODE_TYPE("FUNCEXPR");
WRITE_OID_FIELD(funcid);
WRITE_OID_FIELD(funcresulttype);
WRITE_BOOL_FIELD(funcretset);
WRITE_ENUM_FIELD(funcformat, CoercionForm);
+ WRITE_NODE_FIELD(args);
+}
+
+static void
+_outOpExpr(StringInfo str, OpExpr *node)
+{
+ WRITE_NODE_TYPE("OPEXPR");
+
+ WRITE_OID_FIELD(opno);
+ WRITE_OID_FIELD(opfuncid);
+ WRITE_OID_FIELD(opresulttype);
+ WRITE_BOOL_FIELD(opretset);
+ WRITE_NODE_FIELD(args);
}
static void
-_outOper(StringInfo str, Oper *node)
+_outDistinctExpr(StringInfo str, DistinctExpr *node)
{
- WRITE_NODE_TYPE("OPER");
+ WRITE_NODE_TYPE("DISTINCTEXPR");
WRITE_OID_FIELD(opno);
- WRITE_OID_FIELD(opid);
+ WRITE_OID_FIELD(opfuncid);
WRITE_OID_FIELD(opresulttype);
WRITE_BOOL_FIELD(opretset);
+ WRITE_NODE_FIELD(args);
}
static void
-_outParam(StringInfo str, Param *node)
+_outBoolExpr(StringInfo str, BoolExpr *node)
{
- WRITE_NODE_TYPE("PARAM");
+ char *opstr = NULL;
- WRITE_INT_FIELD(paramkind);
- WRITE_INT_FIELD(paramid);
- WRITE_STRING_FIELD(paramname);
- WRITE_OID_FIELD(paramtype);
+ WRITE_NODE_TYPE("BOOLEXPR");
+
+ /* do-it-yourself enum representation */
+ switch (node->boolop)
+ {
+ case AND_EXPR:
+ opstr = "and";
+ break;
+ case OR_EXPR:
+ opstr = "or";
+ break;
+ case NOT_EXPR:
+ opstr = "not";
+ break;
+ }
+ appendStringInfo(str, " :boolop ");
+ _outToken(str, opstr);
+
+ WRITE_NODE_FIELD(args);
+}
+
+static void
+_outSubLink(StringInfo str, SubLink *node)
+{
+ WRITE_NODE_TYPE("SUBLINK");
+
+ WRITE_ENUM_FIELD(subLinkType, SubLinkType);
+ WRITE_BOOL_FIELD(useor);
+ WRITE_NODE_FIELD(lefthand);
+ WRITE_NODE_FIELD(oper);
+ WRITE_NODE_FIELD(subselect);
+}
+
+static void
+_outSubPlanExpr(StringInfo str, SubPlanExpr *node)
+{
+ WRITE_NODE_TYPE("SUBPLANEXPR");
+
+ WRITE_OID_FIELD(typeOid);
+ WRITE_NODE_FIELD(plan);
+ WRITE_INT_FIELD(plan_id);
+ WRITE_NODE_FIELD(rtable);
+ WRITE_INTLIST_FIELD(setParam);
+ WRITE_INTLIST_FIELD(parParam);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(sublink);
}
static void
}
static void
-_outRangeTblRef(StringInfo str, RangeTblRef *node)
+_outCaseExpr(StringInfo str, CaseExpr *node)
{
- WRITE_NODE_TYPE("RANGETBLREF");
+ WRITE_NODE_TYPE("CASE");
- WRITE_INT_FIELD(rtindex);
+ WRITE_OID_FIELD(casetype);
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(defresult);
}
static void
-_outJoinExpr(StringInfo str, JoinExpr *node)
+_outCaseWhen(StringInfo str, CaseWhen *node)
{
- WRITE_NODE_TYPE("JOINEXPR");
+ WRITE_NODE_TYPE("WHEN");
- WRITE_ENUM_FIELD(jointype, JoinType);
- WRITE_BOOL_FIELD(isNatural);
- WRITE_NODE_FIELD(larg);
- WRITE_NODE_FIELD(rarg);
- WRITE_NODE_FIELD(using);
- WRITE_NODE_FIELD(quals);
- WRITE_NODE_FIELD(alias);
- WRITE_INT_FIELD(rtindex);
+ WRITE_NODE_FIELD(expr);
+ WRITE_NODE_FIELD(result);
}
static void
-_outFromExpr(StringInfo str, FromExpr *node)
+_outNullTest(StringInfo str, NullTest *node)
{
- WRITE_NODE_TYPE("FROMEXPR");
+ WRITE_NODE_TYPE("NULLTEST");
- WRITE_NODE_FIELD(fromlist);
- WRITE_NODE_FIELD(quals);
+ WRITE_NODE_FIELD(arg);
+ WRITE_ENUM_FIELD(nulltesttype, NullTestType);
+}
+
+static void
+_outBooleanTest(StringInfo str, BooleanTest *node)
+{
+ WRITE_NODE_TYPE("BOOLEANTEST");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_ENUM_FIELD(booltesttype, BoolTestType);
+}
+
+static void
+_outConstraintTest(StringInfo str, ConstraintTest *node)
+{
+ WRITE_NODE_TYPE("CONSTRAINTTEST");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_ENUM_FIELD(testtype, ConstraintTestType);
+ WRITE_STRING_FIELD(name);
+ WRITE_STRING_FIELD(domname);
+ WRITE_NODE_FIELD(check_expr);
+}
+
+static void
+_outConstraintTestValue(StringInfo str, ConstraintTestValue *node)
+{
+ WRITE_NODE_TYPE("CONSTRAINTTESTVALUE");
+
+ WRITE_OID_FIELD(typeId);
+ WRITE_INT_FIELD(typeMod);
}
static void
WRITE_NODE_TYPE("TARGETENTRY");
WRITE_NODE_FIELD(resdom);
- /* fjoin not supported ... */
WRITE_NODE_FIELD(expr);
}
static void
-_outAlias(StringInfo str, Alias *node)
+_outRangeTblRef(StringInfo str, RangeTblRef *node)
{
- WRITE_NODE_TYPE("ALIAS");
+ WRITE_NODE_TYPE("RANGETBLREF");
- WRITE_STRING_FIELD(aliasname);
- WRITE_NODE_FIELD(colnames);
+ WRITE_INT_FIELD(rtindex);
}
static void
-_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
+_outJoinExpr(StringInfo str, JoinExpr *node)
{
- WRITE_NODE_TYPE("RTE");
+ WRITE_NODE_TYPE("JOINEXPR");
- /* put alias + eref first to make dump more legible */
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(isNatural);
+ WRITE_NODE_FIELD(larg);
+ WRITE_NODE_FIELD(rarg);
+ WRITE_NODE_FIELD(using);
+ WRITE_NODE_FIELD(quals);
WRITE_NODE_FIELD(alias);
- WRITE_NODE_FIELD(eref);
- WRITE_ENUM_FIELD(rtekind, RTEKind);
+ WRITE_INT_FIELD(rtindex);
+}
- switch (node->rtekind)
- {
- case RTE_RELATION:
- case RTE_SPECIAL:
- WRITE_OID_FIELD(relid);
- break;
- case RTE_SUBQUERY:
- WRITE_NODE_FIELD(subquery);
- break;
- case RTE_FUNCTION:
- WRITE_NODE_FIELD(funcexpr);
- WRITE_NODE_FIELD(coldeflist);
- break;
- case RTE_JOIN:
- WRITE_ENUM_FIELD(jointype, JoinType);
- WRITE_NODE_FIELD(joinaliasvars);
- break;
- default:
- elog(ERROR, "bogus rte kind %d", (int) node->rtekind);
- break;
- }
+static void
+_outFromExpr(StringInfo str, FromExpr *node)
+{
+ WRITE_NODE_TYPE("FROMEXPR");
- WRITE_BOOL_FIELD(inh);
- WRITE_BOOL_FIELD(inFromCl);
- WRITE_BOOL_FIELD(checkForRead);
- WRITE_BOOL_FIELD(checkForWrite);
- WRITE_OID_FIELD(checkAsUser);
+ WRITE_NODE_FIELD(fromlist);
+ WRITE_NODE_FIELD(quals);
}
+/*****************************************************************************
+ *
+ * Stuff from relation.h.
+ *
+ *****************************************************************************/
+
/*
* print the basic stuff of all nodes that inherit from Path
*
WRITE_NODE_FIELD(jinfo_restrictinfo);
}
-/*
- * Print the value of a Datum given its type.
- */
+/*****************************************************************************
+ *
+ * Stuff from parsenodes.h.
+ *
+ *****************************************************************************/
+
static void
-_outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
+_outCreateStmt(StringInfo str, CreateStmt *node)
{
- Size length,
- i;
- char *s;
+ WRITE_NODE_TYPE("CREATE");
- length = datumGetSize(value, typbyval, typlen);
+ WRITE_NODE_FIELD(relation);
+ WRITE_NODE_FIELD(tableElts);
+ WRITE_NODE_FIELD(inhRelations);
+ WRITE_NODE_FIELD(constraints);
+ WRITE_BOOL_FIELD(hasoids);
+ WRITE_ENUM_FIELD(oncommit, OnCommitAction);
+}
- if (typbyval)
- {
- s = (char *) (&value);
- appendStringInfo(str, "%u [ ", (unsigned int) length);
- for (i = 0; i < (Size) sizeof(Datum); i++)
- appendStringInfo(str, "%d ", (int) (s[i]));
- appendStringInfo(str, "]");
- }
- else
+static void
+_outIndexStmt(StringInfo str, IndexStmt *node)
+{
+ WRITE_NODE_TYPE("INDEX");
+
+ WRITE_STRING_FIELD(idxname);
+ WRITE_NODE_FIELD(relation);
+ WRITE_STRING_FIELD(accessMethod);
+ WRITE_NODE_FIELD(indexParams);
+ WRITE_NODE_FIELD(whereClause);
+ WRITE_NODE_FIELD(rangetable);
+ WRITE_BOOL_FIELD(unique);
+ WRITE_BOOL_FIELD(primary);
+ WRITE_BOOL_FIELD(isconstraint);
+}
+
+static void
+_outNotifyStmt(StringInfo str, NotifyStmt *node)
+{
+ WRITE_NODE_TYPE("NOTIFY");
+
+ WRITE_NODE_FIELD(relation);
+}
+
+static void
+_outSelectStmt(StringInfo str, SelectStmt *node)
+{
+ WRITE_NODE_TYPE("SELECT");
+
+ /* XXX this is pretty durn incomplete */
+ WRITE_NODE_FIELD(whereClause);
+}
+
+static void
+_outFuncCall(StringInfo str, FuncCall *node)
+{
+ WRITE_NODE_TYPE("FUNCCALL");
+
+ WRITE_NODE_FIELD(funcname);
+ WRITE_NODE_FIELD(args);
+ WRITE_BOOL_FIELD(agg_star);
+ WRITE_BOOL_FIELD(agg_distinct);
+}
+
+static void
+_outColumnDef(StringInfo str, ColumnDef *node)
+{
+ WRITE_NODE_TYPE("COLUMNDEF");
+
+ WRITE_STRING_FIELD(colname);
+ WRITE_NODE_FIELD(typename);
+ WRITE_INT_FIELD(inhcount);
+ WRITE_BOOL_FIELD(is_local);
+ WRITE_BOOL_FIELD(is_not_null);
+ WRITE_NODE_FIELD(raw_default);
+ WRITE_STRING_FIELD(cooked_default);
+ WRITE_NODE_FIELD(constraints);
+ WRITE_NODE_FIELD(support);
+}
+
+static void
+_outTypeName(StringInfo str, TypeName *node)
+{
+ WRITE_NODE_TYPE("TYPENAME");
+
+ WRITE_NODE_FIELD(names);
+ WRITE_OID_FIELD(typeid);
+ WRITE_BOOL_FIELD(timezone);
+ WRITE_BOOL_FIELD(setof);
+ WRITE_BOOL_FIELD(pct_type);
+ WRITE_INT_FIELD(typmod);
+ WRITE_NODE_FIELD(arrayBounds);
+}
+
+static void
+_outTypeCast(StringInfo str, TypeCast *node)
+{
+ WRITE_NODE_TYPE("TYPECAST");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(typename);
+}
+
+static void
+_outIndexElem(StringInfo str, IndexElem *node)
+{
+ WRITE_NODE_TYPE("INDEXELEM");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(funcname);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(opclass);
+}
+
+static void
+_outQuery(StringInfo str, Query *node)
+{
+ WRITE_NODE_TYPE("QUERY");
+
+ WRITE_ENUM_FIELD(commandType, CmdType);
+ WRITE_ENUM_FIELD(querySource, QuerySource);
+
+ /*
+ * Hack to work around missing outfuncs routines for a lot of the
+ * utility-statement node types. (The only one we actually *need* for
+ * rules support is NotifyStmt.) Someday we ought to support 'em all,
+ * but for the meantime do this to avoid getting lots of warnings when
+ * running with debug_print_parse on.
+ */
+ if (node->utilityStmt)
{
- s = (char *) DatumGetPointer(value);
- if (!PointerIsValid(s))
- appendStringInfo(str, "0 [ ]");
- else
+ switch (nodeTag(node->utilityStmt))
{
- appendStringInfo(str, "%u [ ", (unsigned int) length);
- for (i = 0; i < length; i++)
- appendStringInfo(str, "%d ", (int) (s[i]));
- appendStringInfo(str, "]");
+ case T_CreateStmt:
+ case T_IndexStmt:
+ case T_NotifyStmt:
+ WRITE_NODE_FIELD(utilityStmt);
+ break;
+ default:
+ appendStringInfo(str, " :utilityStmt ?");
+ break;
}
}
+ else
+ appendStringInfo(str, " :utilityStmt <>");
+
+ WRITE_INT_FIELD(resultRelation);
+ WRITE_NODE_FIELD(into);
+ WRITE_BOOL_FIELD(isPortal);
+ WRITE_BOOL_FIELD(isBinary);
+ WRITE_BOOL_FIELD(hasAggs);
+ WRITE_BOOL_FIELD(hasSubLinks);
+ WRITE_NODE_FIELD(rtable);
+ WRITE_NODE_FIELD(jointree);
+ WRITE_INTLIST_FIELD(rowMarks);
+ WRITE_NODE_FIELD(targetList);
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(havingQual);
+ WRITE_NODE_FIELD(distinctClause);
+ WRITE_NODE_FIELD(sortClause);
+ WRITE_NODE_FIELD(limitOffset);
+ WRITE_NODE_FIELD(limitCount);
+ WRITE_NODE_FIELD(setOperations);
+ WRITE_INTLIST_FIELD(resultRelations);
+
+ /* planner-internal fields are not written out */
+}
+
+static void
+_outSortClause(StringInfo str, SortClause *node)
+{
+ WRITE_NODE_TYPE("SORTCLAUSE");
+
+ WRITE_UINT_FIELD(tleSortGroupRef);
+ WRITE_OID_FIELD(sortop);
+}
+
+static void
+_outGroupClause(StringInfo str, GroupClause *node)
+{
+ WRITE_NODE_TYPE("GROUPCLAUSE");
+
+ WRITE_UINT_FIELD(tleSortGroupRef);
+ WRITE_OID_FIELD(sortop);
+}
+
+static void
+_outSetOperationStmt(StringInfo str, SetOperationStmt *node)
+{
+ WRITE_NODE_TYPE("SETOPERATIONSTMT");
+
+ WRITE_ENUM_FIELD(op, SetOperation);
+ WRITE_BOOL_FIELD(all);
+ WRITE_NODE_FIELD(larg);
+ WRITE_NODE_FIELD(rarg);
+ WRITE_OIDLIST_FIELD(colTypes);
+}
+
+static void
+_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
+{
+ WRITE_NODE_TYPE("RTE");
+
+ /* put alias + eref first to make dump more legible */
+ WRITE_NODE_FIELD(alias);
+ WRITE_NODE_FIELD(eref);
+ WRITE_ENUM_FIELD(rtekind, RTEKind);
+
+ switch (node->rtekind)
+ {
+ case RTE_RELATION:
+ case RTE_SPECIAL:
+ WRITE_OID_FIELD(relid);
+ break;
+ case RTE_SUBQUERY:
+ WRITE_NODE_FIELD(subquery);
+ break;
+ case RTE_FUNCTION:
+ WRITE_NODE_FIELD(funcexpr);
+ WRITE_NODE_FIELD(coldeflist);
+ break;
+ case RTE_JOIN:
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_NODE_FIELD(joinaliasvars);
+ break;
+ default:
+ elog(ERROR, "bogus rte kind %d", (int) node->rtekind);
+ break;
+ }
+
+ WRITE_BOOL_FIELD(inh);
+ WRITE_BOOL_FIELD(inFromCl);
+ WRITE_BOOL_FIELD(checkForRead);
+ WRITE_BOOL_FIELD(checkForWrite);
+ WRITE_OID_FIELD(checkAsUser);
}
static void
}
}
-static void
-_outRangeVar(StringInfo str, RangeVar *node)
-{
- WRITE_NODE_TYPE("RANGEVAR");
-
- /*
- * we deliberately ignore catalogname here, since it is presently not
- * semantically meaningful
- */
- WRITE_STRING_FIELD(schemaname);
- WRITE_STRING_FIELD(relname);
- WRITE_ENUM_FIELD(inhOpt, InhOption);
- WRITE_BOOL_FIELD(istemp);
- WRITE_NODE_FIELD(alias);
-}
-
static void
_outColumnRef(StringInfo str, ColumnRef *node)
{
WRITE_NODE_FIELD(indirection);
}
+static void
+_outDomainConstraintValue(StringInfo str, DomainConstraintValue *node)
+{
+ WRITE_NODE_TYPE("DOMAINCONSTRAINTVALUE");
+}
+
static void
_outConstraint(StringInfo str, Constraint *node)
{
WRITE_BOOL_FIELD(skip_validation);
}
-static void
-_outCaseExpr(StringInfo str, CaseExpr *node)
-{
- WRITE_NODE_TYPE("CASE");
-
- WRITE_OID_FIELD(casetype);
- WRITE_NODE_FIELD(arg);
- WRITE_NODE_FIELD(args);
- WRITE_NODE_FIELD(defresult);
-}
-
-static void
-_outCaseWhen(StringInfo str, CaseWhen *node)
-{
- WRITE_NODE_TYPE("WHEN");
-
- WRITE_NODE_FIELD(expr);
- WRITE_NODE_FIELD(result);
-}
-
-static void
-_outNullTest(StringInfo str, NullTest *node)
-{
- WRITE_NODE_TYPE("NULLTEST");
-
- WRITE_NODE_FIELD(arg);
- WRITE_ENUM_FIELD(nulltesttype, NullTestType);
-}
-
-static void
-_outBooleanTest(StringInfo str, BooleanTest *node)
-{
- WRITE_NODE_TYPE("BOOLEANTEST");
-
- WRITE_NODE_FIELD(arg);
- WRITE_ENUM_FIELD(booltesttype, BoolTestType);
-}
-
-static void
-_outConstraintTest(StringInfo str, ConstraintTest *node)
-{
- WRITE_NODE_TYPE("CONSTRAINTTEST");
-
- WRITE_NODE_FIELD(arg);
- WRITE_ENUM_FIELD(testtype, ConstraintTestType);
- WRITE_STRING_FIELD(name);
- WRITE_STRING_FIELD(domname);
- WRITE_NODE_FIELD(check_expr);
-}
-
-static void
-_outDomainConstraintValue(StringInfo str, DomainConstraintValue *node)
-{
- WRITE_NODE_TYPE("DOMAINCONSTRAINTVALUE");
-}
-
-static void
-_outConstraintTestValue(StringInfo str, ConstraintTestValue *node)
-{
- WRITE_NODE_TYPE("CONSTRAINTTESTVALUE");
-
- WRITE_OID_FIELD(typeId);
- WRITE_INT_FIELD(typeMod);
-}
-
/*
* _outNode -
appendStringInfoChar(str, '{');
switch (nodeTag(obj))
{
- case T_CreateStmt:
- _outCreateStmt(str, obj);
- break;
- case T_IndexStmt:
- _outIndexStmt(str, obj);
- break;
- case T_NotifyStmt:
- _outNotifyStmt(str, obj);
- break;
- case T_SelectStmt:
- _outSelectStmt(str, obj);
- break;
- case T_ColumnDef:
- _outColumnDef(str, obj);
- break;
- case T_TypeName:
- _outTypeName(str, obj);
- break;
- case T_TypeCast:
- _outTypeCast(str, obj);
- break;
- case T_IndexElem:
- _outIndexElem(str, obj);
- break;
- case T_Query:
- _outQuery(str, obj);
- break;
- case T_SortClause:
- _outSortClause(str, obj);
- break;
- case T_GroupClause:
- _outGroupClause(str, obj);
- break;
- case T_SetOperationStmt:
- _outSetOperationStmt(str, obj);
- break;
case T_Plan:
_outPlan(str, obj);
break;
case T_Append:
_outAppend(str, obj);
break;
- case T_Join:
- _outJoin(str, obj);
- break;
- case T_NestLoop:
- _outNestLoop(str, obj);
- break;
- case T_MergeJoin:
- _outMergeJoin(str, obj);
- break;
- case T_HashJoin:
- _outHashJoin(str, obj);
- break;
case T_Scan:
_outScan(str, obj);
break;
case T_FunctionScan:
_outFunctionScan(str, obj);
break;
- case T_Material:
- _outMaterial(str, obj);
+ case T_Join:
+ _outJoin(str, obj);
break;
- case T_Sort:
- _outSort(str, obj);
+ case T_NestLoop:
+ _outNestLoop(str, obj);
+ break;
+ case T_MergeJoin:
+ _outMergeJoin(str, obj);
+ break;
+ case T_HashJoin:
+ _outHashJoin(str, obj);
break;
case T_Agg:
_outAgg(str, obj);
case T_Group:
_outGroup(str, obj);
break;
+ case T_Material:
+ _outMaterial(str, obj);
+ break;
+ case T_Sort:
+ _outSort(str, obj);
+ break;
case T_Unique:
_outUnique(str, obj);
break;
case T_Hash:
_outHash(str, obj);
break;
- case T_SubPlan:
- _outSubPlan(str, obj);
- break;
case T_Resdom:
_outResdom(str, obj);
break;
- case T_Expr:
- _outExpr(str, obj);
+ case T_Alias:
+ _outAlias(str, obj);
+ break;
+ case T_RangeVar:
+ _outRangeVar(str, obj);
break;
case T_Var:
_outVar(str, obj);
case T_Const:
_outConst(str, obj);
break;
+ case T_Param:
+ _outParam(str, obj);
+ break;
case T_Aggref:
_outAggref(str, obj);
break;
- case T_SubLink:
- _outSubLink(str, obj);
- break;
case T_ArrayRef:
_outArrayRef(str, obj);
break;
- case T_Func:
- _outFunc(str, obj);
+ case T_FuncExpr:
+ _outFuncExpr(str, obj);
break;
- case T_Oper:
- _outOper(str, obj);
+ case T_OpExpr:
+ _outOpExpr(str, obj);
break;
- case T_Param:
- _outParam(str, obj);
+ case T_DistinctExpr:
+ _outDistinctExpr(str, obj);
+ break;
+ case T_BoolExpr:
+ _outBoolExpr(str, obj);
+ break;
+ case T_SubLink:
+ _outSubLink(str, obj);
+ break;
+ case T_SubPlanExpr:
+ _outSubPlanExpr(str, obj);
break;
case T_FieldSelect:
_outFieldSelect(str, obj);
case T_RelabelType:
_outRelabelType(str, obj);
break;
- case T_RangeTblRef:
- _outRangeTblRef(str, obj);
+ case T_CaseExpr:
+ _outCaseExpr(str, obj);
break;
- case T_FromExpr:
- _outFromExpr(str, obj);
+ case T_CaseWhen:
+ _outCaseWhen(str, obj);
break;
- case T_JoinExpr:
- _outJoinExpr(str, obj);
+ case T_NullTest:
+ _outNullTest(str, obj);
+ break;
+ case T_BooleanTest:
+ _outBooleanTest(str, obj);
+ break;
+ case T_ConstraintTest:
+ _outConstraintTest(str, obj);
+ break;
+ case T_ConstraintTestValue:
+ _outConstraintTestValue(str, obj);
break;
case T_TargetEntry:
_outTargetEntry(str, obj);
break;
- case T_Alias:
- _outAlias(str, obj);
+ case T_RangeTblRef:
+ _outRangeTblRef(str, obj);
break;
- case T_RangeTblEntry:
- _outRangeTblEntry(str, obj);
+ case T_JoinExpr:
+ _outJoinExpr(str, obj);
+ break;
+ case T_FromExpr:
+ _outFromExpr(str, obj);
break;
+
case T_Path:
_outPath(str, obj);
break;
case T_JoinInfo:
_outJoinInfo(str, obj);
break;
+
+ case T_CreateStmt:
+ _outCreateStmt(str, obj);
+ break;
+ case T_IndexStmt:
+ _outIndexStmt(str, obj);
+ break;
+ case T_NotifyStmt:
+ _outNotifyStmt(str, obj);
+ break;
+ case T_SelectStmt:
+ _outSelectStmt(str, obj);
+ break;
+ case T_ColumnDef:
+ _outColumnDef(str, obj);
+ break;
+ case T_TypeName:
+ _outTypeName(str, obj);
+ break;
+ case T_TypeCast:
+ _outTypeCast(str, obj);
+ break;
+ case T_IndexElem:
+ _outIndexElem(str, obj);
+ break;
+ case T_Query:
+ _outQuery(str, obj);
+ break;
+ case T_SortClause:
+ _outSortClause(str, obj);
+ break;
+ case T_GroupClause:
+ _outGroupClause(str, obj);
+ break;
+ case T_SetOperationStmt:
+ _outSetOperationStmt(str, obj);
+ break;
+ case T_RangeTblEntry:
+ _outRangeTblEntry(str, obj);
+ break;
case T_A_Expr:
_outAExpr(str, obj);
break;
- case T_RangeVar:
- _outRangeVar(str, obj);
- break;
case T_ColumnRef:
_outColumnRef(str, obj);
break;
case T_ExprFieldSelect:
_outExprFieldSelect(str, obj);
break;
+ case T_DomainConstraintValue:
+ _outDomainConstraintValue(str, obj);
+ break;
case T_Constraint:
_outConstraint(str, obj);
break;
case T_FkConstraint:
_outFkConstraint(str, obj);
break;
- case T_CaseExpr:
- _outCaseExpr(str, obj);
- break;
- case T_CaseWhen:
- _outCaseWhen(str, obj);
- break;
- case T_NullTest:
- _outNullTest(str, obj);
- break;
- case T_BooleanTest:
- _outBooleanTest(str, obj);
- break;
- case T_ConstraintTest:
- _outConstraintTest(str, obj);
- break;
- case T_ConstraintTestValue:
- _outConstraintTestValue(str, obj);
- break;
case T_FuncCall:
_outFuncCall(str, obj);
break;
- case T_DomainConstraintValue:
- _outDomainConstraintValue(str, obj);
- break;
default:
elog(WARNING, "_outNode: don't know how to print type %d",
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.57 2002/09/04 20:31:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.58 2002/12/12 15:49:28 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
char *opname;
print_expr((Node *) get_leftop(e), rtable);
- opname = get_opname(((Oper *) e->oper)->opno);
+ opname = get_opname(((OpExpr *) e)->opno);
printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)"));
print_expr((Node *) get_rightop(e), rtable);
}
printf("(%d):\t", tle->resdom->reskey);
else
printf(" :\t");
- print_expr(tle->expr, rtable);
+ print_expr((Node *) tle->expr, rtable);
printf("\n");
}
printf(")\n");
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.140 2002/11/25 21:29:38 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.141 2002/12/12 15:49:28 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
READ_DONE();
}
-/*
- * _readExpr
- */
-static Expr *
-_readExpr(void)
+static Alias *
+_readAlias(void)
{
- READ_LOCALS(Expr);
+ READ_LOCALS(Alias);
- READ_OID_FIELD(typeOid);
+ READ_STRING_FIELD(aliasname);
+ READ_NODE_FIELD(colnames);
- /* do-it-yourself enum representation */
- token = pg_strtok(&length); /* skip :opType */
- token = pg_strtok(&length); /* get field value */
- if (strncmp(token, "op", 2) == 0)
- local_node->opType = OP_EXPR;
- else if (strncmp(token, "distinct", 8) == 0)
- local_node->opType = DISTINCT_EXPR;
- else if (strncmp(token, "func", 4) == 0)
- local_node->opType = FUNC_EXPR;
- else if (strncmp(token, "or", 2) == 0)
- local_node->opType = OR_EXPR;
- else if (strncmp(token, "and", 3) == 0)
- local_node->opType = AND_EXPR;
- else if (strncmp(token, "not", 3) == 0)
- local_node->opType = NOT_EXPR;
- else if (strncmp(token, "subp", 4) == 0)
- local_node->opType = SUBPLAN_EXPR;
- else
- elog(ERROR, "_readExpr: unknown opType \"%.*s\"", length, token);
+ READ_DONE();
+}
- READ_NODE_FIELD(oper);
- READ_NODE_FIELD(args);
+static RangeVar *
+_readRangeVar(void)
+{
+ READ_LOCALS(RangeVar);
+
+ local_node->catalogname = NULL; /* not currently saved in output
+ * format */
+
+ READ_STRING_FIELD(schemaname);
+ READ_STRING_FIELD(relname);
+ READ_ENUM_FIELD(inhOpt, InhOption);
+ READ_BOOL_FIELD(istemp);
+ READ_NODE_FIELD(alias);
READ_DONE();
}
READ_DONE();
}
-/*
- * _readArrayRef
- */
-static ArrayRef *
-_readArrayRef(void)
-{
- READ_LOCALS(ArrayRef);
-
- READ_OID_FIELD(refrestype);
- READ_INT_FIELD(refattrlength);
- READ_INT_FIELD(refelemlength);
- READ_BOOL_FIELD(refelembyval);
- READ_CHAR_FIELD(refelemalign);
- READ_NODE_FIELD(refupperindexpr);
- READ_NODE_FIELD(reflowerindexpr);
- READ_NODE_FIELD(refexpr);
- READ_NODE_FIELD(refassgnexpr);
-
- READ_DONE();
-}
-
/*
* _readConst
*/
}
/*
- * _readFunc
+ * _readParam
+ */
+static Param *
+_readParam(void)
+{
+ READ_LOCALS(Param);
+
+ READ_INT_FIELD(paramkind);
+ READ_INT_FIELD(paramid);
+ READ_STRING_FIELD(paramname);
+ READ_OID_FIELD(paramtype);
+
+ READ_DONE();
+}
+
+/*
+ * _readAggref
+ */
+static Aggref *
+_readAggref(void)
+{
+ READ_LOCALS(Aggref);
+
+ READ_OID_FIELD(aggfnoid);
+ READ_OID_FIELD(aggtype);
+ READ_NODE_FIELD(target);
+ READ_BOOL_FIELD(aggstar);
+ READ_BOOL_FIELD(aggdistinct);
+
+ READ_DONE();
+}
+
+/*
+ * _readArrayRef
*/
-static Func *
-_readFunc(void)
+static ArrayRef *
+_readArrayRef(void)
{
- READ_LOCALS(Func);
+ READ_LOCALS(ArrayRef);
+
+ READ_OID_FIELD(refrestype);
+ READ_INT_FIELD(refattrlength);
+ READ_INT_FIELD(refelemlength);
+ READ_BOOL_FIELD(refelembyval);
+ READ_CHAR_FIELD(refelemalign);
+ READ_NODE_FIELD(refupperindexpr);
+ READ_NODE_FIELD(reflowerindexpr);
+ READ_NODE_FIELD(refexpr);
+ READ_NODE_FIELD(refassgnexpr);
+
+ READ_DONE();
+}
+
+/*
+ * _readFuncExpr
+ */
+static FuncExpr *
+_readFuncExpr(void)
+{
+ READ_LOCALS(FuncExpr);
READ_OID_FIELD(funcid);
READ_OID_FIELD(funcresulttype);
READ_BOOL_FIELD(funcretset);
READ_ENUM_FIELD(funcformat, CoercionForm);
+ READ_NODE_FIELD(args);
local_node->func_fcache = NULL;
}
/*
- * _readOper
+ * _readOpExpr
*/
-static Oper *
-_readOper(void)
+static OpExpr *
+_readOpExpr(void)
{
- READ_LOCALS(Oper);
+ READ_LOCALS(OpExpr);
READ_OID_FIELD(opno);
- READ_OID_FIELD(opid);
+ READ_OID_FIELD(opfuncid);
+ /*
+ * The opfuncid is stored in the textual format primarily for debugging
+ * and documentation reasons. We want to always read it as zero to force
+ * it to be re-looked-up in the pg_operator entry. This ensures that
+ * stored rules don't have hidden dependencies on operators' functions.
+ * (We don't currently support an ALTER OPERATOR command, but might
+ * someday.)
+ */
+ local_node->opfuncid = InvalidOid;
+
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
+ READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
}
/*
- * _readParam
+ * _readDistinctExpr
*/
-static Param *
-_readParam(void)
+static DistinctExpr *
+_readDistinctExpr(void)
{
- READ_LOCALS(Param);
-
- READ_INT_FIELD(paramkind);
- READ_INT_FIELD(paramid);
- READ_STRING_FIELD(paramname);
- READ_OID_FIELD(paramtype);
+ READ_LOCALS(DistinctExpr);
- READ_DONE();
-}
+ READ_OID_FIELD(opno);
+ READ_OID_FIELD(opfuncid);
+ /*
+ * The opfuncid is stored in the textual format primarily for debugging
+ * and documentation reasons. We want to always read it as zero to force
+ * it to be re-looked-up in the pg_operator entry. This ensures that
+ * stored rules don't have hidden dependencies on operators' functions.
+ * (We don't currently support an ALTER OPERATOR command, but might
+ * someday.)
+ */
+ local_node->opfuncid = InvalidOid;
-/*
- * _readAggref
- */
-static Aggref *
-_readAggref(void)
-{
- READ_LOCALS(Aggref);
+ READ_OID_FIELD(opresulttype);
+ READ_BOOL_FIELD(opretset);
+ READ_NODE_FIELD(args);
- READ_OID_FIELD(aggfnoid);
- READ_OID_FIELD(aggtype);
- READ_NODE_FIELD(target);
- READ_BOOL_FIELD(aggstar);
- READ_BOOL_FIELD(aggdistinct);
- /* aggno is not saved since it is just executor state */
+ local_node->op_fcache = NULL;
READ_DONE();
}
-static RangeVar *
-_readRangeVar(void)
+/*
+ * _readBoolExpr
+ */
+static BoolExpr *
+_readBoolExpr(void)
{
- READ_LOCALS(RangeVar);
+ READ_LOCALS(BoolExpr);
- local_node->catalogname = NULL; /* not currently saved in output
- * format */
+ /* do-it-yourself enum representation */
+ token = pg_strtok(&length); /* skip :boolop */
+ token = pg_strtok(&length); /* get field value */
+ if (strncmp(token, "and", 3) == 0)
+ local_node->boolop = AND_EXPR;
+ else if (strncmp(token, "or", 2) == 0)
+ local_node->boolop = OR_EXPR;
+ else if (strncmp(token, "not", 3) == 0)
+ local_node->boolop = NOT_EXPR;
+ else
+ elog(ERROR, "_readBoolExpr: unknown boolop \"%.*s\"", length, token);
- READ_STRING_FIELD(schemaname);
- READ_STRING_FIELD(relname);
- READ_ENUM_FIELD(inhOpt, InhOption);
- READ_BOOL_FIELD(istemp);
- READ_NODE_FIELD(alias);
+ READ_NODE_FIELD(args);
READ_DONE();
}
READ_DONE();
}
+/*
+ * _readSubPlanExpr is not needed since it doesn't appear in stored rules.
+ */
+
/*
* _readFieldSelect
*/
READ_DONE();
}
-/*
- * _readRangeTblRef
- */
-static RangeTblRef *
-_readRangeTblRef(void)
-{
- READ_LOCALS(RangeTblRef);
-
- READ_INT_FIELD(rtindex);
-
- READ_DONE();
-}
-
-/*
- * _readJoinExpr
- */
-static JoinExpr *
-_readJoinExpr(void)
-{
- READ_LOCALS(JoinExpr);
-
- READ_ENUM_FIELD(jointype, JoinType);
- READ_BOOL_FIELD(isNatural);
- READ_NODE_FIELD(larg);
- READ_NODE_FIELD(rarg);
- READ_NODE_FIELD(using);
- READ_NODE_FIELD(quals);
- READ_NODE_FIELD(alias);
- READ_INT_FIELD(rtindex);
-
- READ_DONE();
-}
-
-/*
- * _readFromExpr
- */
-static FromExpr *
-_readFromExpr(void)
-{
- READ_LOCALS(FromExpr);
-
- READ_NODE_FIELD(fromlist);
- READ_NODE_FIELD(quals);
-
- READ_DONE();
-}
-
-
-/*
- * Stuff from parsenodes.h.
- */
-
/*
* _readCaseExpr
*/
READ_DONE();
}
-/*
- * _readDomainConstraintValue
- */
-static DomainConstraintValue *
-_readDomainConstraintValue(void)
-{
- READ_LOCALS_NO_FIELDS(DomainConstraintValue);
-
- READ_DONE();
-}
-
/*
* _readConstraintTestValue
*/
READ_LOCALS(TargetEntry);
READ_NODE_FIELD(resdom);
- /* fjoin not supported ... */
READ_NODE_FIELD(expr);
READ_DONE();
}
+/*
+ * _readRangeTblRef
+ */
+static RangeTblRef *
+_readRangeTblRef(void)
+{
+ READ_LOCALS(RangeTblRef);
+
+ READ_INT_FIELD(rtindex);
+
+ READ_DONE();
+}
+
+/*
+ * _readJoinExpr
+ */
+static JoinExpr *
+_readJoinExpr(void)
+{
+ READ_LOCALS(JoinExpr);
+
+ READ_ENUM_FIELD(jointype, JoinType);
+ READ_BOOL_FIELD(isNatural);
+ READ_NODE_FIELD(larg);
+ READ_NODE_FIELD(rarg);
+ READ_NODE_FIELD(using);
+ READ_NODE_FIELD(quals);
+ READ_NODE_FIELD(alias);
+ READ_INT_FIELD(rtindex);
+
+ READ_DONE();
+}
+
+/*
+ * _readFromExpr
+ */
+static FromExpr *
+_readFromExpr(void)
+{
+ READ_LOCALS(FromExpr);
+
+ READ_NODE_FIELD(fromlist);
+ READ_NODE_FIELD(quals);
+
+ READ_DONE();
+}
+
+
+/*
+ * Stuff from parsenodes.h.
+ */
+
static ColumnRef *
_readColumnRef(void)
{
READ_DONE();
}
-static Alias *
-_readAlias(void)
+/*
+ * _readDomainConstraintValue
+ */
+static DomainConstraintValue *
+_readDomainConstraintValue(void)
{
- READ_LOCALS(Alias);
-
- READ_STRING_FIELD(aliasname);
- READ_NODE_FIELD(colnames);
+ READ_LOCALS_NO_FIELDS(DomainConstraintValue);
READ_DONE();
}
#define MATCH(tokname, namelen) \
(length == namelen && strncmp(token, tokname, namelen) == 0)
- if (MATCH("AGGREF", 6))
- return_value = _readAggref();
- else if (MATCH("SUBLINK", 7))
- return_value = _readSubLink();
- else if (MATCH("FIELDSELECT", 11))
- return_value = _readFieldSelect();
- else if (MATCH("RELABELTYPE", 11))
- return_value = _readRelabelType();
- else if (MATCH("RANGETBLREF", 11))
- return_value = _readRangeTblRef();
- else if (MATCH("FROMEXPR", 8))
- return_value = _readFromExpr();
- else if (MATCH("JOINEXPR", 8))
- return_value = _readJoinExpr();
- else if (MATCH("RESDOM", 6))
- return_value = _readResdom();
- else if (MATCH("EXPR", 4))
- return_value = _readExpr();
- else if (MATCH("ARRAYREF", 8))
- return_value = _readArrayRef();
- else if (MATCH("VAR", 3))
- return_value = _readVar();
- else if (MATCH("CONST", 5))
- return_value = _readConst();
- else if (MATCH("FUNC", 4))
- return_value = _readFunc();
- else if (MATCH("OPER", 4))
- return_value = _readOper();
- else if (MATCH("PARAM", 5))
- return_value = _readParam();
- else if (MATCH("TARGETENTRY", 11))
- return_value = _readTargetEntry();
- else if (MATCH("RANGEVAR", 8))
- return_value = _readRangeVar();
- else if (MATCH("COLUMNREF", 9))
- return_value = _readColumnRef();
- else if (MATCH("COLUMNDEF", 9))
- return_value = _readColumnDef();
- else if (MATCH("TYPENAME", 8))
- return_value = _readTypeName();
- else if (MATCH("EXPRFIELDSELECT", 15))
- return_value = _readExprFieldSelect();
- else if (MATCH("ALIAS", 5))
- return_value = _readAlias();
- else if (MATCH("RTE", 3))
- return_value = _readRangeTblEntry();
- else if (MATCH("QUERY", 5))
+ if (MATCH("QUERY", 5))
return_value = _readQuery();
else if (MATCH("NOTIFY", 6))
return_value = _readNotifyStmt();
return_value = _readGroupClause();
else if (MATCH("SETOPERATIONSTMT", 16))
return_value = _readSetOperationStmt();
+ else if (MATCH("RESDOM", 6))
+ return_value = _readResdom();
+ else if (MATCH("ALIAS", 5))
+ return_value = _readAlias();
+ else if (MATCH("RANGEVAR", 8))
+ return_value = _readRangeVar();
+ else if (MATCH("VAR", 3))
+ return_value = _readVar();
+ else if (MATCH("CONST", 5))
+ return_value = _readConst();
+ else if (MATCH("PARAM", 5))
+ return_value = _readParam();
+ else if (MATCH("AGGREF", 6))
+ return_value = _readAggref();
+ else if (MATCH("ARRAYREF", 8))
+ return_value = _readArrayRef();
+ else if (MATCH("FUNCEXPR", 8))
+ return_value = _readFuncExpr();
+ else if (MATCH("OPEXPR", 6))
+ return_value = _readOpExpr();
+ else if (MATCH("DISTINCTEXPR", 12))
+ return_value = _readDistinctExpr();
+ else if (MATCH("BOOLEXPR", 8))
+ return_value = _readBoolExpr();
+ else if (MATCH("SUBLINK", 7))
+ return_value = _readSubLink();
+ else if (MATCH("FIELDSELECT", 11))
+ return_value = _readFieldSelect();
+ else if (MATCH("RELABELTYPE", 11))
+ return_value = _readRelabelType();
else if (MATCH("CASE", 4))
return_value = _readCaseExpr();
else if (MATCH("WHEN", 4))
return_value = _readBooleanTest();
else if (MATCH("CONSTRAINTTEST", 14))
return_value = _readConstraintTest();
- else if (MATCH("DOMAINCONSTRAINTVALUE", 21))
- return_value = _readDomainConstraintValue();
else if (MATCH("CONSTRAINTTESTVALUE", 19))
return_value = _readConstraintTestValue();
+ else if (MATCH("TARGETENTRY", 11))
+ return_value = _readTargetEntry();
+ else if (MATCH("RANGETBLREF", 11))
+ return_value = _readRangeTblRef();
+ else if (MATCH("JOINEXPR", 8))
+ return_value = _readJoinExpr();
+ else if (MATCH("FROMEXPR", 8))
+ return_value = _readFromExpr();
+ else if (MATCH("COLUMNREF", 9))
+ return_value = _readColumnRef();
+ else if (MATCH("COLUMNDEF", 9))
+ return_value = _readColumnDef();
+ else if (MATCH("TYPENAME", 8))
+ return_value = _readTypeName();
+ else if (MATCH("EXPRFIELDSELECT", 15))
+ return_value = _readExprFieldSelect();
+ else if (MATCH("DOMAINCONSTRAINTVALUE", 21))
+ return_value = _readDomainConstraintValue();
+ else if (MATCH("RTE", 3))
+ return_value = _readRangeTblEntry();
else
{
elog(ERROR, "badly formatted node string \"%.32s\"...", token);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
if (is_opclause(clause) &&
(varRelid != 0 || NumRelids(clause) == 1))
{
- Expr *expr = (Expr *) clause;
+ OpExpr *expr = (OpExpr *) clause;
if (length(expr->args) == 2)
{
(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,
{
/* share code with clauselist_selectivity() */
s1 = clauselist_selectivity(root,
- ((Expr *) clause)->args,
+ ((BoolExpr *) clause)->args,
varRelid);
}
else if (or_clause(clause))
List *arg;
s1 = 0.0;
- foreach(arg, ((Expr *) clause)->args)
+ foreach(arg, ((BoolExpr *) clause)->args)
{
Selectivity s2 = clause_selectivity(root,
(Node *) lfirst(arg),
}
else if (is_opclause(clause))
{
- Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
+ Oid opno = ((OpExpr *) clause)->opno;
bool is_join_clause;
if (varRelid != 0)
{
/* 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))
/* 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))
/* 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);
}
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
*/
restrictinfo->subclauseindices =
match_index_orclause(rel, index,
- restrictinfo->clause->args,
+ ((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices);
}
}
{
List *item;
- foreach(item, clause->args)
+ foreach(item, ((BoolExpr *) clause)->args)
{
if (match_clause_to_indexkey(rel, index, indexkey, opclass,
lfirst(item)))
if (and_clause((Node *) orsubclause))
{
- foreach(item, orsubclause->args)
+ foreach(item, ((BoolExpr *) orsubclause)->args)
{
Expr *subsubclause = (Expr *) lfirst(item);
*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);
*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);
* (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 */
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 */
}
else if (and_clause(clause))
{
- items = ((Expr *) clause)->args;
+ items = ((BoolExpr *) clause)->args;
foreach(item, items)
{
/*
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 */
}
else if (and_clause((Node *) predicate))
{
- items = predicate->args;
+ items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/*
StrategyNumber pred_strategy = 0,
clause_strategy,
test_strategy;
- Oper *test_oper;
Expr *test_expr;
Datum test_result;
bool isNull;
* 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);
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
/*
* 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,
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;
/*
* 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;
/* 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) ||
/* 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;
Oid oproid;
char *prefix;
Const *con;
- Oper *op;
Expr *expr;
Const *greaterstr = NULL;
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;
}
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);
/*-------
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);
}
Oid opr2oid;
List *result;
Oid datatype;
- Oper *op;
Expr *expr;
switch (expr_op)
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 )" */
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
best_or_subclause_indices(root,
rel,
- restrictinfo->clause->args,
+ ((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices,
pathnode);
* 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 $
*
*-------------------------------------------------------------------------
*/
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)
{
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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
}
if (!is_funcclause(node))
return false;
- expr = (Expr *) node;
+ expr = (FuncExpr *) node;
foreach(lst, expr->args)
{
if (!isEvaluable(varno, lfirst(lst)))
* 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;
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;
* 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,
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;
}
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
{
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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");
/*
* 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
* 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));
}
* 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
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))
{
* 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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
leftOp,
rightOp;
- if (!is_opclause((Node *) clause))
+ if (!is_opclause(clause))
return;
left = get_leftop(clause);
/* 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,
*right;
Oid opno;
- if (!is_opclause((Node *) clause))
+ if (!is_opclause(clause))
return;
left = get_leftop(clause);
/* 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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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.
*/
/* 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);
-1,
0);
- ctid = makeTargetEntry(resdom, (Node *) var);
+ ctid = makeTargetEntry(resdom, (Expr *) var);
tlist = lappend(tlist, ctid);
}
}
exprTypmod(groupexpr),
NULL,
false),
- groupexpr);
+ (Expr *) groupexpr);
sub_tlist = lappend(sub_tlist, te);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
/*****************************************************************************
*
* 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);
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);
}
}
* 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.
*/
{
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);
}
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;
*****************************************************************************/
/*
- * 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
* 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);
}
* 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 $
*
*-------------------------------------------------------------------------
*/
}
/*
- * 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;
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! */
/*
}
else
{
- Expr *expr = makeNode(Expr);
List *args = NIL;
/*
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)
{
var->varlevelsup = 0;
args = lappend(args, var);
}
- expr->args = args;
+ node->args = args;
- result = (Node *) expr;
+ result = (Node *) node;
}
return result;
* 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
foreach(lst, slink->oper)
{
- Oper *oper = (Oper *) lfirst(lst);
+ OpExpr *oper = (OpExpr *) lfirst(lst);
Node *lefthand = lfirst(leftlist);
TargetEntry *te = lfirst(targetlist);
Param *prm;
*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);
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);
}
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 */
*/
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.
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
List *out_list = NIL;
List *arg;
- foreach(arg, qual->args)
+ foreach(arg, ((BoolExpr *) qual)->args)
{
Expr *subexpr = flatten_andors((Expr *) lfirst(arg));
* 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);
}
List *out_list = NIL;
List *arg;
- foreach(arg, qual->args)
+ foreach(arg, ((BoolExpr *) qual)->args)
{
Expr *subexpr = flatten_andors((Expr *) lfirst(arg));
* 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);
}
}
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;
* 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);
}
* 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);
}
#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))
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));
}
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));
}
* 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);
}
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));
}
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));
}
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));
}
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));
}
if (and_clause((Node *) clause))
{
- int nclauses = length(clause->args);
+ int nclauses = length(((BoolExpr *) clause)->args);
if (nclauses > num_subclauses)
{
*/
orlist = lremove(distributable, orlist);
- foreach(temp, distributable->args)
+ foreach(temp, ((BoolExpr *) distributable)->args)
{
Expr *andclause = lfirst(temp);
List *neworlist;
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));
}
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));
}
if (or_clause((Node *) clause))
{
- int nclauses = length(clause->args);
+ int nclauses = length(((BoolExpr *) clause)->args);
if (nclauses > num_subclauses)
{
*/
andlist = lremove(distributable, andlist);
- foreach(temp, distributable->args)
+ foreach(temp, ((BoolExpr *) distributable)->args)
{
Expr *orclause = lfirst(temp);
List *newandlist;
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));
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));
*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);
*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);
* 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 $
*
*-------------------------------------------------------------------------
*/
if (command_type == CMD_DELETE)
tlist = listCopy(tlist);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Node *) var));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var));
}
return tlist;
atttypmod,
pstrdup(NameStr(att_tup->attname)),
false),
- new_expr);
+ (Expr *) new_expr);
}
new_tlist = lappend(new_tlist, new_tle);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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,
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);
}
Int32GetDatum(flag),
false,
true);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
}
return tlist;
colTypmod,
pstrdup(reftle->resdom->resname),
false);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
refnames_tlist = lnext(refnames_tlist);
}
INT4OID,
-1,
0);
- tlist = lappend(tlist, makeTargetEntry(resdom, expr));
+ tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
}
pfree(colTypmods);
*/
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;
*
*
* 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
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;
}
/*
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;
}
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;
}
/*****************************************************************************
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;
}
/*
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))
* 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");
/*
{
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);
}
{
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);
* 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)
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,
*/
List *t;
- foreach(t, ((Expr *) node)->args)
+ foreach(t, ((SubPlanExpr *) node)->args)
{
Node *thisarg = lfirst(t);
Var *var;
{
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);
{
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);
*
* 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
{
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 */
* 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;
{
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.
*/
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
}
case AND_EXPR:
{
-
/*----------
* AND arguments are handled as follows:
* non constant: keep
}
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))
{
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))
{
{
RelabelType *newrelabel = makeNode(RelabelType);
- newrelabel->arg = arg;
+ newrelabel->arg = (Expr *) arg;
newrelabel->resulttype = relabel->resulttype;
newrelabel->resulttypmod = relabel->resulttypmod;
return (Node *) newrelabel;
* 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.
}
/* Simplify the default result */
- defresult = eval_const_expressions_mutator(caseexpr->defresult,
+ defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
active_fns);
/*
newcase->casetype = caseexpr->casetype;
newcase->arg = NULL;
newcase->args = newargs;
- newcase->defresult = defresult;
+ newcase->defresult = (Expr *) defresult;
return (Node *) newcase;
}
}
/*
- * 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;
* 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);
}
/*
- * 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;
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;
* 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?
}
/*
- * 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
* 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;
* stuff that parsing might create.
*/
mycxt = AllocSetContextCreate(CurrentMemoryContext,
- "inline_op_or_func",
+ "inline_function",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
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));
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
* 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))
* {
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:
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:
{
* 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).
*/
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;
return true;
}
break;
- case T_TargetEntry:
- return walker(((TargetEntry *) node)->expr, context);
case T_FromExpr:
{
FromExpr *from = (FromExpr *) node;
* 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
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;
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;
FieldSelect *newnode;
FLATCOPY(newnode, fselect, FieldSelect);
- MUTATE(newnode->arg, fselect->arg, Node *);
+ MUTATE(newnode->arg, fselect->arg, Expr *);
return (Node *) newnode;
}
break;
RelabelType *newnode;
FLATCOPY(newnode, relabel, RelabelType);
- MUTATE(newnode->arg, relabel->arg, Node *);
+ MUTATE(newnode->arg, relabel->arg, Expr *);
return (Node *) newnode;
}
break;
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;
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;
NullTest *newnode;
FLATCOPY(newnode, ntest, NullTest);
- MUTATE(newnode->arg, ntest->arg, Node *);
+ MUTATE(newnode->arg, ntest->arg, Expr *);
return (Node *) newnode;
}
break;
BooleanTest *newnode;
FLATCOPY(newnode, btest, BooleanTest);
- MUTATE(newnode->arg, btest->arg, Node *);
+ MUTATE(newnode->arg, btest->arg, Expr *);
return (Node *) newnode;
}
break;
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;
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;
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
var->vartypmod,
NULL,
false),
- (Node *) var);
+ (Expr *) var);
}
/*****************************************************************************
{
TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList);
- return tle->expr;
+ return (Node *) tle->expr;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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)
* 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;
* 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)
* 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;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.254 2002/11/15 02:50:07 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.255 2002/12/12 15:49:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
- Node *expr;
+ Expr *expr;
if (resnode->resjunk)
continue;
if (tle->expr && IsA(tle->expr, Const))
expr = tle->expr;
else
- expr = (Node *) makeVar(rtr->rtindex,
+ expr = (Expr *) makeVar(rtr->rtindex,
resnode->resno,
resnode->restype,
resnode->restypmod,
Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom;
char *colName = pstrdup(leftResdom->resname);
Resdom *resdom;
- Node *expr;
+ Expr *expr;
resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
colType,
-1,
colName,
false);
- expr = (Node *) makeVar(1,
+ expr = (Expr *) makeVar(1,
leftResdom->resno,
colType,
-1,
format_type_be(given_type_id),
format_type_be(expected_type_id));
- fix_opids(expr);
+ fix_opfuncids(expr);
lfirst(l) = expr;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.386 2002/12/06 05:00:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.387 2002/12/12 15:49:36 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
| a_expr ISNULL
{
NullTest *n = makeNode(NullTest);
- n->arg = $1;
+ n->arg = (Expr *) $1;
n->nulltesttype = IS_NULL;
$$ = (Node *)n;
}
| a_expr IS NULL_P
{
NullTest *n = makeNode(NullTest);
- n->arg = $1;
+ n->arg = (Expr *) $1;
n->nulltesttype = IS_NULL;
$$ = (Node *)n;
}
| a_expr NOTNULL
{
NullTest *n = makeNode(NullTest);
- n->arg = $1;
+ n->arg = (Expr *) $1;
n->nulltesttype = IS_NOT_NULL;
$$ = (Node *)n;
}
| a_expr IS NOT NULL_P
{
NullTest *n = makeNode(NullTest);
- n->arg = $1;
+ n->arg = (Expr *) $1;
n->nulltesttype = IS_NOT_NULL;
$$ = (Node *)n;
}
| a_expr IS TRUE_P
{
BooleanTest *b = makeNode(BooleanTest);
- b->arg = $1;
+ b->arg = (Expr *) $1;
b->booltesttype = IS_TRUE;
$$ = (Node *)b;
}
| a_expr IS NOT TRUE_P
{
BooleanTest *b = makeNode(BooleanTest);
- b->arg = $1;
+ b->arg = (Expr *) $1;
b->booltesttype = IS_NOT_TRUE;
$$ = (Node *)b;
}
| a_expr IS FALSE_P
{
BooleanTest *b = makeNode(BooleanTest);
- b->arg = $1;
+ b->arg = (Expr *) $1;
b->booltesttype = IS_FALSE;
$$ = (Node *)b;
}
| a_expr IS NOT FALSE_P
{
BooleanTest *b = makeNode(BooleanTest);
- b->arg = $1;
+ b->arg = (Expr *) $1;
b->booltesttype = IS_NOT_FALSE;
$$ = (Node *)b;
}
| a_expr IS UNKNOWN
{
BooleanTest *b = makeNode(BooleanTest);
- b->arg = $1;
+ b->arg = (Expr *) $1;
b->booltesttype = IS_UNKNOWN;
$$ = (Node *)b;
}
| a_expr IS NOT UNKNOWN
{
BooleanTest *b = makeNode(BooleanTest);
- b->arg = $1;
+ b->arg = (Expr *) $1;
b->booltesttype = IS_NOT_UNKNOWN;
$$ = (Node *)b;
}
case_expr: CASE case_arg when_clause_list case_default END_TRANS
{
CaseExpr *c = makeNode(CaseExpr);
- c->arg = $2;
+ c->arg = (Expr *) $2;
c->args = $3;
- c->defresult = $4;
+ c->defresult = (Expr *) $4;
$$ = (Node *)c;
}
| NULLIF '(' a_expr ',' a_expr ')'
CaseExpr *c = makeNode(CaseExpr);
CaseWhen *w = makeNode(CaseWhen);
- w->expr = (Node *) makeSimpleA_Expr(OP, "=", $3, $5);
+ w->expr = (Expr *) makeSimpleA_Expr(OP, "=", $3, $5);
/* w->result is left NULL */
c->args = makeList1(w);
- c->defresult = $3;
+ c->defresult = (Expr *) $3;
$$ = (Node *)c;
}
| COALESCE '(' expr_list ')'
NullTest *n = makeNode(NullTest);
n->arg = lfirst(l);
n->nulltesttype = IS_NOT_NULL;
- w->expr = (Node *) n;
+ w->expr = (Expr *) n;
w->result = lfirst(l);
c->args = lappend(c->args, w);
}
WHEN a_expr THEN a_expr
{
CaseWhen *w = makeNode(CaseWhen);
- w->expr = $2;
- w->result = $4;
+ w->expr = (Expr *) $2;
+ w->result = (Expr *) $4;
$$ = (Node *)w;
}
;
makeRowNullTest(NullTestType test, List *args)
{
Node *expr = NULL;
- Node *arg;
NullTest *n;
if (lnext(args) != NIL)
expr = makeRowNullTest(test, lnext(args));
- arg = lfirst(args);
-
n = makeNode(NullTest);
- n->arg = arg;
+ n->arg = (Expr *) lfirst(args);
n->nulltesttype = test;
if (expr == NULL)
- expr = (Node *)n;
+ expr = (Node *) n;
else if (test == IS_NOT_NULL)
expr = (Node *) makeA_Expr(OR, NIL, expr, (Node *)n);
else
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.100 2002/11/29 21:39:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.101 2002/12/12 15:49:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
elog(ERROR, "cannot use aggregate function in FROM function expression");
}
- /*
- * Insist we have a bare function call (explain.c is the only place
- * that depends on this, I think). If this fails, it's probably
- * because transformExpr interpreted the function notation as a type
- * coercion.
- */
- if (!funcexpr ||
- !IsA(funcexpr, Expr) ||
- ((Expr *) funcexpr)->opType != FUNC_EXPR)
- elog(ERROR, "Coercion function not allowed in FROM clause");
-
/*
* OK, build an RTE for the function.
*/
outcoltype,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (l_colvar->vartypmod != outcoltypmod)
- l_node = (Node *) makeRelabelType((Node *) l_colvar,
+ l_node = (Node *) makeRelabelType((Expr *) l_colvar,
outcoltype, outcoltypmod,
COERCE_IMPLICIT_CAST);
else
outcoltype,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (r_colvar->vartypmod != outcoltypmod)
- r_node = (Node *) makeRelabelType((Node *) r_colvar,
+ r_node = (Node *) makeRelabelType((Expr *) r_colvar,
outcoltype, outcoltypmod,
COERCE_IMPLICIT_CAST);
else
CaseWhen *w = makeNode(CaseWhen);
NullTest *n = makeNode(NullTest);
- n->arg = l_node;
+ n->arg = (Expr *) l_node;
n->nulltesttype = IS_NOT_NULL;
- w->expr = (Node *) n;
- w->result = l_node;
+ w->expr = (Expr *) n;
+ w->result = (Expr *) l_node;
c->casetype = outcoltype;
c->args = makeList1(w);
- c->defresult = r_node;
+ c->defresult = (Expr *) r_node;
res_node = (Node *) c;
break;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.89 2002/11/30 18:28:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.90 2002/12/12 15:49:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ccontext, cformat);
/* Need a RelabelType if no typmod coercion is performed */
if (targettypmod < 0)
- expr = (Node *) makeRelabelType(expr, targettype, -1,
+ expr = (Node *) makeRelabelType((Expr *) expr,
+ targettype, -1,
cformat);
}
else
cformat);
/* We might now need a RelabelType. */
if (exprType(result) != targetTypeId)
- result = (Node *) makeRelabelType(result, targetTypeId, -1,
+ result = (Node *) makeRelabelType((Expr *) result,
+ targetTypeId, -1,
cformat);
}
{
result = coerce_type_constraints(result, targetTypeId,
cformat);
- result = (Node *) makeRelabelType(result, targetTypeId, -1,
+ result = (Node *) makeRelabelType((Expr *) result,
+ targetTypeId, -1,
cformat);
}
* typmod, which is likely but not certain (wrong if target is
* a domain, in any case).
*/
- result = (Node *) makeRelabelType(result, targetTypeId, -1,
+ result = (Node *) makeRelabelType((Expr *) result,
+ targetTypeId, -1,
cformat);
}
}
* except relabel the type. This is binary compatibility for
* complex types.
*/
- result = (Node *) makeRelabelType(node, targetTypeId, -1,
+ result = (Node *) makeRelabelType((Expr *) node,
+ targetTypeId, -1,
cformat);
}
else
elog(ERROR, "coerce_type_constraints: domain %s constraint %s has NULL conbin",
NameStr(typTup->typname), NameStr(c->conname));
- r->arg = arg;
+ r->arg = (Expr *) arg;
r->testtype = CONSTR_TEST_CHECK;
r->name = NameStr(c->conname);
r->domname = NameStr(typTup->typname);
{
ConstraintTest *r = makeNode(ConstraintTest);
- r->arg = arg;
+ r->arg = (Expr *) arg;
r->testtype = CONSTR_TEST_NOTNULL;
r->name = "NOT NULL";
r->domname = notNull;
static Node *
build_func_call(Oid funcid, Oid rettype, List *args, CoercionForm fformat)
{
- Func *funcnode;
- Expr *expr;
-
- funcnode = makeNode(Func);
- funcnode->funcid = funcid;
- funcnode->funcresulttype = rettype;
- funcnode->funcretset = false; /* only possible case here */
- funcnode->funcformat = fformat;
- funcnode->func_fcache = NULL;
-
- expr = makeNode(Expr);
- expr->typeOid = rettype;
- expr->opType = FUNC_EXPR;
- expr->oper = (Node *) funcnode;
- expr->args = args;
-
- return (Node *) expr;
+ FuncExpr *funcexpr;
+
+ funcexpr = makeNode(FuncExpr);
+ funcexpr->funcid = funcid;
+ funcexpr->funcresulttype = rettype;
+ funcexpr->funcretset = false; /* only possible case here */
+ funcexpr->funcformat = fformat;
+ funcexpr->args = args;
+
+ return (Node *) funcexpr;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.135 2002/12/06 05:00:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.136 2002/12/12 15:49:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
n->nulltesttype = IS_NULL;
if (exprIsNullConstant(a->lexpr))
- n->arg = a->rexpr;
+ n->arg = (Expr *) a->rexpr;
else
- n->arg = a->lexpr;
+ n->arg = (Expr *) a->lexpr;
result = transformExpr(pstate,
(Node *) n, domVal);
a->lexpr, domVal);
Node *rexpr = transformExpr(pstate,
a->rexpr, domVal);
- Expr *expr = makeNode(Expr);
lexpr = coerce_to_boolean(lexpr, "AND");
rexpr = coerce_to_boolean(rexpr, "AND");
- expr->typeOid = BOOLOID;
- expr->opType = AND_EXPR;
- expr->args = makeList2(lexpr, rexpr);
- result = (Node *) expr;
+ result = (Node *) makeBoolExpr(AND_EXPR,
+ makeList2(lexpr,
+ rexpr));
}
break;
case OR:
a->lexpr, domVal);
Node *rexpr = transformExpr(pstate,
a->rexpr, domVal);
- Expr *expr = makeNode(Expr);
lexpr = coerce_to_boolean(lexpr, "OR");
rexpr = coerce_to_boolean(rexpr, "OR");
- expr->typeOid = BOOLOID;
- expr->opType = OR_EXPR;
- expr->args = makeList2(lexpr, rexpr);
- result = (Node *) expr;
+ result = (Node *) makeBoolExpr(OR_EXPR,
+ makeList2(lexpr,
+ rexpr));
}
break;
case NOT:
{
Node *rexpr = transformExpr(pstate,
a->rexpr, domVal);
- Expr *expr = makeNode(Expr);
rexpr = coerce_to_boolean(rexpr, "NOT");
- expr->typeOid = BOOLOID;
- expr->opType = NOT_EXPR;
- expr->args = makeList1(rexpr);
- result = (Node *) expr;
+ result = (Node *) makeBoolExpr(NOT_EXPR,
+ makeList1(rexpr));
}
break;
case DISTINCT:
result = (Node *) make_op(a->name,
lexpr,
rexpr);
- if (((Expr *) result)->typeOid != BOOLOID)
+ if (((OpExpr *) result)->opresulttype != BOOLOID)
elog(ERROR, "IS DISTINCT FROM requires = operator to yield boolean");
- ((Expr *) result)->opType = DISTINCT_EXPR;
+ /*
+ * We rely on DistinctExpr and OpExpr being same struct
+ */
+ NodeSetTag(result, T_DistinctExpr);
}
break;
case OF:
Node *lexpr;
Operator optup;
Form_pg_operator opform;
- Oper *newop;
+ OpExpr *newop;
right_list = lnext(right_list);
if (tent->resdom->resjunk)
*/
optup = oper(op,
exprType(lexpr),
- exprType(tent->expr),
+ exprType((Node *) tent->expr),
false);
opform = (Form_pg_operator) GETSTRUCT(optup);
" to be used with quantified predicate subquery",
opname);
- newop = makeOper(oprid(optup), /* opno */
- InvalidOid, /* opid */
- opform->oprresult,
- false);
+ newop = makeNode(OpExpr);
+ newop->opno = oprid(optup);
+ newop->opfuncid = InvalidOid;
+ newop->opresulttype = opform->oprresult;
+ newop->opretset = false;
+ newop->args = NIL; /* for now */
+
sublink->oper = lappend(sublink->oper, newop);
+
ReleaseSysCache(optup);
}
if (left_list != NIL)
Assert(IsA(w, CaseWhen));
- warg = w->expr;
+ warg = (Node *) w->expr;
if (c->arg != NULL)
{
/* shorthand form was specified, so expand... */
warg = (Node *) makeSimpleA_Expr(OP, "=",
- c->arg, warg);
+ (Node *) c->arg,
+ warg);
}
- neww->expr = transformExpr(pstate, warg, domVal);
+ neww->expr = (Expr *) transformExpr(pstate, warg, domVal);
- neww->expr = coerce_to_boolean(neww->expr, "CASE/WHEN");
+ neww->expr = (Expr *) coerce_to_boolean((Node *) neww->expr,
+ "CASE/WHEN");
/*
* result is NULL for NULLIF() construct - thomas
* 1998-11-11
*/
- warg = w->result;
+ warg = (Node *) w->result;
if (warg == NULL)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
warg = (Node *) n;
}
- neww->result = transformExpr(pstate, warg, domVal);
+ neww->result = (Expr *) transformExpr(pstate, warg, domVal);
newargs = lappend(newargs, neww);
- typeids = lappendi(typeids, exprType(neww->result));
+ typeids = lappendi(typeids, exprType((Node *) neww->result));
}
newc->args = newargs;
newc->arg = NULL;
/* transform the default clause */
- defresult = c->defresult;
+ defresult = (Node *) c->defresult;
if (defresult == NULL)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
defresult = (Node *) n;
}
- newc->defresult = transformExpr(pstate, defresult, domVal);
+ newc->defresult = (Expr *) transformExpr(pstate, defresult, domVal);
/*
* Note: default result is considered the most significant
* code worked before, but it seems a little bogus to me
* --- tgl
*/
- typeids = lconsi(exprType(newc->defresult), typeids);
+ typeids = lconsi(exprType((Node *) newc->defresult), typeids);
ptype = select_common_type(typeids, "CASE");
newc->casetype = ptype;
/* Convert default result clause, if necessary */
- newc->defresult = coerce_to_common_type(newc->defresult,
- ptype,
- "CASE/ELSE");
+ newc->defresult = (Expr *)
+ coerce_to_common_type((Node *) newc->defresult,
+ ptype,
+ "CASE/ELSE");
/* Convert when-clause results, if necessary */
foreach(args, newc->args)
{
CaseWhen *w = (CaseWhen *) lfirst(args);
- w->result = coerce_to_common_type(w->result,
- ptype,
- "CASE/WHEN");
+ w->result = (Expr *)
+ coerce_to_common_type((Node *) w->result,
+ ptype,
+ "CASE/WHEN");
}
result = (Node *) newc;
{
NullTest *n = (NullTest *) expr;
- n->arg = transformExpr(pstate, n->arg, domVal);
+ n->arg = (Expr *) transformExpr(pstate, (Node *) n->arg, domVal);
/* the argument can be any type, so don't coerce it */
result = expr;
break;
clausename = NULL; /* keep compiler quiet */
}
- b->arg = transformExpr(pstate, b->arg, domVal);
+ b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg, domVal);
- b->arg = coerce_to_boolean(b->arg, clausename);
+ b->arg = (Expr *) coerce_to_boolean((Node *) b->arg, clausename);
result = expr;
break;
Oid
exprType(Node *expr)
{
- Oid type = (Oid) InvalidOid;
+ Oid type;
if (!expr)
- return type;
+ return InvalidOid;
switch (nodeTag(expr))
{
case T_Var:
type = ((Var *) expr)->vartype;
break;
- case T_Expr:
- type = ((Expr *) expr)->typeOid;
- break;
case T_Const:
type = ((Const *) expr)->consttype;
break;
- case T_ArrayRef:
- type = ((ArrayRef *) expr)->refrestype;
+ case T_Param:
+ type = ((Param *) expr)->paramtype;
break;
case T_Aggref:
type = ((Aggref *) expr)->aggtype;
break;
- case T_Param:
- type = ((Param *) expr)->paramtype;
+ case T_ArrayRef:
+ type = ((ArrayRef *) expr)->refrestype;
break;
- case T_FieldSelect:
- type = ((FieldSelect *) expr)->resulttype;
+ case T_FuncExpr:
+ type = ((FuncExpr *) expr)->funcresulttype;
break;
- case T_RelabelType:
- type = ((RelabelType *) expr)->resulttype;
+ case T_OpExpr:
+ type = ((OpExpr *) expr)->opresulttype;
+ break;
+ case T_DistinctExpr:
+ type = ((DistinctExpr *) expr)->opresulttype;
+ break;
+ case T_BoolExpr:
+ type = BOOLOID;
break;
case T_SubLink:
{
}
}
break;
+ case T_FieldSelect:
+ type = ((FieldSelect *) expr)->resulttype;
+ break;
+ case T_RelabelType:
+ type = ((RelabelType *) expr)->resulttype;
+ break;
case T_CaseExpr:
type = ((CaseExpr *) expr)->casetype;
break;
case T_CaseWhen:
- type = exprType(((CaseWhen *) expr)->result);
+ type = exprType((Node *) ((CaseWhen *) expr)->result);
break;
case T_NullTest:
type = BOOLOID;
type = BOOLOID;
break;
case T_ConstraintTest:
- type = exprType(((ConstraintTest *) expr)->arg);
+ type = exprType((Node *) ((ConstraintTest *) expr)->arg);
break;
case T_ConstraintTestValue:
type = ((ConstraintTestValue *) expr)->typeId;
default:
elog(ERROR, "exprType: Do not know how to get type for %d node",
nodeTag(expr));
+ type = InvalidOid; /* keep compiler quiet */
break;
}
return type;
}
}
break;
- case T_Expr:
+ case T_FuncExpr:
{
int32 coercedTypmod;
if (!cexpr->defresult)
return -1;
- if (exprType(cexpr->defresult) != casetype)
+ if (exprType((Node *) cexpr->defresult) != casetype)
return -1;
- typmod = exprTypmod(cexpr->defresult);
+ typmod = exprTypmod((Node *) cexpr->defresult);
if (typmod < 0)
return -1; /* no point in trying harder */
foreach(arg, cexpr->args)
CaseWhen *w = (CaseWhen *) lfirst(arg);
Assert(IsA(w, CaseWhen));
- if (exprType(w->result) != casetype)
+ if (exprType((Node *) w->result) != casetype)
return -1;
- if (exprTypmod(w->result) != typmod)
+ if (exprTypmod((Node *) w->result) != typmod)
return -1;
}
return typmod;
}
break;
case T_ConstraintTest:
- return exprTypmod(((ConstraintTest *) expr)->arg);
+ return exprTypmod((Node *) ((ConstraintTest *) expr)->arg);
default:
break;
bool
exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
{
- Func *func;
+ FuncExpr *func;
int nargs;
Const *second_arg;
*coercedTypmod = -1; /* default result on failure */
/* Is it a function-call at all? */
- if (expr == NULL ||
- !IsA(expr, Expr) ||
- ((Expr *) expr)->opType != FUNC_EXPR)
+ if (expr == NULL || !IsA(expr, FuncExpr))
return false;
- func = (Func *) (((Expr *) expr)->oper);
- Assert(IsA(func, Func));
+ func = (FuncExpr *) expr;
/*
* If it didn't come from a coercion context, reject.
* argument being an int4 constant, it can't have been created from a
* length coercion (it must be a type coercion, instead).
*/
- nargs = length(((Expr *) expr)->args);
+ nargs = length(func->args);
if (nargs < 2 || nargs > 3)
return false;
- second_arg = (Const *) lsecond(((Expr *) expr)->args);
+ second_arg = (Const *) lsecond(func->args);
if (!IsA(second_arg, Const) ||
second_arg->consttype != INT4OID ||
second_arg->constisnull)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.142 2002/11/13 00:39:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.143 2002/12/12 15:49:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* build the appropriate output structure */
if (fdresult == FUNCDETAIL_NORMAL)
{
- Expr *expr = makeNode(Expr);
- Func *funcnode = makeNode(Func);
+ FuncExpr *funcexpr = makeNode(FuncExpr);
- funcnode->funcid = funcid;
- funcnode->funcresulttype = rettype;
- funcnode->funcretset = retset;
- funcnode->funcformat = COERCE_EXPLICIT_CALL;
- funcnode->func_fcache = NULL;
+ funcexpr->funcid = funcid;
+ funcexpr->funcresulttype = rettype;
+ funcexpr->funcretset = retset;
+ funcexpr->funcformat = COERCE_EXPLICIT_CALL;
+ funcexpr->args = fargs;
- expr->typeOid = rettype;
- expr->opType = FUNC_EXPR;
- expr->oper = (Node *) funcnode;
- expr->args = fargs;
-
- retval = (Node *) expr;
+ retval = (Node *) funcexpr;
}
else
{
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
get_rel_name(relid), attname);
- fselect->arg = input;
+ fselect->arg = (Expr *) input;
fselect->fieldnum = attno;
fselect->resulttype = get_atttype(relid, attno);
fselect->resulttypmod = get_atttypmod(relid, attno);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.74 2002/11/25 21:29:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.75 2002/12/12 15:49:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
rtypeId;
Operator tup;
Form_pg_operator opform;
- Oper *newop;
Node *left,
*right;
- Expr *result;
+ OpExpr *result;
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
right = make_operand(rtree, rtypeId, opform->oprright);
}
- newop = makeOper(oprid(tup), /* opno */
- InvalidOid, /* opid */
- opform->oprresult, /* opresulttype */
- get_func_retset(opform->oprcode)); /* opretset */
-
- result = makeNode(Expr);
- result->typeOid = opform->oprresult;
- result->opType = OP_EXPR;
- result->oper = (Node *) newop;
+ result = makeNode(OpExpr);
+ result->opno = oprid(tup);
+ result->opfuncid = InvalidOid;
+ result->opresulttype = opform->oprresult;
+ result->opretset = get_func_retset(opform->oprcode);
if (!left)
result->args = makeList1(right);
ReleaseSysCache(tup);
- return result;
+ return (Expr *) result;
} /* make_op() */
aref->refelemalign = type_struct_element->typalign;
aref->refupperindexpr = upperIndexpr;
aref->reflowerindexpr = lowerIndexpr;
- aref->refexpr = arrayBase;
- aref->refassgnexpr = assignFrom;
+ aref->refexpr = (Expr *) arrayBase;
+ aref->refassgnexpr = (Expr *) assignFrom;
ReleaseSysCache(type_tuple_array);
ReleaseSysCache(type_tuple_element);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.79 2002/09/04 20:31:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.80 2002/12/12 15:49:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
exprTypmod(varnode),
label,
false);
- te->expr = varnode;
+ te->expr = (Expr *) varnode;
te_list = lappend(te_list, te);
names = lnext(names);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.92 2002/11/15 02:50:09 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.93 2002/12/12 15:49:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
colname,
resjunk);
- return makeTargetEntry(resnode, expr);
+ return makeTargetEntry(resnode, (Expr *) expr);
}
int attrno,
List *indirection)
{
- Oid type_id = exprType(tle->expr); /* type of value provided */
+ Oid type_id = exprType((Node *) tle->expr); /* type of value provided */
Oid attrtype; /* type of target column */
int32 attrtypmod;
Resdom *resnode = tle->resdom;
attrtypmod,
indirection,
pstate->p_is_insert,
- tle->expr);
- tle->expr = (Node *) aref;
+ (Node *) tle->expr);
+ tle->expr = (Expr *) aref;
}
else
{
*/
if (type_id != InvalidOid)
{
- tle->expr = coerce_to_target_type(tle->expr, type_id,
- attrtype, attrtypmod,
- COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST);
+ tle->expr = (Expr *)
+ coerce_to_target_type((Node *) tle->expr, type_id,
+ attrtype, attrtypmod,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST);
if (tle->expr == NULL)
elog(ERROR, "column \"%s\" is of type %s"
" but expression is of type %s"
}
break;
case T_CaseExpr:
- strength = FigureColnameInternal(((CaseExpr *) node)->defresult,
+ strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
name);
if (strength <= 1)
{
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.113 2002/10/20 00:58:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.114 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
att_tup->atttypmod,
pstrdup(NameStr(att_tup->attname)),
false),
- new_expr);
+ (Expr *) new_expr);
}
if (new_tle)
* Prior TLE could be a nest of ArrayRefs if we do this more than
* once.
*/
- priorbottom = ((ArrayRef *) prior_tle->expr)->refexpr;
+ priorbottom = (Node *) ((ArrayRef *) prior_tle->expr)->refexpr;
while (priorbottom != NULL && IsA(priorbottom, ArrayRef) &&
((ArrayRef *) priorbottom)->refassgnexpr != NULL)
- priorbottom = ((ArrayRef *) priorbottom)->refexpr;
+ priorbottom = (Node *) ((ArrayRef *) priorbottom)->refexpr;
if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr))
elog(ERROR, "Multiple assignments to same attribute \"%s\"",
resdom->resname);
memcpy(newexpr, src_tle->expr, sizeof(ArrayRef));
newexpr->refexpr = prior_tle->expr;
- return makeTargetEntry(resdom, (Node *) newexpr);
+ return makeTargetEntry(resdom, (Expr *) newexpr);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.67 2002/10/20 00:58:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.68 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Need not copy input qual, because AddQual will... */
invqual = makeNode(BooleanTest);
- invqual->arg = qual;
+ invqual->arg = (Expr *) qual;
invqual->booltesttype = IS_NOT_TRUE;
AddQual(parsetree, (Node *) invqual);
TargetEntry *tle = lfirst(i);
if (tle->resdom->resno == attno)
- return tle->expr;
+ return (Node *) tle->expr;
}
return NULL;
}
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.45 2002/12/05 04:04:43 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.46 2002/12/12 15:49:40 tgl Exp $
*
* ----------
*/
#include "catalog/pg_operator.h"
#include "commands/trigger.h"
#include "executor/spi_priv.h"
+#include "optimizer/planmain.h"
#include "parser/parse_oper.h"
#include "utils/lsyscache.h"
#include "miscadmin.h"
nth(defval[j].adnum - 1,
spi_plan->targetlist);
spi_qptle->expr = stringToNode(defval[j].adbin);
+ fix_opfuncids((Node *) spi_qptle->expr);
break;
}
nth(defval[j].adnum - 1,
spi_plan->targetlist);
spi_qptle->expr = stringToNode(defval[j].adbin);
+ fix_opfuncids((Node *) spi_qptle->expr);
break;
}
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.127 2002/11/26 03:01:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.128 2002/12/12 15:49:40 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
deparse_context *context);
static void get_rule_expr(Node *node, deparse_context *context,
bool showimplicit);
-static void get_oper_expr(Expr *expr, deparse_context *context);
-static void get_func_expr(Expr *expr, deparse_context *context,
+static void get_oper_expr(OpExpr *expr, deparse_context *context);
+static void get_func_expr(FuncExpr *expr, deparse_context *context,
bool showimplicit);
static void get_agg_expr(Aggref *aggref, deparse_context *context);
static Node *strip_type_coercion(Node *expr, Oid resultType);
static void get_const_expr(Const *constval, deparse_context *context);
-static void get_sublink_expr(Node *node, deparse_context *context);
+static void get_sublink_expr(SubLink *sublink, deparse_context *context);
static void get_from_clause(Query *query, deparse_context *context);
static void get_from_clause_item(Node *jtnode, Query *query,
deparse_context *context);
sep = ", ";
colno++;
- get_rule_expr(tle->expr, context, true);
+ get_rule_expr((Node *) tle->expr, context, true);
/*
* Figure out what the result column should be called. In the
Node *expr;
tle = get_sortgroupclause_tle(srt, tlist);
- expr = tle->expr;
+ expr = (Node *) tle->expr;
/*
* Use column-number form if requested by caller or if expression is a
appendStringInfo(buf, sep);
sep = ", ";
- get_rule_expr(tle->expr, context, false);
+ get_rule_expr((Node *) tle->expr, context, false);
}
appendStringInfoChar(buf, ')');
}
if (!tleIsArrayAssign(tle))
appendStringInfo(buf, "%s = ",
quote_identifier(tle->resdom->resname));
- get_rule_expr(tle->expr, context, false);
+ get_rule_expr((Node *) tle->expr, context, false);
}
/* Add the FROM clause if needed */
*/
switch (nodeTag(node))
{
- case T_Const:
- get_const_expr((Const *) node, context);
- break;
-
case T_Var:
{
Var *var = (Var *) node;
}
break;
- case T_Expr:
+ case T_Const:
+ get_const_expr((Const *) node, context);
+ break;
+
+ case T_Param:
{
- Expr *expr = (Expr *) node;
- List *args = expr->args;
+ Param *param = (Param *) node;
- /*
- * Expr nodes have to be handled a bit detailed
- */
- switch (expr->opType)
+ switch (param->paramkind)
{
- case OP_EXPR:
- get_oper_expr(expr, context);
- break;
-
- case DISTINCT_EXPR:
- appendStringInfoChar(buf, '(');
- Assert(length(args) == 2);
- {
- /* binary operator */
- Node *arg1 = (Node *) lfirst(args);
- Node *arg2 = (Node *) lsecond(args);
-
- get_rule_expr(arg1, context, true);
- appendStringInfo(buf, " IS DISTINCT FROM ");
- get_rule_expr(arg2, context, true);
- }
- appendStringInfoChar(buf, ')');
- break;
-
- case FUNC_EXPR:
- get_func_expr(expr, context, showimplicit);
- break;
-
- case OR_EXPR:
- appendStringInfoChar(buf, '(');
- get_rule_expr((Node *) lfirst(args), context, false);
- while ((args = lnext(args)) != NIL)
- {
- appendStringInfo(buf, " OR ");
- get_rule_expr((Node *) lfirst(args), context,
- false);
- }
- appendStringInfoChar(buf, ')');
- break;
-
- case AND_EXPR:
- appendStringInfoChar(buf, '(');
- get_rule_expr((Node *) lfirst(args), context, false);
- while ((args = lnext(args)) != NIL)
- {
- appendStringInfo(buf, " AND ");
- get_rule_expr((Node *) lfirst(args), context,
- false);
- }
- appendStringInfoChar(buf, ')');
- break;
-
- case NOT_EXPR:
- appendStringInfo(buf, "(NOT ");
- get_rule_expr((Node *) lfirst(args), context, false);
- appendStringInfoChar(buf, ')');
+ case PARAM_NAMED:
+ appendStringInfo(buf, "$%s", param->paramname);
break;
-
- case SUBPLAN_EXPR:
-
- /*
- * We cannot see an already-planned subplan in
- * rule deparsing, only while EXPLAINing a query
- * plan. For now, just punt.
- */
- appendStringInfo(buf, "(subplan)");
+ case PARAM_NUM:
+ case PARAM_EXEC:
+ appendStringInfo(buf, "$%d", param->paramid);
break;
-
default:
- elog(ERROR, "get_rule_expr: expr opType %d not supported",
- expr->opType);
+ appendStringInfo(buf, "(param)");
+ break;
}
}
break;
*/
if (aref->refassgnexpr)
context->varprefix = false;
- get_rule_expr(aref->refexpr, context, showimplicit);
+ get_rule_expr((Node *) aref->refexpr, context, showimplicit);
context->varprefix = savevarprefix;
lowlist = aref->reflowerindexpr;
foreach(uplist, aref->refupperindexpr)
if (aref->refassgnexpr)
{
appendStringInfo(buf, " = ");
- get_rule_expr(aref->refassgnexpr, context, showimplicit);
+ get_rule_expr((Node *) aref->refassgnexpr, context,
+ showimplicit);
+ }
+ }
+ break;
+
+ case T_FuncExpr:
+ get_func_expr((FuncExpr *) node, context, showimplicit);
+ break;
+
+ case T_OpExpr:
+ get_oper_expr((OpExpr *) node, context);
+ break;
+
+ case T_DistinctExpr:
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+ List *args = expr->args;
+
+ Assert(length(args) == 2);
+ {
+ /* binary operator */
+ Node *arg1 = (Node *) lfirst(args);
+ Node *arg2 = (Node *) lsecond(args);
+
+ appendStringInfoChar(buf, '(');
+ get_rule_expr(arg1, context, true);
+ appendStringInfo(buf, " IS DISTINCT FROM ");
+ get_rule_expr(arg2, context, true);
+ appendStringInfoChar(buf, ')');
}
}
break;
+ case T_BoolExpr:
+ {
+ BoolExpr *expr = (BoolExpr *) node;
+ List *args = expr->args;
+
+ switch (expr->boolop)
+ {
+ case AND_EXPR:
+ appendStringInfoChar(buf, '(');
+ get_rule_expr((Node *) lfirst(args), context, false);
+ while ((args = lnext(args)) != NIL)
+ {
+ appendStringInfo(buf, " AND ");
+ get_rule_expr((Node *) lfirst(args), context,
+ false);
+ }
+ appendStringInfoChar(buf, ')');
+ break;
+
+ case OR_EXPR:
+ appendStringInfoChar(buf, '(');
+ get_rule_expr((Node *) lfirst(args), context, false);
+ while ((args = lnext(args)) != NIL)
+ {
+ appendStringInfo(buf, " OR ");
+ get_rule_expr((Node *) lfirst(args), context,
+ false);
+ }
+ appendStringInfoChar(buf, ')');
+ break;
+
+ case NOT_EXPR:
+ appendStringInfo(buf, "(NOT ");
+ get_rule_expr((Node *) lfirst(args), context, false);
+ appendStringInfoChar(buf, ')');
+ break;
+
+ default:
+ elog(ERROR, "get_rule_expr: unknown boolop %d",
+ (int) expr->boolop);
+ }
+ }
+ break;
+
+ case T_SubLink:
+ get_sublink_expr((SubLink *) node, context);
+ break;
+
+ case T_SubPlanExpr:
+ {
+ /*
+ * We cannot see an already-planned subplan in
+ * rule deparsing, only while EXPLAINing a query
+ * plan. For now, just punt.
+ */
+ appendStringInfo(buf, "(subplan)");
+ }
+ break;
+
case T_FieldSelect:
{
FieldSelect *fselect = (FieldSelect *) node;
- Oid argType = exprType(fselect->arg);
+ Oid argType = exprType((Node *) fselect->arg);
Oid typrelid;
char *fieldname;
* are *not* simple. So, always use parenthesized syntax.
*/
appendStringInfoChar(buf, '(');
- get_rule_expr(fselect->arg, context, true);
+ get_rule_expr((Node *) fselect->arg, context, true);
appendStringInfo(buf, ").%s", quote_identifier(fieldname));
}
break;
case T_RelabelType:
{
RelabelType *relabel = (RelabelType *) node;
- Node *arg = relabel->arg;
+ Node *arg = (Node *) relabel->arg;
if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
!showimplicit)
CaseWhen *when = (CaseWhen *) lfirst(temp);
appendStringInfo(buf, " WHEN ");
- get_rule_expr(when->expr, context, false);
+ get_rule_expr((Node *) when->expr, context, false);
appendStringInfo(buf, " THEN ");
- get_rule_expr(when->result, context, true);
+ get_rule_expr((Node *) when->result, context, true);
}
appendStringInfo(buf, " ELSE ");
- get_rule_expr(caseexpr->defresult, context, true);
+ get_rule_expr((Node *) caseexpr->defresult, context, true);
appendStringInfo(buf, " END");
}
break;
NullTest *ntest = (NullTest *) node;
appendStringInfo(buf, "(");
- get_rule_expr(ntest->arg, context, true);
+ get_rule_expr((Node *) ntest->arg, context, true);
switch (ntest->nulltesttype)
{
case IS_NULL:
BooleanTest *btest = (BooleanTest *) node;
appendStringInfo(buf, "(");
- get_rule_expr(btest->arg, context, false);
+ get_rule_expr((Node *) btest->arg, context, false);
switch (btest->booltesttype)
{
case IS_TRUE:
* We assume that the operations of the constraint node
* need not be explicitly represented in the output.
*/
- get_rule_expr(ctest->arg, context, showimplicit);
+ get_rule_expr((Node *) ctest->arg, context, showimplicit);
}
break;
case T_ConstraintTestValue:
- {
- appendStringInfo(buf, "VALUE");
- }
- break;
-
- case T_SubLink:
- get_sublink_expr(node, context);
- break;
-
- case T_Param:
- {
- Param *param = (Param *) node;
-
- switch (param->paramkind)
- {
- case PARAM_NAMED:
- appendStringInfo(buf, "$%s", param->paramname);
- break;
- case PARAM_NUM:
- case PARAM_EXEC:
- appendStringInfo(buf, "$%d", param->paramid);
- break;
- default:
- appendStringInfo(buf, "(param)");
- break;
- }
- }
+ appendStringInfo(buf, "VALUE");
break;
default:
/*
- * get_oper_expr - Parse back an Oper node
+ * get_oper_expr - Parse back an OpExpr node
*/
static void
-get_oper_expr(Expr *expr, deparse_context *context)
+get_oper_expr(OpExpr *expr, deparse_context *context)
{
StringInfo buf = context->buf;
- Oid opno = ((Oper *) expr->oper)->opno;
+ Oid opno = expr->opno;
List *args = expr->args;
appendStringInfoChar(buf, '(');
}
/*
- * get_func_expr - Parse back a Func node
+ * get_func_expr - Parse back a FuncExpr node
*/
static void
-get_func_expr(Expr *expr, deparse_context *context,
+get_func_expr(FuncExpr *expr, deparse_context *context,
bool showimplicit)
{
StringInfo buf = context->buf;
- Func *func = (Func *) (expr->oper);
- Oid funcoid = func->funcid;
+ Oid funcoid = expr->funcid;
Oid argtypes[FUNC_MAX_ARGS];
int nargs;
List *l;
* If the function call came from an implicit coercion, then just show
* the first argument --- unless caller wants to see implicit coercions.
*/
- if (func->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
+ if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
{
get_rule_expr((Node *) lfirst(expr->args), context, showimplicit);
return;
* If the function call came from a cast, then show
* the first argument plus an explicit cast operation.
*/
- if (func->funcformat == COERCE_EXPLICIT_CAST ||
- func->funcformat == COERCE_IMPLICIT_CAST)
+ if (expr->funcformat == COERCE_EXPLICIT_CAST ||
+ expr->funcformat == COERCE_IMPLICIT_CAST)
{
Node *arg = lfirst(expr->args);
- Oid rettype = expr->typeOid;
+ Oid rettype = expr->funcresulttype;
int32 coercedTypmod;
/* Get the typmod if this is a length-coercion function */
get_agg_expr(Aggref *aggref, deparse_context *context)
{
StringInfo buf = context->buf;
- Oid argtype = exprType(aggref->target);
+ Oid argtype = exprType((Node *) aggref->target);
appendStringInfo(buf, "%s(%s",
generate_function_name(aggref->aggfnoid, 1, &argtype),
if (aggref->aggstar)
appendStringInfo(buf, "*");
else
- get_rule_expr(aggref->target, context, true);
+ get_rule_expr((Node *) aggref->target, context, true);
appendStringInfoChar(buf, ')');
}
if (IsA(expr, RelabelType) &&
((RelabelType *) expr)->resulttypmod == -1)
- return ((RelabelType *) expr)->arg;
+ return (Node *) ((RelabelType *) expr)->arg;
- if (IsA(expr, Expr) &&
- ((Expr *) expr)->opType == FUNC_EXPR)
+ if (IsA(expr, FuncExpr))
{
- Func *func = (Func *) (((Expr *) expr)->oper);
+ FuncExpr *func = (FuncExpr *) expr;
- Assert(IsA(func, Func));
if (func->funcformat != COERCE_EXPLICIT_CAST &&
func->funcformat != COERCE_IMPLICIT_CAST)
return expr; /* don't absorb into upper coercion */
if (exprIsLengthCoercion(expr, NULL))
return expr;
- return (Node *) lfirst(((Expr *) expr)->args);
+ return (Node *) lfirst(func->args);
}
return expr;
* ----------
*/
static void
-get_sublink_expr(Node *node, deparse_context *context)
+get_sublink_expr(SubLink *sublink, deparse_context *context)
{
StringInfo buf = context->buf;
- SubLink *sublink = (SubLink *) node;
Query *query = (Query *) (sublink->subselect);
List *l;
char *sep;
- Oper *oper;
+ OpExpr *oper;
bool need_paren;
appendStringInfoChar(buf, '(');
break;
case ANY_SUBLINK:
- oper = (Oper *) lfirst(sublink->oper);
+ oper = (OpExpr *) lfirst(sublink->oper);
appendStringInfo(buf, "%s ANY ", get_opname(oper->opno));
break;
case ALL_SUBLINK:
- oper = (Oper *) lfirst(sublink->oper);
+ oper = (OpExpr *) lfirst(sublink->oper);
appendStringInfo(buf, "%s ALL ", get_opname(oper->opno));
break;
case MULTIEXPR_SUBLINK:
- oper = (Oper *) lfirst(sublink->oper);
+ oper = (OpExpr *) lfirst(sublink->oper);
appendStringInfo(buf, "%s ", get_opname(oper->opno));
break;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.122 2002/11/25 21:29:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.123 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* can't hurt)
*/
if (IsA(arg, RelabelType))
- arg = ((RelabelType *) arg)->arg;
+ arg = (Node *) ((RelabelType *) arg)->arg;
if (IsA(arg, Var) &&(varRelid == 0 || varRelid == ((Var *) arg)->varno))
var = (Var *) arg;
* Ignore any binary-compatible relabeling
*/
if (IsA(arg, RelabelType))
- arg = ((RelabelType *) arg)->arg;
+ arg = (Node *) ((RelabelType *) arg)->arg;
if (IsA(arg, Var) &&
(varRelid == 0 || varRelid == ((Var *) arg)->varno))
/* Deconstruct the merge clause */
if (!is_opclause(clause))
return; /* shouldn't happen */
- opno = ((Oper *) ((Expr *) clause)->oper)->opno;
+ opno = ((OpExpr *) clause)->opno;
left = get_leftop((Expr *) clause);
right = get_rightop((Expr *) clause);
if (!right)
return; /* shouldn't happen */
/* Can't do anything if inputs are not Vars */
- if (!IsA(left, Var) ||!IsA(right, Var))
+ if (!IsA(left, Var) ||
+ !IsA(right, Var))
return;
/* Verify mergejoinability and get left and right "<" operators */
/* Ignore any binary-compatible relabeling */
if (IsA(left, RelabelType))
- left = ((RelabelType *) left)->arg;
+ left = (Node *) ((RelabelType *) left)->arg;
if (IsA(right, RelabelType))
- right = ((RelabelType *) right)->arg;
+ right = (Node *) ((RelabelType *) right)->arg;
/* Look for the var */
/* Ignore any binary-compatible relabeling */
if (IsA(left, RelabelType))
- left = ((RelabelType *) left)->arg;
+ left = (Node *) ((RelabelType *) left)->arg;
if (IsA(right, RelabelType))
- right = ((RelabelType *) right)->arg;
+ right = (Node *) ((RelabelType *) right)->arg;
if (IsA(left, Var))
*var1 = (Var *) left;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.168 2002/12/06 05:20:24 momjian Exp $
+ * $Id: catversion.h,v 1.169 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200212061
+#define CATALOG_VERSION_NO 200212101
#endif
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodeSubplan.h,v 1.12 2002/12/05 15:50:38 tgl Exp $
+ * $Id: nodeSubplan.h,v 1.13 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/execnodes.h"
-extern SubPlanState *ExecInitSubPlan(SubPlan *node, EState *estate);
+extern SubPlanState *ExecInitSubPlan(SubPlanExpr *node, EState *estate);
extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext,
bool *isNull);
extern void ExecEndSubPlan(SubPlanState *node);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: makefuncs.h,v 1.42 2002/11/25 21:29:42 tgl Exp $
+ * $Id: makefuncs.h,v 1.43 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern A_Expr *makeSimpleA_Expr(int oper, const char *name,
Node *lexpr, Node *rexpr);
-extern Oper *makeOper(Oid opno,
- Oid opid,
- Oid opresulttype,
- bool opretset);
-
extern Var *makeVar(Index varno,
AttrNumber varattno,
Oid vartype,
int32 vartypmod,
Index varlevelsup);
-extern TargetEntry *makeTargetEntry(Resdom *resdom, Node *expr);
+extern TargetEntry *makeTargetEntry(Resdom *resdom, Expr *expr);
extern Resdom *makeResdom(AttrNumber resno,
Oid restype,
extern Const *makeNullConst(Oid consttype);
+extern Expr *makeBoolExpr(BoolExprType boolop, List *args);
+
extern Alias *makeAlias(const char *aliasname, List *colnames);
-extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod,
+extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod,
CoercionForm rformat);
extern RangeVar *makeRangeVar(char *schemaname, char *relname);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodeFuncs.h,v 1.17 2002/06/20 20:29:51 momjian Exp $
+ * $Id: nodeFuncs.h,v 1.18 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern bool single_node(Node *node);
extern bool var_is_outer(Var *var);
extern bool var_is_rel(Var *var);
-extern Oper *replace_opid(Oper *oper);
+extern void set_opfuncid(OpExpr *opexpr);
#endif /* NODEFUNCS_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.129 2002/12/06 05:00:31 momjian Exp $
+ * $Id: nodes.h,v 1.130 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
T_Hash,
T_SetOp,
T_Limit,
- T_SubPlan,
/*
* TAGS FOR PLAN STATE NODES (execnodes.h)
* TAGS FOR PRIMITIVE NODES (primnodes.h)
*/
T_Resdom = 300,
- T_Fjoin,
+ T_Alias,
+ T_RangeVar,
T_Expr,
T_Var,
- T_Oper,
T_Const,
T_Param,
T_Aggref,
+ T_ArrayRef,
+ T_FuncExpr,
+ T_OpExpr,
+ T_DistinctExpr,
+ T_BoolExpr,
T_SubLink,
- T_Func,
+ T_SubPlanExpr,
T_FieldSelect,
- T_ArrayRef,
T_RelabelType,
+ T_CaseExpr,
+ T_CaseWhen,
+ T_NullTest,
+ T_BooleanTest,
+ T_ConstraintTest,
+ T_ConstraintTestValue,
+ T_TargetEntry,
T_RangeTblRef,
- T_FromExpr,
T_JoinExpr,
+ T_FromExpr,
/*
* TAGS FOR PLANNER NODES (relation.h)
T_ViewStmt,
T_LoadStmt,
T_CreateDomainStmt,
- T_DomainConstraintValue,
T_CreatedbStmt,
T_DropdbStmt,
T_VacuumStmt,
T_ResTarget,
T_TypeCast,
T_SortGroupBy,
- T_Alias,
- T_RangeVar,
T_RangeSubselect,
T_RangeFunction,
T_TypeName,
- T_IndexElem,
T_ColumnDef,
+ T_IndexElem,
T_Constraint,
T_DefElem,
- T_TargetEntry,
T_RangeTblEntry,
T_SortClause,
T_GroupClause,
- T_NullTest,
- T_BooleanTest,
- T_ConstraintTest,
- T_ConstraintTestValue,
- T_CaseExpr,
- T_CaseWhen,
T_FkConstraint,
T_PrivGrantee,
T_FuncWithArgs,
T_PrivTarget,
T_InsertDefault,
+ T_DomainConstraintValue,
T_CreateOpClassItem,
T_CompositeTypeStmt,
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.221 2002/12/06 05:00:32 momjian Exp $
+ * $Id: parsenodes.h,v 1.222 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Query -
- * all statments are turned into a Query tree (via transformStmt)
+ * all statements are turned into a Query tree (via transformStmt)
* for further processing by the optimizer
* utility statements (i.e. non-optimizable statements)
* have the *utilityStmt field set.
TypeName *typename; /* the target type */
} TypeCast;
-/*
- * CaseExpr - a CASE expression
- */
-typedef struct CaseExpr
-{
- NodeTag type;
- Oid casetype;
- Node *arg; /* implicit equality comparison argument */
- List *args; /* the arguments (list of WHEN clauses) */
- Node *defresult; /* the default result (ELSE clause) */
-} CaseExpr;
-
-/*
- * CaseWhen - an argument to a CASE expression
- */
-typedef struct CaseWhen
-{
- NodeTag type;
- Node *expr; /* comparison expression */
- Node *result; /* substitution result */
-} CaseWhen;
-
-/* ----------------
- * NullTest
- *
- * NullTest represents the operation of testing a value for NULLness.
- * Currently, we only support scalar input values, but eventually a
- * row-constructor input should be supported.
- * The appropriate test is performed and returned as a boolean Datum.
- * ----------------
- */
-
-typedef enum NullTestType
-{
- IS_NULL, IS_NOT_NULL
-} NullTestType;
-
-typedef struct NullTest
-{
- NodeTag type;
- Node *arg; /* input expression */
- NullTestType nulltesttype; /* IS NULL, IS NOT NULL */
-} NullTest;
-
-/*
- * BooleanTest
- *
- * BooleanTest represents the operation of determining whether a boolean
- * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations
- * are supported. Note that a NULL input does *not* cause a NULL result.
- * The appropriate test is performed and returned as a boolean Datum.
- */
-
-typedef enum BoolTestType
-{
- IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN
-} BoolTestType;
-
-typedef struct BooleanTest
-{
- NodeTag type;
- Node *arg; /* input expression */
- BoolTestType booltesttype; /* test type */
-} BooleanTest;
-
-/*
- * ConstraintTest
- *
- * ConstraintTest represents the operation of testing a value to see whether
- * it meets a constraint. If so, the input value is returned as the result;
- * if not, an error is raised.
- */
-
-typedef enum ConstraintTestType
-{
- CONSTR_TEST_NOTNULL,
- CONSTR_TEST_CHECK
-} ConstraintTestType;
-
-typedef struct ConstraintTest
-{
- NodeTag type;
- Node *arg; /* input expression */
- ConstraintTestType testtype; /* test type */
- char *name; /* name of constraint (for error msgs) */
- char *domname; /* name of domain (for error messages) */
- Node *check_expr; /* for CHECK test, a boolean expression */
-} ConstraintTest;
-
-/*
- * Placeholder node for the value to be processed by a domains
- * check constraint.
- */
-typedef struct DomainConstraintValue
-{
- NodeTag type;
-} DomainConstraintValue;
-
-typedef struct ConstraintTestValue
-{
- NodeTag type;
- Oid typeId;
- int32 typeMod;
-} ConstraintTestValue;
-
-/*
- * ColumnDef - column definition (used in various creates)
- *
- * If the column has a default value, we may have the value expression
- * in either "raw" form (an untransformed parse tree) or "cooked" form
- * (the nodeToString representation of an executable expression tree),
- * depending on how this ColumnDef node was created (by parsing, or by
- * inheritance from an existing relation). We should never have both
- * in the same node!
- *
- * The constraints list may contain a CONSTR_DEFAULT item in a raw
- * parsetree produced by gram.y, but transformCreateStmt will remove
- * the item and set raw_default instead. CONSTR_DEFAULT items
- * should not appear in any subsequent processing.
- *
- * The "support" field, if not null, denotes a supporting relation that
- * should be linked by an internal dependency to the column. Currently
- * this is only used to link a SERIAL column's sequence to the column.
- */
-typedef struct ColumnDef
-{
- NodeTag type;
- char *colname; /* name of column */
- TypeName *typename; /* type of column */
- int inhcount; /* number of times column is inherited */
- bool is_local; /* column has local (non-inherited) def'n */
- bool is_not_null; /* NOT NULL constraint specified? */
- Node *raw_default; /* default value (untransformed parse
- * tree) */
- char *cooked_default; /* nodeToString representation */
- List *constraints; /* other constraints on column */
- RangeVar *support; /* supporting relation, if any */
-} ColumnDef;
-
/*
* FuncCall - a function or aggregate invocation
*
NodeTag type;
} InsertDefault;
+/*
+ * Empty node used as raw-parse-tree representation of VALUE keyword
+ * for domain check constraints.
+ */
+typedef struct DomainConstraintValue
+{
+ NodeTag type;
+} DomainConstraintValue;
+
/*
* SortGroupBy - for ORDER BY clause
*/
* assignment of RECORD TupleDesc */
} RangeFunction;
+/*
+ * ColumnDef - column definition (used in various creates)
+ *
+ * If the column has a default value, we may have the value expression
+ * in either "raw" form (an untransformed parse tree) or "cooked" form
+ * (the nodeToString representation of an executable expression tree),
+ * depending on how this ColumnDef node was created (by parsing, or by
+ * inheritance from an existing relation). We should never have both
+ * in the same node!
+ *
+ * The constraints list may contain a CONSTR_DEFAULT item in a raw
+ * parsetree produced by gram.y, but transformCreateStmt will remove
+ * the item and set raw_default instead. CONSTR_DEFAULT items
+ * should not appear in any subsequent processing.
+ *
+ * The "support" field, if not null, denotes a supporting relation that
+ * should be linked by an internal dependency to the column. Currently
+ * this is only used to link a SERIAL column's sequence to the column.
+ */
+typedef struct ColumnDef
+{
+ NodeTag type;
+ char *colname; /* name of column */
+ TypeName *typename; /* type of column */
+ int inhcount; /* number of times column is inherited */
+ bool is_local; /* column has local (non-inherited) def'n */
+ bool is_not_null; /* NOT NULL constraint specified? */
+ Node *raw_default; /* default value (untransformed parse
+ * tree) */
+ char *cooked_default; /* nodeToString representation */
+ List *constraints; /* other constraints on column */
+ RangeVar *support; /* supporting relation, if any */
+} ColumnDef;
+
/*
* IndexElem - index parameters (used in CREATE INDEX)
*
* Nodes for a Query tree
****************************************************************************/
-/*
- * TargetEntry -
- * a target entry (used in the transformed target list)
- *
- * one of resdom or fjoin is not NULL. a target list is
- * ((<resdom | fjoin> expr) (<resdom | fjoin> expr) ...)
- */
-typedef struct TargetEntry
-{
- NodeTag type;
- Resdom *resdom; /* fjoin overload this to be a list?? */
- Fjoin *fjoin;
- Node *expr;
-} TargetEntry;
-
/*--------------------
* RangeTblEntry -
* A range table is a List of RangeTblEntry nodes.
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: plannodes.h,v 1.62 2002/12/05 15:50:39 tgl Exp $
+ * $Id: plannodes.h,v 1.63 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Node *limitCount; /* COUNT parameter, or NULL if none */
} Limit;
-/* ---------------------
- * SubPlan node
- *
- * XXX Perhaps does not belong in this file? It's not really a Plan node.
- * Should we make it inherit from Plan anyway?
- * ---------------------
- */
-typedef struct SubPlan
-{
- NodeTag type;
- Plan *plan; /* subselect plan itself */
- int plan_id; /* dummy thing because of we haven't equal
- * funcs for plan nodes... actually, we
- * could put *plan itself somewhere else
- * (TopPlan node ?)... */
- List *rtable; /* range table for subselect */
- /* setParam and parParam are lists of integers (param IDs) */
- List *setParam; /* non-correlated EXPR & EXISTS subqueries
- * have to set some Params for paren Plan */
- List *parParam; /* indices of corr. Vars from parent plan */
- SubLink *sublink; /* SubLink node from parser; holds info
- * about what to do with subselect's
- * results */
-
- struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
-} SubPlan;
-
#endif /* PLANNODES_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: primnodes.h,v 1.71 2002/11/30 21:25:06 tgl Exp $
+ * $Id: primnodes.h,v 1.72 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* from final target list */
} Resdom;
-/*
- * Fjoin
- */
-typedef struct Fjoin
-{
- NodeTag type;
- bool fj_initialized; /* true if the Fjoin has already been
- * initialized for the current target list
- * evaluation */
- int fj_nNodes; /* The number of Iter nodes returning sets
- * that the node will flatten */
- List *fj_innerNode; /* exactly one Iter node. We eval every
- * node in the outerList once then eval
- * the inner node to completion pair the
- * outerList result vector with each inner
- * result to form the full result. When
- * the inner has been exhausted, we get
- * the next outer result vector and reset
- * the inner. */
- DatumPtr fj_results; /* The complete (flattened) result vector */
- BoolPtr fj_alwaysDone; /* a null vector to indicate sets with a
- * cardinality of 0, we treat them as the
- * set {NULL}. */
-} Fjoin;
-
/*
* Alias -
*/
/*
- * CoercionContext - distinguishes the allowed set of type casts
+ * Expr - generic superclass for executable-expression nodes
*
- * NB: ordering of the alternatives is significant; later (larger) values
- * allow more casts than earlier ones.
+ * All node types that are used in executable expression trees should derive
+ * from Expr (that is, have Expr as their first field). Since Expr only
+ * contains NodeTag, this is a formality, but it is an easy form of
+ * documentation. See also the ExprState node types in execnodes.h.
*/
-typedef enum CoercionContext
-{
- COERCION_IMPLICIT, /* coercion in context of expression */
- COERCION_ASSIGNMENT, /* coercion in context of assignment */
- COERCION_EXPLICIT /* explicit cast operation */
-} CoercionContext;
-
-/*
- * CoercionForm - information showing how to display a function-call node
- */
-typedef enum CoercionForm
-{
- COERCE_EXPLICIT_CALL, /* display as a function call */
- COERCE_EXPLICIT_CAST, /* display as an explicit cast */
- COERCE_IMPLICIT_CAST, /* implicit cast, so hide it */
- COERCE_DONTCARE /* special case for pathkeys */
-} CoercionForm;
-
-/*
- * Expr
- *
- * Note: DISTINCT_EXPR implements the "x IS DISTINCT FROM y" construct.
- * This is similar to an OP_EXPR, except for its handling of NULL inputs.
- * The oper field is always an Oper node for the "=" operator for x and y.
- * (We use "=", not the more obvious "<>", because more datatypes have "="
- * than "<>". This means the executor must invert the operator result.)
- */
-typedef enum OpType
-{
- OP_EXPR, DISTINCT_EXPR, FUNC_EXPR,
- OR_EXPR, AND_EXPR, NOT_EXPR, SUBPLAN_EXPR
-} OpType;
-
typedef struct Expr
{
NodeTag type;
- Oid typeOid; /* oid of the type of this expression */
- OpType opType; /* kind of expression */
- Node *oper; /* operator node if needed (Oper, Func, or
- * SubPlan) */
- List *args; /* arguments to this expression */
} Expr;
/*
- * Oper - Expr subnode for an OP_EXPR (or DISTINCT_EXPR)
- *
- * NOTE: in the good old days 'opno' used to be both (or either, or
- * neither) the pg_operator oid, and/or the pg_proc oid depending
- * on the postgres module in question (parser->pg_operator,
- * executor->pg_proc, planner->both), the mood of the programmer,
- * and the phase of the moon (rumors that it was also depending on the day
- * of the week are probably false). To make things even more postgres-like
- * (i.e. a mess) some comments were referring to 'opno' using the name
- * 'opid'. Anyway, now we have two separate fields, and of course that
- * immediately removes all bugs from the code... [ sp :-) ].
- *
- * Note also that opid is not necessarily filled in immediately on creation
- * of the node. The planner makes sure it is valid before passing the node
- * tree to the executor, but during parsing/planning opid is typically 0.
- */
-typedef struct Oper
-{
- NodeTag type;
- Oid opno; /* PG_OPERATOR OID of the operator */
- Oid opid; /* PG_PROC OID of underlying function */
- Oid opresulttype; /* PG_TYPE OID of result value */
- bool opretset; /* true if operator returns set */
- FunctionCachePtr op_fcache; /* runtime state, else NULL */
-} Oper;
-
-/*
- * Func - Expr subnode for a FUNC_EXPR
- */
-typedef struct Func
-{
- NodeTag type;
- Oid funcid; /* PG_PROC OID of the function */
- Oid funcresulttype; /* PG_TYPE OID of result value */
- bool funcretset; /* true if function returns set */
- CoercionForm funcformat; /* how to display this function call */
- FunctionCachePtr func_fcache; /* runtime state, or NULL */
-} Func;
-
-/*
- * Var
+ * Var - expression node representing a variable (ie, a table column)
*
* Note: during parsing/planning, varnoold/varoattno are always just copies
* of varno/varattno. At the tail end of planning, Var nodes appearing in
typedef struct Var
{
- NodeTag type;
+ Expr xpr;
Index varno; /* index of this var's relation in the
* range table (could also be INNER or
* OUTER) */
*/
typedef struct Const
{
- NodeTag type;
+ Expr xpr;
Oid consttype; /* PG_TYPE OID of the constant's datatype */
int constlen; /* typlen of the constant's datatype */
Datum constvalue; /* the constant's value */
*
* PARAM_EXEC: The parameter is an internal executor parameter.
* It has a number contained in the `paramid' field.
- *
* ----------------
*/
typedef struct Param
{
- NodeTag type;
+ Expr xpr;
int paramkind; /* kind of parameter. See above */
AttrNumber paramid; /* numeric ID for parameter ("$1") */
char *paramname; /* name for parameter ("$.foo") */
*/
typedef struct Aggref
{
- NodeTag type;
+ Expr xpr;
Oid aggfnoid; /* pg_proc Oid of the aggregate */
Oid aggtype; /* type Oid of result of the aggregate */
- Node *target; /* expression we are aggregating on */
+ Expr *target; /* expression we are aggregating on */
bool aggstar; /* TRUE if argument was really '*' */
bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */
+
+ /* XXX this should move to AggrefExprState: */
int aggno; /* workspace for executor (see nodeAgg.c) */
} Aggref;
+/* ----------------
+ * ArrayRef: describes an array subscripting operation
+ *
+ * An ArrayRef can describe fetching a single element from an array,
+ * fetching a subarray (array slice), storing a single element into
+ * an array, or storing a slice. The "store" cases work with an
+ * initial array value and a source value that is inserted into the
+ * appropriate part of the array; the result of the operation is an
+ * entire new modified array value.
+ *
+ * If reflowerindexpr = NIL, then we are fetching or storing a single array
+ * element at the subscripts given by refupperindexpr. Otherwise we are
+ * fetching or storing an array slice, that is a rectangular subarray
+ * with lower and upper bounds given by the index expressions.
+ * reflowerindexpr must be the same length as refupperindexpr when it
+ * is not NIL.
+ *
+ * Note: array types can be fixed-length (refattrlength > 0), but only
+ * when the element type is itself fixed-length. Otherwise they are
+ * varlena structures and have refattrlength = -1. In any case,
+ * an array type is never pass-by-value.
+ *
+ * Note: refrestype is NOT the element type, but the array type,
+ * when doing subarray fetch or either type of store. It might be a good
+ * idea to include a refelemtype field as well.
+ * ----------------
+ */
+typedef struct ArrayRef
+{
+ Expr xpr;
+ Oid refrestype; /* type of the result of the ArrayRef
+ * operation */
+ int refattrlength; /* typlen of array type */
+ int refelemlength; /* typlen of the array element type */
+ bool refelembyval; /* is the element type pass-by-value? */
+ char refelemalign; /* typalign of the element type */
+ List *refupperindexpr;/* expressions that evaluate to upper
+ * array indexes */
+ List *reflowerindexpr;/* expressions that evaluate to lower
+ * array indexes */
+ Expr *refexpr; /* the expression that evaluates to an
+ * array value */
+ Expr *refassgnexpr; /* expression for the source value, or
+ * NULL if fetch */
+} ArrayRef;
+
+/*
+ * CoercionContext - distinguishes the allowed set of type casts
+ *
+ * NB: ordering of the alternatives is significant; later (larger) values
+ * allow more casts than earlier ones.
+ */
+typedef enum CoercionContext
+{
+ COERCION_IMPLICIT, /* coercion in context of expression */
+ COERCION_ASSIGNMENT, /* coercion in context of assignment */
+ COERCION_EXPLICIT /* explicit cast operation */
+} CoercionContext;
+
+/*
+ * CoercionForm - information showing how to display a function-call node
+ */
+typedef enum CoercionForm
+{
+ COERCE_EXPLICIT_CALL, /* display as a function call */
+ COERCE_EXPLICIT_CAST, /* display as an explicit cast */
+ COERCE_IMPLICIT_CAST, /* implicit cast, so hide it */
+ COERCE_DONTCARE /* special case for pathkeys */
+} CoercionForm;
+
+/*
+ * FuncExpr - expression node for a function call
+ */
+typedef struct FuncExpr
+{
+ Expr xpr;
+ Oid funcid; /* PG_PROC OID of the function */
+ Oid funcresulttype; /* PG_TYPE OID of result value */
+ bool funcretset; /* true if function returns set */
+ CoercionForm funcformat; /* how to display this function call */
+ List *args; /* arguments to the function */
+
+ FunctionCachePtr func_fcache; /* XXX runtime state, or NULL */
+} FuncExpr;
+
+/*
+ * OpExpr - expression node for an operator invocation
+ *
+ * Semantically, this is essentially the same as a function call.
+ *
+ * Note that opfuncid is not necessarily filled in immediately on creation
+ * of the node. The planner makes sure it is valid before passing the node
+ * tree to the executor, but during parsing/planning opfuncid is typically 0.
+ */
+typedef struct OpExpr
+{
+ Expr xpr;
+ Oid opno; /* PG_OPERATOR OID of the operator */
+ Oid opfuncid; /* PG_PROC OID of underlying function */
+ Oid opresulttype; /* PG_TYPE OID of result value */
+ bool opretset; /* true if operator returns set */
+ List *args; /* arguments to the operator (1 or 2) */
+
+ FunctionCachePtr op_fcache; /* XXX runtime state, else NULL */
+} OpExpr;
+
+/*
+ * DistinctExpr - expression node for "x IS DISTINCT FROM y"
+ *
+ * Except for the nodetag, this is represented identically to an OpExpr
+ * referencing the "=" operator for x and y.
+ * We use "=", not the more obvious "<>", because more datatypes have "="
+ * than "<>". This means the executor must invert the operator result.
+ * Note that the operator function won't be called at all if either input
+ * is NULL, since then the result can be determined directly.
+ */
+typedef OpExpr DistinctExpr;
+
+/*
+ * BoolExpr - expression node for the basic Boolean operators AND, OR, NOT
+ *
+ * Notice the arguments are given as a List. For NOT, of course the list
+ * must always have exactly one element. For AND and OR, the executor can
+ * handle any number of arguments. The parser treats AND and OR as binary
+ * and so it only produces two-element lists, but the optimizer will flatten
+ * trees of AND and OR nodes to produce longer lists when possible.
+ */
+typedef enum BoolExprType
+{
+ AND_EXPR, OR_EXPR, NOT_EXPR
+} BoolExprType;
+
+typedef struct BoolExpr
+{
+ Expr xpr;
+ BoolExprType boolop;
+ List *args; /* arguments to this expression */
+} BoolExpr;
+
/* ----------------
* SubLink
*
* depending on the "useor" flag. ALL and ANY combine the per-row results
* using AND and OR semantics respectively.
*
+ * SubLink is classed as an Expr node, but it is not actually executable;
+ * it must be replaced in the expression tree by a SubPlanExpr node during
+ * planning.
+ *
* NOTE: lefthand and oper have varying meanings depending on where you look
* in the parse/plan pipeline:
* 1. gram.y delivers a list of the (untransformed) lefthand expressions in
* lefthand, and sets oper to a single A_Expr (not a list!) containing
* the string name of the operator, but no arguments.
* 2. The parser's expression transformation transforms lefthand normally,
- * and replaces oper with a list of Oper nodes, one per lefthand
+ * and replaces oper with a list of OpExpr nodes, one per lefthand
* expression. These nodes represent the parser's resolution of exactly
* which operator to apply to each pair of lefthand and targetlist
- * expressions. However, we have not constructed actual Expr trees for
- * these operators yet. This is the representation seen in saved rules
- * and in the rewriter.
- * 3. Finally, the planner converts the oper list to a list of normal Expr
+ * expressions. However, we have not constructed complete Expr trees for
+ * these operations yet: the args fields of the OpExpr nodes are NIL.
+ * This is the representation seen in saved rules and in the rewriter.
+ * 3. Finally, the planner converts the oper list to a list of normal OpExpr
* nodes representing the application of the operator(s) to the lefthand
* expressions and values from the inner targetlist. The inner
* targetlist items are represented by placeholder Param nodes.
* Planner routines that might see either representation 2 or 3 can tell
* the difference by checking whether lefthand is NIL or not. Also,
* representation 2 appears in a "bare" SubLink, while representation 3 is
- * found in SubLinks that are children of SubPlan nodes.
+ * found in SubLinks that are children of SubPlanExpr nodes.
*
* In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are
* always NIL. useor is not significant either for these sublink types.
typedef struct SubLink
{
- NodeTag type;
+ Expr xpr;
SubLinkType subLinkType; /* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
bool useor; /* TRUE to combine column results with
* "OR" not "AND" */
List *lefthand; /* list of outer-query expressions on the
* left */
- List *oper; /* list of Oper nodes for combining
- * operators */
+ List *oper; /* list of OpExpr nodes for combining
+ * operators, or final list of executable
+ * expressions */
Node *subselect; /* subselect as Query* or parsetree */
} SubLink;
-/* ----------------
- * ArrayRef: describes an array subscripting operation
- *
- * An ArrayRef can describe fetching a single element from an array,
- * fetching a subarray (array slice), storing a single element into
- * an array, or storing a slice. The "store" cases work with an
- * initial array value and a source value that is inserted into the
- * appropriate part of the array; the result of the operation is an
- * entire new modified array value.
- *
- * If reflowerindexpr = NIL, then we are fetching or storing a single array
- * element at the subscripts given by refupperindexpr. Otherwise we are
- * fetching or storing an array slice, that is a rectangular subarray
- * with lower and upper bounds given by the index expressions.
- * reflowerindexpr must be the same length as refupperindexpr when it
- * is not NIL.
- *
- * Note: array types can be fixed-length (refattrlength > 0), but only
- * when the element type is itself fixed-length. Otherwise they are
- * varlena structures and have refattrlength = -1. In any case,
- * an array type is never pass-by-value.
+/*
+ * SubPlanExpr - executable expression node for a subplan (sub-SELECT)
*
- * Note: refrestype is NOT the element type, but the array type,
- * when doing subarray fetch or either type of store. It might be a good
- * idea to include a refelemtype field as well.
- * ----------------
+ * The planner replaces SubLink nodes in expression trees with SubPlanExpr
+ * nodes after it has finished planning the subquery. See notes above.
*/
-typedef struct ArrayRef
+typedef struct SubPlanExpr
{
- NodeTag type;
- Oid refrestype; /* type of the result of the ArrayRef
- * operation */
- int refattrlength; /* typlen of array type */
- int refelemlength; /* typlen of the array element type */
- bool refelembyval; /* is the element type pass-by-value? */
- char refelemalign; /* typalign of the element type */
- List *refupperindexpr;/* expressions that evaluate to upper
- * array indexes */
- List *reflowerindexpr;/* expressions that evaluate to lower
- * array indexes */
- Node *refexpr; /* the expression that evaluates to an
- * array value */
- Node *refassgnexpr; /* expression for the source value, or
- * NULL if fetch */
-} ArrayRef;
+ Expr xpr;
+ Oid typeOid; /* PG_TYPE OID of the expression result */
+ struct Plan *plan; /* subselect plan itself */
+ int plan_id; /* dummy thing because of we haven't equal
+ * funcs for plan nodes... actually, we
+ * could put *plan itself somewhere else
+ * (TopPlan node ?)... */
+ List *rtable; /* range table for subselect */
+ /* setParam and parParam are lists of integers (param IDs) */
+ List *setParam; /* non-correlated EXPR & EXISTS subqueries
+ * have to set some Params for paren Plan */
+ List *parParam; /* indices of input Params from parent plan */
+ List *args; /* exprs to pass as parParam values */
+ SubLink *sublink; /* SubLink node from parser; holds info
+ * about what to do with subselect's
+ * results */
+
+ struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
+} SubPlanExpr;
/* ----------------
* FieldSelect
typedef struct FieldSelect
{
- NodeTag type;
- Node *arg; /* input expression */
+ Expr xpr;
+ Expr *arg; /* input expression */
AttrNumber fieldnum; /* attribute number of field to extract */
Oid resulttype; /* type of the field (result type of this
* node) */
typedef struct RelabelType
{
- NodeTag type;
- Node *arg; /* input expression */
+ Expr xpr;
+ Expr *arg; /* input expression */
Oid resulttype; /* output type of coercion expression */
int32 resulttypmod; /* output typmod (usually -1) */
CoercionForm relabelformat; /* how to display this node */
} RelabelType;
+/*
+ * CaseExpr - a CASE expression
+ */
+typedef struct CaseExpr
+{
+ Expr xpr;
+ Oid casetype; /* type of expression result */
+ Expr *arg; /* implicit equality comparison argument */
+ List *args; /* the arguments (list of WHEN clauses) */
+ Expr *defresult; /* the default result (ELSE clause) */
+} CaseExpr;
+
+/*
+ * CaseWhen - an argument to a CASE expression
+ */
+typedef struct CaseWhen
+{
+ Expr xpr;
+ Expr *expr; /* condition expression */
+ Expr *result; /* substitution result */
+} CaseWhen;
+
+/* ----------------
+ * NullTest
+ *
+ * NullTest represents the operation of testing a value for NULLness.
+ * Currently, we only support scalar input values, but eventually a
+ * row-constructor input should be supported.
+ * The appropriate test is performed and returned as a boolean Datum.
+ * ----------------
+ */
+
+typedef enum NullTestType
+{
+ IS_NULL, IS_NOT_NULL
+} NullTestType;
+
+typedef struct NullTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ NullTestType nulltesttype; /* IS NULL, IS NOT NULL */
+} NullTest;
+
+/*
+ * BooleanTest
+ *
+ * BooleanTest represents the operation of determining whether a boolean
+ * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations
+ * are supported. Note that a NULL input does *not* cause a NULL result.
+ * The appropriate test is performed and returned as a boolean Datum.
+ */
+
+typedef enum BoolTestType
+{
+ IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN
+} BoolTestType;
+
+typedef struct BooleanTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ BoolTestType booltesttype; /* test type */
+} BooleanTest;
+
+/*
+ * ConstraintTest
+ *
+ * ConstraintTest represents the operation of testing a value to see whether
+ * it meets a constraint. If so, the input value is returned as the result;
+ * if not, an error is raised.
+ */
+
+typedef enum ConstraintTestType
+{
+ CONSTR_TEST_NOTNULL,
+ CONSTR_TEST_CHECK
+} ConstraintTestType;
+
+typedef struct ConstraintTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ ConstraintTestType testtype; /* test type */
+ char *name; /* name of constraint (for error msgs) */
+ char *domname; /* name of domain (for error messages) */
+ Expr *check_expr; /* for CHECK test, a boolean expression */
+} ConstraintTest;
+
+/*
+ * Placeholder node for the value to be processed by a domains
+ * check constraint. This is effectively like a Param; could we use
+ * a Param node instead?
+ */
+typedef struct ConstraintTestValue
+{
+ Expr xpr;
+ Oid typeId;
+ int32 typeMod;
+} ConstraintTestValue;
+
+
+/*
+ * TargetEntry -
+ * a target entry (used in query target lists)
+ *
+ * Strictly speaking, a TargetEntry isn't an expression node (since it can't
+ * be evaluated by ExecEvalExpr). But we treat it as one anyway, since in
+ * very many places it's convenient to process a whole query targetlist as a
+ * single expression tree.
+ *
+ * The separation between TargetEntry and Resdom is historical. One of these
+ * days, Resdom should probably get folded into TargetEntry.
+ */
+typedef struct TargetEntry
+{
+ Expr xpr;
+ Resdom *resdom; /* descriptor for targetlist item */
+ Expr *expr; /* expression to evaluate */
+} TargetEntry;
+
/* ----------------------------------------------------------------
* node types for join trees
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: relation.h,v 1.73 2002/12/05 15:50:39 tgl Exp $
+ * $Id: relation.h,v 1.74 2002/12/12 15:49:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* key typically points to a Var node, ie a relation attribute, but it
- * can also point to a Func clause representing the value indexed by a
+ * can also point to a FuncExpr clause representing the value indexed by a
* functional index. Someday we might allow arbitrary expressions as
* path keys, so don't assume more than you must.
*/
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: clauses.h,v 1.56 2002/12/01 21:05:14 tgl Exp $
+ * $Id: clauses.h,v 1.57 2002/12/12 15:49:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/relation.h"
-extern Expr *make_clause(int type, Node *oper, List *args);
-extern bool is_opclause(Node *clause);
-extern Expr *make_opclause(Oper *op, Var *leftop, Var *rightop);
+
+#define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr))
+#define is_funcclause(clause) ((clause) != NULL && IsA(clause, FuncExpr))
+#define is_subplan(clause) ((clause) != NULL && IsA(clause, SubPlanExpr))
+
+
+extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
+ Expr *leftop, Expr *rightop);
extern Var *get_leftop(Expr *clause);
extern Var *get_rightop(Expr *clause);
-extern bool is_funcclause(Node *clause);
-extern Expr *make_funcclause(Func *func, List *funcargs);
-
-extern bool or_clause(Node *clause);
-extern Expr *make_orclause(List *orclauses);
+extern Expr *make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset,
+ CoercionForm funcformat, List *funcargs);
extern bool not_clause(Node *clause);
extern Expr *make_notclause(Expr *notclause);
extern Expr *get_notclausearg(Expr *notclause);
+extern bool or_clause(Node *clause);
+extern Expr *make_orclause(List *orclauses);
+
extern bool and_clause(Node *clause);
extern Expr *make_andclause(List *andclauses);
extern Node *make_and_qual(Node *qual1, Node *qual2);
extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars);
extern int NumRelids(Node *clause);
-extern void CommuteClause(Expr *clause);
+extern void CommuteClause(OpExpr *clause);
extern Node *eval_const_expressions(Node *node);
extern void query_tree_mutator(Query *query, Node *(*mutator) (),
void *context, int flags);
-#define is_subplan(clause) ((clause) != NULL && \
- IsA(clause, Expr) && \
- ((Expr *) (clause))->opType == SUBPLAN_EXPR)
-
#endif /* CLAUSES_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: paths.h,v 1.61 2002/11/24 21:52:15 tgl Exp $
+ * $Id: paths.h,v 1.62 2002/12/12 15:49:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void create_index_paths(Query *root, RelOptInfo *rel);
extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel,
Relids outer_relids, JoinType jointype);
-extern Oid indexable_operator(Expr *clause, Oid opclass,
- bool indexkey_on_left);
extern List *extract_or_indexqual_conditions(RelOptInfo *rel,
IndexOptInfo *index,
Expr *orsubclause);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: planmain.h,v 1.63 2002/11/21 00:42:19 tgl Exp $
+ * $Id: planmain.h,v 1.64 2002/12/12 15:49:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern List *join_references(List *clauses, List *rtable,
List *outer_tlist, List *inner_tlist,
Index acceptable_rel);
-extern void fix_opids(Node *node);
+extern void fix_opfuncids(Node *node);
#endif /* PLANMAIN_H */
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.72 2002/12/05 15:50:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.73 2002/12/12 15:49:42 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
static bool
exec_simple_check_node(Node *node)
{
+ if (node == NULL)
+ return TRUE;
+
switch (nodeTag(node))
{
- case T_Expr:
+ case T_Const:
+ return TRUE;
+
+ case T_Param:
+ return TRUE;
+
+ case T_ArrayRef:
{
- Expr *expr = (Expr *) node;
- List *l;
+ ArrayRef *expr = (ArrayRef *) node;
- switch (expr->opType)
- {
- case OP_EXPR:
- case DISTINCT_EXPR:
- case FUNC_EXPR:
- case OR_EXPR:
- case AND_EXPR:
- case NOT_EXPR:
- break;
+ if (!exec_simple_check_node((Node *) expr->refupperindexpr))
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->reflowerindexpr))
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->refexpr))
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->refassgnexpr))
+ return FALSE;
- default:
- return FALSE;
- }
+ return TRUE;
+ }
- foreach(l, expr->args)
- {
- if (!exec_simple_check_node(lfirst(l)))
- return FALSE;
- }
+ case T_FuncExpr:
+ {
+ FuncExpr *expr = (FuncExpr *) node;
+
+ if (expr->funcretset)
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->args))
+ return FALSE;
return TRUE;
}
- case T_Param:
- return TRUE;
+ case T_OpExpr:
+ {
+ OpExpr *expr = (OpExpr *) node;
- case T_Const:
- return TRUE;
+ if (expr->opretset)
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->args))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ case T_DistinctExpr:
+ {
+ DistinctExpr *expr = (DistinctExpr *) node;
+
+ if (expr->opretset)
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->args))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ case T_BoolExpr:
+ {
+ BoolExpr *expr = (BoolExpr *) node;
+
+ if (!exec_simple_check_node((Node *) expr->args))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ case T_FieldSelect:
+ return exec_simple_check_node((Node *) ((FieldSelect *) node)->arg);
case T_RelabelType:
- return exec_simple_check_node(((RelabelType *) node)->arg);
+ return exec_simple_check_node((Node *) ((RelabelType *) node)->arg);
+
+ case T_CaseExpr:
+ {
+ CaseExpr *expr = (CaseExpr *) node;
+
+ if (!exec_simple_check_node((Node *) expr->arg))
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->args))
+ return FALSE;
+ if (!exec_simple_check_node((Node *) expr->defresult))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ case T_CaseWhen:
+ {
+ CaseWhen *when = (CaseWhen *) node;
+
+ if (!exec_simple_check_node((Node *) when->expr))
+ return FALSE;
+ if (!exec_simple_check_node((Node *) when->result))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ case T_NullTest:
+ return exec_simple_check_node((Node *) ((NullTest *) node)->arg);
+
+ case T_BooleanTest:
+ return exec_simple_check_node((Node *) ((BooleanTest *) node)->arg);
+
+ case T_List:
+ {
+ List *expr = (List *) node;
+ List *l;
+
+ foreach(l, expr)
+ {
+ if (!exec_simple_check_node(lfirst(l)))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
default:
return FALSE;
tle = (TargetEntry *) lfirst(plan->targetlist);
/*
- * 5. Check that all the nodes in the expression are one of Expr,
- * Param or Const.
+ * 5. Check that all the nodes in the expression are non-scary.
*/
- if (!exec_simple_check_node(tle->expr))
+ if (!exec_simple_check_node((Node *) tle->expr))
return;
/*
* Yes - this is a simple expression. Remember the expression and the
* return type
*/
- expr->plan_simple_expr = tle->expr;
- expr->plan_simple_type = exprType(tle->expr);
+ expr->plan_simple_expr = (Node *) tle->expr;
+ expr->plan_simple_type = exprType((Node *) tle->expr);
}
/*