1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-07 11:02:12 +03:00

Phase 2 of read-only-plans project: restructure expression-tree nodes

so that all executable expression nodes inherit from a common supertype
Expr.  This is somewhat of an exercise in code purity rather than any
real functional advance, but getting rid of the extra Oper or Func node
formerly used in each operator or function call should provide at least
a little space and speed improvement.
initdb forced by changes in stored-rules representation.
This commit is contained in:
Tom Lane 2002-12-12 15:49:42 +00:00
parent debb072886
commit a0bf885f9e
69 changed files with 3390 additions and 3433 deletions

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -806,25 +806,28 @@ find_expr_references_walker(Node *node,
} }
return false; return false;
} }
if (IsA(node, Expr)) if (IsA(node, FuncExpr))
{ {
Expr *expr = (Expr *) node; FuncExpr *funcexpr = (FuncExpr *) node;
if (expr->opType == OP_EXPR || add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
expr->opType == DISTINCT_EXPR)
{
Oper *oper = (Oper *) expr->oper;
add_object_address(OCLASS_OPERATOR, oper->opno, 0,
&context->addrs); &context->addrs);
/* fall through to examine arguments */
} }
else if (expr->opType == FUNC_EXPR) if (IsA(node, OpExpr))
{ {
Func *func = (Func *) expr->oper; OpExpr *opexpr = (OpExpr *) node;
add_object_address(OCLASS_PROC, func->funcid, 0, add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
&context->addrs); &context->addrs);
/* fall through to examine arguments */
} }
if (IsA(node, DistinctExpr))
{
DistinctExpr *distinctexpr = (DistinctExpr *) node;
add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
&context->addrs);
/* fall through to examine arguments */ /* fall through to examine arguments */
} }
if (IsA(node, Aggref)) if (IsA(node, Aggref))

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -1602,11 +1602,6 @@ AddRelationRawConstraints(Relation rel,
*/ */
expr = (Node *) make_ands_implicit((Expr *) expr); expr = (Node *) make_ands_implicit((Expr *) expr);
/*
* Must fix opids in operator clauses.
*/
fix_opids(expr);
/* /*
* OK, store it. * OK, store it.
*/ */
@ -1750,11 +1745,6 @@ cookDefault(ParseState *pstate,
*/ */
expr = eval_const_expressions(expr); expr = eval_const_expressions(expr);
/*
* Must fix opids, in case any operators remain...
*/
fix_opids(expr);
return (expr); return (expr);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -41,6 +41,7 @@
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h" #include "optimizer/prep.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "storage/sinval.h" #include "storage/sinval.h"
@ -919,6 +920,7 @@ BuildIndexInfo(Form_pg_index indexStruct)
predString = DatumGetCString(DirectFunctionCall1(textout, predString = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(&indexStruct->indpred))); PointerGetDatum(&indexStruct->indpred)));
ii->ii_Predicate = stringToNode(predString); ii->ii_Predicate = stringToNode(predString);
fix_opfuncids((Node *) ii->ii_Predicate);
pfree(predString); pfree(predString);
} }
else else

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -424,7 +424,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList)
} while (attr->attisdropped); } while (attr->attisdropped);
rellogcols++; rellogcols++;
tletype = exprType(tle->expr); tletype = exprType((Node *) tle->expr);
atttype = attr->atttypid; atttype = attr->atttypid;
if (!IsBinaryCoercible(tletype, atttype)) if (!IsBinaryCoercible(tletype, atttype))
elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -35,6 +35,7 @@
#include "mb/pg_wchar.h" #include "mb/pg_wchar.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "optimizer/planmain.h"
#include "parser/parse_coerce.h" #include "parser/parse_coerce.h"
#include "parser/parse_relation.h" #include "parser/parse_relation.h"
#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteHandler.h"
@ -839,6 +840,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
defexprs[num_defaults] = build_column_default(rel, i + 1); defexprs[num_defaults] = build_column_default(rel, i + 1);
if (defexprs[num_defaults] != NULL) if (defexprs[num_defaults] != NULL)
{ {
fix_opfuncids(defexprs[num_defaults]);
defmap[num_defaults] = i; defmap[num_defaults] = i;
num_defaults++; num_defaults++;
} }
@ -869,6 +871,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
/* check whether any constraints actually found */ /* check whether any constraints actually found */
if (node != (Node *) prm) if (node != (Node *) prm)
{ {
fix_opfuncids(node);
constraintexprs[i] = node; constraintexprs[i] = node;
hasConstraints = true; hasConstraints = true;
} }

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * 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 $
* *
*/ */
@ -417,20 +417,27 @@ explain_outNode(StringInfo str,
{ {
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid, RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
es->rtable); es->rtable);
Expr *expr;
Func *funcnode;
Oid funcid;
char *proname; char *proname;
/* Assert it's on a RangeFunction */ /* Assert it's on a RangeFunction */
Assert(rte->rtekind == RTE_FUNCTION); Assert(rte->rtekind == RTE_FUNCTION);
expr = (Expr *) rte->funcexpr; /*
funcnode = (Func *) expr->oper; * If the expression is still a function call, we can get
funcid = funcnode->funcid; * 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 */ /* We only show the func name, not schema name */
proname = get_func_name(funcid); proname = get_func_name(funcid);
}
else
proname = rte->eref->aliasname;
appendStringInfo(str, " on %s", appendStringInfo(str, " on %s",
quote_identifier(proname)); quote_identifier(proname));
@ -583,7 +590,7 @@ explain_outNode(StringInfo str,
appendStringInfo(str, " InitPlan\n"); appendStringInfo(str, " InitPlan\n");
foreach(lst, plan->initPlan) foreach(lst, plan->initPlan)
{ {
SubPlan *subplan = (SubPlan *) lfirst(lst); SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist); SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist);
es->rtable = subplan->rtable; es->rtable = subplan->rtable;
@ -683,7 +690,7 @@ explain_outNode(StringInfo str,
foreach(lst, planstate->subPlan) foreach(lst, planstate->subPlan)
{ {
SubPlanState *sps = (SubPlanState *) lfirst(lst); SubPlanState *sps = (SubPlanState *) lfirst(lst);
SubPlan *sp = (SubPlan *) sps->ps.plan; SubPlanExpr *sp = (SubPlanExpr *) sps->ps.plan;
es->rtable = sp->rtable; es->rtable = sp->rtable;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
@ -870,7 +877,7 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel,
if (target->resdom->reskey == keyno) if (target->resdom->reskey == keyno)
{ {
/* Deparse the expression, showing any top-level cast */ /* Deparse the expression, showing any top-level cast */
exprstr = deparse_expression(target->expr, context, exprstr = deparse_expression((Node *) target->expr, context,
useprefix, true); useprefix, true);
/* And add to str */ /* And add to str */
if (keyno > 1) if (keyno > 1)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -159,10 +159,10 @@ DefineIndex(RangeVar *heapRelation,
* While we are at it, we reduce it to a canonical (CNF or DNF) form * While we are at it, we reduce it to a canonical (CNF or DNF) form
* to simplify the task of proving implications. * to simplify the task of proving implications.
*/ */
if (predicate != NULL && rangetable != NIL) if (predicate)
{ {
cnfPred = canonicalize_qual((Expr *) copyObject(predicate), true); cnfPred = canonicalize_qual((Expr *) copyObject(predicate), true);
fix_opids((Node *) cnfPred); fix_opfuncids((Node *) cnfPred);
CheckPredicate(cnfPred, rangetable, relationId); CheckPredicate(cnfPred, rangetable, relationId);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -2723,7 +2723,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
/* /*
* We need to make a parse state and range * We need to make a parse state and range
* table to allow us to transformExpr and * 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 * expression we can pass to ExecQual
*/ */
pstate = make_parsestate(NULL); pstate = make_parsestate(NULL);
@ -2764,8 +2764,8 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
*/ */
expr = eval_const_expressions(expr); expr = eval_const_expressions(expr);
/* And fix the opids */ /* And fix the opfuncids */
fix_opids(expr); fix_opfuncids(expr);
qual = makeList1(expr); qual = makeList1(expr);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
@ -1341,7 +1341,9 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
* the constraint is being added to. * the constraint is being added to.
*/ */
expr = stringToNode(ccbin); expr = stringToNode(ccbin);
fix_opfuncids(expr);
rels = get_rels_with_domain(domainoid); rels = get_rels_with_domain(domainoid);
foreach (rt, rels) foreach (rt, rels)
{ {
Relation typrel; Relation typrel;
@ -1522,7 +1524,7 @@ domainPermissionCheck(HeapTuple tup, TypeName *typename)
/* /*
* * domainAddConstraint
*/ */
char * char *
domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
@ -1601,16 +1603,15 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
expr = eval_const_expressions(expr); expr = eval_const_expressions(expr);
/* /*
* Must fix opids in operator clauses. * Convert to string form for storage.
*/ */
fix_opids(expr);
ccbin = nodeToString(expr); ccbin = nodeToString(expr);
/* /*
* Deparse it. Since VARNOs aren't allowed in domain * Deparse it to produce text for consrc.
* constraints, relation context isn't required as anything *
* other than a shell. * Since VARNOs aren't allowed in domain constraints, relation context
* isn't required as anything other than a shell.
*/ */
ccsrc = deparse_expression(expr, ccsrc = deparse_expression(expr,
deparse_context_for(domainName, deparse_context_for(domainName,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -77,7 +77,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType,
bool resjunk; bool resjunk;
AttrNumber cleanResno; AttrNumber cleanResno;
AttrNumber *cleanMap; AttrNumber *cleanMap;
Node *expr; Expr *expr;
/* /*
* Make a memory context that will hold the JunkFilter as well as all * Make a memory context that will hold the JunkFilter as well as all
@ -104,8 +104,6 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType,
{ {
TargetEntry *rtarget = lfirst(t); TargetEntry *rtarget = lfirst(t);
if (rtarget->resdom != NULL)
{
resdom = rtarget->resdom; resdom = rtarget->resdom;
expr = rtarget->expr; expr = rtarget->expr;
resjunk = resdom->resjunk; resjunk = resdom->resjunk;
@ -125,46 +123,6 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType,
cleanTargetList = lappend(cleanTargetList, tle); cleanTargetList = lappend(cleanTargetList, tle);
} }
} }
else
{
#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);
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
}
}
/* /*
* Now calculate the tuple type for the cleaned tuple (we were already * Now calculate the tuple type for the cleaned tuple (we were already
@ -192,10 +150,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType,
{ {
TargetEntry *tle = lfirst(t); TargetEntry *tle = lfirst(t);
if (tle->resdom != NULL)
{
resdom = tle->resdom; resdom = tle->resdom;
expr = tle->expr;
resjunk = resdom->resjunk; resjunk = resdom->resjunk;
if (!resjunk) if (!resjunk)
{ {
@ -203,32 +158,6 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType,
cleanResno++; cleanResno++;
} }
} }
else
{
#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;
cleanResno++;
#ifdef SETS_FIXED
foreach(fjListP, lnext(fjList))
{
TargetEntry *tle = lfirst(fjListP);
resdom = tle->resdom;
cleanMap[cleanResno - 1] = resdom->resno;
cleanResno++;
}
#endif
}
}
} }
else else
cleanMap = NULL; cleanMap = NULL;

View File

@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -40,6 +40,7 @@
#include "executor/execdebug.h" #include "executor/execdebug.h"
#include "executor/execdefs.h" #include "executor/execdefs.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "optimizer/planmain.h"
#include "optimizer/var.h" #include "optimizer/var.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "utils/acl.h" #include "utils/acl.h"
@ -1541,6 +1542,7 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
for (i = 0; i < ncheck; i++) for (i = 0; i < ncheck; i++)
{ {
qual = (List *) stringToNode(check[i].ccbin); qual = (List *) stringToNode(check[i].ccbin);
fix_opfuncids((Node *) qual);
resultRelInfo->ri_ConstraintExprs[i] = qual; resultRelInfo->ri_ConstraintExprs[i] = qual;
} }
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);

View File

@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -228,9 +228,9 @@ ExecInitNode(Plan *node, EState *estate)
subps = NIL; subps = NIL;
foreach(subp, node->initPlan) 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)); subps = lappend(subps, ExecInitSubPlan(subplan, estate));
} }
result->initPlan = subps; result->initPlan = subps;
@ -242,9 +242,9 @@ ExecInitNode(Plan *node, EState *estate)
subps = NIL; subps = NIL;
foreach(subp, result->subPlan) 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)); subps = lappend(subps, ExecInitSubPlan(subplan, estate));
} }
result->subPlan = subps; result->subPlan = subps;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -53,17 +53,20 @@ static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext,
static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext, static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull); 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); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalDistinct(Expr *opClause, ExprContext *econtext, static Datum ExecEvalDistinct(DistinctExpr *op, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext, static Datum ExecEvalFunc(FuncExpr *func, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo, static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
List *argList, ExprContext *econtext); List *argList, ExprContext *econtext);
static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull); static Datum ExecEvalNot(BoolExpr *notclause, ExprContext *econtext,
static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull); bool *isNull);
static Datum ExecEvalOr(Expr *orExpr, 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, static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext, static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
@ -122,7 +125,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
if (arrayRef->refexpr != NULL) if (arrayRef->refexpr != NULL)
{ {
array_source = (ArrayType *) array_source = (ArrayType *)
DatumGetPointer(ExecEvalExpr(arrayRef->refexpr, DatumGetPointer(ExecEvalExpr((Node *) arrayRef->refexpr,
econtext, econtext,
isNull, isNull,
isDone)); isDone));
@ -203,7 +206,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
if (isAssignment) if (isAssignment)
{ {
Datum sourceData = ExecEvalExpr(arrayRef->refassgnexpr, Datum sourceData = ExecEvalExpr((Node *) arrayRef->refassgnexpr,
econtext, econtext,
isNull, isNull,
NULL); NULL);
@ -839,7 +842,7 @@ ExecMakeTableFunctionResult(Node *funcexpr,
bool returnsTuple = false; 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 * grammar only allows a function call at the top level of a table
* function reference. However, if the function doesn't return set then * function reference. However, if the function doesn't return set then
* the planner might have replaced the function call via constant-folding * the planner might have replaced the function call via constant-folding
@ -848,11 +851,9 @@ ExecMakeTableFunctionResult(Node *funcexpr,
* we don't get a chance to pass a special ReturnSetInfo to any functions * we don't get a chance to pass a special ReturnSetInfo to any functions
* buried in the expression. * buried in the expression.
*/ */
if (funcexpr && if (funcexpr && IsA(funcexpr, FuncExpr))
IsA(funcexpr, Expr) &&
((Expr *) funcexpr)->opType == FUNC_EXPR)
{ {
Func *func; FuncExpr *func = (FuncExpr *) funcexpr;
List *argList; List *argList;
FunctionCachePtr fcache; FunctionCachePtr fcache;
ExprDoneCond argDone; ExprDoneCond argDone;
@ -862,13 +863,12 @@ ExecMakeTableFunctionResult(Node *funcexpr,
*/ */
direct_function_call = true; direct_function_call = true;
funcrettype = ((Expr *) funcexpr)->typeOid; funcrettype = func->funcresulttype;
func = (Func *) ((Expr *) funcexpr)->oper; argList = func->args;
argList = ((Expr *) funcexpr)->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
* it * initialize it
*/ */
fcache = func->func_fcache; fcache = func->func_fcache;
if (fcache == NULL) if (fcache == NULL)
@ -1102,12 +1102,11 @@ ExecMakeTableFunctionResult(Node *funcexpr,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalOper(Expr *opClause, ExecEvalOper(OpExpr *op,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
Oper *op;
List *argList; List *argList;
FunctionCachePtr fcache; FunctionCachePtr fcache;
@ -1117,17 +1116,16 @@ ExecEvalOper(Expr *opClause,
* arguments and returns the result of calling the function on the * arguments and returns the result of calling the function on the
* evaluated arguments. * evaluated arguments.
*/ */
op = (Oper *) opClause->oper; argList = op->args;
argList = opClause->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 * it
*/ */
fcache = op->op_fcache; fcache = op->op_fcache;
if (fcache == NULL) if (fcache == NULL)
{ {
fcache = init_fcache(op->opid, length(argList), fcache = init_fcache(op->opfuncid, length(argList),
econtext->ecxt_per_query_memory); econtext->ecxt_per_query_memory);
op->op_fcache = fcache; op->op_fcache = fcache;
} }
@ -1142,12 +1140,11 @@ ExecEvalOper(Expr *opClause,
*/ */
static Datum static Datum
ExecEvalFunc(Expr *funcClause, ExecEvalFunc(FuncExpr *func,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
Func *func;
List *argList; List *argList;
FunctionCachePtr fcache; FunctionCachePtr fcache;
@ -1159,11 +1156,10 @@ ExecEvalFunc(Expr *funcClause,
* *
* this is nearly identical to the ExecEvalOper code. * this is nearly identical to the ExecEvalOper code.
*/ */
func = (Func *) funcClause->oper; argList = func->args;
argList = funcClause->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 * it
*/ */
fcache = func->func_fcache; fcache = func->func_fcache;
@ -1190,7 +1186,7 @@ ExecEvalFunc(Expr *funcClause,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalDistinct(Expr *opClause, ExecEvalDistinct(DistinctExpr *op,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
@ -1199,23 +1195,21 @@ ExecEvalDistinct(Expr *opClause,
FunctionCachePtr fcache; FunctionCachePtr fcache;
FunctionCallInfoData fcinfo; FunctionCallInfoData fcinfo;
ExprDoneCond argDone; ExprDoneCond argDone;
Oper *op;
List *argList; List *argList;
/* /*
* extract info from opClause * extract info from op
*/ */
op = (Oper *) opClause->oper; argList = op->args;
argList = opClause->args;
/* /*
* get the fcache from the Oper node. If it is NULL, then initialize * get the fcache from the DistinctExpr node. If it is NULL, then
* it * initialize it
*/ */
fcache = op->op_fcache; fcache = op->op_fcache;
if (fcache == NULL) if (fcache == NULL)
{ {
fcache = init_fcache(op->opid, length(argList), fcache = init_fcache(op->opfuncid, length(argList),
econtext->ecxt_per_query_memory); econtext->ecxt_per_query_memory);
op->op_fcache = fcache; op->op_fcache = fcache;
} }
@ -1256,8 +1250,7 @@ ExecEvalDistinct(Expr *opClause,
* ExecEvalOr * ExecEvalOr
* ExecEvalAnd * ExecEvalAnd
* *
* Evaluate boolean expressions. Evaluation of 'or' is * Evaluate boolean expressions, with appropriate short-circuiting.
* short-circuited when the first true (or null) value is found.
* *
* The query planner reformulates clause expressions in the * The query planner reformulates clause expressions in the
* qualification to conjunctive normal form. If we ever get * qualification to conjunctive normal form. If we ever get
@ -1268,7 +1261,7 @@ ExecEvalDistinct(Expr *opClause,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull) ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull)
{ {
Node *clause; Node *clause;
Datum expr_value; Datum expr_value;
@ -1296,7 +1289,7 @@ ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull) ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull)
{ {
List *clauses; List *clauses;
List *clause; List *clause;
@ -1344,7 +1337,7 @@ ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull) ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull)
{ {
List *clauses; List *clauses;
List *clause; List *clause;
@ -1409,7 +1402,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
{ {
CaseWhen *wclause = lfirst(clause); CaseWhen *wclause = lfirst(clause);
clause_value = ExecEvalExpr(wclause->expr, clause_value = ExecEvalExpr((Node *) wclause->expr,
econtext, econtext,
isNull, isNull,
NULL); NULL);
@ -1421,7 +1414,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
*/ */
if (DatumGetBool(clause_value) && !*isNull) if (DatumGetBool(clause_value) && !*isNull)
{ {
return ExecEvalExpr(wclause->result, return ExecEvalExpr((Node *) wclause->result,
econtext, econtext,
isNull, isNull,
isDone); isDone);
@ -1430,7 +1423,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
if (caseExpr->defresult) if (caseExpr->defresult)
{ {
return ExecEvalExpr(caseExpr->defresult, return ExecEvalExpr((Node *) caseExpr->defresult,
econtext, econtext,
isNull, isNull,
isDone); isDone);
@ -1454,7 +1447,7 @@ ExecEvalNullTest(NullTest *ntest,
{ {
Datum result; Datum result;
result = ExecEvalExpr(ntest->arg, econtext, isNull, isDone); result = ExecEvalExpr((Node *) ntest->arg, econtext, isNull, isDone);
switch (ntest->nulltesttype) switch (ntest->nulltesttype)
{ {
case IS_NULL: case IS_NULL:
@ -1494,7 +1487,7 @@ ExecEvalBooleanTest(BooleanTest *btest,
{ {
Datum result; Datum result;
result = ExecEvalExpr(btest->arg, econtext, isNull, isDone); result = ExecEvalExpr((Node *) btest->arg, econtext, isNull, isDone);
switch (btest->booltesttype) switch (btest->booltesttype)
{ {
case IS_TRUE: case IS_TRUE:
@ -1590,7 +1583,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext,
{ {
Datum result; Datum result;
result = ExecEvalExpr(constraint->arg, econtext, isNull, isDone); result = ExecEvalExpr((Node *) constraint->arg, econtext, isNull, isDone);
switch (constraint->testtype) switch (constraint->testtype)
{ {
@ -1607,7 +1600,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext,
econtext->domainValue_datum = result; econtext->domainValue_datum = result;
econtext->domainValue_isNull = *isNull; econtext->domainValue_isNull = *isNull;
conResult = ExecEvalExpr(constraint->check_expr, econtext, isNull, isDone); conResult = ExecEvalExpr((Node *) constraint->check_expr, econtext, isNull, isDone);
if (!DatumGetBool(conResult)) if (!DatumGetBool(conResult))
elog(ERROR, "ExecEvalConstraintTest: Domain %s constraint %s failed", elog(ERROR, "ExecEvalConstraintTest: Domain %s constraint %s failed",
@ -1638,7 +1631,7 @@ ExecEvalFieldSelect(FieldSelect *fselect,
Datum result; Datum result;
TupleTableSlot *resSlot; TupleTableSlot *resSlot;
result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone); result = ExecEvalExpr((Node *) fselect->arg, econtext, isNull, isDone);
if (*isNull) if (*isNull)
return result; return result;
resSlot = (TupleTableSlot *) DatumGetPointer(result); resSlot = (TupleTableSlot *) DatumGetPointer(result);
@ -1738,47 +1731,48 @@ ExecEvalExpr(Node *expression,
isNull, isNull,
isDone); isDone);
break; break;
case T_Expr: case T_FuncExpr:
{ retDatum = ExecEvalFunc((FuncExpr *) expression, econtext,
Expr *expr = (Expr *) expression;
switch (expr->opType)
{
case OP_EXPR:
retDatum = ExecEvalOper(expr, econtext,
isNull, isDone); isNull, isDone);
break; break;
case FUNC_EXPR: case T_OpExpr:
retDatum = ExecEvalFunc(expr, econtext, retDatum = ExecEvalOper((OpExpr *) expression, econtext,
isNull, isDone); isNull, isDone);
break; break;
case T_DistinctExpr:
retDatum = ExecEvalDistinct((DistinctExpr *) expression, econtext,
isNull, isDone);
break;
case T_BoolExpr:
{
BoolExpr *expr = (BoolExpr *) expression;
switch (expr->boolop)
{
case AND_EXPR:
retDatum = ExecEvalAnd(expr, econtext, isNull);
break;
case OR_EXPR: case OR_EXPR:
retDatum = ExecEvalOr(expr, econtext, isNull); retDatum = ExecEvalOr(expr, econtext, isNull);
break; break;
case AND_EXPR:
retDatum = ExecEvalAnd(expr, econtext, isNull);
break;
case NOT_EXPR: case NOT_EXPR:
retDatum = ExecEvalNot(expr, econtext, isNull); retDatum = ExecEvalNot(expr, econtext, isNull);
break; 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: default:
elog(ERROR, "ExecEvalExpr: unknown expression type %d", elog(ERROR, "ExecEvalExpr: unknown boolop %d",
expr->opType); expr->boolop);
retDatum = 0; /* keep compiler quiet */ retDatum = 0; /* keep compiler quiet */
break; break;
} }
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: case T_FieldSelect:
retDatum = ExecEvalFieldSelect((FieldSelect *) expression, retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
econtext, econtext,
@ -1786,7 +1780,7 @@ ExecEvalExpr(Node *expression,
isDone); isDone);
break; break;
case T_RelabelType: case T_RelabelType:
retDatum = ExecEvalExpr(((RelabelType *) expression)->arg, retDatum = ExecEvalExpr((Node *) ((RelabelType *) expression)->arg,
econtext, econtext,
isNull, isNull,
isDone); isDone);
@ -1861,7 +1855,7 @@ ExecEvalExprSwitchContext(Node *expression,
* *
* Soon this will generate an expression state tree paralleling the given * Soon this will generate an expression state tree paralleling the given
* expression tree. Right now, it just searches the expression tree for * expression tree. Right now, it just searches the expression tree for
* Aggref and SubPlan nodes. * Aggref and SubPlanExpr nodes.
*/ */
Node * Node *
ExecInitExpr(Node *node, PlanState *parent) ExecInitExpr(Node *node, PlanState *parent)
@ -1887,7 +1881,7 @@ ExecInitExpr(Node *node, PlanState *parent)
aggstate->aggs = lcons(node, aggstate->aggs); aggstate->aggs = lcons(node, aggstate->aggs);
naggs = ++aggstate->numaggs; naggs = ++aggstate->numaggs;
ExecInitExpr(((Aggref *) node)->target, parent); ExecInitExpr((Node *) ((Aggref *) node)->target, parent);
/* /*
* Complain if the aggregate's argument contains any * Complain if the aggregate's argument contains any
@ -1907,64 +1901,67 @@ ExecInitExpr(Node *node, PlanState *parent)
ExecInitExpr((Node *) aref->refupperindexpr, parent); ExecInitExpr((Node *) aref->refupperindexpr, parent);
ExecInitExpr((Node *) aref->reflowerindexpr, parent); ExecInitExpr((Node *) aref->reflowerindexpr, parent);
ExecInitExpr(aref->refexpr, parent); ExecInitExpr((Node *) aref->refexpr, parent);
ExecInitExpr(aref->refassgnexpr, parent); ExecInitExpr((Node *) aref->refassgnexpr, parent);
} }
break; break;
case T_Expr: case T_FuncExpr:
{ {
Expr *expr = (Expr *) node; FuncExpr *funcexpr = (FuncExpr *) node;
switch (expr->opType) ExecInitExpr((Node *) funcexpr->args, parent);
}
break;
case T_OpExpr:
{ {
case OP_EXPR: OpExpr *opexpr = (OpExpr *) node;
ExecInitExpr((Node *) opexpr->args, parent);
}
break; break;
case FUNC_EXPR: case T_DistinctExpr:
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; 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 SubPlan nodes to * Here we just add the SubPlanExpr nodes to
* parent->subPlan. Later they will be expanded * parent->subPlan. Later they will be expanded
* to SubPlanState nodes. * to SubPlanState nodes.
*/ */
parent->subPlan = lcons(expr->oper, parent->subPlan = lcons(subplanexpr, parent->subPlan);
parent->subPlan);
/* Must recurse into oper list too */ /* Must recurse into oper list too */
Assert(IsA(sublink, SubLink));
if (sublink->lefthand) if (sublink->lefthand)
elog(ERROR, "ExecInitExpr: sublink has not been transformed"); elog(ERROR, "ExecInitExpr: sublink has not been transformed");
ExecInitExpr((Node *) sublink->oper, parent); ExecInitExpr((Node *) sublink->oper, parent);
}
else ExecInitExpr((Node *) subplanexpr->args, parent);
elog(ERROR, "ExecInitExpr: SubPlan not expected here");
break;
default:
elog(ERROR, "ExecInitExpr: unknown expression type %d",
expr->opType);
break;
}
/* for all Expr node types, examine args list */
ExecInitExpr((Node *) expr->args, parent);
} }
break; break;
case T_FieldSelect: case T_FieldSelect:
ExecInitExpr(((FieldSelect *) node)->arg, parent); ExecInitExpr((Node *) ((FieldSelect *) node)->arg, parent);
break; break;
case T_RelabelType: case T_RelabelType:
ExecInitExpr(((RelabelType *) node)->arg, parent); ExecInitExpr((Node *) ((RelabelType *) node)->arg, parent);
break; break;
case T_CaseExpr: case T_CaseExpr:
{ {
@ -1975,35 +1972,35 @@ ExecInitExpr(Node *node, PlanState *parent)
CaseWhen *when = (CaseWhen *) lfirst(temp); CaseWhen *when = (CaseWhen *) lfirst(temp);
Assert(IsA(when, CaseWhen)); Assert(IsA(when, CaseWhen));
ExecInitExpr(when->expr, parent); ExecInitExpr((Node *) when->expr, parent);
ExecInitExpr(when->result, parent); ExecInitExpr((Node *) when->result, parent);
} }
/* caseexpr->arg should be null, but we'll check it anyway */ /* caseexpr->arg should be null, but we'll check it anyway */
ExecInitExpr(caseexpr->arg, parent); ExecInitExpr((Node *) caseexpr->arg, parent);
ExecInitExpr(caseexpr->defresult, parent); ExecInitExpr((Node *) caseexpr->defresult, parent);
} }
break; break;
case T_NullTest: case T_NullTest:
ExecInitExpr(((NullTest *) node)->arg, parent); ExecInitExpr((Node *) ((NullTest *) node)->arg, parent);
break; break;
case T_BooleanTest: case T_BooleanTest:
ExecInitExpr(((BooleanTest *) node)->arg, parent); ExecInitExpr((Node *) ((BooleanTest *) node)->arg, parent);
break; break;
case T_ConstraintTest: case T_ConstraintTest:
ExecInitExpr(((ConstraintTest *) node)->arg, parent); ExecInitExpr((Node *) ((ConstraintTest *) node)->arg, parent);
ExecInitExpr(((ConstraintTest *) node)->check_expr, parent); ExecInitExpr((Node *) ((ConstraintTest *) node)->check_expr, parent);
break; break;
case T_ConstraintTestValue: case T_ConstraintTestValue:
break; break;
case T_TargetEntry:
ExecInitExpr((Node *) ((TargetEntry *) node)->expr, parent);
break;
case T_List: case T_List:
foreach(temp, (List *) node) foreach(temp, (List *) node)
{ {
ExecInitExpr((Node *) lfirst(temp), parent); ExecInitExpr((Node *) lfirst(temp), parent);
} }
break; break;
case T_TargetEntry:
ExecInitExpr(((TargetEntry *) node)->expr, parent);
break;
default: default:
elog(ERROR, "ExecInitExpr: unknown expression type %d", elog(ERROR, "ExecInitExpr: unknown expression type %d",
nodeTag(node)); nodeTag(node));
@ -2119,19 +2116,8 @@ ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
int int
ExecTargetListLength(List *targetlist) ExecTargetListLength(List *targetlist)
{ {
int len = 0; /* This used to be more complex, but fjoins are dead */
List *tl; return length(targetlist);
foreach(tl, targetlist)
{
TargetEntry *curTle = (TargetEntry *) lfirst(tl);
if (curTle->resdom != NULL)
len++;
else
len += curTle->fjoin->fj_nNodes;
}
return len;
} }
/* /*
@ -2147,14 +2133,9 @@ ExecCleanTargetListLength(List *targetlist)
{ {
TargetEntry *curTle = (TargetEntry *) lfirst(tl); TargetEntry *curTle = (TargetEntry *) lfirst(tl);
if (curTle->resdom != NULL)
{
if (!curTle->resdom->resjunk) if (!curTle->resdom->resjunk)
len++; len++;
} }
else
len += curTle->fjoin->fj_nNodes;
}
return len; return len;
} }
@ -2182,10 +2163,8 @@ ExecTargetList(List *targetlist,
#define NPREALLOCDOMAINS 64 #define NPREALLOCDOMAINS 64
char nullsArray[NPREALLOCDOMAINS]; char nullsArray[NPREALLOCDOMAINS];
bool fjIsNullArray[NPREALLOCDOMAINS];
ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS]; ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS];
char *nulls; char *nulls;
bool *fjIsNull;
ExprDoneCond *itemIsDone; ExprDoneCond *itemIsDone;
List *tl; List *tl;
TargetEntry *tle; TargetEntry *tle;
@ -2223,24 +2202,20 @@ ExecTargetList(List *targetlist,
* allocate an array of char's to hold the "null" information only if * 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 have a really large targetlist. otherwise we use the stack.
* *
* We also allocate a bool array that is used to hold fjoin result state, * We also allocate another array that holds the isDone status for each
* and another array that holds the isDone status for each targetlist * targetlist item. The isDone status is needed so that we can iterate,
* item. The isDone status is needed so that we can iterate,
* generating multiple tuples, when one or more tlist items return * 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.) * isDone = ExprMultipleResult.)
*/ */
if (nodomains > NPREALLOCDOMAINS) if (nodomains > NPREALLOCDOMAINS)
{ {
nulls = (char *) palloc(nodomains * sizeof(char)); nulls = (char *) palloc(nodomains * sizeof(char));
fjIsNull = (bool *) palloc(nodomains * sizeof(bool));
itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond)); itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond));
} }
else else
{ {
nulls = nullsArray; nulls = nullsArray;
fjIsNull = fjIsNullArray;
itemIsDone = itemIsDoneArray; itemIsDone = itemIsDoneArray;
} }
@ -2257,11 +2232,9 @@ ExecTargetList(List *targetlist,
{ {
tle = lfirst(tl); tle = lfirst(tl);
if (tle->resdom != NULL)
{
resind = tle->resdom->resno - 1; resind = tle->resdom->resno - 1;
values[resind] = ExecEvalExpr(tle->expr, values[resind] = ExecEvalExpr((Node *) tle->expr,
econtext, econtext,
&isNull, &isNull,
&itemIsDone[resind]); &itemIsDone[resind]);
@ -2284,57 +2257,6 @@ ExecTargetList(List *targetlist,
} }
} }
} }
else
{
#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)
{
MemoryContextSwitchTo(oldContext);
newTuple = NULL;
goto exit;
}
/*
* 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))
{
Node *outernode = lfirst(fjTlist);
fjRes = (Resdom *) outernode->iterexpr;
resind = fjRes->resno - 1;
values[resind] = results[curNode];
nulls[resind] = fjIsNull[curNode] ? 'n' : ' ';
}
#else
elog(ERROR, "ExecTargetList: fjoin nodes not currently supported");
#endif
}
}
if (haveDoneSets) if (haveDoneSets)
{ {
@ -2368,7 +2290,7 @@ ExecTargetList(List *targetlist,
if (itemIsDone[resind] == ExprEndResult) if (itemIsDone[resind] == ExprEndResult)
{ {
values[resind] = ExecEvalExpr(tle->expr, values[resind] = ExecEvalExpr((Node *) tle->expr,
econtext, econtext,
&isNull, &isNull,
&itemIsDone[resind]); &itemIsDone[resind]);
@ -2404,7 +2326,7 @@ ExecTargetList(List *targetlist,
while (itemIsDone[resind] == ExprMultipleResult) while (itemIsDone[resind] == ExprMultipleResult)
{ {
(void) ExecEvalExpr(tle->expr, (void) ExecEvalExpr((Node *) tle->expr,
econtext, econtext,
&isNull, &isNull,
&itemIsDone[resind]); &itemIsDone[resind]);
@ -2434,7 +2356,6 @@ exit:
if (nodomains > NPREALLOCDOMAINS) if (nodomains > NPREALLOCDOMAINS)
{ {
pfree(nulls); pfree(nulls);
pfree(fjIsNull);
pfree(itemIsDone); pfree(itemIsDone);
} }

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -576,93 +576,15 @@ ExecTypeFromTL(List *targetList, bool hasoid)
foreach(tlitem, targetList) foreach(tlitem, targetList)
{ {
TargetEntry *tle = lfirst(tlitem); TargetEntry *tle = lfirst(tlitem);
Resdom *resdom; Resdom *resdom = tle->resdom;
Oid restype;
if (tle->resdom != NULL)
{
resdom = tle->resdom;
restype = resdom->restype;
TupleDescInitEntry(typeInfo, TupleDescInitEntry(typeInfo,
resdom->resno, resdom->resno,
resdom->resname, resdom->resname,
restype, resdom->restype,
resdom->restypmod, resdom->restypmod,
0, 0,
false); 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
}
}
} }
return typeInfo; return typeInfo;

View File

@ -45,7 +45,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -415,7 +415,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
Datum newVal; Datum newVal;
bool isNull; bool isNull;
newVal = ExecEvalExprSwitchContext(aggref->target, econtext, newVal = ExecEvalExprSwitchContext((Node *) aggref->target, econtext,
&isNull, NULL); &isNull, NULL);
if (aggref->aggdistinct) if (aggref->aggdistinct)
@ -1298,7 +1298,7 @@ ExecInitAgg(Agg *node, EState *estate)
* pg_proc.proargtypes, because the latter might be 0. * pg_proc.proargtypes, because the latter might be 0.
* (Consider COUNT(*).) * (Consider COUNT(*).)
*/ */
Oid inputType = exprType(aggref->target); Oid inputType = exprType((Node *) aggref->target);
if (!IsBinaryCoercible(inputType, aggform->aggtranstype)) if (!IsBinaryCoercible(inputType, aggform->aggtranstype))
elog(ERROR, "Aggregate %u needs to have compatible input type and transition type", elog(ERROR, "Aggregate %u needs to have compatible input type and transition type",
@ -1312,7 +1312,7 @@ ExecInitAgg(Agg *node, EState *estate)
* pg_proc.proargtypes, because the latter might be a pseudotype. * pg_proc.proargtypes, because the latter might be a pseudotype.
* (Consider COUNT(*).) * (Consider COUNT(*).)
*/ */
Oid inputType = exprType(aggref->target); Oid inputType = exprType((Node *) aggref->target);
Oid eq_function; Oid eq_function;
/* We don't implement DISTINCT aggs in the HASHED case */ /* We don't implement DISTINCT aggs in the HASHED case */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -703,28 +703,26 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
listscan = qual; listscan = qual;
for (j = 0; j < n_keys; j++) for (j = 0; j < n_keys; j++)
{ {
Expr *clause; /* one clause of index qual */ OpExpr *clause; /* one clause of index qual */
Oper *op; /* operator used in clause */
Node *leftop; /* expr on lhs of operator */ Node *leftop; /* expr on lhs of operator */
Node *rightop; /* expr on rhs ... */ Node *rightop; /* expr on rhs ... */
bits16 flags = 0; bits16 flags = 0;
int scanvar; /* which var identifies varattno */ int scanvar; /* which var identifies varattno */
AttrNumber varattno = 0; /* att number used in scan */ 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) */ Datum scanvalue = 0; /* value used in scan (if const) */
/* /*
* extract clause information from the qualification * extract clause information from the qualification
*/ */
clause = lfirst(listscan); clause = (OpExpr *) lfirst(listscan);
listscan = lnext(listscan); listscan = lnext(listscan);
op = (Oper *) clause->oper; if (!IsA(clause, OpExpr))
if (!IsA(clause, Expr) ||!IsA(op, Oper))
elog(ERROR, "ExecInitIndexScan: indxqual not an opclause!"); elog(ERROR, "ExecInitIndexScan: indxqual not an opclause!");
opid = op->opid; opfuncid = clause->opfuncid;
/* /*
* Here we figure out the contents of the index qual. The * Here we figure out the contents of the index qual. The
@ -767,10 +765,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
/* /*
* determine information in leftop * determine information in leftop
*/ */
leftop = (Node *) get_leftop(clause); leftop = (Node *) get_leftop((Expr *) clause);
if (leftop && IsA(leftop, RelabelType)) if (leftop && IsA(leftop, RelabelType))
leftop = ((RelabelType *) leftop)->arg; leftop = (Node *) ((RelabelType *) leftop)->arg;
Assert(leftop != NULL); Assert(leftop != NULL);
@ -834,10 +832,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
/* /*
* now determine information in rightop * now determine information in rightop
*/ */
rightop = (Node *) get_rightop(clause); rightop = (Node *) get_rightop((Expr *) clause);
if (rightop && IsA(rightop, RelabelType)) if (rightop && IsA(rightop, RelabelType))
rightop = ((RelabelType *) rightop)->arg; rightop = (Node *) ((RelabelType *) rightop)->arg;
Assert(rightop != NULL); Assert(rightop != NULL);
@ -921,7 +919,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
flags, flags,
varattno, /* attribute number to varattno, /* attribute number to
* scan */ * scan */
(RegProcedure) opid, /* reg proc to use */ opfuncid, /* reg proc to use */
scanvalue); /* constant */ scanvalue); /* constant */
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -119,16 +119,14 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals)
ltcdr = *ltQuals; ltcdr = *ltQuals;
foreach(gtcdr, *gtQuals) foreach(gtcdr, *gtQuals)
{ {
Expr *ltqual = (Expr *) lfirst(ltcdr); OpExpr *ltop = (OpExpr *) lfirst(ltcdr);
Expr *gtqual = (Expr *) lfirst(gtcdr); OpExpr *gtop = (OpExpr *) lfirst(gtcdr);
Oper *ltop = (Oper *) ltqual->oper;
Oper *gtop = (Oper *) gtqual->oper;
/* /*
* The two ops should be identical, so use either one for lookup. * The two ops should be identical, so use either one for lookup.
*/ */
if (!IsA(ltop, Oper)) if (!IsA(ltop, OpExpr))
elog(ERROR, "MJFormSkipQuals: op not an Oper!"); elog(ERROR, "MJFormSkipQuals: op not an OpExpr!");
/* /*
* Lookup the operators, and replace the data in the copied * Lookup the operators, and replace the data in the copied
@ -137,8 +135,8 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals)
op_mergejoin_crossops(ltop->opno, op_mergejoin_crossops(ltop->opno,
&ltop->opno, &ltop->opno,
&gtop->opno, &gtop->opno,
&ltop->opid, &ltop->opfuncid,
&gtop->opid); &gtop->opfuncid);
ltop->op_fcache = NULL; ltop->op_fcache = NULL;
gtop->op_fcache = NULL; gtop->op_fcache = NULL;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -34,7 +34,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
ExprContext *econtext, bool *isNull) ExprContext *econtext, bool *isNull)
{ {
PlanState *planstate = node->planstate; PlanState *planstate = node->planstate;
SubPlan *subplan = (SubPlan *) node->ps.plan; SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
SubLink *sublink = subplan->sublink; SubLink *sublink = subplan->sublink;
SubLinkType subLinkType = sublink->subLinkType; SubLinkType subLinkType = sublink->subLinkType;
bool useor = sublink->useor; bool useor = sublink->useor;
@ -151,7 +151,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
*/ */
foreach(lst, sublink->oper) foreach(lst, sublink->oper)
{ {
Expr *expr = (Expr *) lfirst(lst); OpExpr *expr = (OpExpr *) lfirst(lst);
Param *prm = lsecond(expr->args); Param *prm = lsecond(expr->args);
ParamExecData *prmdata; ParamExecData *prmdata;
Datum expresult; Datum expresult;
@ -172,8 +172,8 @@ ExecSubPlan(SubPlanState *node, List *pvar,
{ {
switch (nodeTag(prm)) switch (nodeTag(prm))
{ {
case T_Expr: case T_FuncExpr:
prm = lfirst(((Expr *) prm)->args); prm = lfirst(((FuncExpr *) prm)->args);
break; break;
case T_RelabelType: case T_RelabelType:
prm = (Param *) (((RelabelType *) prm)->arg); prm = (Param *) (((RelabelType *) prm)->arg);
@ -288,7 +288,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
SubPlanState * SubPlanState *
ExecInitSubPlan(SubPlan *node, EState *estate) ExecInitSubPlan(SubPlanExpr *node, EState *estate)
{ {
SubPlanState *subplanstate; SubPlanState *subplanstate;
EState *sp_estate; EState *sp_estate;
@ -374,7 +374,7 @@ void
ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{ {
PlanState *planstate = node->planstate; PlanState *planstate = node->planstate;
SubPlan *subplan = (SubPlan *) node->ps.plan; SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
SubLink *sublink = subplan->sublink; SubLink *sublink = subplan->sublink;
EState *estate = node->ps.state; EState *estate = node->ps.state;
MemoryContext oldcontext; MemoryContext oldcontext;
@ -497,7 +497,7 @@ void
ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
{ {
PlanState *planstate = node->planstate; PlanState *planstate = node->planstate;
SubPlan *subplan = (SubPlan *) node->ps.plan; SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
EState *estate = node->ps.state; EState *estate = node->ps.state;
List *lst; List *lst;

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -563,21 +563,6 @@ _copyLimit(Limit *from)
return newnode; 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 * primnodes.h copy functions
* **************************************************************** * ****************************************************************
@ -603,20 +588,9 @@ _copyResdom(Resdom *from)
return newnode; return newnode;
} }
static Fjoin * /*
_copyFjoin(Fjoin *from) * _copyAlias
{ */
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;
}
static Alias * static Alias *
_copyAlias(Alias *from) _copyAlias(Alias *from)
{ {
@ -628,6 +602,9 @@ _copyAlias(Alias *from)
return newnode; return newnode;
} }
/*
* _copyRangeVar
*/
static RangeVar * static RangeVar *
_copyRangeVar(RangeVar *from) _copyRangeVar(RangeVar *from)
{ {
@ -644,20 +621,11 @@ _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 * _copyVar
@ -678,25 +646,6 @@ _copyVar(Var *from)
return newnode; 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 * _copyConst
*/ */
@ -748,25 +697,6 @@ _copyParam(Param *from)
return newnode; return newnode;
} }
/*
* _copyFunc
*/
static Func *
_copyFunc(Func *from)
{
Func *newnode = makeNode(Func);
COPY_SCALAR_FIELD(funcid);
COPY_SCALAR_FIELD(funcresulttype);
COPY_SCALAR_FIELD(funcretset);
COPY_SCALAR_FIELD(funcformat);
/* Do not copy the run-time state, if any */
newnode->func_fcache = NULL;
return newnode;
}
/* /*
* _copyAggref * _copyAggref
*/ */
@ -780,7 +710,102 @@ _copyAggref(Aggref *from)
COPY_NODE_FIELD(target); COPY_NODE_FIELD(target);
COPY_SCALAR_FIELD(aggstar); COPY_SCALAR_FIELD(aggstar);
COPY_SCALAR_FIELD(aggdistinct); COPY_SCALAR_FIELD(aggdistinct);
COPY_SCALAR_FIELD(aggno); /* probably not necessary */ 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;
return newnode;
}
/*
* _copyOpExpr
*/
static OpExpr *
_copyOpExpr(OpExpr *from)
{
OpExpr *newnode = makeNode(OpExpr);
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;
} }
@ -802,6 +827,26 @@ _copySubLink(SubLink *from)
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 * _copyFieldSelect
*/ */
@ -834,6 +879,112 @@ _copyRelabelType(RelabelType *from)
return newnode; 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 * static RangeTblRef *
_copyRangeTblRef(RangeTblRef *from) _copyRangeTblRef(RangeTblRef *from)
{ {
@ -844,6 +995,9 @@ _copyRangeTblRef(RangeTblRef *from)
return newnode; return newnode;
} }
/*
* _copyJoinExpr
*/
static JoinExpr * static JoinExpr *
_copyJoinExpr(JoinExpr *from) _copyJoinExpr(JoinExpr *from)
{ {
@ -861,6 +1015,9 @@ _copyJoinExpr(JoinExpr *from)
return newnode; return newnode;
} }
/*
* _copyFromExpr
*/
static FromExpr * static FromExpr *
_copyFromExpr(FromExpr *from) _copyFromExpr(FromExpr *from)
{ {
@ -872,24 +1029,6 @@ _copyFromExpr(FromExpr *from)
return newnode; 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 * relation.h copy functions
* *
@ -964,18 +1103,6 @@ _copyJoinInfo(JoinInfo *from)
* **************************************************************** * ****************************************************************
*/ */
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 * static RangeTblEntry *
_copyRangeTblEntry(RangeTblEntry *from) _copyRangeTblEntry(RangeTblEntry *from)
{ {
@ -1170,6 +1297,14 @@ _copyTypeName(TypeName *from)
return newnode; return newnode;
} }
static DomainConstraintValue *
_copyDomainConstraintValue(DomainConstraintValue *from)
{
DomainConstraintValue *newnode = makeNode(DomainConstraintValue);
return newnode;
}
static SortGroupBy * static SortGroupBy *
_copySortGroupBy(SortGroupBy *from) _copySortGroupBy(SortGroupBy *from)
{ {
@ -1260,85 +1395,6 @@ _copyConstraint(Constraint *from)
return newnode; 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 * static DefElem *
_copyDefElem(DefElem *from) _copyDefElem(DefElem *from)
{ {
@ -2350,9 +2406,6 @@ copyObject(void *from)
case T_Limit: case T_Limit:
retval = _copyLimit(from); retval = _copyLimit(from);
break; break;
case T_SubPlan:
retval = _copySubPlan(from);
break;
/* /*
* PRIMITIVE NODES * PRIMITIVE NODES
@ -2360,45 +2413,72 @@ copyObject(void *from)
case T_Resdom: case T_Resdom:
retval = _copyResdom(from); retval = _copyResdom(from);
break; break;
case T_Fjoin:
retval = _copyFjoin(from);
break;
case T_Alias: case T_Alias:
retval = _copyAlias(from); retval = _copyAlias(from);
break; break;
case T_RangeVar: case T_RangeVar:
retval = _copyRangeVar(from); retval = _copyRangeVar(from);
break; break;
case T_Expr:
retval = _copyExpr(from);
break;
case T_Var: case T_Var:
retval = _copyVar(from); retval = _copyVar(from);
break; break;
case T_Oper:
retval = _copyOper(from);
break;
case T_Const: case T_Const:
retval = _copyConst(from); retval = _copyConst(from);
break; break;
case T_Param: case T_Param:
retval = _copyParam(from); retval = _copyParam(from);
break; break;
case T_Func:
retval = _copyFunc(from);
break;
case T_Aggref: case T_Aggref:
retval = _copyAggref(from); retval = _copyAggref(from);
break; 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: case T_SubLink:
retval = _copySubLink(from); retval = _copySubLink(from);
break; break;
case T_SubPlanExpr:
retval = _copySubPlanExpr(from);
break;
case T_FieldSelect: case T_FieldSelect:
retval = _copyFieldSelect(from); retval = _copyFieldSelect(from);
break; break;
case T_RelabelType: case T_RelabelType:
retval = _copyRelabelType(from); retval = _copyRelabelType(from);
break; 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: case T_RangeTblRef:
retval = _copyRangeTblRef(from); retval = _copyRangeTblRef(from);
break; break;
@ -2408,9 +2488,6 @@ copyObject(void *from)
case T_FromExpr: case T_FromExpr:
retval = _copyFromExpr(from); retval = _copyFromExpr(from);
break; break;
case T_ArrayRef:
retval = _copyArrayRef(from);
break;
/* /*
* RELATION NODES * RELATION NODES
@ -2686,6 +2763,9 @@ copyObject(void *from)
case T_TypeCast: case T_TypeCast:
retval = _copyTypeCast(from); retval = _copyTypeCast(from);
break; break;
case T_DomainConstraintValue:
retval = _copyDomainConstraintValue(from);
break;
case T_SortGroupBy: case T_SortGroupBy:
retval = _copySortGroupBy(from); retval = _copySortGroupBy(from);
break; break;
@ -2710,9 +2790,6 @@ copyObject(void *from)
case T_DefElem: case T_DefElem:
retval = _copyDefElem(from); retval = _copyDefElem(from);
break; break;
case T_TargetEntry:
retval = _copyTargetEntry(from);
break;
case T_RangeTblEntry: case T_RangeTblEntry:
retval = _copyRangeTblEntry(from); retval = _copyRangeTblEntry(from);
break; break;
@ -2722,24 +2799,6 @@ copyObject(void *from)
case T_GroupClause: case T_GroupClause:
retval = _copyGroupClause(from); retval = _copyGroupClause(from);
break; 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: case T_FkConstraint:
retval = _copyFkConstraint(from); retval = _copyFkConstraint(from);
break; break;
@ -2752,9 +2811,6 @@ copyObject(void *from)
case T_InsertDefault: case T_InsertDefault:
retval = _copyInsertDefault(from); retval = _copyInsertDefault(from);
break; break;
case T_DomainConstraintValue:
retval = _copyDomainConstraintValue(from);
break;
default: default:
elog(ERROR, "copyObject: don't know how to copy node type %d", elog(ERROR, "copyObject: don't know how to copy node type %d",

View File

@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -27,7 +27,6 @@
#include "nodes/params.h" #include "nodes/params.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "nodes/relation.h" #include "nodes/relation.h"
#include "utils/datum.h" #include "utils/datum.h"
@ -98,18 +97,6 @@ _equalResdom(Resdom *a, Resdom *b)
return true; 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 static bool
_equalAlias(Alias *a, Alias *b) _equalAlias(Alias *a, Alias *b)
{ {
@ -132,20 +119,12 @@ _equalRangeVar(RangeVar *a, RangeVar *b)
return true; return true;
} }
static bool
_equalExpr(Expr *a, Expr *b)
{
/* /*
* We do not examine typeOid, since the optimizer often doesn't bother * We don't need an _equalExpr because Expr is an abstract supertype which
* to set it in created nodes, and it is logically a derivative of the * should never actually get instantiated. Also, since it has no common
* oper field anyway. * fields except NodeTag, there's no need for a helper routine to factor
* out comparing the common fields...
*/ */
COMPARE_SCALAR_FIELD(opType);
COMPARE_NODE_FIELD(oper);
COMPARE_NODE_FIELD(args);
return true;
}
static bool static bool
_equalVar(Var *a, Var *b) _equalVar(Var *a, Var *b)
@ -161,28 +140,6 @@ _equalVar(Var *a, Var *b)
return true; 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 static bool
_equalConst(Const *a, Const *b) _equalConst(Const *a, Const *b)
{ {
@ -226,7 +183,35 @@ _equalParam(Param *a, Param *b)
} }
static bool 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(funcid);
COMPARE_SCALAR_FIELD(funcresulttype); COMPARE_SCALAR_FIELD(funcresulttype);
@ -240,20 +225,60 @@ _equalFunc(Func *a, Func *b)
b->funcformat != COERCE_DONTCARE) b->funcformat != COERCE_DONTCARE)
return false; return false;
/* Note we do not look at func_fcache; see notes for _equalOper */ COMPARE_NODE_FIELD(args);
return true; return true;
} }
static bool static bool
_equalAggref(Aggref *a, Aggref *b) _equalOpExpr(OpExpr *a, OpExpr *b)
{ {
COMPARE_SCALAR_FIELD(aggfnoid); COMPARE_SCALAR_FIELD(opno);
COMPARE_SCALAR_FIELD(aggtype); /*
COMPARE_NODE_FIELD(target); * Special-case opfuncid: it is allowable for it to differ if one
COMPARE_SCALAR_FIELD(aggstar); * node contains zero and the other doesn't. This just means that the
COMPARE_SCALAR_FIELD(aggdistinct); * one node isn't as far along in the parse/plan pipeline and hasn't
/* ignore aggno, which is only a private field for the executor */ * 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;
} }
@ -270,6 +295,21 @@ _equalSubLink(SubLink *a, SubLink *b)
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 static bool
_equalFieldSelect(FieldSelect *a, FieldSelect *b) _equalFieldSelect(FieldSelect *a, FieldSelect *b)
{ {
@ -299,6 +339,74 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
return true; 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
_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b)
{
COMPARE_SCALAR_FIELD(typeId);
COMPARE_SCALAR_FIELD(typeMod);
return true;
}
static bool
_equalTargetEntry(TargetEntry *a, TargetEntry *b)
{
COMPARE_NODE_FIELD(resdom);
COMPARE_NODE_FIELD(expr);
return true;
}
static bool static bool
_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b) _equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
{ {
@ -331,39 +439,6 @@ _equalFromExpr(FromExpr *a, FromExpr *b)
return true; 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;
}
/*
* Stuff from plannodes.h
*/
static bool
_equalSubPlan(SubPlan *a, SubPlan *b)
{
/* should compare plans, but have to settle for comparing plan IDs */
COMPARE_SCALAR_FIELD(plan_id);
COMPARE_NODE_FIELD(rtable);
COMPARE_NODE_FIELD(sublink);
return true;
}
/* /*
* Stuff from relation.h * Stuff from relation.h
@ -573,6 +648,12 @@ _equalInsertDefault(InsertDefault *a, InsertDefault *b)
return true; return true;
} }
static bool
_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b)
{
return true;
}
static bool static bool
_equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b) _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
{ {
@ -1340,16 +1421,6 @@ _equalDefElem(DefElem *a, DefElem *b)
return true; 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 static bool
_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b) _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
{ {
@ -1397,71 +1468,6 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
return true; 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 * Stuff from pg_list.h
@ -1519,25 +1525,21 @@ equal(void *a, void *b)
switch (nodeTag(a)) switch (nodeTag(a))
{ {
case T_SubPlan: /*
retval = _equalSubPlan(a, b); * PRIMITIVE NODES
break; */
case T_Resdom: case T_Resdom:
retval = _equalResdom(a, b); retval = _equalResdom(a, b);
break; break;
case T_Fjoin: case T_Alias:
retval = _equalFjoin(a, b); retval = _equalAlias(a, b);
break; break;
case T_Expr: case T_RangeVar:
retval = _equalExpr(a, b); retval = _equalRangeVar(a, b);
break; break;
case T_Var: case T_Var:
retval = _equalVar(a, b); retval = _equalVar(a, b);
break; break;
case T_Oper:
retval = _equalOper(a, b);
break;
case T_Const: case T_Const:
retval = _equalConst(a, b); retval = _equalConst(a, b);
break; break;
@ -1547,21 +1549,54 @@ equal(void *a, void *b)
case T_Aggref: case T_Aggref:
retval = _equalAggref(a, b); retval = _equalAggref(a, b);
break; 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: case T_SubLink:
retval = _equalSubLink(a, b); retval = _equalSubLink(a, b);
break; break;
case T_Func: case T_SubPlanExpr:
retval = _equalFunc(a, b); retval = _equalSubPlanExpr(a, b);
break; break;
case T_FieldSelect: case T_FieldSelect:
retval = _equalFieldSelect(a, b); retval = _equalFieldSelect(a, b);
break; break;
case T_ArrayRef:
retval = _equalArrayRef(a, b);
break;
case T_RelabelType: case T_RelabelType:
retval = _equalRelabelType(a, b); retval = _equalRelabelType(a, b);
break; 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: case T_RangeTblRef:
retval = _equalRangeTblRef(a, b); retval = _equalRangeTblRef(a, b);
break; break;
@ -1572,6 +1607,9 @@ equal(void *a, void *b)
retval = _equalJoinExpr(a, b); retval = _equalJoinExpr(a, b);
break; break;
/*
* RELATION NODES
*/
case T_PathKeyItem: case T_PathKeyItem:
retval = _equalPathKeyItem(a, b); retval = _equalPathKeyItem(a, b);
break; break;
@ -1582,6 +1620,9 @@ equal(void *a, void *b)
retval = _equalJoinInfo(a, b); retval = _equalJoinInfo(a, b);
break; break;
/*
* LIST NODES
*/
case T_List: case T_List:
{ {
List *la = (List *) a; List *la = (List *) a;
@ -1612,6 +1653,9 @@ equal(void *a, void *b)
retval = _equalValue(a, b); retval = _equalValue(a, b);
break; break;
/*
* PARSE NODES
*/
case T_Query: case T_Query:
retval = _equalQuery(a, b); retval = _equalQuery(a, b);
break; break;
@ -1844,12 +1888,6 @@ equal(void *a, void *b)
case T_SortGroupBy: case T_SortGroupBy:
retval = _equalSortGroupBy(a, b); retval = _equalSortGroupBy(a, b);
break; break;
case T_Alias:
retval = _equalAlias(a, b);
break;
case T_RangeVar:
retval = _equalRangeVar(a, b);
break;
case T_RangeSubselect: case T_RangeSubselect:
retval = _equalRangeSubselect(a, b); retval = _equalRangeSubselect(a, b);
break; break;
@ -1871,9 +1909,6 @@ equal(void *a, void *b)
case T_DefElem: case T_DefElem:
retval = _equalDefElem(a, b); retval = _equalDefElem(a, b);
break; break;
case T_TargetEntry:
retval = _equalTargetEntry(a, b);
break;
case T_RangeTblEntry: case T_RangeTblEntry:
retval = _equalRangeTblEntry(a, b); retval = _equalRangeTblEntry(a, b);
break; break;
@ -1884,24 +1919,6 @@ equal(void *a, void *b)
/* GroupClause is equivalent to SortClause */ /* GroupClause is equivalent to SortClause */
retval = _equalSortClause(a, b); retval = _equalSortClause(a, b);
break; 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: case T_FkConstraint:
retval = _equalFkConstraint(a, b); retval = _equalFkConstraint(a, b);
break; break;

View File

@ -1,4 +1,5 @@
/* /*-------------------------------------------------------------------------
*
* makefuncs.c * makefuncs.c
* creator functions for primitive nodes. The functions here are for * creator functions for primitive nodes. The functions here are for
* the most frequently created nodes. * the most frequently created nodes.
@ -8,7 +9,9 @@
* *
* *
* IDENTIFICATION * 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" #include "postgres.h"
@ -49,30 +52,9 @@ makeSimpleA_Expr(int oper, const char *name,
return a; 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 - * makeVar -
* creates a Var node * creates a Var node
*
*/ */
Var * Var *
makeVar(Index varno, makeVar(Index varno,
@ -107,7 +89,7 @@ makeVar(Index varno,
* creates a TargetEntry node (contains a Resdom) * creates a TargetEntry node (contains a Resdom)
*/ */
TargetEntry * TargetEntry *
makeTargetEntry(Resdom *resdom, Node *expr) makeTargetEntry(Resdom *resdom, Expr *expr)
{ {
TargetEntry *rt = makeNode(TargetEntry); TargetEntry *rt = makeNode(TargetEntry);
@ -188,6 +170,21 @@ makeNullConst(Oid consttype)
typByVal); 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 - * makeAlias -
* creates an Alias node * creates an Alias node
@ -210,7 +207,7 @@ makeAlias(const char *aliasname, List *colnames)
* creates a RelabelType node * creates a RelabelType node
*/ */
RelabelType * RelabelType *
makeRelabelType(Node *arg, Oid rtype, int32 rtypmod, CoercionForm rformat) makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat)
{ {
RelabelType *r = makeNode(RelabelType); RelabelType *r = makeNode(RelabelType);

View File

@ -8,12 +8,10 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "nodes/nodeFuncs.h" #include "nodes/nodeFuncs.h"
@ -21,6 +19,7 @@
static bool var_is_inner(Var *var); static bool var_is_inner(Var *var);
/* /*
* single_node - * single_node -
* Returns t if node corresponds to a single-noded expression * Returns t if node corresponds to a single-noded expression
@ -79,41 +78,15 @@ var_is_rel(Var *var)
*****************************************************************************/ *****************************************************************************/
/* /*
* replace_opid - * set_opfuncid -
*
* Given a oper node, resets the opfid field with the
* procedure OID (regproc id).
*
* Returns the modified oper node.
* *
* Set the opfuncid (procedure OID) in an OpExpr node,
* if it hasn't been set already.
*/ */
Oper * void
replace_opid(Oper *oper) set_opfuncid(OpExpr *opexpr)
{ {
oper->opid = get_opcode(oper->opno); if (opexpr->opfuncid == InvalidOid)
oper->op_fcache = NULL; opexpr->opfuncid = get_opcode(opexpr->opno);
return oper; 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

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -371,7 +371,7 @@ print_expr(Node *expr, List *rtable)
char *opname; char *opname;
print_expr((Node *) get_leftop(e), rtable); 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)")); printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)"));
print_expr((Node *) get_rightop(e), rtable); print_expr((Node *) get_rightop(e), rtable);
} }
@ -432,7 +432,7 @@ print_tl(List *tlist, List *rtable)
printf("(%d):\t", tle->resdom->reskey); printf("(%d):\t", tle->resdom->reskey);
else else
printf(" :\t"); printf(" :\t");
print_expr(tle->expr, rtable); print_expr((Node *) tle->expr, rtable);
printf("\n"); printf("\n");
} }
printf(")\n"); printf(")\n");

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
@ -302,38 +302,30 @@ _readResdom(void)
READ_DONE(); READ_DONE();
} }
/* static Alias *
* _readExpr _readAlias(void)
*/
static Expr *
_readExpr(void)
{ {
READ_LOCALS(Expr); READ_LOCALS(Alias);
READ_OID_FIELD(typeOid); READ_STRING_FIELD(aliasname);
READ_NODE_FIELD(colnames);
/* do-it-yourself enum representation */ READ_DONE();
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_NODE_FIELD(oper); static RangeVar *
READ_NODE_FIELD(args); _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();
} }
@ -357,27 +349,6 @@ _readVar(void)
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 * _readConst
*/ */
@ -400,42 +371,6 @@ _readConst(void)
READ_DONE(); READ_DONE();
} }
/*
* _readFunc
*/
static Func *
_readFunc(void)
{
READ_LOCALS(Func);
READ_OID_FIELD(funcid);
READ_OID_FIELD(funcresulttype);
READ_BOOL_FIELD(funcretset);
READ_ENUM_FIELD(funcformat, CoercionForm);
local_node->func_fcache = NULL;
READ_DONE();
}
/*
* _readOper
*/
static Oper *
_readOper(void)
{
READ_LOCALS(Oper);
READ_OID_FIELD(opno);
READ_OID_FIELD(opid);
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
local_node->op_fcache = NULL;
READ_DONE();
}
/* /*
* _readParam * _readParam
*/ */
@ -465,24 +400,129 @@ _readAggref(void)
READ_NODE_FIELD(target); READ_NODE_FIELD(target);
READ_BOOL_FIELD(aggstar); READ_BOOL_FIELD(aggstar);
READ_BOOL_FIELD(aggdistinct); READ_BOOL_FIELD(aggdistinct);
/* aggno is not saved since it is just executor state */
READ_DONE(); READ_DONE();
} }
static RangeVar * /*
_readRangeVar(void) * _readArrayRef
*/
static ArrayRef *
_readArrayRef(void)
{ {
READ_LOCALS(RangeVar); READ_LOCALS(ArrayRef);
local_node->catalogname = NULL; /* not currently saved in output READ_OID_FIELD(refrestype);
* format */ 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_STRING_FIELD(schemaname); READ_DONE();
READ_STRING_FIELD(relname); }
READ_ENUM_FIELD(inhOpt, InhOption);
READ_BOOL_FIELD(istemp); /*
READ_NODE_FIELD(alias); * _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;
READ_DONE();
}
/*
* _readOpExpr
*/
static OpExpr *
_readOpExpr(void)
{
READ_LOCALS(OpExpr);
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;
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
READ_DONE();
}
/*
* _readDistinctExpr
*/
static DistinctExpr *
_readDistinctExpr(void)
{
READ_LOCALS(DistinctExpr);
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;
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
READ_DONE();
}
/*
* _readBoolExpr
*/
static BoolExpr *
_readBoolExpr(void)
{
READ_LOCALS(BoolExpr);
/* 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_NODE_FIELD(args);
READ_DONE(); READ_DONE();
} }
@ -504,6 +544,10 @@ _readSubLink(void)
READ_DONE(); READ_DONE();
} }
/*
* _readSubPlanExpr is not needed since it doesn't appear in stored rules.
*/
/* /*
* _readFieldSelect * _readFieldSelect
*/ */
@ -536,58 +580,6 @@ _readRelabelType(void)
READ_DONE(); 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 * _readCaseExpr
*/ */
@ -663,17 +655,6 @@ _readConstraintTest(void)
READ_DONE(); READ_DONE();
} }
/*
* _readDomainConstraintValue
*/
static DomainConstraintValue *
_readDomainConstraintValue(void)
{
READ_LOCALS_NO_FIELDS(DomainConstraintValue);
READ_DONE();
}
/* /*
* _readConstraintTestValue * _readConstraintTestValue
*/ */
@ -697,12 +678,63 @@ _readTargetEntry(void)
READ_LOCALS(TargetEntry); READ_LOCALS(TargetEntry);
READ_NODE_FIELD(resdom); READ_NODE_FIELD(resdom);
/* fjoin not supported ... */
READ_NODE_FIELD(expr); READ_NODE_FIELD(expr);
READ_DONE(); 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 * static ColumnRef *
_readColumnRef(void) _readColumnRef(void)
{ {
@ -760,13 +792,13 @@ _readExprFieldSelect(void)
READ_DONE(); READ_DONE();
} }
static Alias * /*
_readAlias(void) * _readDomainConstraintValue
*/
static DomainConstraintValue *
_readDomainConstraintValue(void)
{ {
READ_LOCALS(Alias); READ_LOCALS_NO_FIELDS(DomainConstraintValue);
READ_STRING_FIELD(aliasname);
READ_NODE_FIELD(colnames);
READ_DONE(); READ_DONE();
} }
@ -835,53 +867,7 @@ parseNodeString(void)
#define MATCH(tokname, namelen) \ #define MATCH(tokname, namelen) \
(length == namelen && strncmp(token, tokname, namelen) == 0) (length == namelen && strncmp(token, tokname, namelen) == 0)
if (MATCH("AGGREF", 6)) if (MATCH("QUERY", 5))
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))
return_value = _readQuery(); return_value = _readQuery();
else if (MATCH("NOTIFY", 6)) else if (MATCH("NOTIFY", 6))
return_value = _readNotifyStmt(); return_value = _readNotifyStmt();
@ -891,6 +877,36 @@ parseNodeString(void)
return_value = _readGroupClause(); return_value = _readGroupClause();
else if (MATCH("SETOPERATIONSTMT", 16)) else if (MATCH("SETOPERATIONSTMT", 16))
return_value = _readSetOperationStmt(); 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)) else if (MATCH("CASE", 4))
return_value = _readCaseExpr(); return_value = _readCaseExpr();
else if (MATCH("WHEN", 4)) else if (MATCH("WHEN", 4))
@ -901,10 +917,28 @@ parseNodeString(void)
return_value = _readBooleanTest(); return_value = _readBooleanTest();
else if (MATCH("CONSTRAINTTEST", 14)) else if (MATCH("CONSTRAINTTEST", 14))
return_value = _readConstraintTest(); return_value = _readConstraintTest();
else if (MATCH("DOMAINCONSTRAINTVALUE", 21))
return_value = _readDomainConstraintValue();
else if (MATCH("CONSTRAINTTESTVALUE", 19)) else if (MATCH("CONSTRAINTTESTVALUE", 19))
return_value = _readConstraintTestValue(); 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 else
{ {
elog(ERROR, "badly formatted node string \"%.32s\"...", token); elog(ERROR, "badly formatted node string \"%.32s\"...", token);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.53 2002/11/25 21:29:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.54 2002/12/12 15:49:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -141,7 +141,7 @@ clauselist_selectivity(Query *root,
if (is_opclause(clause) && if (is_opclause(clause) &&
(varRelid != 0 || NumRelids(clause) == 1)) (varRelid != 0 || NumRelids(clause) == 1))
{ {
Expr *expr = (Expr *) clause; OpExpr *expr = (OpExpr *) clause;
if (length(expr->args) == 2) if (length(expr->args) == 2)
{ {
@ -151,7 +151,7 @@ clauselist_selectivity(Query *root,
(varonleft = false, (varonleft = false,
is_pseudo_constant_clause(lfirst(expr->args)))) is_pseudo_constant_clause(lfirst(expr->args))))
{ {
Oid opno = ((Oper *) expr->oper)->opno; Oid opno = expr->opno;
RegProcedure oprrest = get_oprrest(opno); RegProcedure oprrest = get_oprrest(opno);
s2 = restriction_selectivity(root, opno, s2 = restriction_selectivity(root, opno,
@ -430,7 +430,7 @@ clause_selectivity(Query *root,
{ {
/* share code with clauselist_selectivity() */ /* share code with clauselist_selectivity() */
s1 = clauselist_selectivity(root, s1 = clauselist_selectivity(root,
((Expr *) clause)->args, ((BoolExpr *) clause)->args,
varRelid); varRelid);
} }
else if (or_clause(clause)) else if (or_clause(clause))
@ -443,7 +443,7 @@ clause_selectivity(Query *root,
List *arg; List *arg;
s1 = 0.0; s1 = 0.0;
foreach(arg, ((Expr *) clause)->args) foreach(arg, ((BoolExpr *) clause)->args)
{ {
Selectivity s2 = clause_selectivity(root, Selectivity s2 = clause_selectivity(root,
(Node *) lfirst(arg), (Node *) lfirst(arg),
@ -454,7 +454,7 @@ clause_selectivity(Query *root,
} }
else if (is_opclause(clause)) else if (is_opclause(clause))
{ {
Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno; Oid opno = ((OpExpr *) clause)->opno;
bool is_join_clause; bool is_join_clause;
if (varRelid != 0) if (varRelid != 0)
@ -479,13 +479,14 @@ clause_selectivity(Query *root,
{ {
/* Estimate selectivity for a join clause. */ /* Estimate selectivity for a join clause. */
s1 = join_selectivity(root, opno, s1 = join_selectivity(root, opno,
((Expr *) clause)->args); ((OpExpr *) clause)->args);
} }
else else
{ {
/* Estimate selectivity for a restriction clause. */ /* Estimate selectivity for a restriction clause. */
s1 = restriction_selectivity(root, opno, s1 = restriction_selectivity(root, opno,
((Expr *) clause)->args, varRelid); ((OpExpr *) clause)->args,
varRelid);
} }
} }
else if (is_funcclause(clause)) else if (is_funcclause(clause))
@ -509,7 +510,7 @@ clause_selectivity(Query *root,
/* Use node specific selectivity calculation function */ /* Use node specific selectivity calculation function */
s1 = nulltestsel(root, s1 = nulltestsel(root,
((NullTest *) clause)->nulltesttype, ((NullTest *) clause)->nulltesttype,
((NullTest *) clause)->arg, (Node *) ((NullTest *) clause)->arg,
varRelid); varRelid);
} }
else if (IsA(clause, BooleanTest)) else if (IsA(clause, BooleanTest))
@ -517,14 +518,14 @@ clause_selectivity(Query *root,
/* Use node specific selectivity calculation function */ /* Use node specific selectivity calculation function */
s1 = booltestsel(root, s1 = booltestsel(root,
((BooleanTest *) clause)->booltesttype, ((BooleanTest *) clause)->booltesttype,
((BooleanTest *) clause)->arg, (Node *) ((BooleanTest *) clause)->arg,
varRelid); varRelid);
} }
else if (IsA(clause, RelabelType)) else if (IsA(clause, RelabelType))
{ {
/* Not sure this case is needed, but it can't hurt */ /* Not sure this case is needed, but it can't hurt */
s1 = clause_selectivity(root, s1 = clause_selectivity(root,
((RelabelType *) clause)->arg, (Node *) ((RelabelType *) clause)->arg,
varRelid); varRelid);
} }

View File

@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.93 2002/11/30 05:21:02 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.94 2002/12/12 15:49:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1220,23 +1220,12 @@ cost_qual_eval_walker(Node *node, Cost *total)
* Should we try to account for the possibility of short-circuit * Should we try to account for the possibility of short-circuit
* evaluation of AND/OR? * evaluation of AND/OR?
*/ */
if (IsA(node, Expr)) if (IsA(node, FuncExpr) ||
{ IsA(node, OpExpr) ||
Expr *expr = (Expr *) node; IsA(node, DistinctExpr))
switch (expr->opType)
{
case OP_EXPR:
case DISTINCT_EXPR:
case FUNC_EXPR:
*total += cpu_operator_cost; *total += cpu_operator_cost;
break; else if (IsA(node, SubPlanExpr))
case OR_EXPR: {
case AND_EXPR:
case NOT_EXPR:
break;
case SUBPLAN_EXPR:
/* /*
* A subplan node in an expression indicates that the * A subplan node in an expression indicates that the
* subplan will be executed on each evaluation, so charge * subplan will be executed on each evaluation, so charge
@ -1247,8 +1236,7 @@ cost_qual_eval_walker(Node *node, Cost *total)
* NOTE: this logic should agree with the estimates used by * NOTE: this logic should agree with the estimates used by
* make_subplan() in plan/subselect.c. * make_subplan() in plan/subselect.c.
*/ */
{ SubPlanExpr *subplan = (SubPlanExpr *) node;
SubPlan *subplan = (SubPlan *) expr->oper;
Plan *plan = subplan->plan; Plan *plan = subplan->plan;
Cost subcost; Cost subcost;
@ -1273,10 +1261,7 @@ cost_qual_eval_walker(Node *node, Cost *total)
} }
*total += subcost; *total += subcost;
} }
break;
}
/* fall through to examine args of Expr node */
}
return expression_tree_walker(node, cost_qual_eval_walker, return expression_tree_walker(node, cost_qual_eval_walker,
(void *) total); (void *) total);
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.126 2002/11/25 21:29:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.127 2002/12/12 15:49:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -73,6 +73,8 @@ static bool match_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass, Expr *clause); int indexkey, Oid opclass, Expr *clause);
static bool match_join_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index, static bool match_join_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass, Expr *clause); 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, static bool pred_test(List *predicate_list, List *restrictinfo_list,
List *joininfo_list, int relvarno); List *joininfo_list, int relvarno);
static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list); static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list);
@ -280,7 +282,7 @@ match_index_orclauses(RelOptInfo *rel,
*/ */
restrictinfo->subclauseindices = restrictinfo->subclauseindices =
match_index_orclause(rel, index, match_index_orclause(rel, index,
restrictinfo->clause->args, ((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices); restrictinfo->subclauseindices);
} }
} }
@ -377,7 +379,7 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
{ {
List *item; List *item;
foreach(item, clause->args) foreach(item, ((BoolExpr *) clause)->args)
{ {
if (match_clause_to_indexkey(rel, index, indexkey, opclass, if (match_clause_to_indexkey(rel, index, indexkey, opclass,
lfirst(item))) lfirst(item)))
@ -443,7 +445,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
if (and_clause((Node *) orsubclause)) if (and_clause((Node *) orsubclause))
{ {
foreach(item, orsubclause->args) foreach(item, ((BoolExpr *) orsubclause)->args)
{ {
Expr *subsubclause = (Expr *) lfirst(item); Expr *subsubclause = (Expr *) lfirst(item);
@ -715,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
*rightop; *rightop;
/* Clause must be a binary opclause. */ /* Clause must be a binary opclause. */
if (!is_opclause((Node *) clause)) if (!is_opclause(clause))
return false; return false;
leftop = get_leftop(clause); leftop = get_leftop(clause);
rightop = get_rightop(clause); rightop = get_rightop(clause);
@ -803,7 +805,7 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
*rightop; *rightop;
/* Clause must be a binary opclause. */ /* Clause must be a binary opclause. */
if (!is_opclause((Node *) clause)) if (!is_opclause(clause))
return false; return false;
leftop = get_leftop(clause); leftop = get_leftop(clause);
rightop = get_rightop(clause); rightop = get_rightop(clause);
@ -857,10 +859,10 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
* (Formerly, this routine might return a binary-compatible operator * (Formerly, this routine might return a binary-compatible operator
* rather than the original one, but that kluge is history.) * rather than the original one, but that kluge is history.)
*/ */
Oid static Oid
indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left) 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; Oid commuted_op;
/* Get the commuted operator if necessary */ /* Get the commuted operator if necessary */
@ -985,7 +987,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause)
Assert(clause != NULL); Assert(clause != NULL);
if (or_clause(clause)) if (or_clause(clause))
{ {
items = ((Expr *) clause)->args; items = ((BoolExpr *) clause)->args;
foreach(item, items) foreach(item, items)
{ {
/* if any OR item doesn't imply the predicate, clause doesn't */ /* if any OR item doesn't imply the predicate, clause doesn't */
@ -996,7 +998,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause)
} }
else if (and_clause(clause)) else if (and_clause(clause))
{ {
items = ((Expr *) clause)->args; items = ((BoolExpr *) clause)->args;
foreach(item, items) foreach(item, items)
{ {
/* /*
@ -1029,7 +1031,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
Assert(predicate != NULL); Assert(predicate != NULL);
if (or_clause((Node *) predicate)) if (or_clause((Node *) predicate))
{ {
items = predicate->args; items = ((BoolExpr *) predicate)->args;
foreach(item, items) foreach(item, items)
{ {
/* if any item is implied, the whole predicate is implied */ /* if any item is implied, the whole predicate is implied */
@ -1040,7 +1042,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
} }
else if (and_clause((Node *) predicate)) else if (and_clause((Node *) predicate))
{ {
items = predicate->args; items = ((BoolExpr *) predicate)->args;
foreach(item, items) foreach(item, items)
{ {
/* /*
@ -1121,7 +1123,6 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
StrategyNumber pred_strategy = 0, StrategyNumber pred_strategy = 0,
clause_strategy, clause_strategy,
test_strategy; test_strategy;
Oper *test_oper;
Expr *test_expr; Expr *test_expr;
Datum test_result; Datum test_result;
bool isNull; bool isNull;
@ -1140,7 +1141,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
* Can't do anything more unless they are both binary opclauses with a * Can't do anything more unless they are both binary opclauses with a
* Var on the left and a Const on the right. * Var on the left and a Const on the right.
*/ */
if (!is_opclause((Node *) predicate)) if (!is_opclause(predicate))
return false; return false;
pred_var = (Var *) get_leftop(predicate); pred_var = (Var *) get_leftop(predicate);
pred_const = (Const *) get_rightop(predicate); pred_const = (Const *) get_rightop(predicate);
@ -1167,8 +1168,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
return false; return false;
/* Get the operators for the two clauses we're comparing */ /* Get the operators for the two clauses we're comparing */
pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno; pred_op = ((OpExpr *) predicate)->opno;
clause_op = ((Oper *) ((Expr *) clause)->oper)->opno; clause_op = ((OpExpr *) clause)->opno;
/* /*
* 1. Find a "btree" strategy number for the pred_op * 1. Find a "btree" strategy number for the pred_op
@ -1267,14 +1268,12 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
/* /*
* 5. Evaluate the test * 5. Evaluate the test
*/ */
test_oper = makeOper(test_op, /* opno */ test_expr = make_opclause(test_op,
InvalidOid, /* opid */ BOOLOID,
BOOLOID, /* opresulttype */ false,
false); /* opretset */ (Expr *) clause_const,
replace_opid(test_oper); (Expr *) pred_const);
test_expr = make_opclause(test_oper, set_opfuncid((OpExpr *) test_expr);
(Var *) clause_const,
(Var *) pred_const);
econtext = MakeExprContext(NULL, TransactionCommandContext); econtext = MakeExprContext(NULL, TransactionCommandContext);
test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext, test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext,
@ -1627,7 +1626,7 @@ static bool
function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index) function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
{ {
int relvarno = lfirsti(rel->relids); int relvarno = lfirsti(rel->relids);
Func *function; FuncExpr *function;
List *funcargs; List *funcargs;
int *indexKeys = index->indexkeys; int *indexKeys = index->indexkeys;
List *arg; List *arg;
@ -1636,13 +1635,12 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
/* /*
* sanity check, make sure we know what we're dealing with here. * sanity check, make sure we know what we're dealing with here.
*/ */
if (funcOpnd == NULL || !IsA(funcOpnd, Expr) || if (funcOpnd == NULL || !IsA(funcOpnd, FuncExpr) ||
funcOpnd->opType != FUNC_EXPR || indexKeys == NULL)
funcOpnd->oper == NULL || indexKeys == NULL)
return false; return false;
function = (Func *) funcOpnd->oper; function = (FuncExpr *) funcOpnd;
funcargs = funcOpnd->args; funcargs = function->args;
if (function->funcid != index->indproc) if (function->funcid != index->indproc)
return false; return false;
@ -1752,7 +1750,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
/* we know these will succeed */ /* we know these will succeed */
leftop = get_leftop(clause); leftop = get_leftop(clause);
rightop = get_rightop(clause); rightop = get_rightop(clause);
expr_op = ((Oper *) clause->oper)->opno; expr_op = ((OpExpr *) clause)->opno;
/* again, required for all current special ops: */ /* again, required for all current special ops: */
if (!IsA(rightop, Const) || if (!IsA(rightop, Const) ||
@ -1916,7 +1914,7 @@ expand_indexqual_conditions(List *indexquals)
/* we know these will succeed */ /* we know these will succeed */
Var *leftop = get_leftop(clause); Var *leftop = get_leftop(clause);
Var *rightop = get_rightop(clause); Var *rightop = get_rightop(clause);
Oid expr_op = ((Oper *) clause->oper)->opno; Oid expr_op = ((OpExpr *) clause)->opno;
Const *patt = (Const *) rightop; Const *patt = (Const *) rightop;
Const *prefix = NULL; Const *prefix = NULL;
Const *rest = NULL; Const *rest = NULL;
@ -2011,7 +2009,6 @@ prefix_quals(Var *leftop, Oid expr_op,
Oid oproid; Oid oproid;
char *prefix; char *prefix;
Const *con; Const *con;
Oper *op;
Expr *expr; Expr *expr;
Const *greaterstr = NULL; Const *greaterstr = NULL;
@ -2070,8 +2067,8 @@ prefix_quals(Var *leftop, Oid expr_op,
if (oproid == InvalidOid) if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no = operator for type %u", datatype); elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
con = string_to_const(prefix, datatype); con = string_to_const(prefix, datatype);
op = makeOper(oproid, InvalidOid, BOOLOID, false); expr = make_opclause(oproid, BOOLOID, false,
expr = make_opclause(op, leftop, (Var *) con); (Expr *) leftop, (Expr *) con);
result = makeList1(expr); result = makeList1(expr);
return result; return result;
} }
@ -2085,8 +2082,8 @@ prefix_quals(Var *leftop, Oid expr_op,
if (oproid == InvalidOid) if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no >= operator for type %u", datatype); elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
con = string_to_const(prefix, datatype); con = string_to_const(prefix, datatype);
op = makeOper(oproid, InvalidOid, BOOLOID, false); expr = make_opclause(oproid, BOOLOID, false,
expr = make_opclause(op, leftop, (Var *) con); (Expr *) leftop, (Expr *) con);
result = makeList1(expr); result = makeList1(expr);
/*------- /*-------
@ -2100,8 +2097,8 @@ prefix_quals(Var *leftop, Oid expr_op,
oproid = find_operator("<", datatype); oproid = find_operator("<", datatype);
if (oproid == InvalidOid) if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no < operator for type %u", datatype); elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
op = makeOper(oproid, InvalidOid, BOOLOID, false); expr = make_opclause(oproid, BOOLOID, false,
expr = make_opclause(op, leftop, (Var *) greaterstr); (Expr *) leftop, (Expr *) greaterstr);
result = lappend(result, expr); result = lappend(result, expr);
} }
@ -2124,7 +2121,6 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
Oid opr2oid; Oid opr2oid;
List *result; List *result;
Oid datatype; Oid datatype;
Oper *op;
Expr *expr; Expr *expr;
switch (expr_op) switch (expr_op)
@ -2164,9 +2160,9 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
opr1right = network_scan_first(rightop); opr1right = network_scan_first(rightop);
op = makeOper(opr1oid, InvalidOid, BOOLOID, false); expr = make_opclause(opr1oid, BOOLOID, false,
expr = make_opclause(op, leftop, (Expr *) leftop,
(Var *) makeConst(datatype, -1, opr1right, (Expr *) makeConst(datatype, -1, opr1right,
false, false)); false, false));
result = makeList1(expr); result = makeList1(expr);
@ -2179,9 +2175,9 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
opr2right = network_scan_last(rightop); opr2right = network_scan_last(rightop);
op = makeOper(opr2oid, InvalidOid, BOOLOID, false); expr = make_opclause(opr2oid, BOOLOID, false,
expr = make_opclause(op, leftop, (Expr *) leftop,
(Var *) makeConst(datatype, -1, opr2right, (Expr *) makeConst(datatype, -1, opr2right,
false, false)); false, false));
result = lappend(result, expr); result = lappend(result, expr);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.48 2002/11/24 21:52:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.49 2002/12/12 15:49:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -96,7 +96,7 @@ create_or_index_paths(Query *root, RelOptInfo *rel)
best_or_subclause_indices(root, best_or_subclause_indices(root,
rel, rel,
restrictinfo->clause->args, ((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices, restrictinfo->subclauseindices,
pathnode); pathnode);

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.41 2002/09/18 21:35:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.42 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -514,22 +514,9 @@ build_index_pathkeys(Query *root,
if (index->indproc) if (index->indproc)
{ {
/* Functional index: build a representation of the function call */ /* Functional index: build a representation of the function call */
Func *funcnode = makeNode(Func); Expr *funcnode;
List *funcargs = NIL; 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;
while (*indexkeys != 0)
{
funcargs = lappend(funcargs,
find_indexkey_var(root, rel, *indexkeys));
indexkeys++;
}
sortop = *ordering; sortop = *ordering;
if (ScanDirectionIsBackward(scandir)) if (ScanDirectionIsBackward(scandir))
{ {
@ -538,9 +525,21 @@ build_index_pathkeys(Query *root,
return NIL; /* oops, no reverse sort operator? */ return NIL; /* oops, no reverse sort operator? */
} }
while (*indexkeys != 0)
{
funcargs = lappend(funcargs,
find_indexkey_var(root, rel, *indexkeys));
indexkeys++;
}
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 */ /* Make a one-sublist pathkeys list for the function expression */
item = makePathKeyItem((Node *) make_funcclause(funcnode, funcargs), item = makePathKeyItem((Node *) funcnode, sortop);
sortop);
retval = makeList1(make_canonical_pathkey(root, item)); retval = makeList1(make_canonical_pathkey(root, item));
} }
else else

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.12 2002/11/24 21:52:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.13 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -27,15 +27,14 @@
static List *TidqualFromRestrictinfo(List *relids, List *restrictinfo); static List *TidqualFromRestrictinfo(List *relids, List *restrictinfo);
static bool isEvaluable(int varno, Node *node); 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 List *TidqualFromExpr(int varno, Expr *expr);
static static bool
bool
isEvaluable(int varno, Node *node) isEvaluable(int varno, Node *node)
{ {
List *lst; List *lst;
Expr *expr; FuncExpr *expr;
if (IsA(node, Const)) if (IsA(node, Const))
return true; return true;
@ -51,7 +50,7 @@ isEvaluable(int varno, Node *node)
} }
if (!is_funcclause(node)) if (!is_funcclause(node))
return false; return false;
expr = (Expr *) node; expr = (FuncExpr *) node;
foreach(lst, expr->args) foreach(lst, expr->args)
{ {
if (!isEvaluable(varno, lfirst(lst))) if (!isEvaluable(varno, lfirst(lst)))
@ -66,33 +65,26 @@ isEvaluable(int varno, Node *node)
* Extract the right node if the opclause is CTID= .... * Extract the right node if the opclause is CTID= ....
* or the left node if the opclause is ....=CTID * or the left node if the opclause is ....=CTID
*/ */
static static Node *
Node * TidequalClause(int varno, OpExpr *node)
TidequalClause(int varno, Expr *node)
{ {
Node *rnode = 0, Node *rnode = NULL,
*arg1, *arg1,
*arg2, *arg2,
*arg; *arg;
Oper *oper;
Var *var; Var *var;
Const *aconst; Const *aconst;
Param *param; Param *param;
Expr *expr; FuncExpr *expr;
if (!node->oper) if (node->opno != TIDEqualOperator)
return rnode;
if (!node->args)
return rnode; return rnode;
if (length(node->args) != 2) if (length(node->args) != 2)
return rnode; return rnode;
oper = (Oper *) node->oper;
if (oper->opno != TIDEqualOperator)
return rnode;
arg1 = lfirst(node->args); arg1 = lfirst(node->args);
arg2 = lsecond(node->args); arg2 = lsecond(node->args);
arg = (Node *) 0; arg = NULL;
if (IsA(arg1, Var)) if (IsA(arg1, Var))
{ {
var = (Var *) arg1; var = (Var *) arg1;
@ -138,11 +130,9 @@ TidequalClause(int varno, Expr *node)
return rnode; return rnode;
rnode = arg; rnode = arg;
break; break;
case T_Expr: case T_FuncExpr:
expr = (Expr *) arg; expr = (FuncExpr *) arg;
if (expr->typeOid != TIDOID) if (expr->funcresulttype != TIDOID)
return rnode;
if (expr->opType != FUNC_EXPR)
return rnode; return rnode;
if (isEvaluable(varno, (Node *) expr)) if (isEvaluable(varno, (Node *) expr))
rnode = arg; rnode = arg;
@ -162,8 +152,7 @@ TidequalClause(int varno, Expr *node)
* CTID values if we could extract the CTID values from a member * CTID values if we could extract the CTID values from a member
* node. * node.
*/ */
static static List *
List *
TidqualFromExpr(int varno, Expr *expr) TidqualFromExpr(int varno, Expr *expr)
{ {
List *rlst = NIL, List *rlst = NIL,
@ -174,17 +163,15 @@ TidqualFromExpr(int varno, Expr *expr)
if (is_opclause(node)) if (is_opclause(node))
{ {
rnode = TidequalClause(varno, expr); rnode = TidequalClause(varno, (OpExpr *) expr);
if (rnode) if (rnode)
rlst = lcons(rnode, rlst); rlst = lcons(rnode, rlst);
} }
else if (and_clause(node)) else if (and_clause(node))
{ {
foreach(lst, expr->args) foreach(lst, ((BoolExpr *) expr)->args)
{ {
node = lfirst(lst); node = lfirst(lst);
if (!IsA(node, Expr))
continue;
rlst = TidqualFromExpr(varno, (Expr *) node); rlst = TidqualFromExpr(varno, (Expr *) node);
if (rlst) if (rlst)
break; break;
@ -192,11 +179,11 @@ TidqualFromExpr(int varno, Expr *expr)
} }
else if (or_clause(node)) else if (or_clause(node))
{ {
foreach(lst, expr->args) foreach(lst, ((BoolExpr *) expr)->args)
{ {
node = lfirst(lst); node = lfirst(lst);
if (IsA(node, Expr) && frtn = TidqualFromExpr(varno, (Expr *) node);
(frtn = TidqualFromExpr(varno, (Expr *) node))) if (frtn)
rlst = nconc(rlst, frtn); rlst = nconc(rlst, frtn);
else else
{ {

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.127 2002/12/05 15:50:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.128 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1041,12 +1041,12 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
foreach(i, indexqual) foreach(i, indexqual)
{ {
Expr *clause = (Expr *) lfirst(i); OpExpr *clause = (OpExpr *) lfirst(i);
Expr *newclause; OpExpr *newclause;
List *leftvarnos; List *leftvarnos;
Oid opclass; 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"); elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause");
/* /*
@ -1056,7 +1056,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
* is a subplan in the arguments of the opclause. So just do a * is a subplan in the arguments of the opclause. So just do a
* full copy. * 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 * Check to see if the indexkey is on the right; if so, commute
@ -1083,7 +1083,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
* Finally, check to see if index is lossy for this operator. If * Finally, check to see if index is lossy for this operator. If
* so, add (a copy of) original form of clause to recheck list. * 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, recheck_qual = lappend(recheck_qual,
copyObject((Node *) clause)); copyObject((Node *) clause));
} }
@ -1100,7 +1100,7 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
* Remove any binary-compatible relabeling of the indexkey * Remove any binary-compatible relabeling of the indexkey
*/ */
if (IsA(node, RelabelType)) 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 * We represent index keys by Var nodes having the varno of the base
@ -1168,11 +1168,11 @@ switch_outer(List *clauses)
foreach(i, clauses) foreach(i, clauses)
{ {
Expr *clause = (Expr *) lfirst(i); OpExpr *clause = (OpExpr *) lfirst(i);
Var *op; Var *op;
Assert(is_opclause((Node *) clause)); Assert(is_opclause(clause));
op = get_rightop(clause); op = get_rightop((Expr *) clause);
Assert(op && IsA(op, Var)); Assert(op && IsA(op, Var));
if (var_is_outer(op)) if (var_is_outer(op))
{ {
@ -1181,10 +1181,13 @@ switch_outer(List *clauses)
* the clause without changing the original list. Could use * the clause without changing the original list. Could use
* copyObject, but a complete deep copy is overkill. * copyObject, but a complete deep copy is overkill.
*/ */
Expr *temp; OpExpr *temp = makeNode(OpExpr);
temp = make_clause(clause->opType, clause->oper, temp->opno = clause->opno;
listCopy(clause->args)); 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. */ /* Commute it --- note this modifies the temp node in-place. */
CommuteClause(temp); CommuteClause(temp);
t_list = lappend(t_list, temp); t_list = lappend(t_list, temp);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.77 2002/11/24 21:52:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.78 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -761,14 +761,11 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
elog(ERROR, "Equality operator for types '%s' and '%s' should be mergejoinable, but isn't", elog(ERROR, "Equality operator for types '%s' and '%s' should be mergejoinable, but isn't",
format_type_be(ltype), format_type_be(rtype)); format_type_be(ltype), format_type_be(rtype));
clause = makeNode(Expr); clause = make_opclause(oprid(eq_operator), /* opno */
clause->typeOid = BOOLOID;
clause->opType = OP_EXPR;
clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */
InvalidOid, /* opid */
BOOLOID, /* opresulttype */ BOOLOID, /* opresulttype */
false); /* opretset */ false, /* opretset */
clause->args = makeList2(item1, item2); (Expr *) item1,
(Expr *) item2);
ReleaseSysCache(eq_operator); ReleaseSysCache(eq_operator);
@ -969,7 +966,7 @@ check_mergejoinable(RestrictInfo *restrictinfo)
leftOp, leftOp,
rightOp; rightOp;
if (!is_opclause((Node *) clause)) if (!is_opclause(clause))
return; return;
left = get_leftop(clause); left = get_leftop(clause);
@ -978,10 +975,11 @@ check_mergejoinable(RestrictInfo *restrictinfo)
/* caution: is_opclause accepts more than I do, so check it */ /* caution: is_opclause accepts more than I do, so check it */
if (!right) if (!right)
return; /* unary opclauses need not apply */ return; /* unary opclauses need not apply */
if (!IsA(left, Var) ||!IsA(right, Var)) if (!IsA(left, Var) ||
!IsA(right, Var))
return; return;
opno = ((Oper *) clause->oper)->opno; opno = ((OpExpr *) clause)->opno;
if (op_mergejoinable(opno, if (op_mergejoinable(opno,
left->vartype, left->vartype,
@ -1012,7 +1010,7 @@ check_hashjoinable(RestrictInfo *restrictinfo)
*right; *right;
Oid opno; Oid opno;
if (!is_opclause((Node *) clause)) if (!is_opclause(clause))
return; return;
left = get_leftop(clause); left = get_leftop(clause);
@ -1021,10 +1019,11 @@ check_hashjoinable(RestrictInfo *restrictinfo)
/* caution: is_opclause accepts more than I do, so check it */ /* caution: is_opclause accepts more than I do, so check it */
if (!right) if (!right)
return; /* unary opclauses need not apply */ return; /* unary opclauses need not apply */
if (!IsA(left, Var) ||!IsA(right, Var)) if (!IsA(left, Var) ||
!IsA(right, Var))
return; return;
opno = ((Oper *) clause->oper)->opno; opno = ((OpExpr *) clause)->opno;
if (op_hashjoinable(opno, if (op_hashjoinable(opno,
left->vartype, left->vartype,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.133 2002/12/05 21:46:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.134 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -91,7 +91,7 @@ planner(Query *parse)
* purpose is communication across multiple sub-Queries. * purpose is communication across multiple sub-Queries.
* *
* Note we do NOT save and restore PlannerPlanId: it exists to assign * 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 * the life of a backend. Also, PlannerInitPlan is saved/restored in
* subquery_planner, not here. * subquery_planner, not here.
*/ */
@ -278,7 +278,7 @@ subquery_planner(Query *parse, double tuple_fraction)
/* Must add the initPlans' extParams to the topmost node's, too */ /* Must add the initPlans' extParams to the topmost node's, too */
foreach(lst, plan->initPlan) foreach(lst, plan->initPlan)
{ {
SubPlan *subplan = (SubPlan *) lfirst(lst); SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
plan->extParam = set_unioni(plan->extParam, plan->extParam = set_unioni(plan->extParam,
subplan->plan->extParam); subplan->plan->extParam);
@ -1015,7 +1015,7 @@ grouping_planner(Query *parse, double tuple_fraction)
-1, -1,
0); 0);
ctid = makeTargetEntry(resdom, (Node *) var); ctid = makeTargetEntry(resdom, (Expr *) var);
tlist = lappend(tlist, ctid); tlist = lappend(tlist, ctid);
} }
} }
@ -1707,7 +1707,7 @@ make_subplanTargetList(Query *parse,
exprTypmod(groupexpr), exprTypmod(groupexpr),
NULL, NULL,
false), false),
groupexpr); (Expr *) groupexpr);
sub_tlist = lappend(sub_tlist, te); sub_tlist = lappend(sub_tlist, te);
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.84 2002/12/05 15:50:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.85 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -52,7 +52,7 @@ static Node *replace_vars_with_subplan_refs(Node *node,
bool tlist_has_non_vars); bool tlist_has_non_vars);
static Node *replace_vars_with_subplan_refs_mutator(Node *node, static Node *replace_vars_with_subplan_refs_mutator(Node *node,
replace_vars_with_subplan_refs_context *context); replace_vars_with_subplan_refs_context *context);
static bool fix_opids_walker(Node *node, void *context); static bool fix_opfuncids_walker(Node *node, void *context);
/***************************************************************************** /*****************************************************************************
* *
@ -219,7 +219,7 @@ set_plan_references(Plan *plan, List *rtable)
* subplan references in this plan's tlist and quals. If we did the * subplan references in this plan's tlist and quals. If we did the
* reference-adjustments bottom-up, then we would fail to match this * reference-adjustments bottom-up, then we would fail to match this
* plan's var nodes against the already-modified nodes of the * 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. * nodes; else we'd need two passes over the expression trees.
*/ */
set_plan_references(plan->lefttree, rtable); set_plan_references(plan->lefttree, rtable);
@ -227,9 +227,9 @@ set_plan_references(Plan *plan, List *rtable)
foreach(pl, plan->initPlan) 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); set_plan_references(sp->plan, sp->rtable);
} }
} }
@ -238,8 +238,8 @@ set_plan_references(Plan *plan, List *rtable)
* fix_expr_references * fix_expr_references
* Do final cleanup on expressions (targetlists or quals). * Do final cleanup on expressions (targetlists or quals).
* *
* This consists of looking up operator opcode info for Oper nodes * This consists of looking up operator opcode info for OpExpr nodes
* and recursively performing set_plan_references on SubPlans. * and recursively performing set_plan_references on subplans.
* *
* The Plan argument is currently unused, but might be needed again someday. * The Plan argument is currently unused, but might be needed again someday.
*/ */
@ -255,21 +255,16 @@ fix_expr_references_walker(Node *node, void *context)
{ {
if (node == NULL) if (node == NULL)
return false; 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); return expression_tree_walker(node, fix_expr_references_walker, context);
} }
@ -362,12 +357,13 @@ set_uppernode_references(Plan *plan, Index subvarno)
TargetEntry *tle = (TargetEntry *) lfirst(l); TargetEntry *tle = (TargetEntry *) lfirst(l);
Node *newexpr; Node *newexpr;
newexpr = replace_vars_with_subplan_refs(tle->expr, newexpr = replace_vars_with_subplan_refs((Node *) tle->expr,
subvarno, subvarno,
subplan_targetlist, subplan_targetlist,
tlist_has_non_vars); tlist_has_non_vars);
output_targetlist = lappend(output_targetlist, output_targetlist = lappend(output_targetlist,
makeTargetEntry(tle->resdom, newexpr)); makeTargetEntry(tle->resdom,
(Expr *) newexpr));
} }
plan->targetlist = output_targetlist; plan->targetlist = output_targetlist;
@ -570,8 +566,8 @@ replace_vars_with_subplan_refs_mutator(Node *node,
*****************************************************************************/ *****************************************************************************/
/* /*
* fix_opids * fix_opfuncids
* Calculate opid field from opno for each Oper node in given tree. * Calculate opfuncid field from opno for each OpExpr node in given tree.
* The given tree can be anything expression_tree_walker handles. * The given tree can be anything expression_tree_walker handles.
* *
* The argument is modified in-place. (This is OK since we'd want the * The argument is modified in-place. (This is OK since we'd want the
@ -579,24 +575,20 @@ replace_vars_with_subplan_refs_mutator(Node *node,
* shared structure.) * shared structure.)
*/ */
void void
fix_opids(Node *node) fix_opfuncids(Node *node)
{ {
/* This tree walk requires no special setup, so away we go... */ /* This tree walk requires no special setup, so away we go... */
fix_opids_walker(node, NULL); fix_opfuncids_walker(node, NULL);
} }
static bool static bool
fix_opids_walker(Node *node, void *context) fix_opfuncids_walker(Node *node, void *context)
{ {
if (node == NULL) if (node == NULL)
return false; return false;
if (IsA(node, Expr)) if (IsA(node, OpExpr))
{ set_opfuncid((OpExpr *) node);
Expr *expr = (Expr *) node; else if (IsA(node, DistinctExpr))
set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
if (expr->opType == OP_EXPR || return expression_tree_walker(node, fix_opfuncids_walker, context);
expr->opType == DISTINCT_EXPR)
replace_opid((Oper *) expr->oper);
}
return expression_tree_walker(node, fix_opids_walker, context);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.59 2002/12/05 15:50:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.60 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -144,12 +144,12 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
} }
/* /*
* Convert a bare SubLink (as created by the parser) into a SubPlan. * Convert a bare SubLink (as created by the parser) into a SubPlanExpr.
*/ */
static Node * static Node *
make_subplan(SubLink *slink) make_subplan(SubLink *slink)
{ {
SubPlan *node = makeNode(SubPlan); SubPlanExpr *node = makeNode(SubPlanExpr);
Query *subquery = (Query *) (slink->subselect); Query *subquery = (Query *) (slink->subselect);
Oid result_type = exprType((Node *) slink); Oid result_type = exprType((Node *) slink);
double tuple_fraction; double tuple_fraction;
@ -210,11 +210,13 @@ make_subplan(SubLink *slink)
node->plan = plan = subquery_planner(subquery, tuple_fraction); node->plan = plan = subquery_planner(subquery, tuple_fraction);
node->plan_id = PlannerPlanId++; /* Assign unique ID to this node->plan_id = PlannerPlanId++; /* Assign unique ID to this
* SubPlan */ * SubPlanExpr */
node->rtable = subquery->rtable; node->rtable = subquery->rtable;
node->sublink = slink; node->sublink = slink;
node->typeOid = result_type;
slink->subselect = NULL; /* cool ?! see error check above! */ slink->subselect = NULL; /* cool ?! see error check above! */
/* /*
@ -270,7 +272,6 @@ make_subplan(SubLink *slink)
} }
else else
{ {
Expr *expr = makeNode(Expr);
List *args = NIL; List *args = NIL;
/* /*
@ -350,14 +351,7 @@ make_subplan(SubLink *slink)
convert_sublink_opers(slink, plan->targetlist, NULL); convert_sublink_opers(slink, plan->targetlist, NULL);
/* /*
* Make expression of SUBPLAN type * Make node->args from parParam.
*/
expr->typeOid = result_type;
expr->opType = SUBPLAN_EXPR;
expr->oper = (Node *) node;
/*
* Make expr->args from parParam.
*/ */
foreach(lst, node->parParam) foreach(lst, node->parParam)
{ {
@ -373,9 +367,9 @@ make_subplan(SubLink *slink)
var->varlevelsup = 0; var->varlevelsup = 0;
args = lappend(args, var); args = lappend(args, var);
} }
expr->args = args; node->args = args;
result = (Node *) expr; result = (Node *) node;
} }
return result; return result;
@ -385,7 +379,7 @@ make_subplan(SubLink *slink)
* convert_sublink_opers: convert a SubLink's oper list from the * convert_sublink_opers: convert a SubLink's oper list from the
* parser/rewriter format into the executor's format. * 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 * with a list of actually executable expressions, in which the specified
* operators are applied to corresponding elements of the lefthand list * operators are applied to corresponding elements of the lefthand list
* and Params representing the results of the subplan. lefthand is then * and Params representing the results of the subplan. lefthand is then
@ -404,7 +398,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
foreach(lst, slink->oper) foreach(lst, slink->oper)
{ {
Oper *oper = (Oper *) lfirst(lst); OpExpr *oper = (OpExpr *) lfirst(lst);
Node *lefthand = lfirst(leftlist); Node *lefthand = lfirst(leftlist);
TargetEntry *te = lfirst(targetlist); TargetEntry *te = lfirst(targetlist);
Param *prm; Param *prm;
@ -422,7 +416,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
*setParams = lappendi(*setParams, prm->paramid); *setParams = lappendi(*setParams, prm->paramid);
/* Look up the operator to check its declared input types */ /* Look up the operator to check its declared input types */
Assert(IsA(oper, Oper)); Assert(IsA(oper, OpExpr));
tup = SearchSysCache(OPEROID, tup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oper->opno), ObjectIdGetDatum(oper->opno),
0, 0, 0); 0, 0, 0);
@ -439,9 +433,11 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
left = make_operand(lefthand, exprType(lefthand), opform->oprleft); left = make_operand(lefthand, exprType(lefthand), opform->oprleft);
right = make_operand((Node *) prm, prm->paramtype, opform->oprright); right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
newoper = lappend(newoper, newoper = lappend(newoper,
make_opclause(oper, make_opclause(oper->opno,
(Var *) left, oper->opresulttype,
(Var *) right)); oper->opretset,
(Expr *) left,
(Expr *) right));
ReleaseSysCache(tup); ReleaseSysCache(tup);
@ -482,7 +478,7 @@ finalize_primnode(Node *node, finalize_primnode_results *results)
} }
if (is_subplan(node)) if (is_subplan(node))
{ {
SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper; SubPlanExpr *subplan = (SubPlanExpr *) node;
List *lst; List *lst;
/* Check extParam list for params to add to paramids */ /* Check extParam list for params to add to paramids */
@ -559,12 +555,12 @@ process_sublinks_mutator(Node *node, void *context)
*/ */
sublink->lefthand = (List *) sublink->lefthand = (List *)
process_sublinks_mutator((Node *) sublink->lefthand, context); 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); 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 * (since this is the very routine that creates 'em to begin with). So
* the code in expression_tree_mutator() that might do inappropriate * the code in expression_tree_mutator() that might do inappropriate
* things with SubPlans or SubLinks will not be exercised. * things with SubPlans or SubLinks will not be exercised.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.33 2002/09/02 02:47:02 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.34 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -294,7 +294,7 @@ flatten_andors(Expr *qual)
List *out_list = NIL; List *out_list = NIL;
List *arg; List *arg;
foreach(arg, qual->args) foreach(arg, ((BoolExpr *) qual)->args)
{ {
Expr *subexpr = flatten_andors((Expr *) lfirst(arg)); Expr *subexpr = flatten_andors((Expr *) lfirst(arg));
@ -305,7 +305,7 @@ flatten_andors(Expr *qual)
* with any other expr. Otherwise we'd need a listCopy here. * with any other expr. Otherwise we'd need a listCopy here.
*/ */
if (and_clause((Node *) subexpr)) if (and_clause((Node *) subexpr))
out_list = nconc(out_list, subexpr->args); out_list = nconc(out_list, ((BoolExpr *) subexpr)->args);
else else
out_list = lappend(out_list, subexpr); out_list = lappend(out_list, subexpr);
} }
@ -316,7 +316,7 @@ flatten_andors(Expr *qual)
List *out_list = NIL; List *out_list = NIL;
List *arg; List *arg;
foreach(arg, qual->args) foreach(arg, ((BoolExpr *) qual)->args)
{ {
Expr *subexpr = flatten_andors((Expr *) lfirst(arg)); Expr *subexpr = flatten_andors((Expr *) lfirst(arg));
@ -327,7 +327,7 @@ flatten_andors(Expr *qual)
* with any other expr. Otherwise we'd need a listCopy here. * with any other expr. Otherwise we'd need a listCopy here.
*/ */
if (or_clause((Node *) subexpr)) if (or_clause((Node *) subexpr))
out_list = nconc(out_list, subexpr->args); out_list = nconc(out_list, ((BoolExpr *) subexpr)->args);
else else
out_list = lappend(out_list, subexpr); out_list = lappend(out_list, subexpr);
} }
@ -335,20 +335,17 @@ flatten_andors(Expr *qual)
} }
else if (not_clause((Node *) qual)) else if (not_clause((Node *) qual))
return make_notclause(flatten_andors(get_notclausearg(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 *left = (Expr *) get_leftop(qual);
Expr *right = (Expr *) get_rightop(qual); Expr *right = (Expr *) get_rightop(qual);
if (right) return make_opclause(opexpr->opno,
return make_clause(qual->opType, qual->oper, opexpr->opresulttype,
lcons(flatten_andors(left), opexpr->opretset,
lcons(flatten_andors(right), flatten_andors(left),
NIL))); flatten_andors(right));
else
return make_clause(qual->opType, qual->oper,
lcons(flatten_andors(left),
NIL));
} }
else else
return qual; return qual;
@ -379,7 +376,8 @@ pull_ors(List *orlist)
* we'd need a listCopy here. * we'd need a listCopy here.
*/ */
if (or_clause((Node *) subexpr)) 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 else
out_list = lappend(out_list, subexpr); out_list = lappend(out_list, subexpr);
} }
@ -410,7 +408,8 @@ pull_ands(List *andlist)
* we'd need a listCopy here. * we'd need a listCopy here.
*/ */
if (and_clause((Node *) subexpr)) 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 else
out_list = lappend(out_list, subexpr); out_list = lappend(out_list, subexpr);
} }
@ -433,20 +432,17 @@ find_nots(Expr *qual)
#ifdef NOT_USED #ifdef NOT_USED
/* recursing into operator expressions is probably not worth it. */ /* 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 *left = (Expr *) get_leftop(qual);
Expr *right = (Expr *) get_rightop(qual); Expr *right = (Expr *) get_rightop(qual);
if (right) return make_opclause(opexpr->opno,
return make_clause(qual->opType, qual->oper, opexpr->opresulttype,
lcons(find_nots(left), opexpr->opretset,
lcons(find_nots(right), find_nots(left),
NIL))); find_nots(right));
else
return make_clause(qual->opType, qual->oper,
lcons(find_nots(left),
NIL));
} }
#endif #endif
if (and_clause((Node *) qual)) if (and_clause((Node *) qual))
@ -454,7 +450,7 @@ find_nots(Expr *qual)
List *t_list = NIL; List *t_list = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, find_nots(lfirst(temp))); t_list = lappend(t_list, find_nots(lfirst(temp)));
return make_andclause(pull_ands(t_list)); return make_andclause(pull_ands(t_list));
} }
@ -463,7 +459,7 @@ find_nots(Expr *qual)
List *t_list = NIL; List *t_list = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, find_nots(lfirst(temp))); t_list = lappend(t_list, find_nots(lfirst(temp)));
return make_orclause(pull_ors(t_list)); return make_orclause(pull_ors(t_list));
} }
@ -492,20 +488,17 @@ push_nots(Expr *qual)
* Otherwise, retain the clause as it is (the 'not' can't be pushed * Otherwise, retain the clause as it is (the 'not' can't be pushed
* down any farther). * down any farther).
*/ */
if (is_opclause((Node *) qual)) if (is_opclause(qual))
{ {
Oper *oper = (Oper *) ((Expr *) qual)->oper; OpExpr *opexpr = (OpExpr *) qual;
Oid negator = get_negator(oper->opno); Oid negator = get_negator(opexpr->opno);
if (negator) if (negator)
{ return make_opclause(negator,
Oper *op = (Oper *) makeOper(negator, opexpr->opresulttype,
InvalidOid, opexpr->opretset,
oper->opresulttype, (Expr *) get_leftop(qual),
oper->opretset); (Expr *) get_rightop(qual));
return make_opclause(op, get_leftop(qual), get_rightop(qual));
}
else else
return make_notclause(qual); return make_notclause(qual);
} }
@ -521,7 +514,7 @@ push_nots(Expr *qual)
List *t_list = NIL; List *t_list = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, push_nots(lfirst(temp))); t_list = lappend(t_list, push_nots(lfirst(temp)));
return make_orclause(pull_ors(t_list)); return make_orclause(pull_ors(t_list));
} }
@ -530,7 +523,7 @@ push_nots(Expr *qual)
List *t_list = NIL; List *t_list = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
t_list = lappend(t_list, push_nots(lfirst(temp))); t_list = lappend(t_list, push_nots(lfirst(temp)));
return make_andclause(pull_ands(t_list)); return make_andclause(pull_ands(t_list));
} }
@ -576,7 +569,7 @@ find_ors(Expr *qual)
List *andlist = NIL; List *andlist = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
andlist = lappend(andlist, find_ors(lfirst(temp))); andlist = lappend(andlist, find_ors(lfirst(temp)));
return make_andclause(pull_ands(andlist)); return make_andclause(pull_ands(andlist));
} }
@ -585,7 +578,7 @@ find_ors(Expr *qual)
List *orlist = NIL; List *orlist = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
orlist = lappend(orlist, find_ors(lfirst(temp))); orlist = lappend(orlist, find_ors(lfirst(temp)));
return or_normalize(pull_ors(orlist)); return or_normalize(pull_ors(orlist));
} }
@ -629,7 +622,7 @@ or_normalize(List *orlist)
if (and_clause((Node *) clause)) if (and_clause((Node *) clause))
{ {
int nclauses = length(clause->args); int nclauses = length(((BoolExpr *) clause)->args);
if (nclauses > num_subclauses) if (nclauses > num_subclauses)
{ {
@ -650,7 +643,7 @@ or_normalize(List *orlist)
*/ */
orlist = lremove(distributable, orlist); orlist = lremove(distributable, orlist);
foreach(temp, distributable->args) foreach(temp, ((BoolExpr *) distributable)->args)
{ {
Expr *andclause = lfirst(temp); Expr *andclause = lfirst(temp);
List *neworlist; List *neworlist;
@ -703,7 +696,7 @@ find_ands(Expr *qual)
List *orlist = NIL; List *orlist = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
orlist = lappend(orlist, find_ands(lfirst(temp))); orlist = lappend(orlist, find_ands(lfirst(temp)));
return make_orclause(pull_ors(orlist)); return make_orclause(pull_ors(orlist));
} }
@ -712,7 +705,7 @@ find_ands(Expr *qual)
List *andlist = NIL; List *andlist = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
andlist = lappend(andlist, find_ands(lfirst(temp))); andlist = lappend(andlist, find_ands(lfirst(temp)));
return and_normalize(pull_ands(andlist)); return and_normalize(pull_ands(andlist));
} }
@ -757,7 +750,7 @@ and_normalize(List *andlist)
if (or_clause((Node *) clause)) if (or_clause((Node *) clause))
{ {
int nclauses = length(clause->args); int nclauses = length(((BoolExpr *) clause)->args);
if (nclauses > num_subclauses) if (nclauses > num_subclauses)
{ {
@ -778,7 +771,7 @@ and_normalize(List *andlist)
*/ */
andlist = lremove(distributable, andlist); andlist = lremove(distributable, andlist);
foreach(temp, distributable->args) foreach(temp, ((BoolExpr *) distributable)->args)
{ {
Expr *orclause = lfirst(temp); Expr *orclause = lfirst(temp);
List *newandlist; List *newandlist;
@ -829,7 +822,7 @@ qual_cleanup(Expr *qual)
List *andlist = NIL; List *andlist = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
andlist = lappend(andlist, qual_cleanup(lfirst(temp))); andlist = lappend(andlist, qual_cleanup(lfirst(temp)));
andlist = remove_duplicates(pull_ands(andlist)); andlist = remove_duplicates(pull_ands(andlist));
@ -844,7 +837,7 @@ qual_cleanup(Expr *qual)
List *orlist = NIL; List *orlist = NIL;
List *temp; List *temp;
foreach(temp, qual->args) foreach(temp, ((BoolExpr *) qual)->args)
orlist = lappend(orlist, qual_cleanup(lfirst(temp))); orlist = lappend(orlist, qual_cleanup(lfirst(temp)));
orlist = remove_duplicates(pull_ors(orlist)); orlist = remove_duplicates(pull_ors(orlist));
@ -910,7 +903,7 @@ count_bool_nodes(Expr *qual,
*nodes = *cnfnodes = 0.0; *nodes = *cnfnodes = 0.0;
*dnfnodes = 1.0; /* DNF nodes will be product of sub-counts */ *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), count_bool_nodes(lfirst(temp),
&subnodes, &subcnfnodes, &subdnfnodes); &subnodes, &subcnfnodes, &subdnfnodes);
@ -931,7 +924,7 @@ count_bool_nodes(Expr *qual,
*nodes = *dnfnodes = 0.0; *nodes = *dnfnodes = 0.0;
*cnfnodes = 1.0; /* CNF nodes will be product of sub-counts */ *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), count_bool_nodes(lfirst(temp),
&subnodes, &subcnfnodes, &subdnfnodes); &subnodes, &subcnfnodes, &subdnfnodes);

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.58 2002/11/25 21:29:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.59 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -96,7 +96,7 @@ preprocess_targetlist(List *tlist,
if (command_type == CMD_DELETE) if (command_type == CMD_DELETE)
tlist = listCopy(tlist); tlist = listCopy(tlist);
tlist = lappend(tlist, makeTargetEntry(resdom, (Node *) var)); tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var));
} }
return tlist; return tlist;
@ -215,7 +215,7 @@ expand_targetlist(List *tlist, int command_type,
atttypmod, atttypmod,
pstrdup(NameStr(att_tup->attname)), pstrdup(NameStr(att_tup->attname)),
false), false),
new_expr); (Expr *) new_expr);
} }
new_tlist = lappend(new_tlist, new_tle); new_tlist = lappend(new_tlist, new_tle);

View File

@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.81 2002/11/25 21:29:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.82 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -406,7 +406,7 @@ generate_setop_tlist(List *colTypes, int flag,
* the output tlists of upper-level nodes! * the output tlists of upper-level nodes!
*/ */
if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const)) if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
expr = inputtle->expr; expr = (Node *) inputtle->expr;
else else
expr = (Node *) makeVar(0, expr = (Node *) makeVar(0,
inputtle->resdom->resno, inputtle->resdom->resno,
@ -430,7 +430,7 @@ generate_setop_tlist(List *colTypes, int flag,
colTypmod, colTypmod,
pstrdup(reftle->resdom->resname), pstrdup(reftle->resdom->resname),
false); false);
tlist = lappend(tlist, makeTargetEntry(resdom, expr)); tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
input_tlist = lnext(input_tlist); input_tlist = lnext(input_tlist);
refnames_tlist = lnext(refnames_tlist); refnames_tlist = lnext(refnames_tlist);
} }
@ -449,7 +449,7 @@ generate_setop_tlist(List *colTypes, int flag,
Int32GetDatum(flag), Int32GetDatum(flag),
false, false,
true); true);
tlist = lappend(tlist, makeTargetEntry(resdom, expr)); tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
} }
return tlist; return tlist;
@ -543,7 +543,7 @@ generate_append_tlist(List *colTypes, bool flag,
colTypmod, colTypmod,
pstrdup(reftle->resdom->resname), pstrdup(reftle->resdom->resname),
false); false);
tlist = lappend(tlist, makeTargetEntry(resdom, expr)); tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
refnames_tlist = lnext(refnames_tlist); refnames_tlist = lnext(refnames_tlist);
} }
@ -561,7 +561,7 @@ generate_append_tlist(List *colTypes, bool flag,
INT4OID, INT4OID,
-1, -1,
0); 0);
tlist = lappend(tlist, makeTargetEntry(resdom, expr)); tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
} }
pfree(colTypmods); pfree(colTypmods);
@ -872,13 +872,13 @@ adjust_inherited_attrs_mutator(Node *node,
*/ */
if (is_subplan(node)) if (is_subplan(node))
{ {
SubPlan *subplan; SubPlanExpr *subplan;
/* Copy the node and process subplan args */ /* Copy the node and process subplan args */
node = expression_tree_mutator(node, adjust_inherited_attrs_mutator, node = expression_tree_mutator(node, adjust_inherited_attrs_mutator,
(void *) context); (void *) context);
/* Make sure we have separate copies of subplan and its rtable */ /* 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->plan = copyObject(subplan->plan);
subplan->rtable = copyObject(subplan->rtable); subplan->rtable = copyObject(subplan->rtable);
return node; return node;

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.52 2002/06/20 20:29:31 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.53 2002/12/12 15:49:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -110,7 +110,7 @@ create_tl_element(Var *var, int resdomno)
var->vartypmod, var->vartypmod,
NULL, NULL,
false), false),
(Node *) var); (Expr *) var);
} }
/***************************************************************************** /*****************************************************************************
@ -253,5 +253,5 @@ get_sortgroupclause_expr(SortClause *sortClause, List *targetList)
{ {
TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList); TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList);
return tle->expr; return (Node *) tle->expr;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.40 2002/09/11 14:48:54 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.41 2002/12/12 15:49:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -65,7 +65,7 @@ static Node *flatten_join_alias_vars_mutator(Node *node,
* NOTE: this is used on not-yet-planned expressions. It may therefore find * 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 * 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 * 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 * List *
pull_varnos(Node *node) pull_varnos(Node *node)
@ -111,12 +111,12 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
* executed by the outer query. But short-circuit recursion into * executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort. * 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)) context))
return true; return true;
if (pull_varnos_walker((Node *) expr->args, if (pull_varnos_walker((Node *) subplan->args,
context)) context))
return true; return true;
return false; return false;
@ -146,7 +146,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
* NOTE: this is used on not-yet-planned expressions. It may therefore find * 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 * 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 * 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 bool
contain_var_reference(Node *node, int varno, int varattno, int levelsup) contain_var_reference(Node *node, int varno, int varattno, int levelsup)
@ -194,12 +194,12 @@ contain_var_reference_walker(Node *node,
* executed by the outer query. But short-circuit recursion into * executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort. * 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)) context))
return true; return true;
if (contain_var_reference_walker((Node *) expr->args, if (contain_var_reference_walker((Node *) subplan->args,
context)) context))
return true; return true;
return false; return false;

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -479,14 +479,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
{ {
TargetEntry *tle = (TargetEntry *) lfirst(tl); TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom; Resdom *resnode = tle->resdom;
Node *expr; Expr *expr;
if (resnode->resjunk) if (resnode->resjunk)
continue; continue;
if (tle->expr && IsA(tle->expr, Const)) if (tle->expr && IsA(tle->expr, Const))
expr = tle->expr; expr = tle->expr;
else else
expr = (Node *) makeVar(rtr->rtindex, expr = (Expr *) makeVar(rtr->rtindex,
resnode->resno, resnode->resno,
resnode->restype, resnode->restype,
resnode->restypmod, resnode->restypmod,
@ -1807,14 +1807,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom; Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom;
char *colName = pstrdup(leftResdom->resname); char *colName = pstrdup(leftResdom->resname);
Resdom *resdom; Resdom *resdom;
Node *expr; Expr *expr;
resdom = makeResdom((AttrNumber) pstate->p_last_resno++, resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
colType, colType,
-1, -1,
colName, colName,
false); false);
expr = (Node *) makeVar(1, expr = (Expr *) makeVar(1,
leftResdom->resno, leftResdom->resno,
colType, colType,
-1, -1,
@ -2424,7 +2424,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
format_type_be(given_type_id), format_type_be(given_type_id),
format_type_be(expected_type_id)); format_type_be(expected_type_id));
fix_opids(expr); fix_opfuncids(expr);
lfirst(l) = expr; lfirst(l) = expr;

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -5755,70 +5755,70 @@ a_expr: c_expr { $$ = $1; }
| a_expr ISNULL | a_expr ISNULL
{ {
NullTest *n = makeNode(NullTest); NullTest *n = makeNode(NullTest);
n->arg = $1; n->arg = (Expr *) $1;
n->nulltesttype = IS_NULL; n->nulltesttype = IS_NULL;
$$ = (Node *)n; $$ = (Node *)n;
} }
| a_expr IS NULL_P | a_expr IS NULL_P
{ {
NullTest *n = makeNode(NullTest); NullTest *n = makeNode(NullTest);
n->arg = $1; n->arg = (Expr *) $1;
n->nulltesttype = IS_NULL; n->nulltesttype = IS_NULL;
$$ = (Node *)n; $$ = (Node *)n;
} }
| a_expr NOTNULL | a_expr NOTNULL
{ {
NullTest *n = makeNode(NullTest); NullTest *n = makeNode(NullTest);
n->arg = $1; n->arg = (Expr *) $1;
n->nulltesttype = IS_NOT_NULL; n->nulltesttype = IS_NOT_NULL;
$$ = (Node *)n; $$ = (Node *)n;
} }
| a_expr IS NOT NULL_P | a_expr IS NOT NULL_P
{ {
NullTest *n = makeNode(NullTest); NullTest *n = makeNode(NullTest);
n->arg = $1; n->arg = (Expr *) $1;
n->nulltesttype = IS_NOT_NULL; n->nulltesttype = IS_NOT_NULL;
$$ = (Node *)n; $$ = (Node *)n;
} }
| a_expr IS TRUE_P | a_expr IS TRUE_P
{ {
BooleanTest *b = makeNode(BooleanTest); BooleanTest *b = makeNode(BooleanTest);
b->arg = $1; b->arg = (Expr *) $1;
b->booltesttype = IS_TRUE; b->booltesttype = IS_TRUE;
$$ = (Node *)b; $$ = (Node *)b;
} }
| a_expr IS NOT TRUE_P | a_expr IS NOT TRUE_P
{ {
BooleanTest *b = makeNode(BooleanTest); BooleanTest *b = makeNode(BooleanTest);
b->arg = $1; b->arg = (Expr *) $1;
b->booltesttype = IS_NOT_TRUE; b->booltesttype = IS_NOT_TRUE;
$$ = (Node *)b; $$ = (Node *)b;
} }
| a_expr IS FALSE_P | a_expr IS FALSE_P
{ {
BooleanTest *b = makeNode(BooleanTest); BooleanTest *b = makeNode(BooleanTest);
b->arg = $1; b->arg = (Expr *) $1;
b->booltesttype = IS_FALSE; b->booltesttype = IS_FALSE;
$$ = (Node *)b; $$ = (Node *)b;
} }
| a_expr IS NOT FALSE_P | a_expr IS NOT FALSE_P
{ {
BooleanTest *b = makeNode(BooleanTest); BooleanTest *b = makeNode(BooleanTest);
b->arg = $1; b->arg = (Expr *) $1;
b->booltesttype = IS_NOT_FALSE; b->booltesttype = IS_NOT_FALSE;
$$ = (Node *)b; $$ = (Node *)b;
} }
| a_expr IS UNKNOWN | a_expr IS UNKNOWN
{ {
BooleanTest *b = makeNode(BooleanTest); BooleanTest *b = makeNode(BooleanTest);
b->arg = $1; b->arg = (Expr *) $1;
b->booltesttype = IS_UNKNOWN; b->booltesttype = IS_UNKNOWN;
$$ = (Node *)b; $$ = (Node *)b;
} }
| a_expr IS NOT UNKNOWN | a_expr IS NOT UNKNOWN
{ {
BooleanTest *b = makeNode(BooleanTest); BooleanTest *b = makeNode(BooleanTest);
b->arg = $1; b->arg = (Expr *) $1;
b->booltesttype = IS_NOT_UNKNOWN; b->booltesttype = IS_NOT_UNKNOWN;
$$ = (Node *)b; $$ = (Node *)b;
} }
@ -6640,9 +6640,9 @@ in_expr: select_with_parens
case_expr: CASE case_arg when_clause_list case_default END_TRANS case_expr: CASE case_arg when_clause_list case_default END_TRANS
{ {
CaseExpr *c = makeNode(CaseExpr); CaseExpr *c = makeNode(CaseExpr);
c->arg = $2; c->arg = (Expr *) $2;
c->args = $3; c->args = $3;
c->defresult = $4; c->defresult = (Expr *) $4;
$$ = (Node *)c; $$ = (Node *)c;
} }
| NULLIF '(' a_expr ',' a_expr ')' | NULLIF '(' a_expr ',' a_expr ')'
@ -6650,10 +6650,10 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS
CaseExpr *c = makeNode(CaseExpr); CaseExpr *c = makeNode(CaseExpr);
CaseWhen *w = makeNode(CaseWhen); 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 */ /* w->result is left NULL */
c->args = makeList1(w); c->args = makeList1(w);
c->defresult = $3; c->defresult = (Expr *) $3;
$$ = (Node *)c; $$ = (Node *)c;
} }
| COALESCE '(' expr_list ')' | COALESCE '(' expr_list ')'
@ -6666,7 +6666,7 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS
NullTest *n = makeNode(NullTest); NullTest *n = makeNode(NullTest);
n->arg = lfirst(l); n->arg = lfirst(l);
n->nulltesttype = IS_NOT_NULL; n->nulltesttype = IS_NOT_NULL;
w->expr = (Node *) n; w->expr = (Expr *) n;
w->result = lfirst(l); w->result = lfirst(l);
c->args = lappend(c->args, w); c->args = lappend(c->args, w);
} }
@ -6684,8 +6684,8 @@ when_clause:
WHEN a_expr THEN a_expr WHEN a_expr THEN a_expr
{ {
CaseWhen *w = makeNode(CaseWhen); CaseWhen *w = makeNode(CaseWhen);
w->expr = $2; w->expr = (Expr *) $2;
w->result = $4; w->result = (Expr *) $4;
$$ = (Node *)w; $$ = (Node *)w;
} }
; ;
@ -7594,16 +7594,13 @@ static Node *
makeRowNullTest(NullTestType test, List *args) makeRowNullTest(NullTestType test, List *args)
{ {
Node *expr = NULL; Node *expr = NULL;
Node *arg;
NullTest *n; NullTest *n;
if (lnext(args) != NIL) if (lnext(args) != NIL)
expr = makeRowNullTest(test, lnext(args)); expr = makeRowNullTest(test, lnext(args));
arg = lfirst(args);
n = makeNode(NullTest); n = makeNode(NullTest);
n->arg = arg; n->arg = (Expr *) lfirst(args);
n->nulltesttype = test; n->nulltesttype = test;
if (expr == NULL) if (expr == NULL)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -502,17 +502,6 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
elog(ERROR, "cannot use aggregate function in FROM function expression"); 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. * OK, build an RTE for the function.
*/ */
@ -876,7 +865,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
outcoltype, outcoltype,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (l_colvar->vartypmod != outcoltypmod) else if (l_colvar->vartypmod != outcoltypmod)
l_node = (Node *) makeRelabelType((Node *) l_colvar, l_node = (Node *) makeRelabelType((Expr *) l_colvar,
outcoltype, outcoltypmod, outcoltype, outcoltypmod,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
else else
@ -887,7 +876,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
outcoltype, outcoltype,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (r_colvar->vartypmod != outcoltypmod) else if (r_colvar->vartypmod != outcoltypmod)
r_node = (Node *) makeRelabelType((Node *) r_colvar, r_node = (Node *) makeRelabelType((Expr *) r_colvar,
outcoltype, outcoltypmod, outcoltype, outcoltypmod,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
else else
@ -928,13 +917,13 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
CaseWhen *w = makeNode(CaseWhen); CaseWhen *w = makeNode(CaseWhen);
NullTest *n = makeNode(NullTest); NullTest *n = makeNode(NullTest);
n->arg = l_node; n->arg = (Expr *) l_node;
n->nulltesttype = IS_NOT_NULL; n->nulltesttype = IS_NOT_NULL;
w->expr = (Node *) n; w->expr = (Expr *) n;
w->result = l_node; w->result = (Expr *) l_node;
c->casetype = outcoltype; c->casetype = outcoltype;
c->args = makeList1(w); c->args = makeList1(w);
c->defresult = r_node; c->defresult = (Expr *) r_node;
res_node = (Node *) c; res_node = (Node *) c;
break; break;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -88,7 +88,8 @@ coerce_to_target_type(Node *expr, Oid exprtype,
ccontext, cformat); ccontext, cformat);
/* Need a RelabelType if no typmod coercion is performed */ /* Need a RelabelType if no typmod coercion is performed */
if (targettypmod < 0) if (targettypmod < 0)
expr = (Node *) makeRelabelType(expr, targettype, -1, expr = (Node *) makeRelabelType((Expr *) expr,
targettype, -1,
cformat); cformat);
} }
else else
@ -190,7 +191,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
cformat); cformat);
/* We might now need a RelabelType. */ /* We might now need a RelabelType. */
if (exprType(result) != targetTypeId) if (exprType(result) != targetTypeId)
result = (Node *) makeRelabelType(result, targetTypeId, -1, result = (Node *) makeRelabelType((Expr *) result,
targetTypeId, -1,
cformat); cformat);
} }
@ -227,7 +229,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
{ {
result = coerce_type_constraints(result, targetTypeId, result = coerce_type_constraints(result, targetTypeId,
cformat); cformat);
result = (Node *) makeRelabelType(result, targetTypeId, -1, result = (Node *) makeRelabelType((Expr *) result,
targetTypeId, -1,
cformat); cformat);
} }
@ -266,7 +269,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
* typmod, which is likely but not certain (wrong if target is * typmod, which is likely but not certain (wrong if target is
* a domain, in any case). * a domain, in any case).
*/ */
result = (Node *) makeRelabelType(result, targetTypeId, -1, result = (Node *) makeRelabelType((Expr *) result,
targetTypeId, -1,
cformat); cformat);
} }
} }
@ -277,7 +281,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
* except relabel the type. This is binary compatibility for * except relabel the type. This is binary compatibility for
* complex types. * complex types.
*/ */
result = (Node *) makeRelabelType(node, targetTypeId, -1, result = (Node *) makeRelabelType((Expr *) node,
targetTypeId, -1,
cformat); cformat);
} }
else else
@ -449,7 +454,7 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat)
elog(ERROR, "coerce_type_constraints: domain %s constraint %s has NULL conbin", elog(ERROR, "coerce_type_constraints: domain %s constraint %s has NULL conbin",
NameStr(typTup->typname), NameStr(c->conname)); NameStr(typTup->typname), NameStr(c->conname));
r->arg = arg; r->arg = (Expr *) arg;
r->testtype = CONSTR_TEST_CHECK; r->testtype = CONSTR_TEST_CHECK;
r->name = NameStr(c->conname); r->name = NameStr(c->conname);
r->domname = NameStr(typTup->typname); r->domname = NameStr(typTup->typname);
@ -492,7 +497,7 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat)
{ {
ConstraintTest *r = makeNode(ConstraintTest); ConstraintTest *r = makeNode(ConstraintTest);
r->arg = arg; r->arg = (Expr *) arg;
r->testtype = CONSTR_TEST_NOTNULL; r->testtype = CONSTR_TEST_NOTNULL;
r->name = "NOT NULL"; r->name = "NOT NULL";
r->domname = notNull; r->domname = notNull;
@ -1140,21 +1145,14 @@ find_typmod_coercion_function(Oid typeId, int *nargs)
static Node * static Node *
build_func_call(Oid funcid, Oid rettype, List *args, CoercionForm fformat) build_func_call(Oid funcid, Oid rettype, List *args, CoercionForm fformat)
{ {
Func *funcnode; FuncExpr *funcexpr;
Expr *expr;
funcnode = makeNode(Func); funcexpr = makeNode(FuncExpr);
funcnode->funcid = funcid; funcexpr->funcid = funcid;
funcnode->funcresulttype = rettype; funcexpr->funcresulttype = rettype;
funcnode->funcretset = false; /* only possible case here */ funcexpr->funcretset = false; /* only possible case here */
funcnode->funcformat = fformat; funcexpr->funcformat = fformat;
funcnode->func_fcache = NULL; funcexpr->args = args;
expr = makeNode(Expr); return (Node *) funcexpr;
expr->typeOid = rettype;
expr->opType = FUNC_EXPR;
expr->oper = (Node *) funcnode;
expr->args = args;
return (Node *) expr;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -199,9 +199,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
n->nulltesttype = IS_NULL; n->nulltesttype = IS_NULL;
if (exprIsNullConstant(a->lexpr)) if (exprIsNullConstant(a->lexpr))
n->arg = a->rexpr; n->arg = (Expr *) a->rexpr;
else else
n->arg = a->lexpr; n->arg = (Expr *) a->lexpr;
result = transformExpr(pstate, result = transformExpr(pstate,
(Node *) n, domVal); (Node *) n, domVal);
@ -225,15 +225,13 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
a->lexpr, domVal); a->lexpr, domVal);
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, domVal); a->rexpr, domVal);
Expr *expr = makeNode(Expr);
lexpr = coerce_to_boolean(lexpr, "AND"); lexpr = coerce_to_boolean(lexpr, "AND");
rexpr = coerce_to_boolean(rexpr, "AND"); rexpr = coerce_to_boolean(rexpr, "AND");
expr->typeOid = BOOLOID; result = (Node *) makeBoolExpr(AND_EXPR,
expr->opType = AND_EXPR; makeList2(lexpr,
expr->args = makeList2(lexpr, rexpr); rexpr));
result = (Node *) expr;
} }
break; break;
case OR: case OR:
@ -242,29 +240,24 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
a->lexpr, domVal); a->lexpr, domVal);
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, domVal); a->rexpr, domVal);
Expr *expr = makeNode(Expr);
lexpr = coerce_to_boolean(lexpr, "OR"); lexpr = coerce_to_boolean(lexpr, "OR");
rexpr = coerce_to_boolean(rexpr, "OR"); rexpr = coerce_to_boolean(rexpr, "OR");
expr->typeOid = BOOLOID; result = (Node *) makeBoolExpr(OR_EXPR,
expr->opType = OR_EXPR; makeList2(lexpr,
expr->args = makeList2(lexpr, rexpr); rexpr));
result = (Node *) expr;
} }
break; break;
case NOT: case NOT:
{ {
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, domVal); a->rexpr, domVal);
Expr *expr = makeNode(Expr);
rexpr = coerce_to_boolean(rexpr, "NOT"); rexpr = coerce_to_boolean(rexpr, "NOT");
expr->typeOid = BOOLOID; result = (Node *) makeBoolExpr(NOT_EXPR,
expr->opType = NOT_EXPR; makeList1(rexpr));
expr->args = makeList1(rexpr);
result = (Node *) expr;
} }
break; break;
case DISTINCT: case DISTINCT:
@ -277,9 +270,12 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
result = (Node *) make_op(a->name, result = (Node *) make_op(a->name,
lexpr, lexpr,
rexpr); rexpr);
if (((Expr *) result)->typeOid != BOOLOID) if (((OpExpr *) result)->opresulttype != BOOLOID)
elog(ERROR, "IS DISTINCT FROM requires = operator to yield boolean"); 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; break;
case OF: case OF:
@ -433,7 +429,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
Node *lexpr; Node *lexpr;
Operator optup; Operator optup;
Form_pg_operator opform; Form_pg_operator opform;
Oper *newop; OpExpr *newop;
right_list = lnext(right_list); right_list = lnext(right_list);
if (tent->resdom->resjunk) if (tent->resdom->resjunk)
@ -451,7 +447,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
*/ */
optup = oper(op, optup = oper(op,
exprType(lexpr), exprType(lexpr),
exprType(tent->expr), exprType((Node *) tent->expr),
false); false);
opform = (Form_pg_operator) GETSTRUCT(optup); opform = (Form_pg_operator) GETSTRUCT(optup);
@ -466,11 +462,15 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
" to be used with quantified predicate subquery", " to be used with quantified predicate subquery",
opname); opname);
newop = makeOper(oprid(optup), /* opno */ newop = makeNode(OpExpr);
InvalidOid, /* opid */ newop->opno = oprid(optup);
opform->oprresult, newop->opfuncid = InvalidOid;
false); newop->opresulttype = opform->oprresult;
newop->opretset = false;
newop->args = NIL; /* for now */
sublink->oper = lappend(sublink->oper, newop); sublink->oper = lappend(sublink->oper, newop);
ReleaseSysCache(optup); ReleaseSysCache(optup);
} }
if (left_list != NIL) if (left_list != NIL)
@ -499,22 +499,24 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
Assert(IsA(w, CaseWhen)); Assert(IsA(w, CaseWhen));
warg = w->expr; warg = (Node *) w->expr;
if (c->arg != NULL) if (c->arg != NULL)
{ {
/* shorthand form was specified, so expand... */ /* shorthand form was specified, so expand... */
warg = (Node *) makeSimpleA_Expr(OP, "=", 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 * result is NULL for NULLIF() construct - thomas
* 1998-11-11 * 1998-11-11
*/ */
warg = w->result; warg = (Node *) w->result;
if (warg == NULL) if (warg == NULL)
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
@ -522,10 +524,10 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
n->val.type = T_Null; n->val.type = T_Null;
warg = (Node *) n; warg = (Node *) n;
} }
neww->result = transformExpr(pstate, warg, domVal); neww->result = (Expr *) transformExpr(pstate, warg, domVal);
newargs = lappend(newargs, neww); newargs = lappend(newargs, neww);
typeids = lappendi(typeids, exprType(neww->result)); typeids = lappendi(typeids, exprType((Node *) neww->result));
} }
newc->args = newargs; newc->args = newargs;
@ -538,7 +540,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
newc->arg = NULL; newc->arg = NULL;
/* transform the default clause */ /* transform the default clause */
defresult = c->defresult; defresult = (Node *) c->defresult;
if (defresult == NULL) if (defresult == NULL)
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
@ -546,7 +548,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
n->val.type = T_Null; n->val.type = T_Null;
defresult = (Node *) n; defresult = (Node *) n;
} }
newc->defresult = transformExpr(pstate, defresult, domVal); newc->defresult = (Expr *) transformExpr(pstate, defresult, domVal);
/* /*
* Note: default result is considered the most significant * Note: default result is considered the most significant
@ -554,13 +556,14 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
* code worked before, but it seems a little bogus to me * code worked before, but it seems a little bogus to me
* --- tgl * --- tgl
*/ */
typeids = lconsi(exprType(newc->defresult), typeids); typeids = lconsi(exprType((Node *) newc->defresult), typeids);
ptype = select_common_type(typeids, "CASE"); ptype = select_common_type(typeids, "CASE");
newc->casetype = ptype; newc->casetype = ptype;
/* Convert default result clause, if necessary */ /* Convert default result clause, if necessary */
newc->defresult = coerce_to_common_type(newc->defresult, newc->defresult = (Expr *)
coerce_to_common_type((Node *) newc->defresult,
ptype, ptype,
"CASE/ELSE"); "CASE/ELSE");
@ -569,7 +572,8 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
{ {
CaseWhen *w = (CaseWhen *) lfirst(args); CaseWhen *w = (CaseWhen *) lfirst(args);
w->result = coerce_to_common_type(w->result, w->result = (Expr *)
coerce_to_common_type((Node *) w->result,
ptype, ptype,
"CASE/WHEN"); "CASE/WHEN");
} }
@ -582,7 +586,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
{ {
NullTest *n = (NullTest *) expr; 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 */ /* the argument can be any type, so don't coerce it */
result = expr; result = expr;
break; break;
@ -619,9 +623,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
clausename = NULL; /* keep compiler quiet */ 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; result = expr;
break; break;
@ -885,36 +889,39 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
Oid Oid
exprType(Node *expr) exprType(Node *expr)
{ {
Oid type = (Oid) InvalidOid; Oid type;
if (!expr) if (!expr)
return type; return InvalidOid;
switch (nodeTag(expr)) switch (nodeTag(expr))
{ {
case T_Var: case T_Var:
type = ((Var *) expr)->vartype; type = ((Var *) expr)->vartype;
break; break;
case T_Expr:
type = ((Expr *) expr)->typeOid;
break;
case T_Const: case T_Const:
type = ((Const *) expr)->consttype; type = ((Const *) expr)->consttype;
break; break;
case T_ArrayRef:
type = ((ArrayRef *) expr)->refrestype;
break;
case T_Aggref:
type = ((Aggref *) expr)->aggtype;
break;
case T_Param: case T_Param:
type = ((Param *) expr)->paramtype; type = ((Param *) expr)->paramtype;
break; break;
case T_FieldSelect: case T_Aggref:
type = ((FieldSelect *) expr)->resulttype; type = ((Aggref *) expr)->aggtype;
break; break;
case T_RelabelType: case T_ArrayRef:
type = ((RelabelType *) expr)->resulttype; type = ((ArrayRef *) expr)->refrestype;
break;
case T_FuncExpr:
type = ((FuncExpr *) expr)->funcresulttype;
break;
case T_OpExpr:
type = ((OpExpr *) expr)->opresulttype;
break;
case T_DistinctExpr:
type = ((DistinctExpr *) expr)->opresulttype;
break;
case T_BoolExpr:
type = BOOLOID;
break; break;
case T_SubLink: case T_SubLink:
{ {
@ -938,11 +945,17 @@ exprType(Node *expr)
} }
} }
break; break;
case T_FieldSelect:
type = ((FieldSelect *) expr)->resulttype;
break;
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;
case T_CaseExpr: case T_CaseExpr:
type = ((CaseExpr *) expr)->casetype; type = ((CaseExpr *) expr)->casetype;
break; break;
case T_CaseWhen: case T_CaseWhen:
type = exprType(((CaseWhen *) expr)->result); type = exprType((Node *) ((CaseWhen *) expr)->result);
break; break;
case T_NullTest: case T_NullTest:
type = BOOLOID; type = BOOLOID;
@ -951,7 +964,7 @@ exprType(Node *expr)
type = BOOLOID; type = BOOLOID;
break; break;
case T_ConstraintTest: case T_ConstraintTest:
type = exprType(((ConstraintTest *) expr)->arg); type = exprType((Node *) ((ConstraintTest *) expr)->arg);
break; break;
case T_ConstraintTestValue: case T_ConstraintTestValue:
type = ((ConstraintTestValue *) expr)->typeId; type = ((ConstraintTestValue *) expr)->typeId;
@ -959,6 +972,7 @@ exprType(Node *expr)
default: default:
elog(ERROR, "exprType: Do not know how to get type for %d node", elog(ERROR, "exprType: Do not know how to get type for %d node",
nodeTag(expr)); nodeTag(expr));
type = InvalidOid; /* keep compiler quiet */
break; break;
} }
return type; return type;
@ -995,7 +1009,7 @@ exprTypmod(Node *expr)
} }
} }
break; break;
case T_Expr: case T_FuncExpr:
{ {
int32 coercedTypmod; int32 coercedTypmod;
@ -1021,9 +1035,9 @@ exprTypmod(Node *expr)
if (!cexpr->defresult) if (!cexpr->defresult)
return -1; return -1;
if (exprType(cexpr->defresult) != casetype) if (exprType((Node *) cexpr->defresult) != casetype)
return -1; return -1;
typmod = exprTypmod(cexpr->defresult); typmod = exprTypmod((Node *) cexpr->defresult);
if (typmod < 0) if (typmod < 0)
return -1; /* no point in trying harder */ return -1; /* no point in trying harder */
foreach(arg, cexpr->args) foreach(arg, cexpr->args)
@ -1031,16 +1045,16 @@ exprTypmod(Node *expr)
CaseWhen *w = (CaseWhen *) lfirst(arg); CaseWhen *w = (CaseWhen *) lfirst(arg);
Assert(IsA(w, CaseWhen)); Assert(IsA(w, CaseWhen));
if (exprType(w->result) != casetype) if (exprType((Node *) w->result) != casetype)
return -1; return -1;
if (exprTypmod(w->result) != typmod) if (exprTypmod((Node *) w->result) != typmod)
return -1; return -1;
} }
return typmod; return typmod;
} }
break; break;
case T_ConstraintTest: case T_ConstraintTest:
return exprTypmod(((ConstraintTest *) expr)->arg); return exprTypmod((Node *) ((ConstraintTest *) expr)->arg);
default: default:
break; break;
@ -1059,7 +1073,7 @@ exprTypmod(Node *expr)
bool bool
exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
{ {
Func *func; FuncExpr *func;
int nargs; int nargs;
Const *second_arg; Const *second_arg;
@ -1067,12 +1081,9 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
*coercedTypmod = -1; /* default result on failure */ *coercedTypmod = -1; /* default result on failure */
/* Is it a function-call at all? */ /* Is it a function-call at all? */
if (expr == NULL || if (expr == NULL || !IsA(expr, FuncExpr))
!IsA(expr, Expr) ||
((Expr *) expr)->opType != FUNC_EXPR)
return false; return false;
func = (Func *) (((Expr *) expr)->oper); func = (FuncExpr *) expr;
Assert(IsA(func, Func));
/* /*
* If it didn't come from a coercion context, reject. * If it didn't come from a coercion context, reject.
@ -1086,11 +1097,11 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
* argument being an int4 constant, it can't have been created from a * argument being an int4 constant, it can't have been created from a
* length coercion (it must be a type coercion, instead). * length coercion (it must be a type coercion, instead).
*/ */
nargs = length(((Expr *) expr)->args); nargs = length(func->args);
if (nargs < 2 || nargs > 3) if (nargs < 2 || nargs > 3)
return false; return false;
second_arg = (Const *) lsecond(((Expr *) expr)->args); second_arg = (Const *) lsecond(func->args);
if (!IsA(second_arg, Const) || if (!IsA(second_arg, Const) ||
second_arg->consttype != INT4OID || second_arg->consttype != INT4OID ||
second_arg->constisnull) second_arg->constisnull)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -315,21 +315,15 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
/* build the appropriate output structure */ /* build the appropriate output structure */
if (fdresult == FUNCDETAIL_NORMAL) if (fdresult == FUNCDETAIL_NORMAL)
{ {
Expr *expr = makeNode(Expr); FuncExpr *funcexpr = makeNode(FuncExpr);
Func *funcnode = makeNode(Func);
funcnode->funcid = funcid; funcexpr->funcid = funcid;
funcnode->funcresulttype = rettype; funcexpr->funcresulttype = rettype;
funcnode->funcretset = retset; funcexpr->funcretset = retset;
funcnode->funcformat = COERCE_EXPLICIT_CALL; funcexpr->funcformat = COERCE_EXPLICIT_CALL;
funcnode->func_fcache = NULL; funcexpr->args = fargs;
expr->typeOid = rettype; retval = (Node *) funcexpr;
expr->opType = FUNC_EXPR;
expr->oper = (Node *) funcnode;
expr->args = fargs;
retval = (Node *) expr;
} }
else else
{ {
@ -1182,7 +1176,7 @@ setup_field_select(Node *input, char *attname, Oid relid)
elog(ERROR, "Relation \"%s\" has no column \"%s\"", elog(ERROR, "Relation \"%s\" has no column \"%s\"",
get_rel_name(relid), attname); get_rel_name(relid), attname);
fselect->arg = input; fselect->arg = (Expr *) input;
fselect->fieldnum = attno; fselect->fieldnum = attno;
fselect->resulttype = get_atttype(relid, attno); fselect->resulttype = get_atttype(relid, attno);
fselect->resulttypmod = get_atttypmod(relid, attno); fselect->resulttypmod = get_atttypmod(relid, attno);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -89,10 +89,9 @@ make_op(List *opname, Node *ltree, Node *rtree)
rtypeId; rtypeId;
Operator tup; Operator tup;
Form_pg_operator opform; Form_pg_operator opform;
Oper *newop;
Node *left, Node *left,
*right; *right;
Expr *result; OpExpr *result;
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree); ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree); rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
@ -124,15 +123,11 @@ make_op(List *opname, Node *ltree, Node *rtree)
right = make_operand(rtree, rtypeId, opform->oprright); right = make_operand(rtree, rtypeId, opform->oprright);
} }
newop = makeOper(oprid(tup), /* opno */ result = makeNode(OpExpr);
InvalidOid, /* opid */ result->opno = oprid(tup);
opform->oprresult, /* opresulttype */ result->opfuncid = InvalidOid;
get_func_retset(opform->oprcode)); /* opretset */ result->opresulttype = opform->oprresult;
result->opretset = get_func_retset(opform->oprcode);
result = makeNode(Expr);
result->typeOid = opform->oprresult;
result->opType = OP_EXPR;
result->oper = (Node *) newop;
if (!left) if (!left)
result->args = makeList1(right); result->args = makeList1(right);
@ -143,7 +138,7 @@ make_op(List *opname, Node *ltree, Node *rtree)
ReleaseSysCache(tup); ReleaseSysCache(tup);
return result; return (Expr *) result;
} /* make_op() */ } /* make_op() */
@ -343,8 +338,8 @@ transformArraySubscripts(ParseState *pstate,
aref->refelemalign = type_struct_element->typalign; aref->refelemalign = type_struct_element->typalign;
aref->refupperindexpr = upperIndexpr; aref->refupperindexpr = upperIndexpr;
aref->reflowerindexpr = lowerIndexpr; aref->reflowerindexpr = lowerIndexpr;
aref->refexpr = arrayBase; aref->refexpr = (Expr *) arrayBase;
aref->refassgnexpr = assignFrom; aref->refassgnexpr = (Expr *) assignFrom;
ReleaseSysCache(type_tuple_array); ReleaseSysCache(type_tuple_array);
ReleaseSysCache(type_tuple_element); ReleaseSysCache(type_tuple_element);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1452,7 +1452,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte)
exprTypmod(varnode), exprTypmod(varnode),
label, label,
false); false);
te->expr = varnode; te->expr = (Expr *) varnode;
te_list = lappend(te_list, te); te_list = lappend(te_list, te);
names = lnext(names); names = lnext(names);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -79,7 +79,7 @@ transformTargetEntry(ParseState *pstate,
colname, colname,
resjunk); resjunk);
return makeTargetEntry(resnode, expr); return makeTargetEntry(resnode, (Expr *) expr);
} }
@ -225,7 +225,7 @@ updateTargetListEntry(ParseState *pstate,
int attrno, int attrno,
List *indirection) 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 */ Oid attrtype; /* type of target column */
int32 attrtypmod; int32 attrtypmod;
Resdom *resnode = tle->resdom; Resdom *resnode = tle->resdom;
@ -277,8 +277,8 @@ updateTargetListEntry(ParseState *pstate,
attrtypmod, attrtypmod,
indirection, indirection,
pstate->p_is_insert, pstate->p_is_insert,
tle->expr); (Node *) tle->expr);
tle->expr = (Node *) aref; tle->expr = (Expr *) aref;
} }
else else
{ {
@ -289,7 +289,8 @@ updateTargetListEntry(ParseState *pstate,
*/ */
if (type_id != InvalidOid) if (type_id != InvalidOid)
{ {
tle->expr = coerce_to_target_type(tle->expr, type_id, tle->expr = (Expr *)
coerce_to_target_type((Node *) tle->expr, type_id,
attrtype, attrtypmod, attrtype, attrtypmod,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
@ -501,7 +502,7 @@ FigureColnameInternal(Node *node, char **name)
} }
break; break;
case T_CaseExpr: case T_CaseExpr:
strength = FigureColnameInternal(((CaseExpr *) node)->defresult, strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
name); name);
if (strength <= 1) if (strength <= 1)
{ {

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -304,7 +304,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
att_tup->atttypmod, att_tup->atttypmod,
pstrdup(NameStr(att_tup->attname)), pstrdup(NameStr(att_tup->attname)),
false), false),
new_expr); (Expr *) new_expr);
} }
if (new_tle) if (new_tle)
@ -389,10 +389,10 @@ process_matched_tle(TargetEntry *src_tle,
* Prior TLE could be a nest of ArrayRefs if we do this more than * Prior TLE could be a nest of ArrayRefs if we do this more than
* once. * once.
*/ */
priorbottom = ((ArrayRef *) prior_tle->expr)->refexpr; priorbottom = (Node *) ((ArrayRef *) prior_tle->expr)->refexpr;
while (priorbottom != NULL && IsA(priorbottom, ArrayRef) && while (priorbottom != NULL && IsA(priorbottom, ArrayRef) &&
((ArrayRef *) priorbottom)->refassgnexpr != NULL) ((ArrayRef *) priorbottom)->refassgnexpr != NULL)
priorbottom = ((ArrayRef *) priorbottom)->refexpr; priorbottom = (Node *) ((ArrayRef *) priorbottom)->refexpr;
if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr)) if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr))
elog(ERROR, "Multiple assignments to same attribute \"%s\"", elog(ERROR, "Multiple assignments to same attribute \"%s\"",
resdom->resname); resdom->resname);
@ -404,7 +404,7 @@ process_matched_tle(TargetEntry *src_tle,
memcpy(newexpr, src_tle->expr, sizeof(ArrayRef)); memcpy(newexpr, src_tle->expr, sizeof(ArrayRef));
newexpr->refexpr = prior_tle->expr; newexpr->refexpr = prior_tle->expr;
return makeTargetEntry(resdom, (Node *) newexpr); return makeTargetEntry(resdom, (Expr *) newexpr);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -706,7 +706,7 @@ AddInvertedQual(Query *parsetree, Node *qual)
/* Need not copy input qual, because AddQual will... */ /* Need not copy input qual, because AddQual will... */
invqual = makeNode(BooleanTest); invqual = makeNode(BooleanTest);
invqual->arg = qual; invqual->arg = (Expr *) qual;
invqual->booltesttype = IS_NOT_TRUE; invqual->booltesttype = IS_NOT_TRUE;
AddQual(parsetree, (Node *) invqual); AddQual(parsetree, (Node *) invqual);
@ -724,7 +724,7 @@ FindMatchingNew(List *tlist, int attno)
TargetEntry *tle = lfirst(i); TargetEntry *tle = lfirst(i);
if (tle->resdom->resno == attno) if (tle->resdom->resno == attno)
return tle->expr; return (Node *) tle->expr;
} }
return NULL; return NULL;
} }

View File

@ -17,7 +17,7 @@
* *
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 $
* *
* ---------- * ----------
*/ */
@ -35,6 +35,7 @@
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "executor/spi_priv.h" #include "executor/spi_priv.h"
#include "optimizer/planmain.h"
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "miscadmin.h" #include "miscadmin.h"
@ -2747,6 +2748,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
nth(defval[j].adnum - 1, nth(defval[j].adnum - 1,
spi_plan->targetlist); spi_plan->targetlist);
spi_qptle->expr = stringToNode(defval[j].adbin); spi_qptle->expr = stringToNode(defval[j].adbin);
fix_opfuncids((Node *) spi_qptle->expr);
break; break;
} }
@ -3037,6 +3039,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
nth(defval[j].adnum - 1, nth(defval[j].adnum - 1,
spi_plan->targetlist); spi_plan->targetlist);
spi_qptle->expr = stringToNode(defval[j].adbin); spi_qptle->expr = stringToNode(defval[j].adbin);
fix_opfuncids((Node *) spi_qptle->expr);
break; break;
} }

View File

@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -149,13 +149,13 @@ static RangeTblEntry *find_rte_by_refname(const char *refname,
deparse_context *context); deparse_context *context);
static void get_rule_expr(Node *node, deparse_context *context, static void get_rule_expr(Node *node, deparse_context *context,
bool showimplicit); bool showimplicit);
static void get_oper_expr(Expr *expr, deparse_context *context); static void get_oper_expr(OpExpr *expr, deparse_context *context);
static void get_func_expr(Expr *expr, deparse_context *context, static void get_func_expr(FuncExpr *expr, deparse_context *context,
bool showimplicit); bool showimplicit);
static void get_agg_expr(Aggref *aggref, deparse_context *context); static void get_agg_expr(Aggref *aggref, deparse_context *context);
static Node *strip_type_coercion(Node *expr, Oid resultType); static Node *strip_type_coercion(Node *expr, Oid resultType);
static void get_const_expr(Const *constval, deparse_context *context); 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(Query *query, deparse_context *context);
static void get_from_clause_item(Node *jtnode, Query *query, static void get_from_clause_item(Node *jtnode, Query *query,
deparse_context *context); deparse_context *context);
@ -1434,7 +1434,7 @@ get_basic_select_query(Query *query, deparse_context *context,
sep = ", "; sep = ", ";
colno++; 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 * Figure out what the result column should be called. In the
@ -1565,7 +1565,7 @@ get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno,
Node *expr; Node *expr;
tle = get_sortgroupclause_tle(srt, tlist); 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 * Use column-number form if requested by caller or if expression is a
@ -1647,7 +1647,7 @@ get_insert_query_def(Query *query, deparse_context *context)
appendStringInfo(buf, sep); appendStringInfo(buf, sep);
sep = ", "; sep = ", ";
get_rule_expr(tle->expr, context, false); get_rule_expr((Node *) tle->expr, context, false);
} }
appendStringInfoChar(buf, ')'); appendStringInfoChar(buf, ')');
} }
@ -1697,7 +1697,7 @@ get_update_query_def(Query *query, deparse_context *context)
if (!tleIsArrayAssign(tle)) if (!tleIsArrayAssign(tle))
appendStringInfo(buf, "%s = ", appendStringInfo(buf, "%s = ",
quote_identifier(tle->resdom->resname)); 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 */ /* Add the FROM clause if needed */
@ -1924,10 +1924,6 @@ get_rule_expr(Node *node, deparse_context *context,
*/ */
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Const:
get_const_expr((Const *) node, context);
break;
case T_Var: case T_Var:
{ {
Var *var = (Var *) node; Var *var = (Var *) node;
@ -1958,82 +1954,26 @@ get_rule_expr(Node *node, deparse_context *context,
} }
break; break;
case T_Expr: case T_Const:
get_const_expr((Const *) node, context);
break;
case T_Param:
{ {
Expr *expr = (Expr *) node; Param *param = (Param *) node;
List *args = expr->args;
/* switch (param->paramkind)
* Expr nodes have to be handled a bit detailed
*/
switch (expr->opType)
{ {
case OP_EXPR: case PARAM_NAMED:
get_oper_expr(expr, context); appendStringInfo(buf, "$%s", param->paramname);
break; break;
case PARAM_NUM:
case DISTINCT_EXPR: case PARAM_EXEC:
appendStringInfoChar(buf, '('); appendStringInfo(buf, "$%d", param->paramid);
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; 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, ')');
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)");
break;
default: default:
elog(ERROR, "get_rule_expr: expr opType %d not supported", appendStringInfo(buf, "(param)");
expr->opType); break;
} }
} }
break; break;
@ -2058,7 +1998,7 @@ get_rule_expr(Node *node, deparse_context *context,
*/ */
if (aref->refassgnexpr) if (aref->refassgnexpr)
context->varprefix = false; context->varprefix = false;
get_rule_expr(aref->refexpr, context, showimplicit); get_rule_expr((Node *) aref->refexpr, context, showimplicit);
context->varprefix = savevarprefix; context->varprefix = savevarprefix;
lowlist = aref->reflowerindexpr; lowlist = aref->reflowerindexpr;
foreach(uplist, aref->refupperindexpr) foreach(uplist, aref->refupperindexpr)
@ -2077,15 +2017,103 @@ get_rule_expr(Node *node, deparse_context *context,
if (aref->refassgnexpr) if (aref->refassgnexpr)
{ {
appendStringInfo(buf, " = "); appendStringInfo(buf, " = ");
get_rule_expr(aref->refassgnexpr, context, showimplicit); get_rule_expr((Node *) aref->refassgnexpr, context,
showimplicit);
} }
} }
break; 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: case T_FieldSelect:
{ {
FieldSelect *fselect = (FieldSelect *) node; FieldSelect *fselect = (FieldSelect *) node;
Oid argType = exprType(fselect->arg); Oid argType = exprType((Node *) fselect->arg);
Oid typrelid; Oid typrelid;
char *fieldname; char *fieldname;
@ -2103,7 +2131,7 @@ get_rule_expr(Node *node, deparse_context *context,
* are *not* simple. So, always use parenthesized syntax. * are *not* simple. So, always use parenthesized syntax.
*/ */
appendStringInfoChar(buf, '('); appendStringInfoChar(buf, '(');
get_rule_expr(fselect->arg, context, true); get_rule_expr((Node *) fselect->arg, context, true);
appendStringInfo(buf, ").%s", quote_identifier(fieldname)); appendStringInfo(buf, ").%s", quote_identifier(fieldname));
} }
break; break;
@ -2111,7 +2139,7 @@ get_rule_expr(Node *node, deparse_context *context,
case T_RelabelType: case T_RelabelType:
{ {
RelabelType *relabel = (RelabelType *) node; RelabelType *relabel = (RelabelType *) node;
Node *arg = relabel->arg; Node *arg = (Node *) relabel->arg;
if (relabel->relabelformat == COERCE_IMPLICIT_CAST && if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
!showimplicit) !showimplicit)
@ -2149,12 +2177,12 @@ get_rule_expr(Node *node, deparse_context *context,
CaseWhen *when = (CaseWhen *) lfirst(temp); CaseWhen *when = (CaseWhen *) lfirst(temp);
appendStringInfo(buf, " WHEN "); appendStringInfo(buf, " WHEN ");
get_rule_expr(when->expr, context, false); get_rule_expr((Node *) when->expr, context, false);
appendStringInfo(buf, " THEN "); appendStringInfo(buf, " THEN ");
get_rule_expr(when->result, context, true); get_rule_expr((Node *) when->result, context, true);
} }
appendStringInfo(buf, " ELSE "); appendStringInfo(buf, " ELSE ");
get_rule_expr(caseexpr->defresult, context, true); get_rule_expr((Node *) caseexpr->defresult, context, true);
appendStringInfo(buf, " END"); appendStringInfo(buf, " END");
} }
break; break;
@ -2164,7 +2192,7 @@ get_rule_expr(Node *node, deparse_context *context,
NullTest *ntest = (NullTest *) node; NullTest *ntest = (NullTest *) node;
appendStringInfo(buf, "("); appendStringInfo(buf, "(");
get_rule_expr(ntest->arg, context, true); get_rule_expr((Node *) ntest->arg, context, true);
switch (ntest->nulltesttype) switch (ntest->nulltesttype)
{ {
case IS_NULL: case IS_NULL:
@ -2185,7 +2213,7 @@ get_rule_expr(Node *node, deparse_context *context,
BooleanTest *btest = (BooleanTest *) node; BooleanTest *btest = (BooleanTest *) node;
appendStringInfo(buf, "("); appendStringInfo(buf, "(");
get_rule_expr(btest->arg, context, false); get_rule_expr((Node *) btest->arg, context, false);
switch (btest->booltesttype) switch (btest->booltesttype)
{ {
case IS_TRUE: case IS_TRUE:
@ -2221,38 +2249,12 @@ get_rule_expr(Node *node, deparse_context *context,
* We assume that the operations of the constraint node * We assume that the operations of the constraint node
* need not be explicitly represented in the output. * need not be explicitly represented in the output.
*/ */
get_rule_expr(ctest->arg, context, showimplicit); get_rule_expr((Node *) ctest->arg, context, showimplicit);
} }
break; break;
case T_ConstraintTestValue: case T_ConstraintTestValue:
{
appendStringInfo(buf, "VALUE"); 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;
}
}
break; break;
default: default:
@ -2263,13 +2265,13 @@ get_rule_expr(Node *node, deparse_context *context,
/* /*
* get_oper_expr - Parse back an Oper node * get_oper_expr - Parse back an OpExpr node
*/ */
static void static void
get_oper_expr(Expr *expr, deparse_context *context) get_oper_expr(OpExpr *expr, deparse_context *context)
{ {
StringInfo buf = context->buf; StringInfo buf = context->buf;
Oid opno = ((Oper *) expr->oper)->opno; Oid opno = expr->opno;
List *args = expr->args; List *args = expr->args;
appendStringInfoChar(buf, '('); appendStringInfoChar(buf, '(');
@ -2324,15 +2326,14 @@ get_oper_expr(Expr *expr, deparse_context *context)
} }
/* /*
* get_func_expr - Parse back a Func node * get_func_expr - Parse back a FuncExpr node
*/ */
static void static void
get_func_expr(Expr *expr, deparse_context *context, get_func_expr(FuncExpr *expr, deparse_context *context,
bool showimplicit) bool showimplicit)
{ {
StringInfo buf = context->buf; StringInfo buf = context->buf;
Func *func = (Func *) (expr->oper); Oid funcoid = expr->funcid;
Oid funcoid = func->funcid;
Oid argtypes[FUNC_MAX_ARGS]; Oid argtypes[FUNC_MAX_ARGS];
int nargs; int nargs;
List *l; List *l;
@ -2342,7 +2343,7 @@ get_func_expr(Expr *expr, deparse_context *context,
* If the function call came from an implicit coercion, then just show * If the function call came from an implicit coercion, then just show
* the first argument --- unless caller wants to see implicit coercions. * 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); get_rule_expr((Node *) lfirst(expr->args), context, showimplicit);
return; return;
@ -2352,11 +2353,11 @@ get_func_expr(Expr *expr, deparse_context *context,
* If the function call came from a cast, then show * If the function call came from a cast, then show
* the first argument plus an explicit cast operation. * the first argument plus an explicit cast operation.
*/ */
if (func->funcformat == COERCE_EXPLICIT_CAST || if (expr->funcformat == COERCE_EXPLICIT_CAST ||
func->funcformat == COERCE_IMPLICIT_CAST) expr->funcformat == COERCE_IMPLICIT_CAST)
{ {
Node *arg = lfirst(expr->args); Node *arg = lfirst(expr->args);
Oid rettype = expr->typeOid; Oid rettype = expr->funcresulttype;
int32 coercedTypmod; int32 coercedTypmod;
/* Get the typmod if this is a length-coercion function */ /* Get the typmod if this is a length-coercion function */
@ -2410,7 +2411,7 @@ static void
get_agg_expr(Aggref *aggref, deparse_context *context) get_agg_expr(Aggref *aggref, deparse_context *context)
{ {
StringInfo buf = context->buf; StringInfo buf = context->buf;
Oid argtype = exprType(aggref->target); Oid argtype = exprType((Node *) aggref->target);
appendStringInfo(buf, "%s(%s", appendStringInfo(buf, "%s(%s",
generate_function_name(aggref->aggfnoid, 1, &argtype), generate_function_name(aggref->aggfnoid, 1, &argtype),
@ -2418,7 +2419,7 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
if (aggref->aggstar) if (aggref->aggstar)
appendStringInfo(buf, "*"); appendStringInfo(buf, "*");
else else
get_rule_expr(aggref->target, context, true); get_rule_expr((Node *) aggref->target, context, true);
appendStringInfoChar(buf, ')'); appendStringInfoChar(buf, ')');
} }
@ -2442,14 +2443,12 @@ strip_type_coercion(Node *expr, Oid resultType)
if (IsA(expr, RelabelType) && if (IsA(expr, RelabelType) &&
((RelabelType *) expr)->resulttypmod == -1) ((RelabelType *) expr)->resulttypmod == -1)
return ((RelabelType *) expr)->arg; return (Node *) ((RelabelType *) expr)->arg;
if (IsA(expr, Expr) && if (IsA(expr, FuncExpr))
((Expr *) expr)->opType == FUNC_EXPR)
{ {
Func *func = (Func *) (((Expr *) expr)->oper); FuncExpr *func = (FuncExpr *) expr;
Assert(IsA(func, Func));
if (func->funcformat != COERCE_EXPLICIT_CAST && if (func->funcformat != COERCE_EXPLICIT_CAST &&
func->funcformat != COERCE_IMPLICIT_CAST) func->funcformat != COERCE_IMPLICIT_CAST)
return expr; /* don't absorb into upper coercion */ return expr; /* don't absorb into upper coercion */
@ -2457,7 +2456,7 @@ strip_type_coercion(Node *expr, Oid resultType)
if (exprIsLengthCoercion(expr, NULL)) if (exprIsLengthCoercion(expr, NULL))
return expr; return expr;
return (Node *) lfirst(((Expr *) expr)->args); return (Node *) lfirst(func->args);
} }
return expr; return expr;
@ -2609,14 +2608,13 @@ get_const_expr(Const *constval, deparse_context *context)
* ---------- * ----------
*/ */
static void static void
get_sublink_expr(Node *node, deparse_context *context) get_sublink_expr(SubLink *sublink, deparse_context *context)
{ {
StringInfo buf = context->buf; StringInfo buf = context->buf;
SubLink *sublink = (SubLink *) node;
Query *query = (Query *) (sublink->subselect); Query *query = (Query *) (sublink->subselect);
List *l; List *l;
char *sep; char *sep;
Oper *oper; OpExpr *oper;
bool need_paren; bool need_paren;
appendStringInfoChar(buf, '('); appendStringInfoChar(buf, '(');
@ -2657,17 +2655,17 @@ get_sublink_expr(Node *node, deparse_context *context)
break; break;
case ANY_SUBLINK: case ANY_SUBLINK:
oper = (Oper *) lfirst(sublink->oper); oper = (OpExpr *) lfirst(sublink->oper);
appendStringInfo(buf, "%s ANY ", get_opname(oper->opno)); appendStringInfo(buf, "%s ANY ", get_opname(oper->opno));
break; break;
case ALL_SUBLINK: case ALL_SUBLINK:
oper = (Oper *) lfirst(sublink->oper); oper = (OpExpr *) lfirst(sublink->oper);
appendStringInfo(buf, "%s ALL ", get_opname(oper->opno)); appendStringInfo(buf, "%s ALL ", get_opname(oper->opno));
break; break;
case MULTIEXPR_SUBLINK: case MULTIEXPR_SUBLINK:
oper = (Oper *) lfirst(sublink->oper); oper = (OpExpr *) lfirst(sublink->oper);
appendStringInfo(buf, "%s ", get_opname(oper->opno)); appendStringInfo(buf, "%s ", get_opname(oper->opno));
break; break;

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1025,7 +1025,7 @@ booltestsel(Query *root, BoolTestType booltesttype, Node *arg, int varRelid)
* can't hurt) * can't hurt)
*/ */
if (IsA(arg, RelabelType)) if (IsA(arg, RelabelType))
arg = ((RelabelType *) arg)->arg; arg = (Node *) ((RelabelType *) arg)->arg;
if (IsA(arg, Var) &&(varRelid == 0 || varRelid == ((Var *) arg)->varno)) if (IsA(arg, Var) &&(varRelid == 0 || varRelid == ((Var *) arg)->varno))
var = (Var *) arg; var = (Var *) arg;
@ -1246,7 +1246,7 @@ nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid)
* Ignore any binary-compatible relabeling * Ignore any binary-compatible relabeling
*/ */
if (IsA(arg, RelabelType)) if (IsA(arg, RelabelType))
arg = ((RelabelType *) arg)->arg; arg = (Node *) ((RelabelType *) arg)->arg;
if (IsA(arg, Var) && if (IsA(arg, Var) &&
(varRelid == 0 || varRelid == ((Var *) arg)->varno)) (varRelid == 0 || varRelid == ((Var *) arg)->varno))
@ -1753,14 +1753,15 @@ mergejoinscansel(Query *root, Node *clause,
/* Deconstruct the merge clause */ /* Deconstruct the merge clause */
if (!is_opclause(clause)) if (!is_opclause(clause))
return; /* shouldn't happen */ return; /* shouldn't happen */
opno = ((Oper *) ((Expr *) clause)->oper)->opno; opno = ((OpExpr *) clause)->opno;
left = get_leftop((Expr *) clause); left = get_leftop((Expr *) clause);
right = get_rightop((Expr *) clause); right = get_rightop((Expr *) clause);
if (!right) if (!right)
return; /* shouldn't happen */ return; /* shouldn't happen */
/* Can't do anything if inputs are not Vars */ /* Can't do anything if inputs are not Vars */
if (!IsA(left, Var) ||!IsA(right, Var)) if (!IsA(left, Var) ||
!IsA(right, Var))
return; return;
/* Verify mergejoinability and get left and right "<" operators */ /* Verify mergejoinability and get left and right "<" operators */
@ -2842,9 +2843,9 @@ get_restriction_var(List *args,
/* Ignore any binary-compatible relabeling */ /* Ignore any binary-compatible relabeling */
if (IsA(left, RelabelType)) if (IsA(left, RelabelType))
left = ((RelabelType *) left)->arg; left = (Node *) ((RelabelType *) left)->arg;
if (IsA(right, RelabelType)) if (IsA(right, RelabelType))
right = ((RelabelType *) right)->arg; right = (Node *) ((RelabelType *) right)->arg;
/* Look for the var */ /* Look for the var */
@ -2895,9 +2896,9 @@ get_join_vars(List *args, Var **var1, Var **var2)
/* Ignore any binary-compatible relabeling */ /* Ignore any binary-compatible relabeling */
if (IsA(left, RelabelType)) if (IsA(left, RelabelType))
left = ((RelabelType *) left)->arg; left = (Node *) ((RelabelType *) left)->arg;
if (IsA(right, RelabelType)) if (IsA(right, RelabelType))
right = ((RelabelType *) right)->arg; right = (Node *) ((RelabelType *) right)->arg;
if (IsA(left, Var)) if (IsA(left, Var))
*var1 = (Var *) left; *var1 = (Var *) left;

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200212061 #define CATALOG_VERSION_NO 200212101
#endif #endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -16,7 +16,7 @@
#include "nodes/execnodes.h" #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, extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext,
bool *isNull); bool *isNull);
extern void ExecEndSubPlan(SubPlanState *node); extern void ExecEndSubPlan(SubPlanState *node);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -22,18 +22,13 @@ extern A_Expr *makeA_Expr(int oper, List *name, Node *lexpr, Node *rexpr);
extern A_Expr *makeSimpleA_Expr(int oper, const char *name, extern A_Expr *makeSimpleA_Expr(int oper, const char *name,
Node *lexpr, Node *rexpr); Node *lexpr, Node *rexpr);
extern Oper *makeOper(Oid opno,
Oid opid,
Oid opresulttype,
bool opretset);
extern Var *makeVar(Index varno, extern Var *makeVar(Index varno,
AttrNumber varattno, AttrNumber varattno,
Oid vartype, Oid vartype,
int32 vartypmod, int32 vartypmod,
Index varlevelsup); Index varlevelsup);
extern TargetEntry *makeTargetEntry(Resdom *resdom, Node *expr); extern TargetEntry *makeTargetEntry(Resdom *resdom, Expr *expr);
extern Resdom *makeResdom(AttrNumber resno, extern Resdom *makeResdom(AttrNumber resno,
Oid restype, Oid restype,
@ -49,9 +44,11 @@ extern Const *makeConst(Oid consttype,
extern Const *makeNullConst(Oid consttype); extern Const *makeNullConst(Oid consttype);
extern Expr *makeBoolExpr(BoolExprType boolop, List *args);
extern Alias *makeAlias(const char *aliasname, List *colnames); 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); CoercionForm rformat);
extern RangeVar *makeRangeVar(char *schemaname, char *relname); extern RangeVar *makeRangeVar(char *schemaname, char *relname);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,6 +19,6 @@
extern bool single_node(Node *node); extern bool single_node(Node *node);
extern bool var_is_outer(Var *var); extern bool var_is_outer(Var *var);
extern bool var_is_rel(Var *var); extern bool var_is_rel(Var *var);
extern Oper *replace_opid(Oper *oper); extern void set_opfuncid(OpExpr *opexpr);
#endif /* NODEFUNCS_H */ #endif /* NODEFUNCS_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -62,7 +62,6 @@ typedef enum NodeTag
T_Hash, T_Hash,
T_SetOp, T_SetOp,
T_Limit, T_Limit,
T_SubPlan,
/* /*
* TAGS FOR PLAN STATE NODES (execnodes.h) * TAGS FOR PLAN STATE NODES (execnodes.h)
@ -96,21 +95,32 @@ typedef enum NodeTag
* TAGS FOR PRIMITIVE NODES (primnodes.h) * TAGS FOR PRIMITIVE NODES (primnodes.h)
*/ */
T_Resdom = 300, T_Resdom = 300,
T_Fjoin, T_Alias,
T_RangeVar,
T_Expr, T_Expr,
T_Var, T_Var,
T_Oper,
T_Const, T_Const,
T_Param, T_Param,
T_Aggref, T_Aggref,
T_SubLink,
T_Func,
T_FieldSelect,
T_ArrayRef, T_ArrayRef,
T_FuncExpr,
T_OpExpr,
T_DistinctExpr,
T_BoolExpr,
T_SubLink,
T_SubPlanExpr,
T_FieldSelect,
T_RelabelType, T_RelabelType,
T_CaseExpr,
T_CaseWhen,
T_NullTest,
T_BooleanTest,
T_ConstraintTest,
T_ConstraintTestValue,
T_TargetEntry,
T_RangeTblRef, T_RangeTblRef,
T_FromExpr,
T_JoinExpr, T_JoinExpr,
T_FromExpr,
/* /*
* TAGS FOR PLANNER NODES (relation.h) * TAGS FOR PLANNER NODES (relation.h)
@ -183,7 +193,6 @@ typedef enum NodeTag
T_ViewStmt, T_ViewStmt,
T_LoadStmt, T_LoadStmt,
T_CreateDomainStmt, T_CreateDomainStmt,
T_DomainConstraintValue,
T_CreatedbStmt, T_CreatedbStmt,
T_DropdbStmt, T_DropdbStmt,
T_VacuumStmt, T_VacuumStmt,
@ -228,30 +237,22 @@ typedef enum NodeTag
T_ResTarget, T_ResTarget,
T_TypeCast, T_TypeCast,
T_SortGroupBy, T_SortGroupBy,
T_Alias,
T_RangeVar,
T_RangeSubselect, T_RangeSubselect,
T_RangeFunction, T_RangeFunction,
T_TypeName, T_TypeName,
T_IndexElem,
T_ColumnDef, T_ColumnDef,
T_IndexElem,
T_Constraint, T_Constraint,
T_DefElem, T_DefElem,
T_TargetEntry,
T_RangeTblEntry, T_RangeTblEntry,
T_SortClause, T_SortClause,
T_GroupClause, T_GroupClause,
T_NullTest,
T_BooleanTest,
T_ConstraintTest,
T_ConstraintTestValue,
T_CaseExpr,
T_CaseWhen,
T_FkConstraint, T_FkConstraint,
T_PrivGrantee, T_PrivGrantee,
T_FuncWithArgs, T_FuncWithArgs,
T_PrivTarget, T_PrivTarget,
T_InsertDefault, T_InsertDefault,
T_DomainConstraintValue,
T_CreateOpClassItem, T_CreateOpClassItem,
T_CompositeTypeStmt, T_CompositeTypeStmt,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -34,7 +34,7 @@ typedef enum QuerySource
/* /*
* Query - * 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 * for further processing by the optimizer
* utility statements (i.e. non-optimizable statements) * utility statements (i.e. non-optimizable statements)
* have the *utilityStmt field set. * have the *utilityStmt field set.
@ -201,145 +201,6 @@ typedef struct TypeCast
TypeName *typename; /* the target type */ TypeName *typename; /* the target type */
} TypeCast; } 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 * FuncCall - a function or aggregate invocation
* *
@ -414,6 +275,15 @@ typedef struct InsertDefault
NodeTag type; NodeTag type;
} InsertDefault; } 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 * SortGroupBy - for ORDER BY clause
*/ */
@ -446,6 +316,40 @@ typedef struct RangeFunction
* assignment of RECORD TupleDesc */ * assignment of RECORD TupleDesc */
} RangeFunction; } 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) * IndexElem - index parameters (used in CREATE INDEX)
* *
@ -479,21 +383,6 @@ typedef struct DefElem
* Nodes for a Query tree * 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 - * RangeTblEntry -
* A range table is a List of RangeTblEntry nodes. * A range table is a List of RangeTblEntry nodes.

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -375,31 +375,4 @@ typedef struct Limit
Node *limitCount; /* COUNT parameter, or NULL if none */ Node *limitCount; /* COUNT parameter, or NULL if none */
} Limit; } 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 */ #endif /* PLANNODES_H */

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -67,31 +67,6 @@ typedef struct Resdom
* from final target list */ * from final target list */
} Resdom; } 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 - * Alias -
@ -140,96 +115,20 @@ typedef struct RangeVar
*/ */
/* /*
* 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 * All node types that are used in executable expression trees should derive
* allow more casts than earlier ones. * 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 typedef struct Expr
{ {
NodeTag type; 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; } Expr;
/* /*
* Oper - Expr subnode for an OP_EXPR (or DISTINCT_EXPR) * Var - expression node representing a variable (ie, a table column)
*
* 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
* *
* Note: during parsing/planning, varnoold/varoattno are always just copies * Note: during parsing/planning, varnoold/varoattno are always just copies
* of varno/varattno. At the tail end of planning, Var nodes appearing in * of varno/varattno. At the tail end of planning, Var nodes appearing in
@ -248,7 +147,7 @@ typedef struct Func
typedef struct Var typedef struct Var
{ {
NodeTag type; Expr xpr;
Index varno; /* index of this var's relation in the Index varno; /* index of this var's relation in the
* range table (could also be INNER or * range table (could also be INNER or
* OUTER) */ * OUTER) */
@ -272,7 +171,7 @@ typedef struct Var
*/ */
typedef struct Const typedef struct Const
{ {
NodeTag type; Expr xpr;
Oid consttype; /* PG_TYPE OID of the constant's datatype */ Oid consttype; /* PG_TYPE OID of the constant's datatype */
int constlen; /* typlen of the constant's datatype */ int constlen; /* typlen of the constant's datatype */
Datum constvalue; /* the constant's value */ Datum constvalue; /* the constant's value */
@ -300,12 +199,11 @@ typedef struct Const
* *
* PARAM_EXEC: The parameter is an internal executor parameter. * PARAM_EXEC: The parameter is an internal executor parameter.
* It has a number contained in the `paramid' field. * It has a number contained in the `paramid' field.
*
* ---------------- * ----------------
*/ */
typedef struct Param typedef struct Param
{ {
NodeTag type; Expr xpr;
int paramkind; /* kind of parameter. See above */ int paramkind; /* kind of parameter. See above */
AttrNumber paramid; /* numeric ID for parameter ("$1") */ AttrNumber paramid; /* numeric ID for parameter ("$1") */
char *paramname; /* name for parameter ("$.foo") */ char *paramname; /* name for parameter ("$.foo") */
@ -317,84 +215,17 @@ typedef struct Param
*/ */
typedef struct Aggref typedef struct Aggref
{ {
NodeTag type; Expr xpr;
Oid aggfnoid; /* pg_proc Oid of the aggregate */ Oid aggfnoid; /* pg_proc Oid of the aggregate */
Oid aggtype; /* type Oid of result 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 aggstar; /* TRUE if argument was really '*' */
bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */ bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */
/* XXX this should move to AggrefExprState: */
int aggno; /* workspace for executor (see nodeAgg.c) */ int aggno; /* workspace for executor (see nodeAgg.c) */
} Aggref; } Aggref;
/* ----------------
* SubLink
*
* A SubLink represents a subselect appearing in an expression, and in some
* cases also the combining operator(s) just above it. The subLinkType
* indicates the form of the expression represented:
* EXISTS_SUBLINK EXISTS(SELECT ...)
* ALL_SUBLINK (lefthand) op ALL (SELECT ...)
* ANY_SUBLINK (lefthand) op ANY (SELECT ...)
* MULTIEXPR_SUBLINK (lefthand) op (SELECT ...)
* EXPR_SUBLINK (SELECT with single targetlist item ...)
* For ALL, ANY, and MULTIEXPR, the lefthand is a list of expressions of the
* same length as the subselect's targetlist. MULTIEXPR will *always* have
* a list with more than one entry; if the subselect has just one target
* then the parser will create an EXPR_SUBLINK instead (and any operator
* above the subselect will be represented separately). Note that both
* MULTIEXPR and EXPR require the subselect to deliver only one row.
* ALL, ANY, and MULTIEXPR require the combining operators to deliver boolean
* results. These are reduced to one result per row using OR or AND semantics
* depending on the "useor" flag. ALL and ANY combine the per-row results
* using AND and OR semantics respectively.
*
* 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
* 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
* 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.
* The lefthand field is set to NIL, since its expressions are now in
* the Expr list. This representation is passed to the executor.
*
* 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.
*
* 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 enum SubLinkType
{
EXISTS_SUBLINK, ALL_SUBLINK, ANY_SUBLINK, MULTIEXPR_SUBLINK, EXPR_SUBLINK
} SubLinkType;
typedef struct SubLink
{
NodeTag type;
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 */
Node *subselect; /* subselect as Query* or parsetree */
} SubLink;
/* ---------------- /* ----------------
* ArrayRef: describes an array subscripting operation * ArrayRef: describes an array subscripting operation
* *
@ -424,7 +255,7 @@ typedef struct SubLink
*/ */
typedef struct ArrayRef typedef struct ArrayRef
{ {
NodeTag type; Expr xpr;
Oid refrestype; /* type of the result of the ArrayRef Oid refrestype; /* type of the result of the ArrayRef
* operation */ * operation */
int refattrlength; /* typlen of array type */ int refattrlength; /* typlen of array type */
@ -435,12 +266,207 @@ typedef struct ArrayRef
* array indexes */ * array indexes */
List *reflowerindexpr;/* expressions that evaluate to lower List *reflowerindexpr;/* expressions that evaluate to lower
* array indexes */ * array indexes */
Node *refexpr; /* the expression that evaluates to an Expr *refexpr; /* the expression that evaluates to an
* array value */ * array value */
Node *refassgnexpr; /* expression for the source value, or Expr *refassgnexpr; /* expression for the source value, or
* NULL if fetch */ * NULL if fetch */
} ArrayRef; } 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
*
* A SubLink represents a subselect appearing in an expression, and in some
* cases also the combining operator(s) just above it. The subLinkType
* indicates the form of the expression represented:
* EXISTS_SUBLINK EXISTS(SELECT ...)
* ALL_SUBLINK (lefthand) op ALL (SELECT ...)
* ANY_SUBLINK (lefthand) op ANY (SELECT ...)
* MULTIEXPR_SUBLINK (lefthand) op (SELECT ...)
* EXPR_SUBLINK (SELECT with single targetlist item ...)
* For ALL, ANY, and MULTIEXPR, the lefthand is a list of expressions of the
* same length as the subselect's targetlist. MULTIEXPR will *always* have
* a list with more than one entry; if the subselect has just one target
* then the parser will create an EXPR_SUBLINK instead (and any operator
* above the subselect will be represented separately). Note that both
* MULTIEXPR and EXPR require the subselect to deliver only one row.
* ALL, ANY, and MULTIEXPR require the combining operators to deliver boolean
* results. These are reduced to one result per row using OR or AND semantics
* 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 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 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.
* The lefthand field is set to NIL, since its expressions are now in
* the Expr list. This representation is passed to the executor.
*
* 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 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 enum SubLinkType
{
EXISTS_SUBLINK, ALL_SUBLINK, ANY_SUBLINK, MULTIEXPR_SUBLINK, EXPR_SUBLINK
} SubLinkType;
typedef struct SubLink
{
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 OpExpr nodes for combining
* operators, or final list of executable
* expressions */
Node *subselect; /* subselect as Query* or parsetree */
} SubLink;
/*
* SubPlanExpr - executable expression node for a subplan (sub-SELECT)
*
* The planner replaces SubLink nodes in expression trees with SubPlanExpr
* nodes after it has finished planning the subquery. See notes above.
*/
typedef struct SubPlanExpr
{
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 * FieldSelect
* *
@ -453,8 +479,8 @@ typedef struct ArrayRef
typedef struct FieldSelect typedef struct FieldSelect
{ {
NodeTag type; Expr xpr;
Node *arg; /* input expression */ Expr *arg; /* input expression */
AttrNumber fieldnum; /* attribute number of field to extract */ AttrNumber fieldnum; /* attribute number of field to extract */
Oid resulttype; /* type of the field (result type of this Oid resulttype; /* type of the field (result type of this
* node) */ * node) */
@ -476,13 +502,134 @@ typedef struct FieldSelect
typedef struct RelabelType typedef struct RelabelType
{ {
NodeTag type; Expr xpr;
Node *arg; /* input expression */ Expr *arg; /* input expression */
Oid resulttype; /* output type of coercion expression */ Oid resulttype; /* output type of coercion expression */
int32 resulttypmod; /* output typmod (usually -1) */ int32 resulttypmod; /* output typmod (usually -1) */
CoercionForm relabelformat; /* how to display this node */ CoercionForm relabelformat; /* how to display this node */
} RelabelType; } 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 * node types for join trees

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -295,7 +295,7 @@ typedef struct PathKeyItem
/* /*
* key typically points to a Var node, ie a relation attribute, but it * 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 * functional index. Someday we might allow arbitrary expressions as
* path keys, so don't assume more than you must. * path keys, so don't assume more than you must.
*/ */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -16,23 +16,28 @@
#include "nodes/relation.h" #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_leftop(Expr *clause);
extern Var *get_rightop(Expr *clause); extern Var *get_rightop(Expr *clause);
extern bool is_funcclause(Node *clause); extern Expr *make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset,
extern Expr *make_funcclause(Func *func, List *funcargs); CoercionForm funcformat, List *funcargs);
extern bool or_clause(Node *clause);
extern Expr *make_orclause(List *orclauses);
extern bool not_clause(Node *clause); extern bool not_clause(Node *clause);
extern Expr *make_notclause(Expr *notclause); extern Expr *make_notclause(Expr *notclause);
extern Expr *get_notclausearg(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 bool and_clause(Node *clause);
extern Expr *make_andclause(List *andclauses); extern Expr *make_andclause(List *andclauses);
extern Node *make_and_qual(Node *qual1, Node *qual2); extern Node *make_and_qual(Node *qual1, Node *qual2);
@ -60,7 +65,7 @@ extern bool has_distinct_on_clause(Query *query);
extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars); extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars);
extern int NumRelids(Node *clause); extern int NumRelids(Node *clause);
extern void CommuteClause(Expr *clause); extern void CommuteClause(OpExpr *clause);
extern Node *eval_const_expressions(Node *node); extern Node *eval_const_expressions(Node *node);
@ -78,8 +83,4 @@ extern bool query_tree_walker(Query *query, bool (*walker) (),
extern void query_tree_mutator(Query *query, Node *(*mutator) (), extern void query_tree_mutator(Query *query, Node *(*mutator) (),
void *context, int flags); void *context, int flags);
#define is_subplan(clause) ((clause) != NULL && \
IsA(clause, Expr) && \
((Expr *) (clause))->opType == SUBPLAN_EXPR)
#endif /* CLAUSES_H */ #endif /* CLAUSES_H */

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -42,8 +42,6 @@ extern void debug_print_rel(Query *root, RelOptInfo *rel);
extern void create_index_paths(Query *root, RelOptInfo *rel); extern void create_index_paths(Query *root, RelOptInfo *rel);
extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel, extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel,
Relids outer_relids, JoinType jointype); 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, extern List *extract_or_indexqual_conditions(RelOptInfo *rel,
IndexOptInfo *index, IndexOptInfo *index,
Expr *orsubclause); Expr *orsubclause);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -68,6 +68,6 @@ extern void set_plan_references(Plan *plan, List *rtable);
extern List *join_references(List *clauses, List *rtable, extern List *join_references(List *clauses, List *rtable,
List *outer_tlist, List *inner_tlist, List *outer_tlist, List *inner_tlist,
Index acceptable_rel); Index acceptable_rel);
extern void fix_opids(Node *node); extern void fix_opfuncids(Node *node);
#endif /* PLANMAIN_H */ #endif /* PLANMAIN_H */

View File

@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -3499,28 +3499,123 @@ exec_cast_value(Datum value, Oid valtype,
static bool static bool
exec_simple_check_node(Node *node) exec_simple_check_node(Node *node)
{ {
if (node == NULL)
return TRUE;
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Expr: case T_Const:
{ return TRUE;
Expr *expr = (Expr *) node;
List *l;
switch (expr->opType) case T_Param:
{ return TRUE;
case OP_EXPR:
case DISTINCT_EXPR:
case FUNC_EXPR:
case OR_EXPR:
case AND_EXPR:
case NOT_EXPR:
break;
default: case T_ArrayRef:
{
ArrayRef *expr = (ArrayRef *) node;
if (!exec_simple_check_node((Node *) expr->refupperindexpr))
return FALSE; 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;
return TRUE;
} }
foreach(l, expr->args) 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_OpExpr:
{
OpExpr *expr = (OpExpr *) node;
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((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))) if (!exec_simple_check_node(lfirst(l)))
return FALSE; return FALSE;
@ -3529,15 +3624,6 @@ exec_simple_check_node(Node *node)
return TRUE; return TRUE;
} }
case T_Param:
return TRUE;
case T_Const:
return TRUE;
case T_RelabelType:
return exec_simple_check_node(((RelabelType *) node)->arg);
default: default:
return FALSE; return FALSE;
} }
@ -3596,18 +3682,17 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
tle = (TargetEntry *) lfirst(plan->targetlist); tle = (TargetEntry *) lfirst(plan->targetlist);
/* /*
* 5. Check that all the nodes in the expression are one of Expr, * 5. Check that all the nodes in the expression are non-scary.
* Param or Const.
*/ */
if (!exec_simple_check_node(tle->expr)) if (!exec_simple_check_node((Node *) tle->expr))
return; return;
/* /*
* Yes - this is a simple expression. Remember the expression and the * Yes - this is a simple expression. Remember the expression and the
* return type * return type
*/ */
expr->plan_simple_expr = tle->expr; expr->plan_simple_expr = (Node *) tle->expr;
expr->plan_simple_type = exprType(tle->expr); expr->plan_simple_type = exprType((Node *) tle->expr);
} }
/* /*