diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index bd837da31ac278e36e7dcdd54a41da70ebcad0db..bcc92bfab0f779fd5fdf835f2e3445841a3a3c87 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.17 2002/12/06 05:00:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.18 2002/12/12 15:49:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -806,25 +806,28 @@ find_expr_references_walker(Node *node, } return false; } - if (IsA(node, Expr)) + if (IsA(node, FuncExpr)) { - Expr *expr = (Expr *) node; + FuncExpr *funcexpr = (FuncExpr *) node; - if (expr->opType == OP_EXPR || - expr->opType == DISTINCT_EXPR) - { - Oper *oper = (Oper *) expr->oper; + add_object_address(OCLASS_PROC, funcexpr->funcid, 0, + &context->addrs); + /* fall through to examine arguments */ + } + if (IsA(node, OpExpr)) + { + OpExpr *opexpr = (OpExpr *) node; - add_object_address(OCLASS_OPERATOR, oper->opno, 0, - &context->addrs); - } - else if (expr->opType == FUNC_EXPR) - { - Func *func = (Func *) expr->oper; + add_object_address(OCLASS_OPERATOR, opexpr->opno, 0, + &context->addrs); + /* fall through to examine arguments */ + } + if (IsA(node, DistinctExpr)) + { + DistinctExpr *distinctexpr = (DistinctExpr *) node; - add_object_address(OCLASS_PROC, func->funcid, 0, - &context->addrs); - } + add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0, + &context->addrs); /* fall through to examine arguments */ } if (IsA(node, Aggref)) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index f8f667e24a9d8f01f4c89b27ca86b66aba61cb09..bd068271acdcc7d9cafa06e97f9d764bda523d68 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * 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 @@ -1602,11 +1602,6 @@ AddRelationRawConstraints(Relation rel, */ expr = (Node *) make_ands_implicit((Expr *) expr); - /* - * Must fix opids in operator clauses. - */ - fix_opids(expr); - /* * OK, store it. */ @@ -1750,11 +1745,6 @@ cookDefault(ParseState *pstate, */ expr = eval_const_expressions(expr); - /* - * Must fix opids, in case any operators remain... - */ - fix_opids(expr); - return (expr); } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index cdac597ae5fde2866d4782741f9821630f86b2fa..c11bd5b172bb82da21c31510ab205973f7b6a454 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * 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 @@ -41,6 +41,7 @@ #include "executor/executor.h" #include "miscadmin.h" #include "optimizer/clauses.h" +#include "optimizer/planmain.h" #include "optimizer/prep.h" #include "parser/parse_func.h" #include "storage/sinval.h" @@ -919,6 +920,7 @@ BuildIndexInfo(Form_pg_index indexStruct) predString = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(&indexStruct->indpred))); ii->ii_Predicate = stringToNode(predString); + fix_opfuncids((Node *) ii->ii_Predicate); pfree(predString); } else diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index b915a02c310ac4b619fccce47ce87e98b97037d5..14f37344b4d65e7e787e418163c8431c47340edc 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * 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); rellogcols++; - tletype = exprType(tle->expr); + tletype = exprType((Node *) tle->expr); atttype = attr->atttypid; if (!IsBinaryCoercible(tletype, atttype)) elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 45749ab673ab65f6ba789eb4fc73609e3c795a11..41586331af07faebea0517dc3d9109c8aef475a9 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -9,7 +9,7 @@ * * * 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 "miscadmin.h" #include "nodes/makefuncs.h" +#include "optimizer/planmain.h" #include "parser/parse_coerce.h" #include "parser/parse_relation.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); if (defexprs[num_defaults] != NULL) { + fix_opfuncids(defexprs[num_defaults]); defmap[num_defaults] = i; num_defaults++; } @@ -869,6 +871,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, /* check whether any constraints actually found */ if (node != (Node *) prm) { + fix_opfuncids(node); constraintexprs[i] = node; hasConstraints = true; } diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 0b5efaa319e732c3501e981b8fd4faffa3445e96..c587765bd5af0d236bf8a65d0c30dce854016009 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.95 2002/12/06 19:28:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.96 2002/12/12 15:49:24 tgl Exp $ * */ @@ -417,20 +417,27 @@ explain_outNode(StringInfo str, { RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid, es->rtable); - Expr *expr; - Func *funcnode; - Oid funcid; char *proname; /* Assert it's on a RangeFunction */ Assert(rte->rtekind == RTE_FUNCTION); - expr = (Expr *) rte->funcexpr; - funcnode = (Func *) expr->oper; - funcid = funcnode->funcid; - - /* We only show the func name, not schema name */ - proname = get_func_name(funcid); + /* + * If the expression is still a function call, we can get + * the real name of the function. Otherwise, punt (this + * can happen if the optimizer simplified away the function + * call, for example). + */ + if (rte->funcexpr && IsA(rte->funcexpr, FuncExpr)) + { + FuncExpr *funcexpr = (FuncExpr *) rte->funcexpr; + Oid funcid = funcexpr->funcid; + + /* We only show the func name, not schema name */ + proname = get_func_name(funcid); + } + else + proname = rte->eref->aliasname; appendStringInfo(str, " on %s", quote_identifier(proname)); @@ -583,7 +590,7 @@ explain_outNode(StringInfo str, appendStringInfo(str, " InitPlan\n"); foreach(lst, plan->initPlan) { - SubPlan *subplan = (SubPlan *) lfirst(lst); + SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst); SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist); es->rtable = subplan->rtable; @@ -683,7 +690,7 @@ explain_outNode(StringInfo str, foreach(lst, planstate->subPlan) { SubPlanState *sps = (SubPlanState *) lfirst(lst); - SubPlan *sp = (SubPlan *) sps->ps.plan; + SubPlanExpr *sp = (SubPlanExpr *) sps->ps.plan; es->rtable = sp->rtable; for (i = 0; i < indent; i++) @@ -870,7 +877,7 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel, if (target->resdom->reskey == keyno) { /* Deparse the expression, showing any top-level cast */ - exprstr = deparse_expression(target->expr, context, + exprstr = deparse_expression((Node *) target->expr, context, useprefix, true); /* And add to str */ if (keyno > 1) diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 5447780b69e2f8e0f8b56b5ed78cff4b1394019e..d6ccdb926131daaf468fafd4c9ede6a67891aee1 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * 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 * to simplify the task of proving implications. */ - if (predicate != NULL && rangetable != NIL) + if (predicate) { cnfPred = canonicalize_qual((Expr *) copyObject(predicate), true); - fix_opids((Node *) cnfPred); + fix_opfuncids((Node *) cnfPred); CheckPredicate(cnfPred, rangetable, relationId); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8da1de580fb8516320a9f8b4fa6b3aedc4536d90..19687737337c897dc539b28345c60f61ed0b89f0 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * 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 * table to allow us to transformExpr and - * fix_opids to get a version of the + * fix_opfuncids to get a version of the * expression we can pass to ExecQual */ pstate = make_parsestate(NULL); @@ -2764,8 +2764,8 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr) */ expr = eval_const_expressions(expr); - /* And fix the opids */ - fix_opids(expr); + /* And fix the opfuncids */ + fix_opfuncids(expr); qual = makeList1(expr); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index d5260ad119074c89ef20ad6309652041499065fd..e16942acd72d43b9df817b128dbae4d46b677b55 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.21 2002/12/09 20:31:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.22 2002/12/12 15:49:24 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -1341,7 +1341,9 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) * the constraint is being added to. */ expr = stringToNode(ccbin); + fix_opfuncids(expr); rels = get_rels_with_domain(domainoid); + foreach (rt, rels) { Relation typrel; @@ -1522,7 +1524,7 @@ domainPermissionCheck(HeapTuple tup, TypeName *typename) /* - * + * domainAddConstraint */ char * domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, @@ -1601,21 +1603,20 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, expr = eval_const_expressions(expr); /* - * Must fix opids in operator clauses. + * Convert to string form for storage. */ - fix_opids(expr); - ccbin = nodeToString(expr); /* - * Deparse it. Since VARNOs aren't allowed in domain - * constraints, relation context isn't required as anything - * other than a shell. + * Deparse it to produce text for consrc. + * + * Since VARNOs aren't allowed in domain constraints, relation context + * isn't required as anything other than a shell. */ ccsrc = deparse_expression(expr, - deparse_context_for(domainName, - InvalidOid), - false, false); + deparse_context_for(domainName, + InvalidOid), + false, false); /* Write the constraint */ CreateConstraintEntry(constr->name, /* Constraint Name */ diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index 761ff403dd81dee564ea741c7202aa6e746fd32a..edaf7aa40cd511c0ae12586b124559742533a249 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -8,7 +8,7 @@ * * * 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; AttrNumber cleanResno; AttrNumber *cleanMap; - Node *expr; + Expr *expr; /* * Make a memory context that will hold the JunkFilter as well as all @@ -104,65 +104,23 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType, { TargetEntry *rtarget = lfirst(t); - if (rtarget->resdom != NULL) - { - resdom = rtarget->resdom; - expr = rtarget->expr; - resjunk = resdom->resjunk; - if (!resjunk) - { - /* - * make a copy of the resdom node, changing its resno. - */ - cleanResdom = (Resdom *) copyObject(resdom); - cleanResdom->resno = cleanResno; - cleanResno++; - - /* - * create a new target list entry - */ - tle = makeTargetEntry(cleanResdom, expr); - cleanTargetList = lappend(cleanTargetList, tle); - } - } - else + resdom = rtarget->resdom; + expr = rtarget->expr; + resjunk = resdom->resjunk; + if (!resjunk) { -#ifdef SETS_FIXED - List *fjListP; - Fjoin *cleanFjoin; - List *cleanFjList; - List *fjList = lfirst(t); - Fjoin *fjNode = (Fjoin *) tl_node(fjList); - - cleanFjoin = (Fjoin) copyObject((Node) fjNode); - cleanFjList = makeList1(cleanFjoin); - - resdom = (Resdom) lfirst(get_fj_innerNode(fjNode)); - expr = lsecond(get_fj_innerNode(fjNode)); - cleanResdom = (Resdom) copyObject((Node) resdom); - set_resno(cleanResdom, cleanResno); + /* + * make a copy of the resdom node, changing its resno. + */ + cleanResdom = (Resdom *) copyObject(resdom); + cleanResdom->resno = cleanResno; cleanResno++; - tle = (List) makeTargetEntry(cleanResdom, (Node *) expr); - set_fj_innerNode(cleanFjoin, tle); - - foreach(fjListP, lnext(fjList)) - { - TargetEntry *tle = lfirst(fjListP); - resdom = tle->resdom; - expr = tle->expr; - cleanResdom = (Resdom *) copyObject((Node) resdom); - cleanResno++; - cleanResdom->Resno = cleanResno; - - /* - * create a new target list entry - */ - tle = (List) makeTargetEntry(cleanResdom, (Node *) expr); - cleanFjList = lappend(cleanFjList, tle); - } - lappend(cleanTargetList, cleanFjList); -#endif + /* + * create a new target list entry + */ + tle = makeTargetEntry(cleanResdom, expr); + cleanTargetList = lappend(cleanTargetList, tle); } } @@ -192,41 +150,12 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType, { TargetEntry *tle = lfirst(t); - if (tle->resdom != NULL) - { - resdom = tle->resdom; - expr = tle->expr; - resjunk = resdom->resjunk; - if (!resjunk) - { - cleanMap[cleanResno - 1] = resdom->resno; - cleanResno++; - } - } - else + resdom = tle->resdom; + resjunk = resdom->resjunk; + if (!resjunk) { -#ifdef SETS_FIXED - List fjListP; - List fjList = lfirst(t); - Fjoin fjNode = (Fjoin) lfirst(fjList); - - /* what the hell is this????? */ - resdom = (Resdom) lfirst(get_fj_innerNode(fjNode)); -#endif - - cleanMap[cleanResno - 1] = tle->resdom->resno; + cleanMap[cleanResno - 1] = resdom->resno; cleanResno++; - -#ifdef SETS_FIXED - foreach(fjListP, lnext(fjList)) - { - TargetEntry *tle = lfirst(fjListP); - - resdom = tle->resdom; - cleanMap[cleanResno - 1] = resdom->resno; - cleanResno++; - } -#endif } } } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 15d47df669f38c7096fa8cc3ee15603f21555fb3..abd099c08c08a4ce966446ae039d87d938184df9 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * 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/execdefs.h" #include "miscadmin.h" +#include "optimizer/planmain.h" #include "optimizer/var.h" #include "parser/parsetree.h" #include "utils/acl.h" @@ -1541,6 +1542,7 @@ ExecRelCheck(ResultRelInfo *resultRelInfo, for (i = 0; i < ncheck; i++) { qual = (List *) stringToNode(check[i].ccbin); + fix_opfuncids((Node *) qual); resultRelInfo->ri_ConstraintExprs[i] = qual; } MemoryContextSwitchTo(oldContext); diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 2db4a146bc16cefb8ff3e58eba817b2bc9c0a60b..680a6da609baff0c63fe127deb841356e5aedf11 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -12,7 +12,7 @@ * * * 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; foreach(subp, node->initPlan) { - SubPlan *subplan = (SubPlan *) lfirst(subp); + SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp); - Assert(IsA(subplan, SubPlan)); + Assert(IsA(subplan, SubPlanExpr)); subps = lappend(subps, ExecInitSubPlan(subplan, estate)); } result->initPlan = subps; @@ -242,9 +242,9 @@ ExecInitNode(Plan *node, EState *estate) subps = NIL; foreach(subp, result->subPlan) { - SubPlan *subplan = (SubPlan *) lfirst(subp); + SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp); - Assert(IsA(subplan, SubPlan)); + Assert(IsA(subplan, SubPlanExpr)); subps = lappend(subps, ExecInitSubPlan(subplan, estate)); } result->subPlan = subps; diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 2392981a5ec3746ef2901a949f8d58e9e5f12607..d96e983fa30ab6eae2a7aec79d126f17b0b285e5 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.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, bool *isNull, ExprDoneCond *isDone); static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull); -static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext, +static Datum ExecEvalOper(OpExpr *op, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); -static Datum ExecEvalDistinct(Expr *opClause, ExprContext *econtext, +static Datum ExecEvalDistinct(DistinctExpr *op, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); -static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext, +static Datum ExecEvalFunc(FuncExpr *func, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo, List *argList, ExprContext *econtext); -static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull); -static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull); -static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull); +static Datum ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, + bool *isNull); +static Datum ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, + bool *isNull); +static Datum ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, + bool *isNull); static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext, @@ -122,7 +125,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, if (arrayRef->refexpr != NULL) { array_source = (ArrayType *) - DatumGetPointer(ExecEvalExpr(arrayRef->refexpr, + DatumGetPointer(ExecEvalExpr((Node *) arrayRef->refexpr, econtext, isNull, isDone)); @@ -203,7 +206,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, if (isAssignment) { - Datum sourceData = ExecEvalExpr(arrayRef->refassgnexpr, + Datum sourceData = ExecEvalExpr((Node *) arrayRef->refassgnexpr, econtext, isNull, NULL); @@ -839,7 +842,7 @@ ExecMakeTableFunctionResult(Node *funcexpr, bool returnsTuple = false; /* - * Normally the passed expression tree will be a FUNC_EXPR, since the + * Normally the passed expression tree will be a FuncExpr, since the * grammar only allows a function call at the top level of a table * function reference. However, if the function doesn't return set then * the planner might have replaced the function call via constant-folding @@ -848,11 +851,9 @@ ExecMakeTableFunctionResult(Node *funcexpr, * we don't get a chance to pass a special ReturnSetInfo to any functions * buried in the expression. */ - if (funcexpr && - IsA(funcexpr, Expr) && - ((Expr *) funcexpr)->opType == FUNC_EXPR) + if (funcexpr && IsA(funcexpr, FuncExpr)) { - Func *func; + FuncExpr *func = (FuncExpr *) funcexpr; List *argList; FunctionCachePtr fcache; ExprDoneCond argDone; @@ -862,13 +863,12 @@ ExecMakeTableFunctionResult(Node *funcexpr, */ direct_function_call = true; - funcrettype = ((Expr *) funcexpr)->typeOid; - func = (Func *) ((Expr *) funcexpr)->oper; - argList = ((Expr *) funcexpr)->args; + funcrettype = func->funcresulttype; + argList = func->args; /* - * get the fcache from the Func node. If it is NULL, then initialize - * it + * get the fcache from the FuncExpr node. If it is NULL, then + * initialize it */ fcache = func->func_fcache; if (fcache == NULL) @@ -1102,12 +1102,11 @@ ExecMakeTableFunctionResult(Node *funcexpr, * ---------------------------------------------------------------- */ static Datum -ExecEvalOper(Expr *opClause, +ExecEvalOper(OpExpr *op, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) { - Oper *op; List *argList; FunctionCachePtr fcache; @@ -1117,17 +1116,16 @@ ExecEvalOper(Expr *opClause, * arguments and returns the result of calling the function on the * evaluated arguments. */ - op = (Oper *) opClause->oper; - argList = opClause->args; + argList = op->args; /* - * get the fcache from the Oper node. If it is NULL, then initialize + * get the fcache from the OpExpr node. If it is NULL, then initialize * it */ fcache = op->op_fcache; if (fcache == NULL) { - fcache = init_fcache(op->opid, length(argList), + fcache = init_fcache(op->opfuncid, length(argList), econtext->ecxt_per_query_memory); op->op_fcache = fcache; } @@ -1142,12 +1140,11 @@ ExecEvalOper(Expr *opClause, */ static Datum -ExecEvalFunc(Expr *funcClause, +ExecEvalFunc(FuncExpr *func, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) { - Func *func; List *argList; FunctionCachePtr fcache; @@ -1159,11 +1156,10 @@ ExecEvalFunc(Expr *funcClause, * * this is nearly identical to the ExecEvalOper code. */ - func = (Func *) funcClause->oper; - argList = funcClause->args; + argList = func->args; /* - * get the fcache from the Func node. If it is NULL, then initialize + * get the fcache from the FuncExpr node. If it is NULL, then initialize * it */ fcache = func->func_fcache; @@ -1190,7 +1186,7 @@ ExecEvalFunc(Expr *funcClause, * ---------------------------------------------------------------- */ static Datum -ExecEvalDistinct(Expr *opClause, +ExecEvalDistinct(DistinctExpr *op, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) @@ -1199,23 +1195,21 @@ ExecEvalDistinct(Expr *opClause, FunctionCachePtr fcache; FunctionCallInfoData fcinfo; ExprDoneCond argDone; - Oper *op; List *argList; /* - * extract info from opClause + * extract info from op */ - op = (Oper *) opClause->oper; - argList = opClause->args; + argList = op->args; /* - * get the fcache from the Oper node. If it is NULL, then initialize - * it + * get the fcache from the DistinctExpr node. If it is NULL, then + * initialize it */ fcache = op->op_fcache; if (fcache == NULL) { - fcache = init_fcache(op->opid, length(argList), + fcache = init_fcache(op->opfuncid, length(argList), econtext->ecxt_per_query_memory); op->op_fcache = fcache; } @@ -1256,8 +1250,7 @@ ExecEvalDistinct(Expr *opClause, * ExecEvalOr * ExecEvalAnd * - * Evaluate boolean expressions. Evaluation of 'or' is - * short-circuited when the first true (or null) value is found. + * Evaluate boolean expressions, with appropriate short-circuiting. * * The query planner reformulates clause expressions in the * qualification to conjunctive normal form. If we ever get @@ -1268,7 +1261,7 @@ ExecEvalDistinct(Expr *opClause, * ---------------------------------------------------------------- */ static Datum -ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull) +ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull) { Node *clause; Datum expr_value; @@ -1296,7 +1289,7 @@ ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull) * ---------------------------------------------------------------- */ static Datum -ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull) +ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) { List *clauses; List *clause; @@ -1344,7 +1337,7 @@ ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull) * ---------------------------------------------------------------- */ static Datum -ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull) +ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) { List *clauses; List *clause; @@ -1409,7 +1402,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, { CaseWhen *wclause = lfirst(clause); - clause_value = ExecEvalExpr(wclause->expr, + clause_value = ExecEvalExpr((Node *) wclause->expr, econtext, isNull, NULL); @@ -1421,7 +1414,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, */ if (DatumGetBool(clause_value) && !*isNull) { - return ExecEvalExpr(wclause->result, + return ExecEvalExpr((Node *) wclause->result, econtext, isNull, isDone); @@ -1430,7 +1423,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, if (caseExpr->defresult) { - return ExecEvalExpr(caseExpr->defresult, + return ExecEvalExpr((Node *) caseExpr->defresult, econtext, isNull, isDone); @@ -1454,7 +1447,7 @@ ExecEvalNullTest(NullTest *ntest, { Datum result; - result = ExecEvalExpr(ntest->arg, econtext, isNull, isDone); + result = ExecEvalExpr((Node *) ntest->arg, econtext, isNull, isDone); switch (ntest->nulltesttype) { case IS_NULL: @@ -1494,7 +1487,7 @@ ExecEvalBooleanTest(BooleanTest *btest, { Datum result; - result = ExecEvalExpr(btest->arg, econtext, isNull, isDone); + result = ExecEvalExpr((Node *) btest->arg, econtext, isNull, isDone); switch (btest->booltesttype) { case IS_TRUE: @@ -1590,7 +1583,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, { Datum result; - result = ExecEvalExpr(constraint->arg, econtext, isNull, isDone); + result = ExecEvalExpr((Node *) constraint->arg, econtext, isNull, isDone); switch (constraint->testtype) { @@ -1607,7 +1600,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, econtext->domainValue_datum = result; econtext->domainValue_isNull = *isNull; - conResult = ExecEvalExpr(constraint->check_expr, econtext, isNull, isDone); + conResult = ExecEvalExpr((Node *) constraint->check_expr, econtext, isNull, isDone); if (!DatumGetBool(conResult)) elog(ERROR, "ExecEvalConstraintTest: Domain %s constraint %s failed", @@ -1638,7 +1631,7 @@ ExecEvalFieldSelect(FieldSelect *fselect, Datum result; TupleTableSlot *resSlot; - result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone); + result = ExecEvalExpr((Node *) fselect->arg, econtext, isNull, isDone); if (*isNull) return result; resSlot = (TupleTableSlot *) DatumGetPointer(result); @@ -1738,47 +1731,48 @@ ExecEvalExpr(Node *expression, isNull, isDone); break; - case T_Expr: + case T_FuncExpr: + retDatum = ExecEvalFunc((FuncExpr *) expression, econtext, + isNull, isDone); + break; + case T_OpExpr: + retDatum = ExecEvalOper((OpExpr *) expression, econtext, + isNull, isDone); + break; + case T_DistinctExpr: + retDatum = ExecEvalDistinct((DistinctExpr *) expression, econtext, + isNull, isDone); + break; + case T_BoolExpr: { - Expr *expr = (Expr *) expression; + BoolExpr *expr = (BoolExpr *) expression; - switch (expr->opType) + switch (expr->boolop) { - case OP_EXPR: - retDatum = ExecEvalOper(expr, econtext, - isNull, isDone); - break; - case FUNC_EXPR: - retDatum = ExecEvalFunc(expr, econtext, - isNull, isDone); + case AND_EXPR: + retDatum = ExecEvalAnd(expr, econtext, isNull); break; case OR_EXPR: retDatum = ExecEvalOr(expr, econtext, isNull); break; - case AND_EXPR: - retDatum = ExecEvalAnd(expr, econtext, isNull); - break; case NOT_EXPR: retDatum = ExecEvalNot(expr, econtext, isNull); break; - case DISTINCT_EXPR: - retDatum = ExecEvalDistinct(expr, econtext, - isNull, isDone); - break; - case SUBPLAN_EXPR: - /* XXX temporary hack to find exec state node */ - retDatum = ExecSubPlan(((SubPlan *) expr->oper)->pstate, - expr->args, econtext, - isNull); - break; default: - elog(ERROR, "ExecEvalExpr: unknown expression type %d", - expr->opType); + elog(ERROR, "ExecEvalExpr: unknown boolop %d", + expr->boolop); retDatum = 0; /* keep compiler quiet */ break; } break; } + case T_SubPlanExpr: + /* XXX temporary hack to find exec state node */ + retDatum = ExecSubPlan(((SubPlanExpr *) expression)->pstate, + ((SubPlanExpr *) expression)->args, + econtext, + isNull); + break; case T_FieldSelect: retDatum = ExecEvalFieldSelect((FieldSelect *) expression, econtext, @@ -1786,7 +1780,7 @@ ExecEvalExpr(Node *expression, isDone); break; case T_RelabelType: - retDatum = ExecEvalExpr(((RelabelType *) expression)->arg, + retDatum = ExecEvalExpr((Node *) ((RelabelType *) expression)->arg, econtext, isNull, isDone); @@ -1861,7 +1855,7 @@ ExecEvalExprSwitchContext(Node *expression, * * Soon this will generate an expression state tree paralleling the given * expression tree. Right now, it just searches the expression tree for - * Aggref and SubPlan nodes. + * Aggref and SubPlanExpr nodes. */ Node * ExecInitExpr(Node *node, PlanState *parent) @@ -1887,7 +1881,7 @@ ExecInitExpr(Node *node, PlanState *parent) aggstate->aggs = lcons(node, aggstate->aggs); naggs = ++aggstate->numaggs; - ExecInitExpr(((Aggref *) node)->target, parent); + ExecInitExpr((Node *) ((Aggref *) node)->target, parent); /* * Complain if the aggregate's argument contains any @@ -1907,64 +1901,67 @@ ExecInitExpr(Node *node, PlanState *parent) ExecInitExpr((Node *) aref->refupperindexpr, parent); ExecInitExpr((Node *) aref->reflowerindexpr, parent); - ExecInitExpr(aref->refexpr, parent); - ExecInitExpr(aref->refassgnexpr, parent); + ExecInitExpr((Node *) aref->refexpr, parent); + ExecInitExpr((Node *) aref->refassgnexpr, parent); } break; - case T_Expr: + case T_FuncExpr: { - Expr *expr = (Expr *) node; + FuncExpr *funcexpr = (FuncExpr *) node; - switch (expr->opType) - { - case OP_EXPR: - break; - case FUNC_EXPR: - break; - case OR_EXPR: - break; - case AND_EXPR: - break; - case NOT_EXPR: - break; - case DISTINCT_EXPR: - break; - case SUBPLAN_EXPR: - if (parent) - { - SubLink *sublink = ((SubPlan *) expr->oper)->sublink; + ExecInitExpr((Node *) funcexpr->args, parent); + } + break; + case T_OpExpr: + { + OpExpr *opexpr = (OpExpr *) node; - /* - * Here we just add the SubPlan nodes to - * parent->subPlan. Later they will be expanded - * to SubPlanState nodes. - */ - parent->subPlan = lcons(expr->oper, - parent->subPlan); - - /* Must recurse into oper list too */ - Assert(IsA(sublink, SubLink)); - if (sublink->lefthand) - elog(ERROR, "ExecInitExpr: sublink has not been transformed"); - ExecInitExpr((Node *) sublink->oper, parent); - } - else - elog(ERROR, "ExecInitExpr: SubPlan not expected here"); - break; - default: - elog(ERROR, "ExecInitExpr: unknown expression type %d", - expr->opType); - break; - } - /* for all Expr node types, examine args list */ - ExecInitExpr((Node *) expr->args, parent); + ExecInitExpr((Node *) opexpr->args, parent); + } + break; + case T_DistinctExpr: + { + DistinctExpr *distinctexpr = (DistinctExpr *) node; + + ExecInitExpr((Node *) distinctexpr->args, parent); + } + break; + case T_BoolExpr: + { + BoolExpr *boolexpr = (BoolExpr *) node; + + ExecInitExpr((Node *) boolexpr->args, parent); + } + break; + case T_SubPlanExpr: + { + SubPlanExpr *subplanexpr = (SubPlanExpr *) node; + SubLink *sublink = subplanexpr->sublink; + + Assert(IsA(sublink, SubLink)); + if (!parent) + elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here"); + + /* + * Here we just add the SubPlanExpr nodes to + * parent->subPlan. Later they will be expanded + * to SubPlanState nodes. + */ + parent->subPlan = lcons(subplanexpr, parent->subPlan); + + /* Must recurse into oper list too */ + if (sublink->lefthand) + elog(ERROR, "ExecInitExpr: sublink has not been transformed"); + ExecInitExpr((Node *) sublink->oper, parent); + + ExecInitExpr((Node *) subplanexpr->args, parent); } break; case T_FieldSelect: - ExecInitExpr(((FieldSelect *) node)->arg, parent); + ExecInitExpr((Node *) ((FieldSelect *) node)->arg, parent); break; case T_RelabelType: - ExecInitExpr(((RelabelType *) node)->arg, parent); + ExecInitExpr((Node *) ((RelabelType *) node)->arg, parent); break; case T_CaseExpr: { @@ -1975,35 +1972,35 @@ ExecInitExpr(Node *node, PlanState *parent) CaseWhen *when = (CaseWhen *) lfirst(temp); Assert(IsA(when, CaseWhen)); - ExecInitExpr(when->expr, parent); - ExecInitExpr(when->result, parent); + ExecInitExpr((Node *) when->expr, parent); + ExecInitExpr((Node *) when->result, parent); } /* caseexpr->arg should be null, but we'll check it anyway */ - ExecInitExpr(caseexpr->arg, parent); - ExecInitExpr(caseexpr->defresult, parent); + ExecInitExpr((Node *) caseexpr->arg, parent); + ExecInitExpr((Node *) caseexpr->defresult, parent); } break; case T_NullTest: - ExecInitExpr(((NullTest *) node)->arg, parent); + ExecInitExpr((Node *) ((NullTest *) node)->arg, parent); break; case T_BooleanTest: - ExecInitExpr(((BooleanTest *) node)->arg, parent); + ExecInitExpr((Node *) ((BooleanTest *) node)->arg, parent); break; case T_ConstraintTest: - ExecInitExpr(((ConstraintTest *) node)->arg, parent); - ExecInitExpr(((ConstraintTest *) node)->check_expr, parent); + ExecInitExpr((Node *) ((ConstraintTest *) node)->arg, parent); + ExecInitExpr((Node *) ((ConstraintTest *) node)->check_expr, parent); break; case T_ConstraintTestValue: break; + case T_TargetEntry: + ExecInitExpr((Node *) ((TargetEntry *) node)->expr, parent); + break; case T_List: foreach(temp, (List *) node) { ExecInitExpr((Node *) lfirst(temp), parent); } break; - case T_TargetEntry: - ExecInitExpr(((TargetEntry *) node)->expr, parent); - break; default: elog(ERROR, "ExecInitExpr: unknown expression type %d", nodeTag(node)); @@ -2119,19 +2116,8 @@ ExecQual(List *qual, ExprContext *econtext, bool resultForNull) int ExecTargetListLength(List *targetlist) { - int len = 0; - List *tl; - - foreach(tl, targetlist) - { - TargetEntry *curTle = (TargetEntry *) lfirst(tl); - - if (curTle->resdom != NULL) - len++; - else - len += curTle->fjoin->fj_nNodes; - } - return len; + /* This used to be more complex, but fjoins are dead */ + return length(targetlist); } /* @@ -2147,13 +2133,8 @@ ExecCleanTargetListLength(List *targetlist) { TargetEntry *curTle = (TargetEntry *) lfirst(tl); - if (curTle->resdom != NULL) - { - if (!curTle->resdom->resjunk) - len++; - } - else - len += curTle->fjoin->fj_nNodes; + if (!curTle->resdom->resjunk) + len++; } return len; } @@ -2182,10 +2163,8 @@ ExecTargetList(List *targetlist, #define NPREALLOCDOMAINS 64 char nullsArray[NPREALLOCDOMAINS]; - bool fjIsNullArray[NPREALLOCDOMAINS]; ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS]; char *nulls; - bool *fjIsNull; ExprDoneCond *itemIsDone; List *tl; TargetEntry *tle; @@ -2223,24 +2202,20 @@ ExecTargetList(List *targetlist, * allocate an array of char's to hold the "null" information only if * we have a really large targetlist. otherwise we use the stack. * - * We also allocate a bool array that is used to hold fjoin result state, - * and another array that holds the isDone status for each targetlist - * item. The isDone status is needed so that we can iterate, + * We also allocate another array that holds the isDone status for each + * targetlist item. The isDone status is needed so that we can iterate, * generating multiple tuples, when one or more tlist items return - * sets. (We expect the caller to call us again if we return: - * + * sets. (We expect the caller to call us again if we return * isDone = ExprMultipleResult.) */ if (nodomains > NPREALLOCDOMAINS) { nulls = (char *) palloc(nodomains * sizeof(char)); - fjIsNull = (bool *) palloc(nodomains * sizeof(bool)); itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond)); } else { nulls = nullsArray; - fjIsNull = fjIsNullArray; itemIsDone = itemIsDoneArray; } @@ -2257,82 +2232,29 @@ ExecTargetList(List *targetlist, { tle = lfirst(tl); - if (tle->resdom != NULL) - { - resind = tle->resdom->resno - 1; + resind = tle->resdom->resno - 1; - values[resind] = ExecEvalExpr(tle->expr, - econtext, - &isNull, - &itemIsDone[resind]); - nulls[resind] = isNull ? 'n' : ' '; + values[resind] = ExecEvalExpr((Node *) tle->expr, + econtext, + &isNull, + &itemIsDone[resind]); + nulls[resind] = isNull ? 'n' : ' '; - if (itemIsDone[resind] != ExprSingleResult) - { - /* We have a set-valued expression in the tlist */ - if (isDone == NULL) - elog(ERROR, "Set-valued function called in context that cannot accept a set"); - if (itemIsDone[resind] == ExprMultipleResult) - { - /* we have undone sets in the tlist, set flag */ - *isDone = ExprMultipleResult; - } - else - { - /* we have done sets in the tlist, set flag for that */ - haveDoneSets = true; - } - } - } - else + if (itemIsDone[resind] != ExprSingleResult) { -#ifdef SETS_FIXED - int curNode; - Resdom *fjRes; - List *fjTlist = (List *) tle->expr; - Fjoin *fjNode = tle->fjoin; - int nNodes = fjNode->fj_nNodes; - DatumPtr results = fjNode->fj_results; - - ExecEvalFjoin(tle, econtext, fjIsNull, isDone); - - /* - * XXX this is wrong, but since fjoin code is completely - * broken anyway, I'm not going to worry about it now --- tgl - * 8/23/00 - */ - if (isDone && *isDone == ExprEndResult) + /* We have a set-valued expression in the tlist */ + if (isDone == NULL) + elog(ERROR, "Set-valued function called in context that cannot accept a set"); + if (itemIsDone[resind] == ExprMultipleResult) { - MemoryContextSwitchTo(oldContext); - newTuple = NULL; - goto exit; + /* we have undone sets in the tlist, set flag */ + *isDone = ExprMultipleResult; } - - /* - * get the result from the inner node - */ - fjRes = (Resdom *) fjNode->fj_innerNode; - resind = fjRes->resno - 1; - values[resind] = results[0]; - nulls[resind] = fjIsNull[0] ? 'n' : ' '; - - /* - * Get results from all of the outer nodes - */ - for (curNode = 1; - curNode < nNodes; - curNode++, fjTlist = lnext(fjTlist)) + else { - Node *outernode = lfirst(fjTlist); - - fjRes = (Resdom *) outernode->iterexpr; - resind = fjRes->resno - 1; - values[resind] = results[curNode]; - nulls[resind] = fjIsNull[curNode] ? 'n' : ' '; + /* we have done sets in the tlist, set flag for that */ + haveDoneSets = true; } -#else - elog(ERROR, "ExecTargetList: fjoin nodes not currently supported"); -#endif } } @@ -2368,7 +2290,7 @@ ExecTargetList(List *targetlist, if (itemIsDone[resind] == ExprEndResult) { - values[resind] = ExecEvalExpr(tle->expr, + values[resind] = ExecEvalExpr((Node *) tle->expr, econtext, &isNull, &itemIsDone[resind]); @@ -2404,7 +2326,7 @@ ExecTargetList(List *targetlist, while (itemIsDone[resind] == ExprMultipleResult) { - (void) ExecEvalExpr(tle->expr, + (void) ExecEvalExpr((Node *) tle->expr, econtext, &isNull, &itemIsDone[resind]); @@ -2434,7 +2356,6 @@ exit: if (nodomains > NPREALLOCDOMAINS) { pfree(nulls); - pfree(fjIsNull); pfree(itemIsDone); } diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index f5a6863b1ac77e736e7f18f6072cd1e0611a4599..eecc108fb1c1f453a0a47f47b420c215d8c59868 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * 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) { TargetEntry *tle = lfirst(tlitem); - Resdom *resdom; - Oid restype; - - if (tle->resdom != NULL) - { - resdom = tle->resdom; - restype = resdom->restype; - - TupleDescInitEntry(typeInfo, - resdom->resno, - resdom->resname, - restype, - resdom->restypmod, - 0, - false); - -#ifdef NOT_USED - ExecSetTypeInfo(resdom->resno - 1, - typeInfo, - (Oid) restype, - resdom->resno, - resdom->reslen, - NameStr(*resdom->resname), - get_typbyval(restype), - get_typalign(restype)); -#endif - } - else - { - /* XXX this branch looks fairly broken ... tgl 12/2000 */ - Resdom *fjRes; - List *fjTlistP; - List *fjList = lfirst(tlitem); - -#ifdef SETS_FIXED - TargetEntry *tle; - Fjoin *fjNode = ((TargetEntry *) lfirst(fjList))->fjoin; - - tle = fjNode->fj_innerNode; /* ??? */ -#endif - fjRes = tle->resdom; - restype = fjRes->restype; - - TupleDescInitEntry(typeInfo, - fjRes->resno, - fjRes->resname, - restype, - fjRes->restypmod, - 0, - false); -#ifdef NOT_USED - ExecSetTypeInfo(fjRes->resno - 1, - typeInfo, - (Oid) restype, - fjRes->resno, - fjRes->reslen, - (char *) fjRes->resname, - get_typbyval(restype), - get_typalign(restype)); -#endif - - foreach(fjTlistP, lnext(fjList)) - { - TargetEntry *fjTle = lfirst(fjTlistP); - - fjRes = fjTle->resdom; - - TupleDescInitEntry(typeInfo, - fjRes->resno, - fjRes->resname, - restype, - fjRes->restypmod, - 0, - false); - -#ifdef NOT_USED - ExecSetTypeInfo(fjRes->resno - 1, - typeInfo, - (Oid) fjRes->restype, - fjRes->resno, - fjRes->reslen, - (char *) fjRes->resname, - get_typbyval(fjRes->restype), - get_typalign(fjRes->restype)); -#endif - } - } + Resdom *resdom = tle->resdom; + + TupleDescInitEntry(typeInfo, + resdom->resno, + resdom->resname, + resdom->restype, + resdom->restypmod, + 0, + false); } return typeInfo; diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index bdbe61cb10ac94d2bf50f0a2bbbc6fd480da7d1f..73e4a8044ef332ff4028842cf3705029b65b68eb 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -45,7 +45,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.98 2002/12/05 15:50:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.99 2002/12/12 15:49:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -415,7 +415,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup) Datum newVal; bool isNull; - newVal = ExecEvalExprSwitchContext(aggref->target, econtext, + newVal = ExecEvalExprSwitchContext((Node *) aggref->target, econtext, &isNull, NULL); if (aggref->aggdistinct) @@ -1298,7 +1298,7 @@ ExecInitAgg(Agg *node, EState *estate) * pg_proc.proargtypes, because the latter might be 0. * (Consider COUNT(*).) */ - Oid inputType = exprType(aggref->target); + Oid inputType = exprType((Node *) aggref->target); if (!IsBinaryCoercible(inputType, aggform->aggtranstype)) elog(ERROR, "Aggregate %u needs to have compatible input type and transition type", @@ -1312,7 +1312,7 @@ ExecInitAgg(Agg *node, EState *estate) * pg_proc.proargtypes, because the latter might be a pseudotype. * (Consider COUNT(*).) */ - Oid inputType = exprType(aggref->target); + Oid inputType = exprType((Node *) aggref->target); Oid eq_function; /* We don't implement DISTINCT aggs in the HASHED case */ diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index e9888c4d3f533db8313ef4fe36b7870687835377..0112d3641dea3871b48db1336c3eb02399362e0d 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * 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; for (j = 0; j < n_keys; j++) { - Expr *clause; /* one clause of index qual */ - Oper *op; /* operator used in clause */ + OpExpr *clause; /* one clause of index qual */ Node *leftop; /* expr on lhs of operator */ Node *rightop; /* expr on rhs ... */ bits16 flags = 0; int scanvar; /* which var identifies varattno */ AttrNumber varattno = 0; /* att number used in scan */ - Oid opid; /* operator id used in scan */ + Oid opfuncid; /* operator id used in scan */ Datum scanvalue = 0; /* value used in scan (if const) */ /* * extract clause information from the qualification */ - clause = lfirst(listscan); + clause = (OpExpr *) lfirst(listscan); listscan = lnext(listscan); - op = (Oper *) clause->oper; - if (!IsA(clause, Expr) ||!IsA(op, Oper)) + if (!IsA(clause, OpExpr)) elog(ERROR, "ExecInitIndexScan: indxqual not an opclause!"); - opid = op->opid; + opfuncid = clause->opfuncid; /* * Here we figure out the contents of the index qual. The @@ -767,10 +765,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate) /* * determine information in leftop */ - leftop = (Node *) get_leftop(clause); + leftop = (Node *) get_leftop((Expr *) clause); if (leftop && IsA(leftop, RelabelType)) - leftop = ((RelabelType *) leftop)->arg; + leftop = (Node *) ((RelabelType *) leftop)->arg; Assert(leftop != NULL); @@ -834,10 +832,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate) /* * now determine information in rightop */ - rightop = (Node *) get_rightop(clause); + rightop = (Node *) get_rightop((Expr *) clause); if (rightop && IsA(rightop, RelabelType)) - rightop = ((RelabelType *) rightop)->arg; + rightop = (Node *) ((RelabelType *) rightop)->arg; Assert(rightop != NULL); @@ -921,7 +919,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) flags, varattno, /* attribute number to * scan */ - (RegProcedure) opid, /* reg proc to use */ + opfuncid, /* reg proc to use */ scanvalue); /* constant */ } diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 171738dd34917876e3a8afd31787746b4a87a50d..e6c2c86be19672d15c37f4f7ed94bdaf4819ff8c 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * 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; foreach(gtcdr, *gtQuals) { - Expr *ltqual = (Expr *) lfirst(ltcdr); - Expr *gtqual = (Expr *) lfirst(gtcdr); - Oper *ltop = (Oper *) ltqual->oper; - Oper *gtop = (Oper *) gtqual->oper; + OpExpr *ltop = (OpExpr *) lfirst(ltcdr); + OpExpr *gtop = (OpExpr *) lfirst(gtcdr); /* * The two ops should be identical, so use either one for lookup. */ - if (!IsA(ltop, Oper)) - elog(ERROR, "MJFormSkipQuals: op not an Oper!"); + if (!IsA(ltop, OpExpr)) + elog(ERROR, "MJFormSkipQuals: op not an OpExpr!"); /* * Lookup the operators, and replace the data in the copied @@ -137,8 +135,8 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals) op_mergejoin_crossops(ltop->opno, <op->opno, >op->opno, - <op->opid, - >op->opid); + <op->opfuncid, + >op->opfuncid); ltop->op_fcache = NULL; gtop->op_fcache = NULL; diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 195634c128982bc0b19c3704ebe8669060bbdc44..880a6233db287da218f64337b13c4226d63906e0 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.35 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.36 2002/12/12 15:49:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext, bool *isNull) { PlanState *planstate = node->planstate; - SubPlan *subplan = (SubPlan *) node->ps.plan; + SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; SubLink *sublink = subplan->sublink; SubLinkType subLinkType = sublink->subLinkType; bool useor = sublink->useor; @@ -151,7 +151,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, */ foreach(lst, sublink->oper) { - Expr *expr = (Expr *) lfirst(lst); + OpExpr *expr = (OpExpr *) lfirst(lst); Param *prm = lsecond(expr->args); ParamExecData *prmdata; Datum expresult; @@ -172,8 +172,8 @@ ExecSubPlan(SubPlanState *node, List *pvar, { switch (nodeTag(prm)) { - case T_Expr: - prm = lfirst(((Expr *) prm)->args); + case T_FuncExpr: + prm = lfirst(((FuncExpr *) prm)->args); break; case T_RelabelType: prm = (Param *) (((RelabelType *) prm)->arg); @@ -288,7 +288,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, * ---------------------------------------------------------------- */ SubPlanState * -ExecInitSubPlan(SubPlan *node, EState *estate) +ExecInitSubPlan(SubPlanExpr *node, EState *estate) { SubPlanState *subplanstate; EState *sp_estate; @@ -374,7 +374,7 @@ void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) { PlanState *planstate = node->planstate; - SubPlan *subplan = (SubPlan *) node->ps.plan; + SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; SubLink *sublink = subplan->sublink; EState *estate = node->ps.state; MemoryContext oldcontext; @@ -497,7 +497,7 @@ void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) { PlanState *planstate = node->planstate; - SubPlan *subplan = (SubPlan *) node->ps.plan; + SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; EState *estate = node->ps.state; List *lst; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index a978e233e3dfecdd970e0cb3b053096e6e3d63d9..f7aa8fcb7ec83771c8310905551f563e5e0925fd 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.229 2002/12/06 05:00:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.230 2002/12/12 15:49:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -563,21 +563,6 @@ _copyLimit(Limit *from) 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 * **************************************************************** @@ -603,20 +588,9 @@ _copyResdom(Resdom *from) return newnode; } -static Fjoin * -_copyFjoin(Fjoin *from) -{ - Fjoin *newnode = makeNode(Fjoin); - - COPY_SCALAR_FIELD(fj_initialized); - COPY_SCALAR_FIELD(fj_nNodes); - COPY_NODE_FIELD(fj_innerNode); - COPY_POINTER_FIELD(fj_results, from->fj_nNodes * sizeof(Datum)); - COPY_POINTER_FIELD(fj_alwaysDone, from->fj_nNodes * sizeof(bool)); - - return newnode; -} - +/* + * _copyAlias + */ static Alias * _copyAlias(Alias *from) { @@ -628,6 +602,9 @@ _copyAlias(Alias *from) return newnode; } +/* + * _copyRangeVar + */ static RangeVar * _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 @@ -678,25 +646,6 @@ _copyVar(Var *from) 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 */ @@ -749,17 +698,57 @@ _copyParam(Param *from) } /* - * _copyFunc + * _copyAggref */ -static Func * -_copyFunc(Func *from) +static Aggref * +_copyAggref(Aggref *from) { - Func *newnode = makeNode(Func); + Aggref *newnode = makeNode(Aggref); + + COPY_SCALAR_FIELD(aggfnoid); + COPY_SCALAR_FIELD(aggtype); + COPY_NODE_FIELD(target); + COPY_SCALAR_FIELD(aggstar); + COPY_SCALAR_FIELD(aggdistinct); + COPY_SCALAR_FIELD(aggno); /* will go away soon */ + + return newnode; +} + +/* + * _copyArrayRef + */ +static ArrayRef * +_copyArrayRef(ArrayRef *from) +{ + ArrayRef *newnode = makeNode(ArrayRef); + + COPY_SCALAR_FIELD(refrestype); + COPY_SCALAR_FIELD(refattrlength); + COPY_SCALAR_FIELD(refelemlength); + COPY_SCALAR_FIELD(refelembyval); + COPY_SCALAR_FIELD(refelemalign); + COPY_NODE_FIELD(refupperindexpr); + COPY_NODE_FIELD(reflowerindexpr); + COPY_NODE_FIELD(refexpr); + COPY_NODE_FIELD(refassgnexpr); + + return newnode; +} + +/* + * _copyFuncExpr + */ +static FuncExpr * +_copyFuncExpr(FuncExpr *from) +{ + FuncExpr *newnode = makeNode(FuncExpr); COPY_SCALAR_FIELD(funcid); COPY_SCALAR_FIELD(funcresulttype); COPY_SCALAR_FIELD(funcretset); COPY_SCALAR_FIELD(funcformat); + COPY_NODE_FIELD(args); /* Do not copy the run-time state, if any */ newnode->func_fcache = NULL; @@ -768,19 +757,55 @@ _copyFunc(Func *from) } /* - * _copyAggref + * _copyOpExpr */ -static Aggref * -_copyAggref(Aggref *from) +static OpExpr * +_copyOpExpr(OpExpr *from) { - Aggref *newnode = makeNode(Aggref); + OpExpr *newnode = makeNode(OpExpr); - COPY_SCALAR_FIELD(aggfnoid); - COPY_SCALAR_FIELD(aggtype); - COPY_NODE_FIELD(target); - COPY_SCALAR_FIELD(aggstar); - COPY_SCALAR_FIELD(aggdistinct); - COPY_SCALAR_FIELD(aggno); /* probably not necessary */ + COPY_SCALAR_FIELD(opno); + COPY_SCALAR_FIELD(opfuncid); + COPY_SCALAR_FIELD(opresulttype); + COPY_SCALAR_FIELD(opretset); + COPY_NODE_FIELD(args); + + /* Do not copy the run-time state, if any */ + newnode->op_fcache = NULL; + + return newnode; +} + +/* + * _copyDistinctExpr + */ +static DistinctExpr * +_copyDistinctExpr(DistinctExpr *from) +{ + DistinctExpr *newnode = makeNode(DistinctExpr); + + COPY_SCALAR_FIELD(opno); + COPY_SCALAR_FIELD(opfuncid); + COPY_SCALAR_FIELD(opresulttype); + COPY_SCALAR_FIELD(opretset); + COPY_NODE_FIELD(args); + + /* Do not copy the run-time state, if any */ + newnode->op_fcache = NULL; + + return newnode; +} + +/* + * _copyBoolExpr + */ +static BoolExpr * +_copyBoolExpr(BoolExpr *from) +{ + BoolExpr *newnode = makeNode(BoolExpr); + + COPY_SCALAR_FIELD(boolop); + COPY_NODE_FIELD(args); return newnode; } @@ -802,6 +827,26 @@ _copySubLink(SubLink *from) 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 */ @@ -834,6 +879,112 @@ _copyRelabelType(RelabelType *from) return newnode; } +/* + * _copyCaseExpr + */ +static CaseExpr * +_copyCaseExpr(CaseExpr *from) +{ + CaseExpr *newnode = makeNode(CaseExpr); + + COPY_SCALAR_FIELD(casetype); + COPY_NODE_FIELD(arg); + COPY_NODE_FIELD(args); + COPY_NODE_FIELD(defresult); + + return newnode; +} + +/* + * _copyCaseWhen + */ +static CaseWhen * +_copyCaseWhen(CaseWhen *from) +{ + CaseWhen *newnode = makeNode(CaseWhen); + + COPY_NODE_FIELD(expr); + COPY_NODE_FIELD(result); + + return newnode; +} + +/* + * _copyNullTest + */ +static NullTest * +_copyNullTest(NullTest *from) +{ + NullTest *newnode = makeNode(NullTest); + + COPY_NODE_FIELD(arg); + COPY_SCALAR_FIELD(nulltesttype); + + return newnode; +} + +/* + * _copyBooleanTest + */ +static BooleanTest * +_copyBooleanTest(BooleanTest *from) +{ + BooleanTest *newnode = makeNode(BooleanTest); + + COPY_NODE_FIELD(arg); + COPY_SCALAR_FIELD(booltesttype); + + return newnode; +} + +/* + * _copyConstraintTest + */ +static ConstraintTest * +_copyConstraintTest(ConstraintTest *from) +{ + ConstraintTest *newnode = makeNode(ConstraintTest); + + COPY_NODE_FIELD(arg); + COPY_SCALAR_FIELD(testtype); + COPY_STRING_FIELD(name); + COPY_STRING_FIELD(domname); + COPY_NODE_FIELD(check_expr); + + return newnode; +} + +/* + * _copyConstraintTestValue + */ +static ConstraintTestValue * +_copyConstraintTestValue(ConstraintTestValue *from) +{ + ConstraintTestValue *newnode = makeNode(ConstraintTestValue); + + COPY_SCALAR_FIELD(typeId); + COPY_SCALAR_FIELD(typeMod); + + return newnode; +} + +/* + * _copyTargetEntry + */ +static TargetEntry * +_copyTargetEntry(TargetEntry *from) +{ + TargetEntry *newnode = makeNode(TargetEntry); + + COPY_NODE_FIELD(resdom); + COPY_NODE_FIELD(expr); + + return newnode; +} + +/* + * _copyRangeTblRef + */ static RangeTblRef * _copyRangeTblRef(RangeTblRef *from) { @@ -844,6 +995,9 @@ _copyRangeTblRef(RangeTblRef *from) return newnode; } +/* + * _copyJoinExpr + */ static JoinExpr * _copyJoinExpr(JoinExpr *from) { @@ -861,6 +1015,9 @@ _copyJoinExpr(JoinExpr *from) return newnode; } +/* + * _copyFromExpr + */ static FromExpr * _copyFromExpr(FromExpr *from) { @@ -872,24 +1029,6 @@ _copyFromExpr(FromExpr *from) return newnode; } -static ArrayRef * -_copyArrayRef(ArrayRef *from) -{ - ArrayRef *newnode = makeNode(ArrayRef); - - COPY_SCALAR_FIELD(refrestype); - COPY_SCALAR_FIELD(refattrlength); - COPY_SCALAR_FIELD(refelemlength); - COPY_SCALAR_FIELD(refelembyval); - COPY_SCALAR_FIELD(refelemalign); - COPY_NODE_FIELD(refupperindexpr); - COPY_NODE_FIELD(reflowerindexpr); - COPY_NODE_FIELD(refexpr); - COPY_NODE_FIELD(refassgnexpr); - - return newnode; -} - /* **************************************************************** * relation.h copy functions * @@ -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 * _copyRangeTblEntry(RangeTblEntry *from) { @@ -1170,6 +1297,14 @@ _copyTypeName(TypeName *from) return newnode; } +static DomainConstraintValue * +_copyDomainConstraintValue(DomainConstraintValue *from) +{ + DomainConstraintValue *newnode = makeNode(DomainConstraintValue); + + return newnode; +} + static SortGroupBy * _copySortGroupBy(SortGroupBy *from) { @@ -1260,85 +1395,6 @@ _copyConstraint(Constraint *from) return newnode; } -static CaseExpr * -_copyCaseExpr(CaseExpr *from) -{ - CaseExpr *newnode = makeNode(CaseExpr); - - COPY_SCALAR_FIELD(casetype); - COPY_NODE_FIELD(arg); - COPY_NODE_FIELD(args); - COPY_NODE_FIELD(defresult); - - return newnode; -} - -static CaseWhen * -_copyCaseWhen(CaseWhen *from) -{ - CaseWhen *newnode = makeNode(CaseWhen); - - COPY_NODE_FIELD(expr); - COPY_NODE_FIELD(result); - - return newnode; -} - -static NullTest * -_copyNullTest(NullTest *from) -{ - NullTest *newnode = makeNode(NullTest); - - COPY_NODE_FIELD(arg); - COPY_SCALAR_FIELD(nulltesttype); - - return newnode; -} - -static BooleanTest * -_copyBooleanTest(BooleanTest *from) -{ - BooleanTest *newnode = makeNode(BooleanTest); - - COPY_NODE_FIELD(arg); - COPY_SCALAR_FIELD(booltesttype); - - return newnode; -} - -static ConstraintTest * -_copyConstraintTest(ConstraintTest *from) -{ - ConstraintTest *newnode = makeNode(ConstraintTest); - - COPY_NODE_FIELD(arg); - COPY_SCALAR_FIELD(testtype); - COPY_STRING_FIELD(name); - COPY_STRING_FIELD(domname); - COPY_NODE_FIELD(check_expr); - - return newnode; -} - -static DomainConstraintValue * -_copyDomainConstraintValue(DomainConstraintValue *from) -{ - DomainConstraintValue *newnode = makeNode(DomainConstraintValue); - - return newnode; -} - -static ConstraintTestValue * -_copyConstraintTestValue(ConstraintTestValue *from) -{ - ConstraintTestValue *newnode = makeNode(ConstraintTestValue); - - COPY_SCALAR_FIELD(typeId); - COPY_SCALAR_FIELD(typeMod); - - return newnode; -} - static DefElem * _copyDefElem(DefElem *from) { @@ -2350,9 +2406,6 @@ copyObject(void *from) case T_Limit: retval = _copyLimit(from); break; - case T_SubPlan: - retval = _copySubPlan(from); - break; /* * PRIMITIVE NODES @@ -2360,45 +2413,72 @@ copyObject(void *from) case T_Resdom: retval = _copyResdom(from); break; - case T_Fjoin: - retval = _copyFjoin(from); - break; case T_Alias: retval = _copyAlias(from); break; case T_RangeVar: retval = _copyRangeVar(from); break; - case T_Expr: - retval = _copyExpr(from); - break; case T_Var: retval = _copyVar(from); break; - case T_Oper: - retval = _copyOper(from); - break; case T_Const: retval = _copyConst(from); break; case T_Param: retval = _copyParam(from); break; - case T_Func: - retval = _copyFunc(from); - break; case T_Aggref: retval = _copyAggref(from); break; + case T_ArrayRef: + retval = _copyArrayRef(from); + break; + case T_FuncExpr: + retval = _copyFuncExpr(from); + break; + case T_OpExpr: + retval = _copyOpExpr(from); + break; + case T_DistinctExpr: + retval = _copyDistinctExpr(from); + break; + case T_BoolExpr: + retval = _copyBoolExpr(from); + break; case T_SubLink: retval = _copySubLink(from); break; + case T_SubPlanExpr: + retval = _copySubPlanExpr(from); + break; case T_FieldSelect: retval = _copyFieldSelect(from); break; case T_RelabelType: retval = _copyRelabelType(from); break; + case T_CaseExpr: + retval = _copyCaseExpr(from); + break; + case T_CaseWhen: + retval = _copyCaseWhen(from); + break; + case T_NullTest: + retval = _copyNullTest(from); + break; + case T_BooleanTest: + retval = _copyBooleanTest(from); + break; + case T_ConstraintTest: + retval = _copyConstraintTest(from); + break; + case T_ConstraintTestValue: + retval = _copyConstraintTestValue(from); + break; + case T_TargetEntry: + retval = _copyTargetEntry(from); + break; case T_RangeTblRef: retval = _copyRangeTblRef(from); break; @@ -2408,9 +2488,6 @@ copyObject(void *from) case T_FromExpr: retval = _copyFromExpr(from); break; - case T_ArrayRef: - retval = _copyArrayRef(from); - break; /* * RELATION NODES @@ -2686,6 +2763,9 @@ copyObject(void *from) case T_TypeCast: retval = _copyTypeCast(from); break; + case T_DomainConstraintValue: + retval = _copyDomainConstraintValue(from); + break; case T_SortGroupBy: retval = _copySortGroupBy(from); break; @@ -2710,9 +2790,6 @@ copyObject(void *from) case T_DefElem: retval = _copyDefElem(from); break; - case T_TargetEntry: - retval = _copyTargetEntry(from); - break; case T_RangeTblEntry: retval = _copyRangeTblEntry(from); break; @@ -2722,24 +2799,6 @@ copyObject(void *from) case T_GroupClause: retval = _copyGroupClause(from); break; - case T_CaseExpr: - retval = _copyCaseExpr(from); - break; - case T_CaseWhen: - retval = _copyCaseWhen(from); - break; - case T_NullTest: - retval = _copyNullTest(from); - break; - case T_BooleanTest: - retval = _copyBooleanTest(from); - break; - case T_ConstraintTest: - retval = _copyConstraintTest(from); - break; - case T_ConstraintTestValue: - retval = _copyConstraintTestValue(from); - break; case T_FkConstraint: retval = _copyFkConstraint(from); break; @@ -2752,9 +2811,6 @@ copyObject(void *from) case T_InsertDefault: retval = _copyInsertDefault(from); break; - case T_DomainConstraintValue: - retval = _copyDomainConstraintValue(from); - break; default: elog(ERROR, "copyObject: don't know how to copy node type %d", diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 7122709710476ee3ef5329595dee0d01823d2a49..3b5103820688fc065bcb7bbd08087b7eae9eddf1 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.174 2002/12/06 05:00:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.175 2002/12/12 15:49:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,6 @@ #include "nodes/params.h" #include "nodes/parsenodes.h" -#include "nodes/plannodes.h" #include "nodes/relation.h" #include "utils/datum.h" @@ -98,18 +97,6 @@ _equalResdom(Resdom *a, Resdom *b) return true; } -static bool -_equalFjoin(Fjoin *a, Fjoin *b) -{ - COMPARE_SCALAR_FIELD(fj_initialized); - COMPARE_SCALAR_FIELD(fj_nNodes); - COMPARE_NODE_FIELD(fj_innerNode); - COMPARE_POINTER_FIELD(fj_results, a->fj_nNodes * sizeof(Datum)); - COMPARE_POINTER_FIELD(fj_alwaysDone, a->fj_nNodes * sizeof(bool)); - - return true; -} - static bool _equalAlias(Alias *a, Alias *b) { @@ -132,20 +119,12 @@ _equalRangeVar(RangeVar *a, RangeVar *b) return true; } -static bool -_equalExpr(Expr *a, Expr *b) -{ - /* - * We do not examine typeOid, since the optimizer often doesn't bother - * to set it in created nodes, and it is logically a derivative of the - * oper field anyway. - */ - COMPARE_SCALAR_FIELD(opType); - COMPARE_NODE_FIELD(oper); - COMPARE_NODE_FIELD(args); - - return true; -} +/* + * We don't need an _equalExpr because Expr is an abstract supertype which + * should never actually get instantiated. Also, since it has no common + * fields except NodeTag, there's no need for a helper routine to factor + * out comparing the common fields... + */ static bool _equalVar(Var *a, Var *b) @@ -161,28 +140,6 @@ _equalVar(Var *a, Var *b) return true; } -static bool -_equalOper(Oper *a, Oper *b) -{ - COMPARE_SCALAR_FIELD(opno); - COMPARE_SCALAR_FIELD(opresulttype); - COMPARE_SCALAR_FIELD(opretset); - - /* - * We do not examine opid or op_fcache, since these are logically - * derived from opno, and they may not be set yet depending on how far - * along the node is in the parse/plan pipeline. - * - * (Besides, op_fcache is executor state, which we don't check --- see - * notes at head of file.) - * - * It's probably not really necessary to check opresulttype or opretset, - * either... - */ - - return true; -} - static bool _equalConst(Const *a, Const *b) { @@ -226,7 +183,35 @@ _equalParam(Param *a, Param *b) } static bool -_equalFunc(Func *a, Func *b) +_equalAggref(Aggref *a, Aggref *b) +{ + COMPARE_SCALAR_FIELD(aggfnoid); + COMPARE_SCALAR_FIELD(aggtype); + COMPARE_NODE_FIELD(target); + COMPARE_SCALAR_FIELD(aggstar); + COMPARE_SCALAR_FIELD(aggdistinct); + + return true; +} + +static bool +_equalArrayRef(ArrayRef *a, ArrayRef *b) +{ + COMPARE_SCALAR_FIELD(refrestype); + COMPARE_SCALAR_FIELD(refattrlength); + COMPARE_SCALAR_FIELD(refelemlength); + COMPARE_SCALAR_FIELD(refelembyval); + COMPARE_SCALAR_FIELD(refelemalign); + COMPARE_NODE_FIELD(refupperindexpr); + COMPARE_NODE_FIELD(reflowerindexpr); + COMPARE_NODE_FIELD(refexpr); + COMPARE_NODE_FIELD(refassgnexpr); + + return true; +} + +static bool +_equalFuncExpr(FuncExpr *a, FuncExpr *b) { COMPARE_SCALAR_FIELD(funcid); COMPARE_SCALAR_FIELD(funcresulttype); @@ -240,20 +225,60 @@ _equalFunc(Func *a, Func *b) b->funcformat != COERCE_DONTCARE) return false; - /* Note we do not look at func_fcache; see notes for _equalOper */ + COMPARE_NODE_FIELD(args); return true; } static bool -_equalAggref(Aggref *a, Aggref *b) +_equalOpExpr(OpExpr *a, OpExpr *b) { - COMPARE_SCALAR_FIELD(aggfnoid); - COMPARE_SCALAR_FIELD(aggtype); - COMPARE_NODE_FIELD(target); - COMPARE_SCALAR_FIELD(aggstar); - COMPARE_SCALAR_FIELD(aggdistinct); - /* ignore aggno, which is only a private field for the executor */ + COMPARE_SCALAR_FIELD(opno); + /* + * Special-case opfuncid: it is allowable for it to differ if one + * node contains zero and the other doesn't. This just means that the + * one node isn't as far along in the parse/plan pipeline and hasn't + * had the opfuncid cache filled yet. + */ + if (a->opfuncid != b->opfuncid && + a->opfuncid != 0 && + b->opfuncid != 0) + return false; + + COMPARE_SCALAR_FIELD(opresulttype); + COMPARE_SCALAR_FIELD(opretset); + COMPARE_NODE_FIELD(args); + + return true; +} + +static bool +_equalDistinctExpr(DistinctExpr *a, DistinctExpr *b) +{ + COMPARE_SCALAR_FIELD(opno); + /* + * Special-case opfuncid: it is allowable for it to differ if one + * node contains zero and the other doesn't. This just means that the + * one node isn't as far along in the parse/plan pipeline and hasn't + * had the opfuncid cache filled yet. + */ + if (a->opfuncid != b->opfuncid && + a->opfuncid != 0 && + b->opfuncid != 0) + return false; + + COMPARE_SCALAR_FIELD(opresulttype); + COMPARE_SCALAR_FIELD(opretset); + COMPARE_NODE_FIELD(args); + + return true; +} + +static bool +_equalBoolExpr(BoolExpr *a, BoolExpr *b) +{ + COMPARE_SCALAR_FIELD(boolop); + COMPARE_NODE_FIELD(args); return true; } @@ -270,6 +295,21 @@ _equalSubLink(SubLink *a, SubLink *b) return true; } +static bool +_equalSubPlanExpr(SubPlanExpr *a, SubPlanExpr *b) +{ + COMPARE_SCALAR_FIELD(typeOid); + /* should compare plans, but have to settle for comparing plan IDs */ + COMPARE_SCALAR_FIELD(plan_id); + COMPARE_NODE_FIELD(rtable); + COMPARE_INTLIST_FIELD(setParam); + COMPARE_INTLIST_FIELD(parParam); + COMPARE_NODE_FIELD(args); + COMPARE_NODE_FIELD(sublink); + + return true; +} + static bool _equalFieldSelect(FieldSelect *a, FieldSelect *b) { @@ -300,66 +340,101 @@ _equalRelabelType(RelabelType *a, RelabelType *b) } static bool -_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b) +_equalCaseExpr(CaseExpr *a, CaseExpr *b) { - COMPARE_SCALAR_FIELD(rtindex); + COMPARE_SCALAR_FIELD(casetype); + COMPARE_NODE_FIELD(arg); + COMPARE_NODE_FIELD(args); + COMPARE_NODE_FIELD(defresult); return true; } static bool -_equalJoinExpr(JoinExpr *a, JoinExpr *b) +_equalCaseWhen(CaseWhen *a, CaseWhen *b) { - COMPARE_SCALAR_FIELD(jointype); - COMPARE_SCALAR_FIELD(isNatural); - COMPARE_NODE_FIELD(larg); - COMPARE_NODE_FIELD(rarg); - COMPARE_NODE_FIELD(using); - COMPARE_NODE_FIELD(quals); - COMPARE_NODE_FIELD(alias); - COMPARE_SCALAR_FIELD(rtindex); + COMPARE_NODE_FIELD(expr); + COMPARE_NODE_FIELD(result); return true; } static bool -_equalFromExpr(FromExpr *a, FromExpr *b) +_equalNullTest(NullTest *a, NullTest *b) { - COMPARE_NODE_FIELD(fromlist); - COMPARE_NODE_FIELD(quals); + COMPARE_NODE_FIELD(arg); + COMPARE_SCALAR_FIELD(nulltesttype); return true; } static bool -_equalArrayRef(ArrayRef *a, ArrayRef *b) +_equalBooleanTest(BooleanTest *a, BooleanTest *b) { - COMPARE_SCALAR_FIELD(refrestype); - COMPARE_SCALAR_FIELD(refattrlength); - COMPARE_SCALAR_FIELD(refelemlength); - COMPARE_SCALAR_FIELD(refelembyval); - COMPARE_SCALAR_FIELD(refelemalign); - COMPARE_NODE_FIELD(refupperindexpr); - COMPARE_NODE_FIELD(reflowerindexpr); - COMPARE_NODE_FIELD(refexpr); - COMPARE_NODE_FIELD(refassgnexpr); + COMPARE_NODE_FIELD(arg); + COMPARE_SCALAR_FIELD(booltesttype); return true; } +static bool +_equalConstraintTest(ConstraintTest *a, ConstraintTest *b) +{ + COMPARE_NODE_FIELD(arg); + COMPARE_SCALAR_FIELD(testtype); + COMPARE_STRING_FIELD(name); + COMPARE_STRING_FIELD(domname); + COMPARE_NODE_FIELD(check_expr); -/* - * Stuff from plannodes.h - */ + return true; +} static bool -_equalSubPlan(SubPlan *a, SubPlan *b) +_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b) { - /* should compare plans, but have to settle for comparing plan IDs */ - COMPARE_SCALAR_FIELD(plan_id); + COMPARE_SCALAR_FIELD(typeId); + COMPARE_SCALAR_FIELD(typeMod); - COMPARE_NODE_FIELD(rtable); - COMPARE_NODE_FIELD(sublink); + return true; +} + +static bool +_equalTargetEntry(TargetEntry *a, TargetEntry *b) +{ + COMPARE_NODE_FIELD(resdom); + COMPARE_NODE_FIELD(expr); + + return true; +} + +static bool +_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b) +{ + COMPARE_SCALAR_FIELD(rtindex); + + return true; +} + +static bool +_equalJoinExpr(JoinExpr *a, JoinExpr *b) +{ + COMPARE_SCALAR_FIELD(jointype); + COMPARE_SCALAR_FIELD(isNatural); + COMPARE_NODE_FIELD(larg); + COMPARE_NODE_FIELD(rarg); + COMPARE_NODE_FIELD(using); + COMPARE_NODE_FIELD(quals); + COMPARE_NODE_FIELD(alias); + COMPARE_SCALAR_FIELD(rtindex); + + return true; +} + +static bool +_equalFromExpr(FromExpr *a, FromExpr *b) +{ + COMPARE_NODE_FIELD(fromlist); + COMPARE_NODE_FIELD(quals); return true; } @@ -573,6 +648,12 @@ _equalInsertDefault(InsertDefault *a, InsertDefault *b) return true; } +static bool +_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b) +{ + return true; +} + static bool _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b) { @@ -1340,16 +1421,6 @@ _equalDefElem(DefElem *a, DefElem *b) return true; } -static bool -_equalTargetEntry(TargetEntry *a, TargetEntry *b) -{ - COMPARE_NODE_FIELD(resdom); - COMPARE_NODE_FIELD(fjoin); - COMPARE_NODE_FIELD(expr); - - return true; -} - static bool _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b) { @@ -1397,71 +1468,6 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b) return true; } -static bool -_equalCaseExpr(CaseExpr *a, CaseExpr *b) -{ - COMPARE_SCALAR_FIELD(casetype); - COMPARE_NODE_FIELD(arg); - COMPARE_NODE_FIELD(args); - COMPARE_NODE_FIELD(defresult); - - return true; -} - -static bool -_equalCaseWhen(CaseWhen *a, CaseWhen *b) -{ - COMPARE_NODE_FIELD(expr); - COMPARE_NODE_FIELD(result); - - return true; -} - -static bool -_equalNullTest(NullTest *a, NullTest *b) -{ - COMPARE_NODE_FIELD(arg); - COMPARE_SCALAR_FIELD(nulltesttype); - - return true; -} - -static bool -_equalBooleanTest(BooleanTest *a, BooleanTest *b) -{ - COMPARE_NODE_FIELD(arg); - COMPARE_SCALAR_FIELD(booltesttype); - - return true; -} - -static bool -_equalConstraintTest(ConstraintTest *a, ConstraintTest *b) -{ - COMPARE_NODE_FIELD(arg); - COMPARE_SCALAR_FIELD(testtype); - COMPARE_STRING_FIELD(name); - COMPARE_STRING_FIELD(domname); - COMPARE_NODE_FIELD(check_expr); - - return true; -} - -static bool -_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b) -{ - return true; -} - -static bool -_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b) -{ - COMPARE_SCALAR_FIELD(typeId); - COMPARE_SCALAR_FIELD(typeMod); - - return true; -} - /* * Stuff from pg_list.h @@ -1519,25 +1525,21 @@ equal(void *a, void *b) switch (nodeTag(a)) { - case T_SubPlan: - retval = _equalSubPlan(a, b); - break; - + /* + * PRIMITIVE NODES + */ case T_Resdom: retval = _equalResdom(a, b); break; - case T_Fjoin: - retval = _equalFjoin(a, b); + case T_Alias: + retval = _equalAlias(a, b); break; - case T_Expr: - retval = _equalExpr(a, b); + case T_RangeVar: + retval = _equalRangeVar(a, b); break; case T_Var: retval = _equalVar(a, b); break; - case T_Oper: - retval = _equalOper(a, b); - break; case T_Const: retval = _equalConst(a, b); break; @@ -1547,21 +1549,54 @@ equal(void *a, void *b) case T_Aggref: retval = _equalAggref(a, b); break; + case T_ArrayRef: + retval = _equalArrayRef(a, b); + break; + case T_FuncExpr: + retval = _equalFuncExpr(a, b); + break; + case T_OpExpr: + retval = _equalOpExpr(a, b); + break; + case T_DistinctExpr: + retval = _equalDistinctExpr(a, b); + break; + case T_BoolExpr: + retval = _equalBoolExpr(a, b); + break; case T_SubLink: retval = _equalSubLink(a, b); break; - case T_Func: - retval = _equalFunc(a, b); + case T_SubPlanExpr: + retval = _equalSubPlanExpr(a, b); break; case T_FieldSelect: retval = _equalFieldSelect(a, b); break; - case T_ArrayRef: - retval = _equalArrayRef(a, b); - break; case T_RelabelType: retval = _equalRelabelType(a, b); break; + case T_CaseExpr: + retval = _equalCaseExpr(a, b); + break; + case T_CaseWhen: + retval = _equalCaseWhen(a, b); + break; + case T_NullTest: + retval = _equalNullTest(a, b); + break; + case T_BooleanTest: + retval = _equalBooleanTest(a, b); + break; + case T_ConstraintTest: + retval = _equalConstraintTest(a, b); + break; + case T_ConstraintTestValue: + retval = _equalConstraintTestValue(a, b); + break; + case T_TargetEntry: + retval = _equalTargetEntry(a, b); + break; case T_RangeTblRef: retval = _equalRangeTblRef(a, b); break; @@ -1572,6 +1607,9 @@ equal(void *a, void *b) retval = _equalJoinExpr(a, b); break; + /* + * RELATION NODES + */ case T_PathKeyItem: retval = _equalPathKeyItem(a, b); break; @@ -1582,6 +1620,9 @@ equal(void *a, void *b) retval = _equalJoinInfo(a, b); break; + /* + * LIST NODES + */ case T_List: { List *la = (List *) a; @@ -1612,6 +1653,9 @@ equal(void *a, void *b) retval = _equalValue(a, b); break; + /* + * PARSE NODES + */ case T_Query: retval = _equalQuery(a, b); break; @@ -1844,12 +1888,6 @@ equal(void *a, void *b) case T_SortGroupBy: retval = _equalSortGroupBy(a, b); break; - case T_Alias: - retval = _equalAlias(a, b); - break; - case T_RangeVar: - retval = _equalRangeVar(a, b); - break; case T_RangeSubselect: retval = _equalRangeSubselect(a, b); break; @@ -1871,9 +1909,6 @@ equal(void *a, void *b) case T_DefElem: retval = _equalDefElem(a, b); break; - case T_TargetEntry: - retval = _equalTargetEntry(a, b); - break; case T_RangeTblEntry: retval = _equalRangeTblEntry(a, b); break; @@ -1884,24 +1919,6 @@ equal(void *a, void *b) /* GroupClause is equivalent to SortClause */ retval = _equalSortClause(a, b); break; - case T_CaseExpr: - retval = _equalCaseExpr(a, b); - break; - case T_CaseWhen: - retval = _equalCaseWhen(a, b); - break; - case T_NullTest: - retval = _equalNullTest(a, b); - break; - case T_BooleanTest: - retval = _equalBooleanTest(a, b); - break; - case T_ConstraintTest: - retval = _equalConstraintTest(a, b); - break; - case T_ConstraintTestValue: - retval = _equalConstraintTestValue(a, b); - break; case T_FkConstraint: retval = _equalFkConstraint(a, b); break; diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index a97a6df2fda3d0ae366b352bc33d80f02fca31f6..de13e943d5e22f2b5023e9d8d506f25111365123 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -1,4 +1,5 @@ -/* +/*------------------------------------------------------------------------- + * * makefuncs.c * creator functions for primitive nodes. The functions here are for * the most frequently created nodes. @@ -8,7 +9,9 @@ * * * 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" @@ -49,30 +52,9 @@ makeSimpleA_Expr(int oper, const char *name, return a; } -/* - * makeOper - - * creates an Oper node - */ -Oper * -makeOper(Oid opno, - Oid opid, - Oid opresulttype, - bool opretset) -{ - Oper *oper = makeNode(Oper); - - oper->opno = opno; - oper->opid = opid; - oper->opresulttype = opresulttype; - oper->opretset = opretset; - oper->op_fcache = NULL; - return oper; -} - /* * makeVar - * creates a Var node - * */ Var * makeVar(Index varno, @@ -104,10 +86,10 @@ makeVar(Index varno, /* * makeTargetEntry - - * creates a TargetEntry node(contains a Resdom) + * creates a TargetEntry node (contains a Resdom) */ TargetEntry * -makeTargetEntry(Resdom *resdom, Node *expr) +makeTargetEntry(Resdom *resdom, Expr *expr) { TargetEntry *rt = makeNode(TargetEntry); @@ -188,6 +170,21 @@ makeNullConst(Oid consttype) typByVal); } +/* + * makeBoolExpr - + * creates a BoolExpr node + */ +Expr * +makeBoolExpr(BoolExprType boolop, List *args) +{ + BoolExpr *b = makeNode(BoolExpr); + + b->boolop = boolop; + b->args = args; + + return (Expr *) b; +} + /* * makeAlias - * creates an Alias node @@ -210,7 +207,7 @@ makeAlias(const char *aliasname, List *colnames) * creates a RelabelType node */ RelabelType * -makeRelabelType(Node *arg, Oid rtype, int32 rtypmod, CoercionForm rformat) +makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat) { RelabelType *r = makeNode(RelabelType); diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index f2bfb0a7d2d6b0c62725c6ffa8902825f02389c2..299c910cc3bd9f349796d5d158066c8efe3516c4 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -8,12 +8,10 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.19 2002/09/02 02:47:02 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.20 2002/12/12 15:49:28 tgl Exp $ * *------------------------------------------------------------------------- */ - - #include "postgres.h" #include "nodes/nodeFuncs.h" @@ -21,6 +19,7 @@ static bool var_is_inner(Var *var); + /* * single_node - * Returns t if node corresponds to a single-noded expression @@ -79,41 +78,15 @@ var_is_rel(Var *var) *****************************************************************************/ /* - * replace_opid - - * - * Given a oper node, resets the opfid field with the - * procedure OID (regproc id). - * - * Returns the modified oper node. + * set_opfuncid - * + * Set the opfuncid (procedure OID) in an OpExpr node, + * if it hasn't been set already. */ -Oper * -replace_opid(Oper *oper) +void +set_opfuncid(OpExpr *opexpr) { - oper->opid = get_opcode(oper->opno); - oper->op_fcache = NULL; - return oper; + if (opexpr->opfuncid == InvalidOid) + opexpr->opfuncid = get_opcode(opexpr->opno); + opexpr->op_fcache = NULL; /* XXX will go away soon */ } - -/***************************************************************************** - * constant (CONST, PARAM) nodes - *****************************************************************************/ - -#ifdef NOT_USED -/* - * non_null - - * Returns t if the node is a non-null constant, e.g., if the node has a - * valid `constvalue' field. - */ -bool -non_null(Expr *c) -{ - - if (IsA(c, Const) && - !((Const *) c)->constisnull) - return true; - else - return false; -} - -#endif diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 2c254001eec926522737828c579f710819e17ee2..bd44816e6fab60020e9e05814a5308382e70195b 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.186 2002/12/05 15:50:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.187 2002/12/12 15:49:28 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -99,9 +99,9 @@ #define booltostr(x) ((x) ? "true" : "false") -static void _outDatum(StringInfo str, Datum value, int typlen, bool typbyval); static void _outNode(StringInfo str, void *obj); + /* * _outToken * Convert an ordinary string (eg, an identifier) into a form that @@ -172,196 +172,41 @@ _outOidList(StringInfo str, List *list) appendStringInfoChar(str, ')'); } +/* + * Print the value of a Datum given its type. + */ static void -_outCreateStmt(StringInfo str, CreateStmt *node) -{ - WRITE_NODE_TYPE("CREATE"); - - WRITE_NODE_FIELD(relation); - WRITE_NODE_FIELD(tableElts); - WRITE_NODE_FIELD(inhRelations); - WRITE_NODE_FIELD(constraints); - WRITE_BOOL_FIELD(hasoids); - WRITE_ENUM_FIELD(oncommit, OnCommitAction); -} - -static void -_outIndexStmt(StringInfo str, IndexStmt *node) -{ - WRITE_NODE_TYPE("INDEX"); - - WRITE_STRING_FIELD(idxname); - WRITE_NODE_FIELD(relation); - WRITE_STRING_FIELD(accessMethod); - WRITE_NODE_FIELD(indexParams); - WRITE_NODE_FIELD(whereClause); - WRITE_NODE_FIELD(rangetable); - WRITE_BOOL_FIELD(unique); - WRITE_BOOL_FIELD(primary); - WRITE_BOOL_FIELD(isconstraint); -} - -static void -_outNotifyStmt(StringInfo str, NotifyStmt *node) -{ - WRITE_NODE_TYPE("NOTIFY"); - - WRITE_NODE_FIELD(relation); -} - -static void -_outSelectStmt(StringInfo str, SelectStmt *node) -{ - WRITE_NODE_TYPE("SELECT"); - - /* XXX this is pretty durn incomplete */ - WRITE_NODE_FIELD(whereClause); -} - -static void -_outFuncCall(StringInfo str, FuncCall *node) -{ - WRITE_NODE_TYPE("FUNCCALL"); - - WRITE_NODE_FIELD(funcname); - WRITE_NODE_FIELD(args); - WRITE_BOOL_FIELD(agg_star); - WRITE_BOOL_FIELD(agg_distinct); -} - -static void -_outColumnDef(StringInfo str, ColumnDef *node) -{ - WRITE_NODE_TYPE("COLUMNDEF"); - - WRITE_STRING_FIELD(colname); - WRITE_NODE_FIELD(typename); - WRITE_INT_FIELD(inhcount); - WRITE_BOOL_FIELD(is_local); - WRITE_BOOL_FIELD(is_not_null); - WRITE_NODE_FIELD(raw_default); - WRITE_STRING_FIELD(cooked_default); - WRITE_NODE_FIELD(constraints); - WRITE_NODE_FIELD(support); -} - -static void -_outTypeName(StringInfo str, TypeName *node) -{ - WRITE_NODE_TYPE("TYPENAME"); - - WRITE_NODE_FIELD(names); - WRITE_OID_FIELD(typeid); - WRITE_BOOL_FIELD(timezone); - WRITE_BOOL_FIELD(setof); - WRITE_BOOL_FIELD(pct_type); - WRITE_INT_FIELD(typmod); - WRITE_NODE_FIELD(arrayBounds); -} - -static void -_outTypeCast(StringInfo str, TypeCast *node) -{ - WRITE_NODE_TYPE("TYPECAST"); - - WRITE_NODE_FIELD(arg); - WRITE_NODE_FIELD(typename); -} - -static void -_outIndexElem(StringInfo str, IndexElem *node) -{ - WRITE_NODE_TYPE("INDEXELEM"); - - WRITE_STRING_FIELD(name); - WRITE_NODE_FIELD(funcname); - WRITE_NODE_FIELD(args); - WRITE_NODE_FIELD(opclass); -} - -static void -_outQuery(StringInfo str, Query *node) +_outDatum(StringInfo str, Datum value, int typlen, bool typbyval) { - WRITE_NODE_TYPE("QUERY"); + Size length, + i; + char *s; - WRITE_ENUM_FIELD(commandType, CmdType); - WRITE_ENUM_FIELD(querySource, QuerySource); + length = datumGetSize(value, typbyval, typlen); - /* - * Hack to work around missing outfuncs routines for a lot of the - * utility-statement node types. (The only one we actually *need* for - * rules support is NotifyStmt.) Someday we ought to support 'em all, - * but for the meantime do this to avoid getting lots of warnings when - * running with debug_print_parse on. - */ - if (node->utilityStmt) + if (typbyval) { - switch (nodeTag(node->utilityStmt)) + s = (char *) (&value); + appendStringInfo(str, "%u [ ", (unsigned int) length); + for (i = 0; i < (Size) sizeof(Datum); i++) + appendStringInfo(str, "%d ", (int) (s[i])); + appendStringInfo(str, "]"); + } + else + { + s = (char *) DatumGetPointer(value); + if (!PointerIsValid(s)) + appendStringInfo(str, "0 [ ]"); + else { - case T_CreateStmt: - case T_IndexStmt: - case T_NotifyStmt: - WRITE_NODE_FIELD(utilityStmt); - break; - default: - appendStringInfo(str, " :utilityStmt ?"); - break; + appendStringInfo(str, "%u [ ", (unsigned int) length); + for (i = 0; i < length; i++) + appendStringInfo(str, "%d ", (int) (s[i])); + appendStringInfo(str, "]"); } } - else - appendStringInfo(str, " :utilityStmt <>"); - - WRITE_INT_FIELD(resultRelation); - WRITE_NODE_FIELD(into); - WRITE_BOOL_FIELD(isPortal); - WRITE_BOOL_FIELD(isBinary); - WRITE_BOOL_FIELD(hasAggs); - WRITE_BOOL_FIELD(hasSubLinks); - WRITE_NODE_FIELD(rtable); - WRITE_NODE_FIELD(jointree); - WRITE_INTLIST_FIELD(rowMarks); - WRITE_NODE_FIELD(targetList); - WRITE_NODE_FIELD(groupClause); - WRITE_NODE_FIELD(havingQual); - WRITE_NODE_FIELD(distinctClause); - WRITE_NODE_FIELD(sortClause); - WRITE_NODE_FIELD(limitOffset); - WRITE_NODE_FIELD(limitCount); - WRITE_NODE_FIELD(setOperations); - WRITE_INTLIST_FIELD(resultRelations); - - /* planner-internal fields are not written out */ -} - -static void -_outSortClause(StringInfo str, SortClause *node) -{ - WRITE_NODE_TYPE("SORTCLAUSE"); - - WRITE_UINT_FIELD(tleSortGroupRef); - WRITE_OID_FIELD(sortop); -} - -static void -_outGroupClause(StringInfo str, GroupClause *node) -{ - WRITE_NODE_TYPE("GROUPCLAUSE"); - - WRITE_UINT_FIELD(tleSortGroupRef); - WRITE_OID_FIELD(sortop); } -static void -_outSetOperationStmt(StringInfo str, SetOperationStmt *node) -{ - WRITE_NODE_TYPE("SETOPERATIONSTMT"); - - WRITE_ENUM_FIELD(op, SetOperation); - WRITE_BOOL_FIELD(all); - WRITE_NODE_FIELD(larg); - WRITE_NODE_FIELD(rarg); - WRITE_OIDLIST_FIELD(colTypes); -} /* * Stuff from plannodes.h @@ -631,19 +476,6 @@ _outHash(StringInfo str, Hash *node) WRITE_NODE_FIELD(hashkeys); } -static void -_outSubPlan(StringInfo str, SubPlan *node) -{ - WRITE_NODE_TYPE("SUBPLAN"); - - WRITE_NODE_FIELD(plan); - WRITE_INT_FIELD(plan_id); - WRITE_NODE_FIELD(rtable); - WRITE_INTLIST_FIELD(setParam); - WRITE_INTLIST_FIELD(parParam); - WRITE_NODE_FIELD(sublink); -} - /***************************************************************************** * * Stuff from primnodes.h. @@ -666,58 +498,42 @@ _outResdom(StringInfo str, Resdom *node) } static void -_outExpr(StringInfo str, Expr *node) +_outAlias(StringInfo str, Alias *node) { - char *opstr = NULL; - - WRITE_NODE_TYPE("EXPR"); - - WRITE_OID_FIELD(typeOid); - - /* do-it-yourself enum representation */ - switch (node->opType) - { - case OP_EXPR: - opstr = "op"; - break; - case DISTINCT_EXPR: - opstr = "distinct"; - break; - case FUNC_EXPR: - opstr = "func"; - break; - case OR_EXPR: - opstr = "or"; - break; - case AND_EXPR: - opstr = "and"; - break; - case NOT_EXPR: - opstr = "not"; - break; - case SUBPLAN_EXPR: - opstr = "subp"; - break; - } - appendStringInfo(str, " :opType "); - _outToken(str, opstr); + WRITE_NODE_TYPE("ALIAS"); - WRITE_NODE_FIELD(oper); - WRITE_NODE_FIELD(args); + WRITE_STRING_FIELD(aliasname); + WRITE_NODE_FIELD(colnames); } static void -_outVar(StringInfo str, Var *node) +_outRangeVar(StringInfo str, RangeVar *node) { - WRITE_NODE_TYPE("VAR"); + WRITE_NODE_TYPE("RANGEVAR"); - WRITE_UINT_FIELD(varno); - WRITE_INT_FIELD(varattno); - WRITE_OID_FIELD(vartype); - WRITE_INT_FIELD(vartypmod); - WRITE_UINT_FIELD(varlevelsup); - WRITE_UINT_FIELD(varnoold); - WRITE_INT_FIELD(varoattno); + /* + * we deliberately ignore catalogname here, since it is presently not + * semantically meaningful + */ + WRITE_STRING_FIELD(schemaname); + WRITE_STRING_FIELD(relname); + WRITE_ENUM_FIELD(inhOpt, InhOption); + WRITE_BOOL_FIELD(istemp); + WRITE_NODE_FIELD(alias); +} + +static void +_outVar(StringInfo str, Var *node) +{ + WRITE_NODE_TYPE("VAR"); + + WRITE_UINT_FIELD(varno); + WRITE_INT_FIELD(varattno); + WRITE_OID_FIELD(vartype); + WRITE_INT_FIELD(vartypmod); + WRITE_UINT_FIELD(varlevelsup); + WRITE_UINT_FIELD(varnoold); + WRITE_INT_FIELD(varoattno); } static void @@ -737,6 +553,17 @@ _outConst(StringInfo str, Const *node) _outDatum(str, node->constvalue, node->constlen, node->constbyval); } +static void +_outParam(StringInfo str, Param *node) +{ + WRITE_NODE_TYPE("PARAM"); + + WRITE_INT_FIELD(paramkind); + WRITE_INT_FIELD(paramid); + WRITE_STRING_FIELD(paramname); + WRITE_OID_FIELD(paramtype); +} + static void _outAggref(StringInfo str, Aggref *node) { @@ -747,19 +574,6 @@ _outAggref(StringInfo str, Aggref *node) WRITE_NODE_FIELD(target); WRITE_BOOL_FIELD(aggstar); WRITE_BOOL_FIELD(aggdistinct); - /* aggno is not saved since it is just executor state */ -} - -static void -_outSubLink(StringInfo str, SubLink *node) -{ - WRITE_NODE_TYPE("SUBLINK"); - - WRITE_ENUM_FIELD(subLinkType, SubLinkType); - WRITE_BOOL_FIELD(useor); - WRITE_NODE_FIELD(lefthand); - WRITE_NODE_FIELD(oper); - WRITE_NODE_FIELD(subselect); } static void @@ -779,36 +593,92 @@ _outArrayRef(StringInfo str, ArrayRef *node) } static void -_outFunc(StringInfo str, Func *node) +_outFuncExpr(StringInfo str, FuncExpr *node) { - WRITE_NODE_TYPE("FUNC"); + WRITE_NODE_TYPE("FUNCEXPR"); WRITE_OID_FIELD(funcid); WRITE_OID_FIELD(funcresulttype); WRITE_BOOL_FIELD(funcretset); WRITE_ENUM_FIELD(funcformat, CoercionForm); + WRITE_NODE_FIELD(args); +} + +static void +_outOpExpr(StringInfo str, OpExpr *node) +{ + WRITE_NODE_TYPE("OPEXPR"); + + WRITE_OID_FIELD(opno); + WRITE_OID_FIELD(opfuncid); + WRITE_OID_FIELD(opresulttype); + WRITE_BOOL_FIELD(opretset); + WRITE_NODE_FIELD(args); } static void -_outOper(StringInfo str, Oper *node) +_outDistinctExpr(StringInfo str, DistinctExpr *node) { - WRITE_NODE_TYPE("OPER"); + WRITE_NODE_TYPE("DISTINCTEXPR"); WRITE_OID_FIELD(opno); - WRITE_OID_FIELD(opid); + WRITE_OID_FIELD(opfuncid); WRITE_OID_FIELD(opresulttype); WRITE_BOOL_FIELD(opretset); + WRITE_NODE_FIELD(args); } static void -_outParam(StringInfo str, Param *node) +_outBoolExpr(StringInfo str, BoolExpr *node) { - WRITE_NODE_TYPE("PARAM"); + char *opstr = NULL; - WRITE_INT_FIELD(paramkind); - WRITE_INT_FIELD(paramid); - WRITE_STRING_FIELD(paramname); - WRITE_OID_FIELD(paramtype); + WRITE_NODE_TYPE("BOOLEXPR"); + + /* do-it-yourself enum representation */ + switch (node->boolop) + { + case AND_EXPR: + opstr = "and"; + break; + case OR_EXPR: + opstr = "or"; + break; + case NOT_EXPR: + opstr = "not"; + break; + } + appendStringInfo(str, " :boolop "); + _outToken(str, opstr); + + WRITE_NODE_FIELD(args); +} + +static void +_outSubLink(StringInfo str, SubLink *node) +{ + WRITE_NODE_TYPE("SUBLINK"); + + WRITE_ENUM_FIELD(subLinkType, SubLinkType); + WRITE_BOOL_FIELD(useor); + WRITE_NODE_FIELD(lefthand); + WRITE_NODE_FIELD(oper); + WRITE_NODE_FIELD(subselect); +} + +static void +_outSubPlanExpr(StringInfo str, SubPlanExpr *node) +{ + WRITE_NODE_TYPE("SUBPLANEXPR"); + + WRITE_OID_FIELD(typeOid); + WRITE_NODE_FIELD(plan); + WRITE_INT_FIELD(plan_id); + WRITE_NODE_FIELD(rtable); + WRITE_INTLIST_FIELD(setParam); + WRITE_INTLIST_FIELD(parParam); + WRITE_NODE_FIELD(args); + WRITE_NODE_FIELD(sublink); } static void @@ -834,35 +704,62 @@ _outRelabelType(StringInfo str, RelabelType *node) } static void -_outRangeTblRef(StringInfo str, RangeTblRef *node) +_outCaseExpr(StringInfo str, CaseExpr *node) { - WRITE_NODE_TYPE("RANGETBLREF"); + WRITE_NODE_TYPE("CASE"); - WRITE_INT_FIELD(rtindex); + WRITE_OID_FIELD(casetype); + WRITE_NODE_FIELD(arg); + WRITE_NODE_FIELD(args); + WRITE_NODE_FIELD(defresult); } static void -_outJoinExpr(StringInfo str, JoinExpr *node) +_outCaseWhen(StringInfo str, CaseWhen *node) { - WRITE_NODE_TYPE("JOINEXPR"); + WRITE_NODE_TYPE("WHEN"); - WRITE_ENUM_FIELD(jointype, JoinType); - WRITE_BOOL_FIELD(isNatural); - WRITE_NODE_FIELD(larg); - WRITE_NODE_FIELD(rarg); - WRITE_NODE_FIELD(using); - WRITE_NODE_FIELD(quals); - WRITE_NODE_FIELD(alias); - WRITE_INT_FIELD(rtindex); + WRITE_NODE_FIELD(expr); + WRITE_NODE_FIELD(result); } static void -_outFromExpr(StringInfo str, FromExpr *node) +_outNullTest(StringInfo str, NullTest *node) { - WRITE_NODE_TYPE("FROMEXPR"); + WRITE_NODE_TYPE("NULLTEST"); - WRITE_NODE_FIELD(fromlist); - WRITE_NODE_FIELD(quals); + WRITE_NODE_FIELD(arg); + WRITE_ENUM_FIELD(nulltesttype, NullTestType); +} + +static void +_outBooleanTest(StringInfo str, BooleanTest *node) +{ + WRITE_NODE_TYPE("BOOLEANTEST"); + + WRITE_NODE_FIELD(arg); + WRITE_ENUM_FIELD(booltesttype, BoolTestType); +} + +static void +_outConstraintTest(StringInfo str, ConstraintTest *node) +{ + WRITE_NODE_TYPE("CONSTRAINTTEST"); + + WRITE_NODE_FIELD(arg); + WRITE_ENUM_FIELD(testtype, ConstraintTestType); + WRITE_STRING_FIELD(name); + WRITE_STRING_FIELD(domname); + WRITE_NODE_FIELD(check_expr); +} + +static void +_outConstraintTestValue(StringInfo str, ConstraintTestValue *node) +{ + WRITE_NODE_TYPE("CONSTRAINTTESTVALUE"); + + WRITE_OID_FIELD(typeId); + WRITE_INT_FIELD(typeMod); } static void @@ -871,58 +768,47 @@ _outTargetEntry(StringInfo str, TargetEntry *node) WRITE_NODE_TYPE("TARGETENTRY"); WRITE_NODE_FIELD(resdom); - /* fjoin not supported ... */ WRITE_NODE_FIELD(expr); } static void -_outAlias(StringInfo str, Alias *node) +_outRangeTblRef(StringInfo str, RangeTblRef *node) { - WRITE_NODE_TYPE("ALIAS"); + WRITE_NODE_TYPE("RANGETBLREF"); - WRITE_STRING_FIELD(aliasname); - WRITE_NODE_FIELD(colnames); + WRITE_INT_FIELD(rtindex); } static void -_outRangeTblEntry(StringInfo str, RangeTblEntry *node) +_outJoinExpr(StringInfo str, JoinExpr *node) { - WRITE_NODE_TYPE("RTE"); + WRITE_NODE_TYPE("JOINEXPR"); - /* put alias + eref first to make dump more legible */ + WRITE_ENUM_FIELD(jointype, JoinType); + WRITE_BOOL_FIELD(isNatural); + WRITE_NODE_FIELD(larg); + WRITE_NODE_FIELD(rarg); + WRITE_NODE_FIELD(using); + WRITE_NODE_FIELD(quals); WRITE_NODE_FIELD(alias); - WRITE_NODE_FIELD(eref); - WRITE_ENUM_FIELD(rtekind, RTEKind); + WRITE_INT_FIELD(rtindex); +} - switch (node->rtekind) - { - case RTE_RELATION: - case RTE_SPECIAL: - WRITE_OID_FIELD(relid); - break; - case RTE_SUBQUERY: - WRITE_NODE_FIELD(subquery); - break; - case RTE_FUNCTION: - WRITE_NODE_FIELD(funcexpr); - WRITE_NODE_FIELD(coldeflist); - break; - case RTE_JOIN: - WRITE_ENUM_FIELD(jointype, JoinType); - WRITE_NODE_FIELD(joinaliasvars); - break; - default: - elog(ERROR, "bogus rte kind %d", (int) node->rtekind); - break; - } +static void +_outFromExpr(StringInfo str, FromExpr *node) +{ + WRITE_NODE_TYPE("FROMEXPR"); - WRITE_BOOL_FIELD(inh); - WRITE_BOOL_FIELD(inFromCl); - WRITE_BOOL_FIELD(checkForRead); - WRITE_BOOL_FIELD(checkForWrite); - WRITE_OID_FIELD(checkAsUser); + WRITE_NODE_FIELD(fromlist); + WRITE_NODE_FIELD(quals); } +/***************************************************************************** + * + * Stuff from relation.h. + * + *****************************************************************************/ + /* * print the basic stuff of all nodes that inherit from Path * @@ -1078,39 +964,240 @@ _outJoinInfo(StringInfo str, JoinInfo *node) WRITE_NODE_FIELD(jinfo_restrictinfo); } -/* - * Print the value of a Datum given its type. - */ +/***************************************************************************** + * + * Stuff from parsenodes.h. + * + *****************************************************************************/ + static void -_outDatum(StringInfo str, Datum value, int typlen, bool typbyval) +_outCreateStmt(StringInfo str, CreateStmt *node) { - Size length, - i; - char *s; + WRITE_NODE_TYPE("CREATE"); - length = datumGetSize(value, typbyval, typlen); + WRITE_NODE_FIELD(relation); + WRITE_NODE_FIELD(tableElts); + WRITE_NODE_FIELD(inhRelations); + WRITE_NODE_FIELD(constraints); + WRITE_BOOL_FIELD(hasoids); + WRITE_ENUM_FIELD(oncommit, OnCommitAction); +} - if (typbyval) - { - s = (char *) (&value); - appendStringInfo(str, "%u [ ", (unsigned int) length); - for (i = 0; i < (Size) sizeof(Datum); i++) - appendStringInfo(str, "%d ", (int) (s[i])); - appendStringInfo(str, "]"); - } - else +static void +_outIndexStmt(StringInfo str, IndexStmt *node) +{ + WRITE_NODE_TYPE("INDEX"); + + WRITE_STRING_FIELD(idxname); + WRITE_NODE_FIELD(relation); + WRITE_STRING_FIELD(accessMethod); + WRITE_NODE_FIELD(indexParams); + WRITE_NODE_FIELD(whereClause); + WRITE_NODE_FIELD(rangetable); + WRITE_BOOL_FIELD(unique); + WRITE_BOOL_FIELD(primary); + WRITE_BOOL_FIELD(isconstraint); +} + +static void +_outNotifyStmt(StringInfo str, NotifyStmt *node) +{ + WRITE_NODE_TYPE("NOTIFY"); + + WRITE_NODE_FIELD(relation); +} + +static void +_outSelectStmt(StringInfo str, SelectStmt *node) +{ + WRITE_NODE_TYPE("SELECT"); + + /* XXX this is pretty durn incomplete */ + WRITE_NODE_FIELD(whereClause); +} + +static void +_outFuncCall(StringInfo str, FuncCall *node) +{ + WRITE_NODE_TYPE("FUNCCALL"); + + WRITE_NODE_FIELD(funcname); + WRITE_NODE_FIELD(args); + WRITE_BOOL_FIELD(agg_star); + WRITE_BOOL_FIELD(agg_distinct); +} + +static void +_outColumnDef(StringInfo str, ColumnDef *node) +{ + WRITE_NODE_TYPE("COLUMNDEF"); + + WRITE_STRING_FIELD(colname); + WRITE_NODE_FIELD(typename); + WRITE_INT_FIELD(inhcount); + WRITE_BOOL_FIELD(is_local); + WRITE_BOOL_FIELD(is_not_null); + WRITE_NODE_FIELD(raw_default); + WRITE_STRING_FIELD(cooked_default); + WRITE_NODE_FIELD(constraints); + WRITE_NODE_FIELD(support); +} + +static void +_outTypeName(StringInfo str, TypeName *node) +{ + WRITE_NODE_TYPE("TYPENAME"); + + WRITE_NODE_FIELD(names); + WRITE_OID_FIELD(typeid); + WRITE_BOOL_FIELD(timezone); + WRITE_BOOL_FIELD(setof); + WRITE_BOOL_FIELD(pct_type); + WRITE_INT_FIELD(typmod); + WRITE_NODE_FIELD(arrayBounds); +} + +static void +_outTypeCast(StringInfo str, TypeCast *node) +{ + WRITE_NODE_TYPE("TYPECAST"); + + WRITE_NODE_FIELD(arg); + WRITE_NODE_FIELD(typename); +} + +static void +_outIndexElem(StringInfo str, IndexElem *node) +{ + WRITE_NODE_TYPE("INDEXELEM"); + + WRITE_STRING_FIELD(name); + WRITE_NODE_FIELD(funcname); + WRITE_NODE_FIELD(args); + WRITE_NODE_FIELD(opclass); +} + +static void +_outQuery(StringInfo str, Query *node) +{ + WRITE_NODE_TYPE("QUERY"); + + WRITE_ENUM_FIELD(commandType, CmdType); + WRITE_ENUM_FIELD(querySource, QuerySource); + + /* + * Hack to work around missing outfuncs routines for a lot of the + * utility-statement node types. (The only one we actually *need* for + * rules support is NotifyStmt.) Someday we ought to support 'em all, + * but for the meantime do this to avoid getting lots of warnings when + * running with debug_print_parse on. + */ + if (node->utilityStmt) { - s = (char *) DatumGetPointer(value); - if (!PointerIsValid(s)) - appendStringInfo(str, "0 [ ]"); - else + switch (nodeTag(node->utilityStmt)) { - appendStringInfo(str, "%u [ ", (unsigned int) length); - for (i = 0; i < length; i++) - appendStringInfo(str, "%d ", (int) (s[i])); - appendStringInfo(str, "]"); + case T_CreateStmt: + case T_IndexStmt: + case T_NotifyStmt: + WRITE_NODE_FIELD(utilityStmt); + break; + default: + appendStringInfo(str, " :utilityStmt ?"); + break; } } + else + appendStringInfo(str, " :utilityStmt <>"); + + WRITE_INT_FIELD(resultRelation); + WRITE_NODE_FIELD(into); + WRITE_BOOL_FIELD(isPortal); + WRITE_BOOL_FIELD(isBinary); + WRITE_BOOL_FIELD(hasAggs); + WRITE_BOOL_FIELD(hasSubLinks); + WRITE_NODE_FIELD(rtable); + WRITE_NODE_FIELD(jointree); + WRITE_INTLIST_FIELD(rowMarks); + WRITE_NODE_FIELD(targetList); + WRITE_NODE_FIELD(groupClause); + WRITE_NODE_FIELD(havingQual); + WRITE_NODE_FIELD(distinctClause); + WRITE_NODE_FIELD(sortClause); + WRITE_NODE_FIELD(limitOffset); + WRITE_NODE_FIELD(limitCount); + WRITE_NODE_FIELD(setOperations); + WRITE_INTLIST_FIELD(resultRelations); + + /* planner-internal fields are not written out */ +} + +static void +_outSortClause(StringInfo str, SortClause *node) +{ + WRITE_NODE_TYPE("SORTCLAUSE"); + + WRITE_UINT_FIELD(tleSortGroupRef); + WRITE_OID_FIELD(sortop); +} + +static void +_outGroupClause(StringInfo str, GroupClause *node) +{ + WRITE_NODE_TYPE("GROUPCLAUSE"); + + WRITE_UINT_FIELD(tleSortGroupRef); + WRITE_OID_FIELD(sortop); +} + +static void +_outSetOperationStmt(StringInfo str, SetOperationStmt *node) +{ + WRITE_NODE_TYPE("SETOPERATIONSTMT"); + + WRITE_ENUM_FIELD(op, SetOperation); + WRITE_BOOL_FIELD(all); + WRITE_NODE_FIELD(larg); + WRITE_NODE_FIELD(rarg); + WRITE_OIDLIST_FIELD(colTypes); +} + +static void +_outRangeTblEntry(StringInfo str, RangeTblEntry *node) +{ + WRITE_NODE_TYPE("RTE"); + + /* put alias + eref first to make dump more legible */ + WRITE_NODE_FIELD(alias); + WRITE_NODE_FIELD(eref); + WRITE_ENUM_FIELD(rtekind, RTEKind); + + switch (node->rtekind) + { + case RTE_RELATION: + case RTE_SPECIAL: + WRITE_OID_FIELD(relid); + break; + case RTE_SUBQUERY: + WRITE_NODE_FIELD(subquery); + break; + case RTE_FUNCTION: + WRITE_NODE_FIELD(funcexpr); + WRITE_NODE_FIELD(coldeflist); + break; + case RTE_JOIN: + WRITE_ENUM_FIELD(jointype, JoinType); + WRITE_NODE_FIELD(joinaliasvars); + break; + default: + elog(ERROR, "bogus rte kind %d", (int) node->rtekind); + break; + } + + WRITE_BOOL_FIELD(inh); + WRITE_BOOL_FIELD(inFromCl); + WRITE_BOOL_FIELD(checkForRead); + WRITE_BOOL_FIELD(checkForWrite); + WRITE_OID_FIELD(checkAsUser); } static void @@ -1174,22 +1261,6 @@ _outValue(StringInfo str, Value *value) } } -static void -_outRangeVar(StringInfo str, RangeVar *node) -{ - WRITE_NODE_TYPE("RANGEVAR"); - - /* - * we deliberately ignore catalogname here, since it is presently not - * semantically meaningful - */ - WRITE_STRING_FIELD(schemaname); - WRITE_STRING_FIELD(relname); - WRITE_ENUM_FIELD(inhOpt, InhOption); - WRITE_BOOL_FIELD(istemp); - WRITE_NODE_FIELD(alias); -} - static void _outColumnRef(StringInfo str, ColumnRef *node) { @@ -1228,6 +1299,12 @@ _outExprFieldSelect(StringInfo str, ExprFieldSelect *node) WRITE_NODE_FIELD(indirection); } +static void +_outDomainConstraintValue(StringInfo str, DomainConstraintValue *node) +{ + WRITE_NODE_TYPE("DOMAINCONSTRAINTVALUE"); +} + static void _outConstraint(StringInfo str, Constraint *node) { @@ -1287,71 +1364,6 @@ _outFkConstraint(StringInfo str, FkConstraint *node) WRITE_BOOL_FIELD(skip_validation); } -static void -_outCaseExpr(StringInfo str, CaseExpr *node) -{ - WRITE_NODE_TYPE("CASE"); - - WRITE_OID_FIELD(casetype); - WRITE_NODE_FIELD(arg); - WRITE_NODE_FIELD(args); - WRITE_NODE_FIELD(defresult); -} - -static void -_outCaseWhen(StringInfo str, CaseWhen *node) -{ - WRITE_NODE_TYPE("WHEN"); - - WRITE_NODE_FIELD(expr); - WRITE_NODE_FIELD(result); -} - -static void -_outNullTest(StringInfo str, NullTest *node) -{ - WRITE_NODE_TYPE("NULLTEST"); - - WRITE_NODE_FIELD(arg); - WRITE_ENUM_FIELD(nulltesttype, NullTestType); -} - -static void -_outBooleanTest(StringInfo str, BooleanTest *node) -{ - WRITE_NODE_TYPE("BOOLEANTEST"); - - WRITE_NODE_FIELD(arg); - WRITE_ENUM_FIELD(booltesttype, BoolTestType); -} - -static void -_outConstraintTest(StringInfo str, ConstraintTest *node) -{ - WRITE_NODE_TYPE("CONSTRAINTTEST"); - - WRITE_NODE_FIELD(arg); - WRITE_ENUM_FIELD(testtype, ConstraintTestType); - WRITE_STRING_FIELD(name); - WRITE_STRING_FIELD(domname); - WRITE_NODE_FIELD(check_expr); -} - -static void -_outDomainConstraintValue(StringInfo str, DomainConstraintValue *node) -{ - WRITE_NODE_TYPE("DOMAINCONSTRAINTVALUE"); -} - -static void -_outConstraintTestValue(StringInfo str, ConstraintTestValue *node) -{ - WRITE_NODE_TYPE("CONSTRAINTTESTVALUE"); - - WRITE_OID_FIELD(typeId); - WRITE_INT_FIELD(typeMod); -} - /* * _outNode - @@ -1392,42 +1404,6 @@ _outNode(StringInfo str, void *obj) appendStringInfoChar(str, '{'); switch (nodeTag(obj)) { - case T_CreateStmt: - _outCreateStmt(str, obj); - break; - case T_IndexStmt: - _outIndexStmt(str, obj); - break; - case T_NotifyStmt: - _outNotifyStmt(str, obj); - break; - case T_SelectStmt: - _outSelectStmt(str, obj); - break; - case T_ColumnDef: - _outColumnDef(str, obj); - break; - case T_TypeName: - _outTypeName(str, obj); - break; - case T_TypeCast: - _outTypeCast(str, obj); - break; - case T_IndexElem: - _outIndexElem(str, obj); - break; - case T_Query: - _outQuery(str, obj); - break; - case T_SortClause: - _outSortClause(str, obj); - break; - case T_GroupClause: - _outGroupClause(str, obj); - break; - case T_SetOperationStmt: - _outSetOperationStmt(str, obj); - break; case T_Plan: _outPlan(str, obj); break; @@ -1437,18 +1413,6 @@ _outNode(StringInfo str, void *obj) case T_Append: _outAppend(str, obj); break; - case T_Join: - _outJoin(str, obj); - break; - case T_NestLoop: - _outNestLoop(str, obj); - break; - case T_MergeJoin: - _outMergeJoin(str, obj); - break; - case T_HashJoin: - _outHashJoin(str, obj); - break; case T_Scan: _outScan(str, obj); break; @@ -1467,11 +1431,17 @@ _outNode(StringInfo str, void *obj) case T_FunctionScan: _outFunctionScan(str, obj); break; - case T_Material: - _outMaterial(str, obj); + case T_Join: + _outJoin(str, obj); break; - case T_Sort: - _outSort(str, obj); + case T_NestLoop: + _outNestLoop(str, obj); + break; + case T_MergeJoin: + _outMergeJoin(str, obj); + break; + case T_HashJoin: + _outHashJoin(str, obj); break; case T_Agg: _outAgg(str, obj); @@ -1479,6 +1449,12 @@ _outNode(StringInfo str, void *obj) case T_Group: _outGroup(str, obj); break; + case T_Material: + _outMaterial(str, obj); + break; + case T_Sort: + _outSort(str, obj); + break; case T_Unique: _outUnique(str, obj); break; @@ -1491,14 +1467,14 @@ _outNode(StringInfo str, void *obj) case T_Hash: _outHash(str, obj); break; - case T_SubPlan: - _outSubPlan(str, obj); - break; case T_Resdom: _outResdom(str, obj); break; - case T_Expr: - _outExpr(str, obj); + case T_Alias: + _outAlias(str, obj); + break; + case T_RangeVar: + _outRangeVar(str, obj); break; case T_Var: _outVar(str, obj); @@ -1506,23 +1482,32 @@ _outNode(StringInfo str, void *obj) case T_Const: _outConst(str, obj); break; + case T_Param: + _outParam(str, obj); + break; case T_Aggref: _outAggref(str, obj); break; - case T_SubLink: - _outSubLink(str, obj); - break; case T_ArrayRef: _outArrayRef(str, obj); break; - case T_Func: - _outFunc(str, obj); + case T_FuncExpr: + _outFuncExpr(str, obj); break; - case T_Oper: - _outOper(str, obj); + case T_OpExpr: + _outOpExpr(str, obj); break; - case T_Param: - _outParam(str, obj); + case T_DistinctExpr: + _outDistinctExpr(str, obj); + break; + case T_BoolExpr: + _outBoolExpr(str, obj); + break; + case T_SubLink: + _outSubLink(str, obj); + break; + case T_SubPlanExpr: + _outSubPlanExpr(str, obj); break; case T_FieldSelect: _outFieldSelect(str, obj); @@ -1530,24 +1515,37 @@ _outNode(StringInfo str, void *obj) case T_RelabelType: _outRelabelType(str, obj); break; - case T_RangeTblRef: - _outRangeTblRef(str, obj); + case T_CaseExpr: + _outCaseExpr(str, obj); break; - case T_FromExpr: - _outFromExpr(str, obj); + case T_CaseWhen: + _outCaseWhen(str, obj); break; - case T_JoinExpr: - _outJoinExpr(str, obj); + case T_NullTest: + _outNullTest(str, obj); + break; + case T_BooleanTest: + _outBooleanTest(str, obj); + break; + case T_ConstraintTest: + _outConstraintTest(str, obj); + break; + case T_ConstraintTestValue: + _outConstraintTestValue(str, obj); break; case T_TargetEntry: _outTargetEntry(str, obj); break; - case T_Alias: - _outAlias(str, obj); + case T_RangeTblRef: + _outRangeTblRef(str, obj); break; - case T_RangeTblEntry: - _outRangeTblEntry(str, obj); + case T_JoinExpr: + _outJoinExpr(str, obj); + break; + case T_FromExpr: + _outFromExpr(str, obj); break; + case T_Path: _outPath(str, obj); break; @@ -1584,12 +1582,49 @@ _outNode(StringInfo str, void *obj) case T_JoinInfo: _outJoinInfo(str, obj); break; + + case T_CreateStmt: + _outCreateStmt(str, obj); + break; + case T_IndexStmt: + _outIndexStmt(str, obj); + break; + case T_NotifyStmt: + _outNotifyStmt(str, obj); + break; + case T_SelectStmt: + _outSelectStmt(str, obj); + break; + case T_ColumnDef: + _outColumnDef(str, obj); + break; + case T_TypeName: + _outTypeName(str, obj); + break; + case T_TypeCast: + _outTypeCast(str, obj); + break; + case T_IndexElem: + _outIndexElem(str, obj); + break; + case T_Query: + _outQuery(str, obj); + break; + case T_SortClause: + _outSortClause(str, obj); + break; + case T_GroupClause: + _outGroupClause(str, obj); + break; + case T_SetOperationStmt: + _outSetOperationStmt(str, obj); + break; + case T_RangeTblEntry: + _outRangeTblEntry(str, obj); + break; case T_A_Expr: _outAExpr(str, obj); break; - case T_RangeVar: - _outRangeVar(str, obj); - break; case T_ColumnRef: _outColumnRef(str, obj); break; @@ -1602,36 +1637,18 @@ _outNode(StringInfo str, void *obj) case T_ExprFieldSelect: _outExprFieldSelect(str, obj); break; + case T_DomainConstraintValue: + _outDomainConstraintValue(str, obj); + break; case T_Constraint: _outConstraint(str, obj); break; case T_FkConstraint: _outFkConstraint(str, obj); break; - case T_CaseExpr: - _outCaseExpr(str, obj); - break; - case T_CaseWhen: - _outCaseWhen(str, obj); - break; - case T_NullTest: - _outNullTest(str, obj); - break; - case T_BooleanTest: - _outBooleanTest(str, obj); - break; - case T_ConstraintTest: - _outConstraintTest(str, obj); - break; - case T_ConstraintTestValue: - _outConstraintTestValue(str, obj); - break; case T_FuncCall: _outFuncCall(str, obj); break; - case T_DomainConstraintValue: - _outDomainConstraintValue(str, obj); - break; default: elog(WARNING, "_outNode: don't know how to print type %d", diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index e8afda6b20835eb9abb0b7cad8a55d6b8bffe7ab..dd5186860bfe33fb37ed3427e60904ef24ec3177 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.57 2002/09/04 20:31:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.58 2002/12/12 15:49:28 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -371,7 +371,7 @@ print_expr(Node *expr, List *rtable) char *opname; print_expr((Node *) get_leftop(e), rtable); - opname = get_opname(((Oper *) e->oper)->opno); + opname = get_opname(((OpExpr *) e)->opno); printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)")); print_expr((Node *) get_rightop(e), rtable); } @@ -432,7 +432,7 @@ print_tl(List *tlist, List *rtable) printf("(%d):\t", tle->resdom->reskey); else printf(" :\t"); - print_expr(tle->expr, rtable); + print_expr((Node *) tle->expr, rtable); printf("\n"); } printf(")\n"); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index eca2e3017b07b5e43d35baa5cbf8168f0ab9211a..bb4a565a8b54213895f102f84d9ff28240da9811 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.140 2002/11/25 21:29:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.141 2002/12/12 15:49:28 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -302,38 +302,30 @@ _readResdom(void) READ_DONE(); } -/* - * _readExpr - */ -static Expr * -_readExpr(void) +static Alias * +_readAlias(void) { - READ_LOCALS(Expr); + READ_LOCALS(Alias); - READ_OID_FIELD(typeOid); + READ_STRING_FIELD(aliasname); + READ_NODE_FIELD(colnames); - /* do-it-yourself enum representation */ - token = pg_strtok(&length); /* skip :opType */ - token = pg_strtok(&length); /* get field value */ - if (strncmp(token, "op", 2) == 0) - local_node->opType = OP_EXPR; - else if (strncmp(token, "distinct", 8) == 0) - local_node->opType = DISTINCT_EXPR; - else if (strncmp(token, "func", 4) == 0) - local_node->opType = FUNC_EXPR; - else if (strncmp(token, "or", 2) == 0) - local_node->opType = OR_EXPR; - else if (strncmp(token, "and", 3) == 0) - local_node->opType = AND_EXPR; - else if (strncmp(token, "not", 3) == 0) - local_node->opType = NOT_EXPR; - else if (strncmp(token, "subp", 4) == 0) - local_node->opType = SUBPLAN_EXPR; - else - elog(ERROR, "_readExpr: unknown opType \"%.*s\"", length, token); + READ_DONE(); +} - READ_NODE_FIELD(oper); - READ_NODE_FIELD(args); +static RangeVar * +_readRangeVar(void) +{ + READ_LOCALS(RangeVar); + + local_node->catalogname = NULL; /* not currently saved in output + * format */ + + READ_STRING_FIELD(schemaname); + READ_STRING_FIELD(relname); + READ_ENUM_FIELD(inhOpt, InhOption); + READ_BOOL_FIELD(istemp); + READ_NODE_FIELD(alias); READ_DONE(); } @@ -357,27 +349,6 @@ _readVar(void) 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 */ @@ -401,17 +372,72 @@ _readConst(void) } /* - * _readFunc + * _readParam + */ +static Param * +_readParam(void) +{ + READ_LOCALS(Param); + + READ_INT_FIELD(paramkind); + READ_INT_FIELD(paramid); + READ_STRING_FIELD(paramname); + READ_OID_FIELD(paramtype); + + READ_DONE(); +} + +/* + * _readAggref + */ +static Aggref * +_readAggref(void) +{ + READ_LOCALS(Aggref); + + READ_OID_FIELD(aggfnoid); + READ_OID_FIELD(aggtype); + READ_NODE_FIELD(target); + READ_BOOL_FIELD(aggstar); + READ_BOOL_FIELD(aggdistinct); + + READ_DONE(); +} + +/* + * _readArrayRef */ -static Func * -_readFunc(void) +static ArrayRef * +_readArrayRef(void) { - READ_LOCALS(Func); + READ_LOCALS(ArrayRef); + + READ_OID_FIELD(refrestype); + READ_INT_FIELD(refattrlength); + READ_INT_FIELD(refelemlength); + READ_BOOL_FIELD(refelembyval); + READ_CHAR_FIELD(refelemalign); + READ_NODE_FIELD(refupperindexpr); + READ_NODE_FIELD(reflowerindexpr); + READ_NODE_FIELD(refexpr); + READ_NODE_FIELD(refassgnexpr); + + READ_DONE(); +} + +/* + * _readFuncExpr + */ +static FuncExpr * +_readFuncExpr(void) +{ + READ_LOCALS(FuncExpr); READ_OID_FIELD(funcid); READ_OID_FIELD(funcresulttype); READ_BOOL_FIELD(funcretset); READ_ENUM_FIELD(funcformat, CoercionForm); + READ_NODE_FIELD(args); local_node->func_fcache = NULL; @@ -419,17 +445,28 @@ _readFunc(void) } /* - * _readOper + * _readOpExpr */ -static Oper * -_readOper(void) +static OpExpr * +_readOpExpr(void) { - READ_LOCALS(Oper); + READ_LOCALS(OpExpr); READ_OID_FIELD(opno); - READ_OID_FIELD(opid); + READ_OID_FIELD(opfuncid); + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + READ_OID_FIELD(opresulttype); READ_BOOL_FIELD(opretset); + READ_NODE_FIELD(args); local_node->op_fcache = NULL; @@ -437,52 +474,55 @@ _readOper(void) } /* - * _readParam + * _readDistinctExpr */ -static Param * -_readParam(void) +static DistinctExpr * +_readDistinctExpr(void) { - READ_LOCALS(Param); - - READ_INT_FIELD(paramkind); - READ_INT_FIELD(paramid); - READ_STRING_FIELD(paramname); - READ_OID_FIELD(paramtype); + READ_LOCALS(DistinctExpr); - READ_DONE(); -} + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; -/* - * _readAggref - */ -static Aggref * -_readAggref(void) -{ - READ_LOCALS(Aggref); + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_NODE_FIELD(args); - READ_OID_FIELD(aggfnoid); - READ_OID_FIELD(aggtype); - READ_NODE_FIELD(target); - READ_BOOL_FIELD(aggstar); - READ_BOOL_FIELD(aggdistinct); - /* aggno is not saved since it is just executor state */ + local_node->op_fcache = NULL; READ_DONE(); } -static RangeVar * -_readRangeVar(void) +/* + * _readBoolExpr + */ +static BoolExpr * +_readBoolExpr(void) { - READ_LOCALS(RangeVar); + READ_LOCALS(BoolExpr); - local_node->catalogname = NULL; /* not currently saved in output - * format */ + /* do-it-yourself enum representation */ + token = pg_strtok(&length); /* skip :boolop */ + token = pg_strtok(&length); /* get field value */ + if (strncmp(token, "and", 3) == 0) + local_node->boolop = AND_EXPR; + else if (strncmp(token, "or", 2) == 0) + local_node->boolop = OR_EXPR; + else if (strncmp(token, "not", 3) == 0) + local_node->boolop = NOT_EXPR; + else + elog(ERROR, "_readBoolExpr: unknown boolop \"%.*s\"", length, token); - READ_STRING_FIELD(schemaname); - READ_STRING_FIELD(relname); - READ_ENUM_FIELD(inhOpt, InhOption); - READ_BOOL_FIELD(istemp); - READ_NODE_FIELD(alias); + READ_NODE_FIELD(args); READ_DONE(); } @@ -504,6 +544,10 @@ _readSubLink(void) READ_DONE(); } +/* + * _readSubPlanExpr is not needed since it doesn't appear in stored rules. + */ + /* * _readFieldSelect */ @@ -536,58 +580,6 @@ _readRelabelType(void) 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 */ @@ -663,17 +655,6 @@ _readConstraintTest(void) READ_DONE(); } -/* - * _readDomainConstraintValue - */ -static DomainConstraintValue * -_readDomainConstraintValue(void) -{ - READ_LOCALS_NO_FIELDS(DomainConstraintValue); - - READ_DONE(); -} - /* * _readConstraintTestValue */ @@ -697,12 +678,63 @@ _readTargetEntry(void) READ_LOCALS(TargetEntry); READ_NODE_FIELD(resdom); - /* fjoin not supported ... */ READ_NODE_FIELD(expr); READ_DONE(); } +/* + * _readRangeTblRef + */ +static RangeTblRef * +_readRangeTblRef(void) +{ + READ_LOCALS(RangeTblRef); + + READ_INT_FIELD(rtindex); + + READ_DONE(); +} + +/* + * _readJoinExpr + */ +static JoinExpr * +_readJoinExpr(void) +{ + READ_LOCALS(JoinExpr); + + READ_ENUM_FIELD(jointype, JoinType); + READ_BOOL_FIELD(isNatural); + READ_NODE_FIELD(larg); + READ_NODE_FIELD(rarg); + READ_NODE_FIELD(using); + READ_NODE_FIELD(quals); + READ_NODE_FIELD(alias); + READ_INT_FIELD(rtindex); + + READ_DONE(); +} + +/* + * _readFromExpr + */ +static FromExpr * +_readFromExpr(void) +{ + READ_LOCALS(FromExpr); + + READ_NODE_FIELD(fromlist); + READ_NODE_FIELD(quals); + + READ_DONE(); +} + + +/* + * Stuff from parsenodes.h. + */ + static ColumnRef * _readColumnRef(void) { @@ -760,13 +792,13 @@ _readExprFieldSelect(void) READ_DONE(); } -static Alias * -_readAlias(void) +/* + * _readDomainConstraintValue + */ +static DomainConstraintValue * +_readDomainConstraintValue(void) { - READ_LOCALS(Alias); - - READ_STRING_FIELD(aliasname); - READ_NODE_FIELD(colnames); + READ_LOCALS_NO_FIELDS(DomainConstraintValue); READ_DONE(); } @@ -835,53 +867,7 @@ parseNodeString(void) #define MATCH(tokname, namelen) \ (length == namelen && strncmp(token, tokname, namelen) == 0) - if (MATCH("AGGREF", 6)) - return_value = _readAggref(); - else if (MATCH("SUBLINK", 7)) - return_value = _readSubLink(); - else if (MATCH("FIELDSELECT", 11)) - return_value = _readFieldSelect(); - else if (MATCH("RELABELTYPE", 11)) - return_value = _readRelabelType(); - else if (MATCH("RANGETBLREF", 11)) - return_value = _readRangeTblRef(); - else if (MATCH("FROMEXPR", 8)) - return_value = _readFromExpr(); - else if (MATCH("JOINEXPR", 8)) - return_value = _readJoinExpr(); - else if (MATCH("RESDOM", 6)) - return_value = _readResdom(); - else if (MATCH("EXPR", 4)) - return_value = _readExpr(); - else if (MATCH("ARRAYREF", 8)) - return_value = _readArrayRef(); - else if (MATCH("VAR", 3)) - return_value = _readVar(); - else if (MATCH("CONST", 5)) - return_value = _readConst(); - else if (MATCH("FUNC", 4)) - return_value = _readFunc(); - else if (MATCH("OPER", 4)) - return_value = _readOper(); - else if (MATCH("PARAM", 5)) - return_value = _readParam(); - else if (MATCH("TARGETENTRY", 11)) - return_value = _readTargetEntry(); - else if (MATCH("RANGEVAR", 8)) - return_value = _readRangeVar(); - else if (MATCH("COLUMNREF", 9)) - return_value = _readColumnRef(); - else if (MATCH("COLUMNDEF", 9)) - return_value = _readColumnDef(); - else if (MATCH("TYPENAME", 8)) - return_value = _readTypeName(); - else if (MATCH("EXPRFIELDSELECT", 15)) - return_value = _readExprFieldSelect(); - else if (MATCH("ALIAS", 5)) - return_value = _readAlias(); - else if (MATCH("RTE", 3)) - return_value = _readRangeTblEntry(); - else if (MATCH("QUERY", 5)) + if (MATCH("QUERY", 5)) return_value = _readQuery(); else if (MATCH("NOTIFY", 6)) return_value = _readNotifyStmt(); @@ -891,6 +877,36 @@ parseNodeString(void) return_value = _readGroupClause(); else if (MATCH("SETOPERATIONSTMT", 16)) return_value = _readSetOperationStmt(); + else if (MATCH("RESDOM", 6)) + return_value = _readResdom(); + else if (MATCH("ALIAS", 5)) + return_value = _readAlias(); + else if (MATCH("RANGEVAR", 8)) + return_value = _readRangeVar(); + else if (MATCH("VAR", 3)) + return_value = _readVar(); + else if (MATCH("CONST", 5)) + return_value = _readConst(); + else if (MATCH("PARAM", 5)) + return_value = _readParam(); + else if (MATCH("AGGREF", 6)) + return_value = _readAggref(); + else if (MATCH("ARRAYREF", 8)) + return_value = _readArrayRef(); + else if (MATCH("FUNCEXPR", 8)) + return_value = _readFuncExpr(); + else if (MATCH("OPEXPR", 6)) + return_value = _readOpExpr(); + else if (MATCH("DISTINCTEXPR", 12)) + return_value = _readDistinctExpr(); + else if (MATCH("BOOLEXPR", 8)) + return_value = _readBoolExpr(); + else if (MATCH("SUBLINK", 7)) + return_value = _readSubLink(); + else if (MATCH("FIELDSELECT", 11)) + return_value = _readFieldSelect(); + else if (MATCH("RELABELTYPE", 11)) + return_value = _readRelabelType(); else if (MATCH("CASE", 4)) return_value = _readCaseExpr(); else if (MATCH("WHEN", 4)) @@ -901,10 +917,28 @@ parseNodeString(void) return_value = _readBooleanTest(); else if (MATCH("CONSTRAINTTEST", 14)) return_value = _readConstraintTest(); - else if (MATCH("DOMAINCONSTRAINTVALUE", 21)) - return_value = _readDomainConstraintValue(); else if (MATCH("CONSTRAINTTESTVALUE", 19)) return_value = _readConstraintTestValue(); + else if (MATCH("TARGETENTRY", 11)) + return_value = _readTargetEntry(); + else if (MATCH("RANGETBLREF", 11)) + return_value = _readRangeTblRef(); + else if (MATCH("JOINEXPR", 8)) + return_value = _readJoinExpr(); + else if (MATCH("FROMEXPR", 8)) + return_value = _readFromExpr(); + else if (MATCH("COLUMNREF", 9)) + return_value = _readColumnRef(); + else if (MATCH("COLUMNDEF", 9)) + return_value = _readColumnDef(); + else if (MATCH("TYPENAME", 8)) + return_value = _readTypeName(); + else if (MATCH("EXPRFIELDSELECT", 15)) + return_value = _readExprFieldSelect(); + else if (MATCH("DOMAINCONSTRAINTVALUE", 21)) + return_value = _readDomainConstraintValue(); + else if (MATCH("RTE", 3)) + return_value = _readRangeTblEntry(); else { elog(ERROR, "badly formatted node string \"%.32s\"...", token); diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index d0976ca4219b866e37eaa68b88d760c904294659..0294c828124e4ea9ee07a1337264e3105c8450bc 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.53 2002/11/25 21:29:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.54 2002/12/12 15:49:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -141,7 +141,7 @@ clauselist_selectivity(Query *root, if (is_opclause(clause) && (varRelid != 0 || NumRelids(clause) == 1)) { - Expr *expr = (Expr *) clause; + OpExpr *expr = (OpExpr *) clause; if (length(expr->args) == 2) { @@ -151,7 +151,7 @@ clauselist_selectivity(Query *root, (varonleft = false, is_pseudo_constant_clause(lfirst(expr->args)))) { - Oid opno = ((Oper *) expr->oper)->opno; + Oid opno = expr->opno; RegProcedure oprrest = get_oprrest(opno); s2 = restriction_selectivity(root, opno, @@ -430,7 +430,7 @@ clause_selectivity(Query *root, { /* share code with clauselist_selectivity() */ s1 = clauselist_selectivity(root, - ((Expr *) clause)->args, + ((BoolExpr *) clause)->args, varRelid); } else if (or_clause(clause)) @@ -443,7 +443,7 @@ clause_selectivity(Query *root, List *arg; s1 = 0.0; - foreach(arg, ((Expr *) clause)->args) + foreach(arg, ((BoolExpr *) clause)->args) { Selectivity s2 = clause_selectivity(root, (Node *) lfirst(arg), @@ -454,7 +454,7 @@ clause_selectivity(Query *root, } else if (is_opclause(clause)) { - Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno; + Oid opno = ((OpExpr *) clause)->opno; bool is_join_clause; if (varRelid != 0) @@ -479,13 +479,14 @@ clause_selectivity(Query *root, { /* Estimate selectivity for a join clause. */ s1 = join_selectivity(root, opno, - ((Expr *) clause)->args); + ((OpExpr *) clause)->args); } else { /* Estimate selectivity for a restriction clause. */ s1 = restriction_selectivity(root, opno, - ((Expr *) clause)->args, varRelid); + ((OpExpr *) clause)->args, + varRelid); } } else if (is_funcclause(clause)) @@ -509,7 +510,7 @@ clause_selectivity(Query *root, /* Use node specific selectivity calculation function */ s1 = nulltestsel(root, ((NullTest *) clause)->nulltesttype, - ((NullTest *) clause)->arg, + (Node *) ((NullTest *) clause)->arg, varRelid); } else if (IsA(clause, BooleanTest)) @@ -517,14 +518,14 @@ clause_selectivity(Query *root, /* Use node specific selectivity calculation function */ s1 = booltestsel(root, ((BooleanTest *) clause)->booltesttype, - ((BooleanTest *) clause)->arg, + (Node *) ((BooleanTest *) clause)->arg, varRelid); } else if (IsA(clause, RelabelType)) { /* Not sure this case is needed, but it can't hurt */ s1 = clause_selectivity(root, - ((RelabelType *) clause)->arg, + (Node *) ((RelabelType *) clause)->arg, varRelid); } diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 1db310fc52e763221ddadf5e2030551a93b25649..2125ff034f3644f52f80b6cedf810d06042b1a79 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.93 2002/11/30 05:21:02 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.94 2002/12/12 15:49:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1220,63 +1220,48 @@ cost_qual_eval_walker(Node *node, Cost *total) * Should we try to account for the possibility of short-circuit * evaluation of AND/OR? */ - if (IsA(node, Expr)) + if (IsA(node, FuncExpr) || + IsA(node, OpExpr) || + IsA(node, DistinctExpr)) + *total += cpu_operator_cost; + else if (IsA(node, SubPlanExpr)) { - Expr *expr = (Expr *) node; + /* + * A subplan node in an expression indicates that the + * subplan will be executed on each evaluation, so charge + * accordingly. (We assume that sub-selects that can be + * executed as InitPlans have already been removed from + * the expression.) + * + * NOTE: this logic should agree with the estimates used by + * make_subplan() in plan/subselect.c. + */ + SubPlanExpr *subplan = (SubPlanExpr *) node; + Plan *plan = subplan->plan; + Cost subcost; - switch (expr->opType) + if (subplan->sublink->subLinkType == EXISTS_SUBLINK) { - case OP_EXPR: - case DISTINCT_EXPR: - case FUNC_EXPR: - *total += cpu_operator_cost; - break; - case OR_EXPR: - case AND_EXPR: - case NOT_EXPR: - break; - case SUBPLAN_EXPR: - - /* - * A subplan node in an expression indicates that the - * subplan will be executed on each evaluation, so charge - * accordingly. (We assume that sub-selects that can be - * executed as InitPlans have already been removed from - * the expression.) - * - * NOTE: this logic should agree with the estimates used by - * make_subplan() in plan/subselect.c. - */ - { - SubPlan *subplan = (SubPlan *) expr->oper; - Plan *plan = subplan->plan; - Cost subcost; - - if (subplan->sublink->subLinkType == EXISTS_SUBLINK) - { - /* we only need to fetch 1 tuple */ - subcost = plan->startup_cost + - (plan->total_cost - plan->startup_cost) / plan->plan_rows; - } - else if (subplan->sublink->subLinkType == ALL_SUBLINK || - subplan->sublink->subLinkType == ANY_SUBLINK) - { - /* assume we need 50% of the tuples */ - subcost = plan->startup_cost + - 0.50 * (plan->total_cost - plan->startup_cost); - /* XXX what if subplan has been materialized? */ - } - else - { - /* assume we need all tuples */ - subcost = plan->total_cost; - } - *total += subcost; - } - break; + /* we only need to fetch 1 tuple */ + subcost = plan->startup_cost + + (plan->total_cost - plan->startup_cost) / plan->plan_rows; } - /* fall through to examine args of Expr node */ + else if (subplan->sublink->subLinkType == ALL_SUBLINK || + subplan->sublink->subLinkType == ANY_SUBLINK) + { + /* assume we need 50% of the tuples */ + subcost = plan->startup_cost + + 0.50 * (plan->total_cost - plan->startup_cost); + /* XXX what if subplan has been materialized? */ + } + else + { + /* assume we need all tuples */ + subcost = plan->total_cost; + } + *total += subcost; } + return expression_tree_walker(node, cost_qual_eval_walker, (void *) total); } diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index c0241bb9ef3665976fd20b4d4b3d0ed892955f71..7a20de8c1c1bc0a1b29aa6fcb8a5f42bf42e29b8 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.126 2002/11/25 21:29:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.127 2002/12/12 15:49:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,6 +73,8 @@ static bool match_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index, int indexkey, Oid opclass, Expr *clause); static bool match_join_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index, int indexkey, Oid opclass, Expr *clause); +static Oid indexable_operator(Expr *clause, Oid opclass, + bool indexkey_on_left); static bool pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list, int relvarno); static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list); @@ -280,7 +282,7 @@ match_index_orclauses(RelOptInfo *rel, */ restrictinfo->subclauseindices = match_index_orclause(rel, index, - restrictinfo->clause->args, + ((BoolExpr *) restrictinfo->clause)->args, restrictinfo->subclauseindices); } } @@ -377,7 +379,7 @@ match_or_subclause_to_indexkey(RelOptInfo *rel, { List *item; - foreach(item, clause->args) + foreach(item, ((BoolExpr *) clause)->args) { if (match_clause_to_indexkey(rel, index, indexkey, opclass, lfirst(item))) @@ -443,7 +445,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel, if (and_clause((Node *) orsubclause)) { - foreach(item, orsubclause->args) + foreach(item, ((BoolExpr *) orsubclause)->args) { Expr *subsubclause = (Expr *) lfirst(item); @@ -715,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel, *rightop; /* Clause must be a binary opclause. */ - if (!is_opclause((Node *) clause)) + if (!is_opclause(clause)) return false; leftop = get_leftop(clause); rightop = get_rightop(clause); @@ -803,7 +805,7 @@ match_join_clause_to_indexkey(RelOptInfo *rel, *rightop; /* Clause must be a binary opclause. */ - if (!is_opclause((Node *) clause)) + if (!is_opclause(clause)) return false; leftop = get_leftop(clause); rightop = get_rightop(clause); @@ -857,10 +859,10 @@ match_join_clause_to_indexkey(RelOptInfo *rel, * (Formerly, this routine might return a binary-compatible operator * rather than the original one, but that kluge is history.) */ -Oid +static Oid indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left) { - Oid expr_op = ((Oper *) clause->oper)->opno; + Oid expr_op = ((OpExpr *) clause)->opno; Oid commuted_op; /* Get the commuted operator if necessary */ @@ -985,7 +987,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause) Assert(clause != NULL); if (or_clause(clause)) { - items = ((Expr *) clause)->args; + items = ((BoolExpr *) clause)->args; foreach(item, items) { /* if any OR item doesn't imply the predicate, clause doesn't */ @@ -996,7 +998,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause) } else if (and_clause(clause)) { - items = ((Expr *) clause)->args; + items = ((BoolExpr *) clause)->args; foreach(item, items) { /* @@ -1029,7 +1031,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause) Assert(predicate != NULL); if (or_clause((Node *) predicate)) { - items = predicate->args; + items = ((BoolExpr *) predicate)->args; foreach(item, items) { /* if any item is implied, the whole predicate is implied */ @@ -1040,7 +1042,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause) } else if (and_clause((Node *) predicate)) { - items = predicate->args; + items = ((BoolExpr *) predicate)->args; foreach(item, items) { /* @@ -1121,7 +1123,6 @@ pred_test_simple_clause(Expr *predicate, Node *clause) StrategyNumber pred_strategy = 0, clause_strategy, test_strategy; - Oper *test_oper; Expr *test_expr; Datum test_result; bool isNull; @@ -1140,7 +1141,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause) * Can't do anything more unless they are both binary opclauses with a * Var on the left and a Const on the right. */ - if (!is_opclause((Node *) predicate)) + if (!is_opclause(predicate)) return false; pred_var = (Var *) get_leftop(predicate); pred_const = (Const *) get_rightop(predicate); @@ -1167,8 +1168,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause) return false; /* Get the operators for the two clauses we're comparing */ - pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno; - clause_op = ((Oper *) ((Expr *) clause)->oper)->opno; + pred_op = ((OpExpr *) predicate)->opno; + clause_op = ((OpExpr *) clause)->opno; /* * 1. Find a "btree" strategy number for the pred_op @@ -1267,14 +1268,12 @@ pred_test_simple_clause(Expr *predicate, Node *clause) /* * 5. Evaluate the test */ - test_oper = makeOper(test_op, /* opno */ - InvalidOid, /* opid */ - BOOLOID, /* opresulttype */ - false); /* opretset */ - replace_opid(test_oper); - test_expr = make_opclause(test_oper, - (Var *) clause_const, - (Var *) pred_const); + test_expr = make_opclause(test_op, + BOOLOID, + false, + (Expr *) clause_const, + (Expr *) pred_const); + set_opfuncid((OpExpr *) test_expr); econtext = MakeExprContext(NULL, TransactionCommandContext); test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext, @@ -1627,7 +1626,7 @@ static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index) { int relvarno = lfirsti(rel->relids); - Func *function; + FuncExpr *function; List *funcargs; int *indexKeys = index->indexkeys; List *arg; @@ -1636,13 +1635,12 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index) /* * sanity check, make sure we know what we're dealing with here. */ - if (funcOpnd == NULL || !IsA(funcOpnd, Expr) || - funcOpnd->opType != FUNC_EXPR || - funcOpnd->oper == NULL || indexKeys == NULL) + if (funcOpnd == NULL || !IsA(funcOpnd, FuncExpr) || + indexKeys == NULL) return false; - function = (Func *) funcOpnd->oper; - funcargs = funcOpnd->args; + function = (FuncExpr *) funcOpnd; + funcargs = function->args; if (function->funcid != index->indproc) return false; @@ -1752,7 +1750,7 @@ match_special_index_operator(Expr *clause, Oid opclass, /* we know these will succeed */ leftop = get_leftop(clause); rightop = get_rightop(clause); - expr_op = ((Oper *) clause->oper)->opno; + expr_op = ((OpExpr *) clause)->opno; /* again, required for all current special ops: */ if (!IsA(rightop, Const) || @@ -1916,7 +1914,7 @@ expand_indexqual_conditions(List *indexquals) /* we know these will succeed */ Var *leftop = get_leftop(clause); Var *rightop = get_rightop(clause); - Oid expr_op = ((Oper *) clause->oper)->opno; + Oid expr_op = ((OpExpr *) clause)->opno; Const *patt = (Const *) rightop; Const *prefix = NULL; Const *rest = NULL; @@ -2011,7 +2009,6 @@ prefix_quals(Var *leftop, Oid expr_op, Oid oproid; char *prefix; Const *con; - Oper *op; Expr *expr; Const *greaterstr = NULL; @@ -2070,8 +2067,8 @@ prefix_quals(Var *leftop, Oid expr_op, if (oproid == InvalidOid) elog(ERROR, "prefix_quals: no = operator for type %u", datatype); con = string_to_const(prefix, datatype); - op = makeOper(oproid, InvalidOid, BOOLOID, false); - expr = make_opclause(op, leftop, (Var *) con); + expr = make_opclause(oproid, BOOLOID, false, + (Expr *) leftop, (Expr *) con); result = makeList1(expr); return result; } @@ -2085,8 +2082,8 @@ prefix_quals(Var *leftop, Oid expr_op, if (oproid == InvalidOid) elog(ERROR, "prefix_quals: no >= operator for type %u", datatype); con = string_to_const(prefix, datatype); - op = makeOper(oproid, InvalidOid, BOOLOID, false); - expr = make_opclause(op, leftop, (Var *) con); + expr = make_opclause(oproid, BOOLOID, false, + (Expr *) leftop, (Expr *) con); result = makeList1(expr); /*------- @@ -2100,8 +2097,8 @@ prefix_quals(Var *leftop, Oid expr_op, oproid = find_operator("<", datatype); if (oproid == InvalidOid) elog(ERROR, "prefix_quals: no < operator for type %u", datatype); - op = makeOper(oproid, InvalidOid, BOOLOID, false); - expr = make_opclause(op, leftop, (Var *) greaterstr); + expr = make_opclause(oproid, BOOLOID, false, + (Expr *) leftop, (Expr *) greaterstr); result = lappend(result, expr); } @@ -2124,7 +2121,6 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop) Oid opr2oid; List *result; Oid datatype; - Oper *op; Expr *expr; switch (expr_op) @@ -2164,10 +2160,10 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop) opr1right = network_scan_first(rightop); - op = makeOper(opr1oid, InvalidOid, BOOLOID, false); - expr = make_opclause(op, leftop, - (Var *) makeConst(datatype, -1, opr1right, - false, false)); + expr = make_opclause(opr1oid, BOOLOID, false, + (Expr *) leftop, + (Expr *) makeConst(datatype, -1, opr1right, + false, false)); result = makeList1(expr); /* create clause "key <= network_scan_last( rightop )" */ @@ -2179,10 +2175,10 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop) opr2right = network_scan_last(rightop); - op = makeOper(opr2oid, InvalidOid, BOOLOID, false); - expr = make_opclause(op, leftop, - (Var *) makeConst(datatype, -1, opr2right, - false, false)); + expr = make_opclause(opr2oid, BOOLOID, false, + (Expr *) leftop, + (Expr *) makeConst(datatype, -1, opr2right, + false, false)); result = lappend(result, expr); return result; diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c index 009afdff07919241a48dea8763b460c21cede0ba..101866867b9627a6f8c82fc572ce2adba277f435 100644 --- a/src/backend/optimizer/path/orindxpath.c +++ b/src/backend/optimizer/path/orindxpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.48 2002/11/24 21:52:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.49 2002/12/12 15:49:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -96,7 +96,7 @@ create_or_index_paths(Query *root, RelOptInfo *rel) best_or_subclause_indices(root, rel, - restrictinfo->clause->args, + ((BoolExpr *) restrictinfo->clause)->args, restrictinfo->subclauseindices, pathnode); diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 350c761165b4ff65505676f03591ac2d232c7f2e..af0b61a40347766139921361883f47ebc5e29b04 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.41 2002/09/18 21:35:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.42 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -514,14 +514,16 @@ build_index_pathkeys(Query *root, if (index->indproc) { /* Functional index: build a representation of the function call */ - Func *funcnode = makeNode(Func); + Expr *funcnode; List *funcargs = NIL; - funcnode->funcid = index->indproc; - funcnode->funcresulttype = get_func_rettype(index->indproc); - funcnode->funcretset = false; /* can never be a set */ - funcnode->funcformat = COERCE_DONTCARE; /* to match any user expr */ - funcnode->func_fcache = NULL; + sortop = *ordering; + if (ScanDirectionIsBackward(scandir)) + { + sortop = get_commutator(sortop); + if (sortop == InvalidOid) + return NIL; /* oops, no reverse sort operator? */ + } while (*indexkeys != 0) { @@ -530,17 +532,14 @@ build_index_pathkeys(Query *root, indexkeys++; } - sortop = *ordering; - if (ScanDirectionIsBackward(scandir)) - { - sortop = get_commutator(sortop); - if (sortop == InvalidOid) - return NIL; /* oops, no reverse sort operator? */ - } + funcnode = make_funcclause(index->indproc, + get_func_rettype(index->indproc), + false, /* cannot be a set */ + COERCE_DONTCARE, /* to match any user expr */ + funcargs); /* Make a one-sublist pathkeys list for the function expression */ - item = makePathKeyItem((Node *) make_funcclause(funcnode, funcargs), - sortop); + item = makePathKeyItem((Node *) funcnode, sortop); retval = makeList1(make_canonical_pathkey(root, item)); } else diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c index 27fe9e281f3993657f21ce4f209352d283f1bda7..f11ff81ea410b2931cf091ccfe1a3ce648d7c9e4 100644 --- a/src/backend/optimizer/path/tidpath.c +++ b/src/backend/optimizer/path/tidpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.12 2002/11/24 21:52:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.13 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,15 +27,14 @@ static List *TidqualFromRestrictinfo(List *relids, List *restrictinfo); static bool isEvaluable(int varno, Node *node); -static Node *TidequalClause(int varno, Expr *node); +static Node *TidequalClause(int varno, OpExpr *node); static List *TidqualFromExpr(int varno, Expr *expr); -static -bool +static bool isEvaluable(int varno, Node *node) { List *lst; - Expr *expr; + FuncExpr *expr; if (IsA(node, Const)) return true; @@ -51,7 +50,7 @@ isEvaluable(int varno, Node *node) } if (!is_funcclause(node)) return false; - expr = (Expr *) node; + expr = (FuncExpr *) node; foreach(lst, expr->args) { if (!isEvaluable(varno, lfirst(lst))) @@ -66,33 +65,26 @@ isEvaluable(int varno, Node *node) * Extract the right node if the opclause is CTID= .... * or the left node if the opclause is ....=CTID */ -static -Node * -TidequalClause(int varno, Expr *node) +static Node * +TidequalClause(int varno, OpExpr *node) { - Node *rnode = 0, + Node *rnode = NULL, *arg1, *arg2, *arg; - Oper *oper; Var *var; Const *aconst; Param *param; - Expr *expr; + FuncExpr *expr; - if (!node->oper) - return rnode; - if (!node->args) + if (node->opno != TIDEqualOperator) return rnode; if (length(node->args) != 2) return rnode; - oper = (Oper *) node->oper; - if (oper->opno != TIDEqualOperator) - return rnode; arg1 = lfirst(node->args); arg2 = lsecond(node->args); - arg = (Node *) 0; + arg = NULL; if (IsA(arg1, Var)) { var = (Var *) arg1; @@ -138,11 +130,9 @@ TidequalClause(int varno, Expr *node) return rnode; rnode = arg; break; - case T_Expr: - expr = (Expr *) arg; - if (expr->typeOid != TIDOID) - return rnode; - if (expr->opType != FUNC_EXPR) + case T_FuncExpr: + expr = (FuncExpr *) arg; + if (expr->funcresulttype != TIDOID) return rnode; if (isEvaluable(varno, (Node *) expr)) rnode = arg; @@ -162,8 +152,7 @@ TidequalClause(int varno, Expr *node) * CTID values if we could extract the CTID values from a member * node. */ -static -List * +static List * TidqualFromExpr(int varno, Expr *expr) { List *rlst = NIL, @@ -174,17 +163,15 @@ TidqualFromExpr(int varno, Expr *expr) if (is_opclause(node)) { - rnode = TidequalClause(varno, expr); + rnode = TidequalClause(varno, (OpExpr *) expr); if (rnode) rlst = lcons(rnode, rlst); } else if (and_clause(node)) { - foreach(lst, expr->args) + foreach(lst, ((BoolExpr *) expr)->args) { node = lfirst(lst); - if (!IsA(node, Expr)) - continue; rlst = TidqualFromExpr(varno, (Expr *) node); if (rlst) break; @@ -192,11 +179,11 @@ TidqualFromExpr(int varno, Expr *expr) } else if (or_clause(node)) { - foreach(lst, expr->args) + foreach(lst, ((BoolExpr *) expr)->args) { node = lfirst(lst); - if (IsA(node, Expr) && - (frtn = TidqualFromExpr(varno, (Expr *) node))) + frtn = TidqualFromExpr(varno, (Expr *) node); + if (frtn) rlst = nconc(rlst, frtn); else { diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 0414fdf2f3f1ced062251f73330294a75f75a79c..a67e23fbf200a0a49290d1cf0052084ba6bf7927 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.127 2002/12/05 15:50:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.128 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1041,12 +1041,12 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index, foreach(i, indexqual) { - Expr *clause = (Expr *) lfirst(i); - Expr *newclause; + OpExpr *clause = (OpExpr *) lfirst(i); + OpExpr *newclause; List *leftvarnos; Oid opclass; - if (!is_opclause((Node *) clause) || length(clause->args) != 2) + if (!IsA(clause, OpExpr) || length(clause->args) != 2) elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause"); /* @@ -1056,7 +1056,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index, * is a subplan in the arguments of the opclause. So just do a * full copy. */ - newclause = (Expr *) copyObject((Node *) clause); + newclause = (OpExpr *) copyObject((Node *) clause); /* * Check to see if the indexkey is on the right; if so, commute @@ -1083,7 +1083,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index, * Finally, check to see if index is lossy for this operator. If * so, add (a copy of) original form of clause to recheck list. */ - if (op_requires_recheck(((Oper *) newclause->oper)->opno, opclass)) + if (op_requires_recheck(newclause->opno, opclass)) recheck_qual = lappend(recheck_qual, copyObject((Node *) clause)); } @@ -1100,7 +1100,7 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index, * Remove any binary-compatible relabeling of the indexkey */ if (IsA(node, RelabelType)) - node = ((RelabelType *) node)->arg; + node = (Node *) ((RelabelType *) node)->arg; /* * We represent index keys by Var nodes having the varno of the base @@ -1168,11 +1168,11 @@ switch_outer(List *clauses) foreach(i, clauses) { - Expr *clause = (Expr *) lfirst(i); + OpExpr *clause = (OpExpr *) lfirst(i); Var *op; - Assert(is_opclause((Node *) clause)); - op = get_rightop(clause); + Assert(is_opclause(clause)); + op = get_rightop((Expr *) clause); Assert(op && IsA(op, Var)); if (var_is_outer(op)) { @@ -1181,10 +1181,13 @@ switch_outer(List *clauses) * the clause without changing the original list. Could use * copyObject, but a complete deep copy is overkill. */ - Expr *temp; + OpExpr *temp = makeNode(OpExpr); - temp = make_clause(clause->opType, clause->oper, - listCopy(clause->args)); + temp->opno = clause->opno; + temp->opfuncid = InvalidOid; + temp->opresulttype = clause->opresulttype; + temp->opretset = clause->opretset; + temp->args = listCopy(clause->args); /* Commute it --- note this modifies the temp node in-place. */ CommuteClause(temp); t_list = lappend(t_list, temp); diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 529ba712f411bc74a51a9a993b5ed7fb8efeabdf..aca2c6f4f67cefd0405955d072bac191f17b5452 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.77 2002/11/24 21:52:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.78 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -761,14 +761,11 @@ process_implied_equality(Query *root, Node *item1, Node *item2, elog(ERROR, "Equality operator for types '%s' and '%s' should be mergejoinable, but isn't", format_type_be(ltype), format_type_be(rtype)); - clause = makeNode(Expr); - clause->typeOid = BOOLOID; - clause->opType = OP_EXPR; - clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */ - InvalidOid, /* opid */ - BOOLOID, /* opresulttype */ - false); /* opretset */ - clause->args = makeList2(item1, item2); + clause = make_opclause(oprid(eq_operator), /* opno */ + BOOLOID, /* opresulttype */ + false, /* opretset */ + (Expr *) item1, + (Expr *) item2); ReleaseSysCache(eq_operator); @@ -969,7 +966,7 @@ check_mergejoinable(RestrictInfo *restrictinfo) leftOp, rightOp; - if (!is_opclause((Node *) clause)) + if (!is_opclause(clause)) return; left = get_leftop(clause); @@ -978,10 +975,11 @@ check_mergejoinable(RestrictInfo *restrictinfo) /* caution: is_opclause accepts more than I do, so check it */ if (!right) return; /* unary opclauses need not apply */ - if (!IsA(left, Var) ||!IsA(right, Var)) + if (!IsA(left, Var) || + !IsA(right, Var)) return; - opno = ((Oper *) clause->oper)->opno; + opno = ((OpExpr *) clause)->opno; if (op_mergejoinable(opno, left->vartype, @@ -1012,7 +1010,7 @@ check_hashjoinable(RestrictInfo *restrictinfo) *right; Oid opno; - if (!is_opclause((Node *) clause)) + if (!is_opclause(clause)) return; left = get_leftop(clause); @@ -1021,10 +1019,11 @@ check_hashjoinable(RestrictInfo *restrictinfo) /* caution: is_opclause accepts more than I do, so check it */ if (!right) return; /* unary opclauses need not apply */ - if (!IsA(left, Var) ||!IsA(right, Var)) + if (!IsA(left, Var) || + !IsA(right, Var)) return; - opno = ((Oper *) clause->oper)->opno; + opno = ((OpExpr *) clause)->opno; if (op_hashjoinable(opno, left->vartype, diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index ebb9f3d2092f43c8db0b062ac28961c3b51293c8..b3d7b5303c4f46716b73ab8001823826ed157725 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.133 2002/12/05 21:46:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.134 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -91,7 +91,7 @@ planner(Query *parse) * purpose is communication across multiple sub-Queries. * * Note we do NOT save and restore PlannerPlanId: it exists to assign - * unique IDs to SubPlan nodes, and we want those IDs to be unique for + * unique IDs to SubPlanExpr nodes, and we want those IDs to be unique for * the life of a backend. Also, PlannerInitPlan is saved/restored in * subquery_planner, not here. */ @@ -278,7 +278,7 @@ subquery_planner(Query *parse, double tuple_fraction) /* Must add the initPlans' extParams to the topmost node's, too */ foreach(lst, plan->initPlan) { - SubPlan *subplan = (SubPlan *) lfirst(lst); + SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst); plan->extParam = set_unioni(plan->extParam, subplan->plan->extParam); @@ -1015,7 +1015,7 @@ grouping_planner(Query *parse, double tuple_fraction) -1, 0); - ctid = makeTargetEntry(resdom, (Node *) var); + ctid = makeTargetEntry(resdom, (Expr *) var); tlist = lappend(tlist, ctid); } } @@ -1707,7 +1707,7 @@ make_subplanTargetList(Query *parse, exprTypmod(groupexpr), NULL, false), - groupexpr); + (Expr *) groupexpr); sub_tlist = lappend(sub_tlist, te); } diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index b23843a030cdcb7556d2f992ba2a9e17dc40cb17..0d66c97964c421e3b3bc79857d53a1b66582438a 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.84 2002/12/05 15:50:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.85 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -52,7 +52,7 @@ static Node *replace_vars_with_subplan_refs(Node *node, bool tlist_has_non_vars); static Node *replace_vars_with_subplan_refs_mutator(Node *node, replace_vars_with_subplan_refs_context *context); -static bool fix_opids_walker(Node *node, void *context); +static bool fix_opfuncids_walker(Node *node, void *context); /***************************************************************************** * @@ -219,7 +219,7 @@ set_plan_references(Plan *plan, List *rtable) * subplan references in this plan's tlist and quals. If we did the * reference-adjustments bottom-up, then we would fail to match this * plan's var nodes against the already-modified nodes of the - * children. Fortunately, that consideration doesn't apply to SubPlan + * children. Fortunately, that consideration doesn't apply to SubPlanExpr * nodes; else we'd need two passes over the expression trees. */ set_plan_references(plan->lefttree, rtable); @@ -227,9 +227,9 @@ set_plan_references(Plan *plan, List *rtable) foreach(pl, plan->initPlan) { - SubPlan *sp = (SubPlan *) lfirst(pl); + SubPlanExpr *sp = (SubPlanExpr *) lfirst(pl); - Assert(IsA(sp, SubPlan)); + Assert(IsA(sp, SubPlanExpr)); set_plan_references(sp->plan, sp->rtable); } } @@ -238,8 +238,8 @@ set_plan_references(Plan *plan, List *rtable) * fix_expr_references * Do final cleanup on expressions (targetlists or quals). * - * This consists of looking up operator opcode info for Oper nodes - * and recursively performing set_plan_references on SubPlans. + * This consists of looking up operator opcode info for OpExpr nodes + * and recursively performing set_plan_references on subplans. * * The Plan argument is currently unused, but might be needed again someday. */ @@ -255,20 +255,15 @@ fix_expr_references_walker(Node *node, void *context) { if (node == NULL) return false; - if (IsA(node, Expr)) + if (IsA(node, OpExpr)) + set_opfuncid((OpExpr *) node); + else if (IsA(node, DistinctExpr)) + set_opfuncid((OpExpr *) node); /* rely on struct equivalence */ + else if (IsA(node, SubPlanExpr)) { - Expr *expr = (Expr *) node; + SubPlanExpr *sp = (SubPlanExpr *) node; - if (expr->opType == OP_EXPR || - expr->opType == DISTINCT_EXPR) - replace_opid((Oper *) expr->oper); - else if (expr->opType == SUBPLAN_EXPR) - { - SubPlan *sp = (SubPlan *) expr->oper; - - Assert(IsA(sp, SubPlan)); - set_plan_references(sp->plan, sp->rtable); - } + set_plan_references(sp->plan, sp->rtable); } return expression_tree_walker(node, fix_expr_references_walker, context); } @@ -362,12 +357,13 @@ set_uppernode_references(Plan *plan, Index subvarno) TargetEntry *tle = (TargetEntry *) lfirst(l); Node *newexpr; - newexpr = replace_vars_with_subplan_refs(tle->expr, + newexpr = replace_vars_with_subplan_refs((Node *) tle->expr, subvarno, subplan_targetlist, tlist_has_non_vars); output_targetlist = lappend(output_targetlist, - makeTargetEntry(tle->resdom, newexpr)); + makeTargetEntry(tle->resdom, + (Expr *) newexpr)); } plan->targetlist = output_targetlist; @@ -570,8 +566,8 @@ replace_vars_with_subplan_refs_mutator(Node *node, *****************************************************************************/ /* - * fix_opids - * Calculate opid field from opno for each Oper node in given tree. + * fix_opfuncids + * Calculate opfuncid field from opno for each OpExpr node in given tree. * The given tree can be anything expression_tree_walker handles. * * The argument is modified in-place. (This is OK since we'd want the @@ -579,24 +575,20 @@ replace_vars_with_subplan_refs_mutator(Node *node, * shared structure.) */ void -fix_opids(Node *node) +fix_opfuncids(Node *node) { /* This tree walk requires no special setup, so away we go... */ - fix_opids_walker(node, NULL); + fix_opfuncids_walker(node, NULL); } static bool -fix_opids_walker(Node *node, void *context) +fix_opfuncids_walker(Node *node, void *context) { if (node == NULL) return false; - if (IsA(node, Expr)) - { - Expr *expr = (Expr *) node; - - if (expr->opType == OP_EXPR || - expr->opType == DISTINCT_EXPR) - replace_opid((Oper *) expr->oper); - } - return expression_tree_walker(node, fix_opids_walker, context); + if (IsA(node, OpExpr)) + set_opfuncid((OpExpr *) node); + else if (IsA(node, DistinctExpr)) + set_opfuncid((OpExpr *) node); /* rely on struct equivalence */ + return expression_tree_walker(node, fix_opfuncids_walker, context); } diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index a65de72c90b89c0f198df27c0dcff685dc23ce8e..fe17b8ebb018eab2e835a70d4ad59bf2d2c0a0bf 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.59 2002/12/05 15:50:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.60 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -144,12 +144,12 @@ generate_new_param(Oid paramtype, int32 paramtypmod) } /* - * Convert a bare SubLink (as created by the parser) into a SubPlan. + * Convert a bare SubLink (as created by the parser) into a SubPlanExpr. */ static Node * make_subplan(SubLink *slink) { - SubPlan *node = makeNode(SubPlan); + SubPlanExpr *node = makeNode(SubPlanExpr); Query *subquery = (Query *) (slink->subselect); Oid result_type = exprType((Node *) slink); double tuple_fraction; @@ -210,11 +210,13 @@ make_subplan(SubLink *slink) node->plan = plan = subquery_planner(subquery, tuple_fraction); node->plan_id = PlannerPlanId++; /* Assign unique ID to this - * SubPlan */ + * SubPlanExpr */ node->rtable = subquery->rtable; node->sublink = slink; + node->typeOid = result_type; + slink->subselect = NULL; /* cool ?! see error check above! */ /* @@ -270,7 +272,6 @@ make_subplan(SubLink *slink) } else { - Expr *expr = makeNode(Expr); List *args = NIL; /* @@ -350,14 +351,7 @@ make_subplan(SubLink *slink) convert_sublink_opers(slink, plan->targetlist, NULL); /* - * Make expression of SUBPLAN type - */ - expr->typeOid = result_type; - expr->opType = SUBPLAN_EXPR; - expr->oper = (Node *) node; - - /* - * Make expr->args from parParam. + * Make node->args from parParam. */ foreach(lst, node->parParam) { @@ -373,9 +367,9 @@ make_subplan(SubLink *slink) var->varlevelsup = 0; args = lappend(args, var); } - expr->args = args; + node->args = args; - result = (Node *) expr; + result = (Node *) node; } return result; @@ -385,7 +379,7 @@ make_subplan(SubLink *slink) * convert_sublink_opers: convert a SubLink's oper list from the * parser/rewriter format into the executor's format. * - * The oper list is initially just a list of Oper nodes. We replace it + * The oper list is initially just a list of OpExpr nodes. We replace it * with a list of actually executable expressions, in which the specified * operators are applied to corresponding elements of the lefthand list * and Params representing the results of the subplan. lefthand is then @@ -404,7 +398,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist, foreach(lst, slink->oper) { - Oper *oper = (Oper *) lfirst(lst); + OpExpr *oper = (OpExpr *) lfirst(lst); Node *lefthand = lfirst(leftlist); TargetEntry *te = lfirst(targetlist); Param *prm; @@ -422,7 +416,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist, *setParams = lappendi(*setParams, prm->paramid); /* Look up the operator to check its declared input types */ - Assert(IsA(oper, Oper)); + Assert(IsA(oper, OpExpr)); tup = SearchSysCache(OPEROID, ObjectIdGetDatum(oper->opno), 0, 0, 0); @@ -439,9 +433,11 @@ convert_sublink_opers(SubLink *slink, List *targetlist, left = make_operand(lefthand, exprType(lefthand), opform->oprleft); right = make_operand((Node *) prm, prm->paramtype, opform->oprright); newoper = lappend(newoper, - make_opclause(oper, - (Var *) left, - (Var *) right)); + make_opclause(oper->opno, + oper->opresulttype, + oper->opretset, + (Expr *) left, + (Expr *) right)); ReleaseSysCache(tup); @@ -482,7 +478,7 @@ finalize_primnode(Node *node, finalize_primnode_results *results) } if (is_subplan(node)) { - SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper; + SubPlanExpr *subplan = (SubPlanExpr *) node; List *lst; /* Check extParam list for params to add to paramids */ @@ -559,12 +555,12 @@ process_sublinks_mutator(Node *node, void *context) */ sublink->lefthand = (List *) process_sublinks_mutator((Node *) sublink->lefthand, context); - /* Now build the SubPlan node and make the expr to return */ + /* Now build the SubPlanExpr node and make the expr to return */ return make_subplan(sublink); } /* - * Note that we will never see a SubPlan expression in the input + * Note that we will never see a SubPlanExpr expression in the input * (since this is the very routine that creates 'em to begin with). So * the code in expression_tree_mutator() that might do inappropriate * things with SubPlans or SubLinks will not be exercised. diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c index bb00555f69d9d02fb42112a230758017e0706de2..4016ba476deafc55e542eb2c3024317861db9ee1 100644 --- a/src/backend/optimizer/prep/prepqual.c +++ b/src/backend/optimizer/prep/prepqual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.33 2002/09/02 02:47:02 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.34 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -294,7 +294,7 @@ flatten_andors(Expr *qual) List *out_list = NIL; List *arg; - foreach(arg, qual->args) + foreach(arg, ((BoolExpr *) qual)->args) { Expr *subexpr = flatten_andors((Expr *) lfirst(arg)); @@ -305,7 +305,7 @@ flatten_andors(Expr *qual) * with any other expr. Otherwise we'd need a listCopy here. */ if (and_clause((Node *) subexpr)) - out_list = nconc(out_list, subexpr->args); + out_list = nconc(out_list, ((BoolExpr *) subexpr)->args); else out_list = lappend(out_list, subexpr); } @@ -316,7 +316,7 @@ flatten_andors(Expr *qual) List *out_list = NIL; List *arg; - foreach(arg, qual->args) + foreach(arg, ((BoolExpr *) qual)->args) { Expr *subexpr = flatten_andors((Expr *) lfirst(arg)); @@ -327,7 +327,7 @@ flatten_andors(Expr *qual) * with any other expr. Otherwise we'd need a listCopy here. */ if (or_clause((Node *) subexpr)) - out_list = nconc(out_list, subexpr->args); + out_list = nconc(out_list, ((BoolExpr *) subexpr)->args); else out_list = lappend(out_list, subexpr); } @@ -335,20 +335,17 @@ flatten_andors(Expr *qual) } else if (not_clause((Node *) qual)) return make_notclause(flatten_andors(get_notclausearg(qual))); - else if (is_opclause((Node *) qual)) + else if (is_opclause(qual)) { + OpExpr *opexpr = (OpExpr *) qual; Expr *left = (Expr *) get_leftop(qual); Expr *right = (Expr *) get_rightop(qual); - if (right) - return make_clause(qual->opType, qual->oper, - lcons(flatten_andors(left), - lcons(flatten_andors(right), - NIL))); - else - return make_clause(qual->opType, qual->oper, - lcons(flatten_andors(left), - NIL)); + return make_opclause(opexpr->opno, + opexpr->opresulttype, + opexpr->opretset, + flatten_andors(left), + flatten_andors(right)); } else return qual; @@ -379,7 +376,8 @@ pull_ors(List *orlist) * we'd need a listCopy here. */ if (or_clause((Node *) subexpr)) - out_list = nconc(out_list, pull_ors(subexpr->args)); + out_list = nconc(out_list, + pull_ors(((BoolExpr *) subexpr)->args)); else out_list = lappend(out_list, subexpr); } @@ -410,7 +408,8 @@ pull_ands(List *andlist) * we'd need a listCopy here. */ if (and_clause((Node *) subexpr)) - out_list = nconc(out_list, pull_ands(subexpr->args)); + out_list = nconc(out_list, + pull_ands(((BoolExpr *) subexpr)->args)); else out_list = lappend(out_list, subexpr); } @@ -433,20 +432,17 @@ find_nots(Expr *qual) #ifdef NOT_USED /* recursing into operator expressions is probably not worth it. */ - if (is_opclause((Node *) qual)) + if (is_opclause(qual)) { + OpExpr *opexpr = (OpExpr *) qual; Expr *left = (Expr *) get_leftop(qual); Expr *right = (Expr *) get_rightop(qual); - if (right) - return make_clause(qual->opType, qual->oper, - lcons(find_nots(left), - lcons(find_nots(right), - NIL))); - else - return make_clause(qual->opType, qual->oper, - lcons(find_nots(left), - NIL)); + return make_opclause(opexpr->opno, + opexpr->opresulttype, + opexpr->opretset, + find_nots(left), + find_nots(right)); } #endif if (and_clause((Node *) qual)) @@ -454,7 +450,7 @@ find_nots(Expr *qual) List *t_list = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) t_list = lappend(t_list, find_nots(lfirst(temp))); return make_andclause(pull_ands(t_list)); } @@ -463,7 +459,7 @@ find_nots(Expr *qual) List *t_list = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) t_list = lappend(t_list, find_nots(lfirst(temp))); return make_orclause(pull_ors(t_list)); } @@ -492,20 +488,17 @@ push_nots(Expr *qual) * Otherwise, retain the clause as it is (the 'not' can't be pushed * down any farther). */ - if (is_opclause((Node *) qual)) + if (is_opclause(qual)) { - Oper *oper = (Oper *) ((Expr *) qual)->oper; - Oid negator = get_negator(oper->opno); + OpExpr *opexpr = (OpExpr *) qual; + Oid negator = get_negator(opexpr->opno); if (negator) - { - Oper *op = (Oper *) makeOper(negator, - InvalidOid, - oper->opresulttype, - oper->opretset); - - return make_opclause(op, get_leftop(qual), get_rightop(qual)); - } + return make_opclause(negator, + opexpr->opresulttype, + opexpr->opretset, + (Expr *) get_leftop(qual), + (Expr *) get_rightop(qual)); else return make_notclause(qual); } @@ -521,7 +514,7 @@ push_nots(Expr *qual) List *t_list = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) t_list = lappend(t_list, push_nots(lfirst(temp))); return make_orclause(pull_ors(t_list)); } @@ -530,7 +523,7 @@ push_nots(Expr *qual) List *t_list = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) t_list = lappend(t_list, push_nots(lfirst(temp))); return make_andclause(pull_ands(t_list)); } @@ -576,7 +569,7 @@ find_ors(Expr *qual) List *andlist = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) andlist = lappend(andlist, find_ors(lfirst(temp))); return make_andclause(pull_ands(andlist)); } @@ -585,7 +578,7 @@ find_ors(Expr *qual) List *orlist = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) orlist = lappend(orlist, find_ors(lfirst(temp))); return or_normalize(pull_ors(orlist)); } @@ -629,7 +622,7 @@ or_normalize(List *orlist) if (and_clause((Node *) clause)) { - int nclauses = length(clause->args); + int nclauses = length(((BoolExpr *) clause)->args); if (nclauses > num_subclauses) { @@ -650,7 +643,7 @@ or_normalize(List *orlist) */ orlist = lremove(distributable, orlist); - foreach(temp, distributable->args) + foreach(temp, ((BoolExpr *) distributable)->args) { Expr *andclause = lfirst(temp); List *neworlist; @@ -703,7 +696,7 @@ find_ands(Expr *qual) List *orlist = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) orlist = lappend(orlist, find_ands(lfirst(temp))); return make_orclause(pull_ors(orlist)); } @@ -712,7 +705,7 @@ find_ands(Expr *qual) List *andlist = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) andlist = lappend(andlist, find_ands(lfirst(temp))); return and_normalize(pull_ands(andlist)); } @@ -757,7 +750,7 @@ and_normalize(List *andlist) if (or_clause((Node *) clause)) { - int nclauses = length(clause->args); + int nclauses = length(((BoolExpr *) clause)->args); if (nclauses > num_subclauses) { @@ -778,7 +771,7 @@ and_normalize(List *andlist) */ andlist = lremove(distributable, andlist); - foreach(temp, distributable->args) + foreach(temp, ((BoolExpr *) distributable)->args) { Expr *orclause = lfirst(temp); List *newandlist; @@ -829,7 +822,7 @@ qual_cleanup(Expr *qual) List *andlist = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) andlist = lappend(andlist, qual_cleanup(lfirst(temp))); andlist = remove_duplicates(pull_ands(andlist)); @@ -844,7 +837,7 @@ qual_cleanup(Expr *qual) List *orlist = NIL; List *temp; - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) orlist = lappend(orlist, qual_cleanup(lfirst(temp))); orlist = remove_duplicates(pull_ors(orlist)); @@ -910,7 +903,7 @@ count_bool_nodes(Expr *qual, *nodes = *cnfnodes = 0.0; *dnfnodes = 1.0; /* DNF nodes will be product of sub-counts */ - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) { count_bool_nodes(lfirst(temp), &subnodes, &subcnfnodes, &subdnfnodes); @@ -931,7 +924,7 @@ count_bool_nodes(Expr *qual, *nodes = *dnfnodes = 0.0; *cnfnodes = 1.0; /* CNF nodes will be product of sub-counts */ - foreach(temp, qual->args) + foreach(temp, ((BoolExpr *) qual)->args) { count_bool_nodes(lfirst(temp), &subnodes, &subcnfnodes, &subdnfnodes); diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 68895143061b5e4ffeced0db43882fbbf7c7543e..87d3c983a70830684c9be6547a63fb568e48d26f 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.58 2002/11/25 21:29:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.59 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -96,7 +96,7 @@ preprocess_targetlist(List *tlist, if (command_type == CMD_DELETE) tlist = listCopy(tlist); - tlist = lappend(tlist, makeTargetEntry(resdom, (Node *) var)); + tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var)); } return tlist; @@ -215,7 +215,7 @@ expand_targetlist(List *tlist, int command_type, atttypmod, pstrdup(NameStr(att_tup->attname)), false), - new_expr); + (Expr *) new_expr); } new_tlist = lappend(new_tlist, new_tle); diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 79063c02806945194f3ba96b0fce2c973cd04654..a55af2e2d060d3094fb1dae91ca26bbcf13bc200 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.81 2002/11/25 21:29:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.82 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -406,7 +406,7 @@ generate_setop_tlist(List *colTypes, int flag, * the output tlists of upper-level nodes! */ if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const)) - expr = inputtle->expr; + expr = (Node *) inputtle->expr; else expr = (Node *) makeVar(0, inputtle->resdom->resno, @@ -430,7 +430,7 @@ generate_setop_tlist(List *colTypes, int flag, colTypmod, pstrdup(reftle->resdom->resname), false); - tlist = lappend(tlist, makeTargetEntry(resdom, expr)); + tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); input_tlist = lnext(input_tlist); refnames_tlist = lnext(refnames_tlist); } @@ -449,7 +449,7 @@ generate_setop_tlist(List *colTypes, int flag, Int32GetDatum(flag), false, true); - tlist = lappend(tlist, makeTargetEntry(resdom, expr)); + tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); } return tlist; @@ -543,7 +543,7 @@ generate_append_tlist(List *colTypes, bool flag, colTypmod, pstrdup(reftle->resdom->resname), false); - tlist = lappend(tlist, makeTargetEntry(resdom, expr)); + tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); refnames_tlist = lnext(refnames_tlist); } @@ -561,7 +561,7 @@ generate_append_tlist(List *colTypes, bool flag, INT4OID, -1, 0); - tlist = lappend(tlist, makeTargetEntry(resdom, expr)); + tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); } pfree(colTypmods); @@ -872,13 +872,13 @@ adjust_inherited_attrs_mutator(Node *node, */ if (is_subplan(node)) { - SubPlan *subplan; + SubPlanExpr *subplan; /* Copy the node and process subplan args */ node = expression_tree_mutator(node, adjust_inherited_attrs_mutator, (void *) context); /* Make sure we have separate copies of subplan and its rtable */ - subplan = (SubPlan *) ((Expr *) node)->oper; + subplan = (SubPlanExpr *) node; subplan->plan = copyObject(subplan->plan); subplan->rtable = copyObject(subplan->rtable); return node; diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index a0d1b752bc4d5133eb3d73deba99775a20db102d..ef317c5b2231ee007affa2b8eacdfafd700b8ec0 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.115 2002/12/01 21:05:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.116 2002/12/12 15:49:32 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -70,84 +70,41 @@ static bool contain_mutable_functions_walker(Node *node, void *context); static bool contain_volatile_functions_walker(Node *node, void *context); static bool contain_nonstrict_functions_walker(Node *node, void *context); static Node *eval_const_expressions_mutator(Node *node, List *active_fns); -static Expr *simplify_op_or_func(Expr *expr, List *args, bool allow_inline, - List *active_fns); -static Expr *evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple); -static Expr *inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple, +static Expr *simplify_function(Oid funcid, List *args, bool allow_inline, List *active_fns); +static Expr *evaluate_function(Oid funcid, List *args, HeapTuple func_tuple); +static Expr *inline_function(Oid funcid, List *args, HeapTuple func_tuple, + List *active_fns); static Node *substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts); static Node *substitute_actual_parameters_mutator(Node *node, substitute_actual_parameters_context *context); -Expr * -make_clause(int type, Node *oper, List *args) -{ - Expr *expr = makeNode(Expr); - - switch (type) - { - case AND_EXPR: - case OR_EXPR: - case NOT_EXPR: - expr->typeOid = BOOLOID; - break; - case OP_EXPR: - case DISTINCT_EXPR: - expr->typeOid = ((Oper *) oper)->opresulttype; - break; - case FUNC_EXPR: - expr->typeOid = ((Func *) oper)->funcresulttype; - break; - default: - elog(ERROR, "make_clause: unsupported type %d", type); - break; - } - expr->opType = type; - expr->oper = oper; /* ignored for AND, OR, NOT */ - expr->args = args; - return expr; -} - - /***************************************************************************** * OPERATOR clause functions *****************************************************************************/ - -/* - * is_opclause - * - * Returns t iff the clause is an operator clause: - * (op expr expr) or (op expr). - */ -bool -is_opclause(Node *clause) -{ - return (clause != NULL && - IsA(clause, Expr) && - ((Expr *) clause)->opType == OP_EXPR); -} - /* * make_opclause - * Creates a clause given its operator, left operand, and right - * operand (pass NULL to create single-operand clause). + * Creates an operator clause given its operator info, left operand, + * and right operand (pass NULL to create single-operand clause). */ Expr * -make_opclause(Oper *op, Var *leftop, Var *rightop) +make_opclause(Oid opno, Oid opresulttype, bool opretset, + Expr *leftop, Expr *rightop) { - Expr *expr = makeNode(Expr); + OpExpr *expr = makeNode(OpExpr); - expr->typeOid = op->opresulttype; - expr->opType = OP_EXPR; - expr->oper = (Node *) op; + expr->opno = opno; + expr->opfuncid = InvalidOid; + expr->opresulttype = opresulttype; + expr->opretset = opretset; if (rightop) expr->args = makeList2(leftop, rightop); else expr->args = makeList1(leftop); - return expr; + return (Expr *) expr; } /* @@ -163,8 +120,10 @@ make_opclause(Oper *op, Var *leftop, Var *rightop) Var * get_leftop(Expr *clause) { - if (clause->args != NULL) - return lfirst(clause->args); + OpExpr *expr = (OpExpr *) clause; + + if (expr->args != NULL) + return lfirst(expr->args); else return NULL; } @@ -178,124 +137,109 @@ get_leftop(Expr *clause) Var * get_rightop(Expr *clause) { - if (clause->args != NULL && lnext(clause->args) != NULL) - return lfirst(lnext(clause->args)); + OpExpr *expr = (OpExpr *) clause; + + if (expr->args != NULL && lnext(expr->args) != NULL) + return lfirst(lnext(expr->args)); else return NULL; } /***************************************************************************** - * FUNC clause functions + * FUNCTION clause functions *****************************************************************************/ -/* - * is_funcclause - * - * Returns t iff the clause is a function clause: (func { expr }). - */ -bool -is_funcclause(Node *clause) -{ - return (clause != NULL && - IsA(clause, Expr) && - ((Expr *) clause)->opType == FUNC_EXPR); -} - /* * make_funcclause - * - * Creates a function clause given the FUNC node and the functional - * arguments. + * Creates a function clause given its function info and argument list. */ Expr * -make_funcclause(Func *func, List *funcargs) +make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset, + CoercionForm funcformat, List *funcargs) { - Expr *expr = makeNode(Expr); + FuncExpr *expr = makeNode(FuncExpr); - expr->typeOid = func->funcresulttype; - expr->opType = FUNC_EXPR; - expr->oper = (Node *) func; + expr->funcid = funcid; + expr->funcresulttype = funcresulttype; + expr->funcretset = funcretset; + expr->funcformat = funcformat; expr->args = funcargs; - return expr; + return (Expr *) expr; } /***************************************************************************** - * OR clause functions + * NOT clause functions *****************************************************************************/ /* - * or_clause + * not_clause * - * Returns t iff the clause is an 'or' clause: (OR { expr }). + * Returns t iff this is a 'not' clause: (NOT expr). */ bool -or_clause(Node *clause) +not_clause(Node *clause) { return (clause != NULL && - IsA(clause, Expr) && - ((Expr *) clause)->opType == OR_EXPR); + IsA(clause, BoolExpr) && + ((BoolExpr *) clause)->boolop == NOT_EXPR); } /* - * make_orclause + * make_notclause * - * Creates an 'or' clause given a list of its subclauses. + * Create a 'not' clause given the expression to be negated. */ Expr * -make_orclause(List *orclauses) +make_notclause(Expr *notclause) { - Expr *expr = makeNode(Expr); + BoolExpr *expr = makeNode(BoolExpr); - expr->typeOid = BOOLOID; - expr->opType = OR_EXPR; - expr->oper = NULL; - expr->args = orclauses; - return expr; + expr->boolop = NOT_EXPR; + expr->args = makeList1(notclause); + return (Expr *) expr; } -/***************************************************************************** - * NOT clause functions - *****************************************************************************/ - /* - * not_clause + * get_notclausearg * - * Returns t iff this is a 'not' clause: (NOT expr). + * Retrieve the clause within a 'not' clause */ -bool -not_clause(Node *clause) +Expr * +get_notclausearg(Expr *notclause) { - return (clause != NULL && - IsA(clause, Expr) && - ((Expr *) clause)->opType == NOT_EXPR); + return lfirst(((BoolExpr *) notclause)->args); } +/***************************************************************************** + * OR clause functions + *****************************************************************************/ + /* - * make_notclause + * or_clause * - * Create a 'not' clause given the expression to be negated. + * Returns t iff the clause is an 'or' clause: (OR { expr }). */ -Expr * -make_notclause(Expr *notclause) +bool +or_clause(Node *clause) { - Expr *expr = makeNode(Expr); - - expr->typeOid = BOOLOID; - expr->opType = NOT_EXPR; - expr->oper = NULL; - expr->args = makeList1(notclause); - return expr; + return (clause != NULL && + IsA(clause, BoolExpr) && + ((BoolExpr *) clause)->boolop == OR_EXPR); } /* - * get_notclausearg + * make_orclause * - * Retrieve the clause within a 'not' clause + * Creates an 'or' clause given a list of its subclauses. */ Expr * -get_notclausearg(Expr *notclause) +make_orclause(List *orclauses) { - return lfirst(notclause->args); + BoolExpr *expr = makeNode(BoolExpr); + + expr->boolop = OR_EXPR; + expr->args = orclauses; + return (Expr *) expr; } /***************************************************************************** @@ -312,25 +256,23 @@ bool and_clause(Node *clause) { return (clause != NULL && - IsA(clause, Expr) && - ((Expr *) clause)->opType == AND_EXPR); + IsA(clause, BoolExpr) && + ((BoolExpr *) clause)->boolop == AND_EXPR); } /* * make_andclause * - * Create an 'and' clause given its arguments in a list. + * Creates an 'and' clause given a list of its subclauses. */ Expr * make_andclause(List *andclauses) { - Expr *expr = makeNode(Expr); + BoolExpr *expr = makeNode(BoolExpr); - expr->typeOid = BOOLOID; - expr->opType = AND_EXPR; - expr->oper = NULL; + expr->boolop = AND_EXPR; expr->args = andclauses; - return expr; + return (Expr *) expr; } /* @@ -382,7 +324,7 @@ make_ands_implicit(Expr *clause) if (clause == NULL) return NIL; /* NULL -> NIL list == TRUE */ else if (and_clause((Node *) clause)) - return clause->args; + return ((BoolExpr *) clause)->args; else if (IsA(clause, Const) && !((Const *) clause)->constisnull && DatumGetBool(((Const *) clause)->constvalue)) @@ -476,7 +418,7 @@ pull_agg_clause_walker(Node *node, List **listptr) * Complain if the aggregate's argument contains any aggregates; * nested agg functions are semantically nonsensical. */ - if (contain_agg_clause(((Aggref *) node)->target)) + if (contain_agg_clause((Node *) ((Aggref *) node)->target)) elog(ERROR, "Aggregate function calls may not be nested"); /* @@ -512,38 +454,41 @@ expression_returns_set_walker(Node *node, void *context) { if (node == NULL) return false; - if (IsA(node, Expr)) + if (IsA(node, FuncExpr)) { - Expr *expr = (Expr *) node; + FuncExpr *expr = (FuncExpr *) node; - switch (expr->opType) - { - case OP_EXPR: - case DISTINCT_EXPR: - if (((Oper *) expr->oper)->opretset) - return true; - /* else fall through to check args */ - break; - case FUNC_EXPR: - if (((Func *) expr->oper)->funcretset) - return true; - /* else fall through to check args */ - break; - case OR_EXPR: - case AND_EXPR: - case NOT_EXPR: - /* Booleans can't return a set, so no need to recurse */ - return false; - case SUBPLAN_EXPR: - /* Subplans can't presently return sets either */ - return false; - } + if (expr->funcretset) + return true; + /* else fall through to check args */ + } + if (IsA(node, OpExpr)) + { + OpExpr *expr = (OpExpr *) node; + + if (expr->opretset) + return true; + /* else fall through to check args */ + } + if (IsA(node, DistinctExpr)) + { + DistinctExpr *expr = (DistinctExpr *) node; + + if (expr->opretset) + return true; + /* else fall through to check args */ } - /* Avoid recursion for some other cases that can't return a set */ + + /* Avoid recursion for some cases that can't return a set */ + if (IsA(node, BoolExpr)) + return false; if (IsA(node, Aggref)) return false; if (IsA(node, SubLink)) return false; + if (IsA(node, SubPlanExpr)) + return false; + return expression_tree_walker(node, expression_returns_set_walker, context); } @@ -574,7 +519,8 @@ contain_subplans_walker(Node *node, void *context) { if (node == NULL) return false; - if (is_subplan(node) || IsA(node, SubLink)) + if (IsA(node, SubPlanExpr) || + IsA(node, SubLink)) return true; /* abort the tree traversal and return * true */ return expression_tree_walker(node, contain_subplans_walker, context); @@ -584,8 +530,8 @@ contain_subplans_walker(Node *node, void *context) * pull_subplans * Recursively pulls all subplans from an expression tree. * - * Returns list of subplan nodes found. Note the nodes themselves are not - * copied, only referenced. + * Returns list of SubPlanExpr nodes found. Note the nodes themselves + * are not copied, only referenced. */ List * pull_subplans(Node *clause) @@ -603,7 +549,7 @@ pull_subplans_walker(Node *node, List **listptr) return false; if (is_subplan(node)) { - *listptr = lappend(*listptr, ((Expr *) node)->oper); + *listptr = lappend(*listptr, node); /* fall through to check args to subplan */ } return expression_tree_walker(node, pull_subplans_walker, @@ -710,7 +656,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node, */ List *t; - foreach(t, ((Expr *) node)->args) + foreach(t, ((SubPlanExpr *) node)->args) { Node *thisarg = lfirst(t); Var *var; @@ -789,24 +735,29 @@ contain_mutable_functions_walker(Node *node, void *context) { if (node == NULL) return false; - if (IsA(node, Expr)) + if (IsA(node, FuncExpr)) { - Expr *expr = (Expr *) node; + FuncExpr *expr = (FuncExpr *) node; - switch (expr->opType) - { - case OP_EXPR: - case DISTINCT_EXPR: - if (op_volatile(((Oper *) expr->oper)->opno) != PROVOLATILE_IMMUTABLE) - return true; - break; - case FUNC_EXPR: - if (func_volatile(((Func *) expr->oper)->funcid) != PROVOLATILE_IMMUTABLE) - return true; - break; - default: - break; - } + if (func_volatile(expr->funcid) != PROVOLATILE_IMMUTABLE) + return true; + /* else fall through to check args */ + } + if (IsA(node, OpExpr)) + { + OpExpr *expr = (OpExpr *) node; + + if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE) + return true; + /* else fall through to check args */ + } + if (IsA(node, DistinctExpr)) + { + DistinctExpr *expr = (DistinctExpr *) node; + + if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE) + return true; + /* else fall through to check args */ } return expression_tree_walker(node, contain_mutable_functions_walker, context); @@ -839,24 +790,29 @@ contain_volatile_functions_walker(Node *node, void *context) { if (node == NULL) return false; - if (IsA(node, Expr)) + if (IsA(node, FuncExpr)) { - Expr *expr = (Expr *) node; + FuncExpr *expr = (FuncExpr *) node; - switch (expr->opType) - { - case OP_EXPR: - case DISTINCT_EXPR: - if (op_volatile(((Oper *) expr->oper)->opno) == PROVOLATILE_VOLATILE) - return true; - break; - case FUNC_EXPR: - if (func_volatile(((Func *) expr->oper)->funcid) == PROVOLATILE_VOLATILE) - return true; - break; - default: - break; - } + if (func_volatile(expr->funcid) == PROVOLATILE_VOLATILE) + return true; + /* else fall through to check args */ + } + if (IsA(node, OpExpr)) + { + OpExpr *expr = (OpExpr *) node; + + if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE) + return true; + /* else fall through to check args */ + } + if (IsA(node, DistinctExpr)) + { + DistinctExpr *expr = (DistinctExpr *) node; + + if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE) + return true; + /* else fall through to check args */ } return expression_tree_walker(node, contain_volatile_functions_walker, context); @@ -876,7 +832,7 @@ contain_volatile_functions_walker(Node *node, void *context) * * XXX we do not examine sublinks/subplans to see if they contain uses of * nonstrict functions. It's not real clear if that is correct or not... - * for the current usage it does not matter, since inline_op_or_func() + * for the current usage it does not matter, since inline_function() * rejects cases with sublinks. */ bool @@ -890,23 +846,33 @@ contain_nonstrict_functions_walker(Node *node, void *context) { if (node == NULL) return false; - if (IsA(node, Expr)) + if (IsA(node, FuncExpr)) + { + FuncExpr *expr = (FuncExpr *) node; + + if (!func_strict(expr->funcid)) + return true; + /* else fall through to check args */ + } + if (IsA(node, OpExpr)) + { + OpExpr *expr = (OpExpr *) node; + + if (!op_strict(expr->opno)) + return true; + /* else fall through to check args */ + } + if (IsA(node, DistinctExpr)) + { + /* IS DISTINCT FROM is inherently non-strict */ + return true; + } + if (IsA(node, BoolExpr)) { - Expr *expr = (Expr *) node; + BoolExpr *expr = (BoolExpr *) node; - switch (expr->opType) + switch (expr->boolop) { - case OP_EXPR: - if (!op_strict(((Oper *) expr->oper)->opno)) - return true; - break; - case DISTINCT_EXPR: - /* IS DISTINCT FROM is inherently non-strict */ - return true; - case FUNC_EXPR: - if (!func_strict(((Func *) expr->oper)->funcid)) - return true; - break; case OR_EXPR: case AND_EXPR: /* OR, AND are inherently non-strict */ @@ -1147,39 +1113,28 @@ NumRelids(Node *clause) * XXX the clause is destructively modified! */ void -CommuteClause(Expr *clause) +CommuteClause(OpExpr *clause) { Oid opoid; - HeapTuple optup; - Form_pg_operator commuTup; - Oper *commu; Node *temp; - if (!is_opclause((Node *) clause) || + if (!is_opclause(clause) || length(clause->args) != 2) elog(ERROR, "CommuteClause: applied to non-binary-operator clause"); - opoid = ((Oper *) clause->oper)->opno; - - optup = SearchSysCache(OPEROID, - ObjectIdGetDatum(get_commutator(opoid)), - 0, 0, 0); - if (!HeapTupleIsValid(optup)) - elog(ERROR, "CommuteClause: no commutator for operator %u", opoid); - - commuTup = (Form_pg_operator) GETSTRUCT(optup); + opoid = get_commutator(clause->opno); - commu = makeOper(HeapTupleGetOid(optup), - commuTup->oprcode, - commuTup->oprresult, - ((Oper *) clause->oper)->opretset); - - ReleaseSysCache(optup); + if (!OidIsValid(opoid)) + elog(ERROR, "CommuteClause: no commutator for operator %u", + clause->opno); /* - * re-form the clause in-place! + * modify the clause in-place! */ - clause->oper = (Node *) commu; + clause->opno = opoid; + clause->opfuncid = InvalidOid; + /* opresulttype and opretset are assumed not to change */ + temp = lfirst(clause->args); lfirst(clause->args) = lsecond(clause->args); lsecond(clause->args) = temp; @@ -1223,15 +1178,94 @@ eval_const_expressions_mutator(Node *node, List *active_fns) { if (node == NULL) return NULL; - if (IsA(node, Expr)) + if (IsA(node, FuncExpr)) { - Expr *expr = (Expr *) node; + FuncExpr *expr = (FuncExpr *) node; List *args; - Const *const_input; - Expr *newexpr; + Expr *simple; + FuncExpr *newexpr; + + /* + * Reduce constants in the FuncExpr's arguments. We know args is + * either NIL or a List node, so we can call + * expression_tree_mutator directly rather than recursing to self. + */ + args = (List *) expression_tree_mutator((Node *) expr->args, + eval_const_expressions_mutator, + (void *) active_fns); + /* + * Code for op/func reduction is pretty bulky, so split it out + * as a separate function. + */ + simple = simplify_function(expr->funcid, args, true, active_fns); + if (simple) /* successfully simplified it */ + return (Node *) simple; + /* + * The expression cannot be simplified any further, so build and + * return a replacement FuncExpr node using the possibly-simplified + * arguments. + */ + newexpr = makeNode(FuncExpr); + newexpr->funcid = expr->funcid; + newexpr->funcresulttype = expr->funcresulttype; + newexpr->funcretset = expr->funcretset; + newexpr->funcformat = expr->funcformat; + newexpr->args = args; + return (Node *) newexpr; + } + if (IsA(node, OpExpr)) + { + OpExpr *expr = (OpExpr *) node; + List *args; + Expr *simple; + OpExpr *newexpr; /* - * Reduce constants in the Expr's arguments. We know args is + * Reduce constants in the OpExpr's arguments. We know args is + * either NIL or a List node, so we can call + * expression_tree_mutator directly rather than recursing to self. + */ + args = (List *) expression_tree_mutator((Node *) expr->args, + eval_const_expressions_mutator, + (void *) active_fns); + /* + * Need to get OID of underlying function. Okay to scribble on + * input to this extent. + */ + set_opfuncid(expr); + /* + * Code for op/func reduction is pretty bulky, so split it out + * as a separate function. + */ + simple = simplify_function(expr->opfuncid, args, true, active_fns); + if (simple) /* successfully simplified it */ + return (Node *) simple; + /* + * The expression cannot be simplified any further, so build and + * return a replacement OpExpr node using the possibly-simplified + * arguments. + */ + newexpr = makeNode(OpExpr); + newexpr->opno = expr->opno; + newexpr->opfuncid = expr->opfuncid; + newexpr->opresulttype = expr->opresulttype; + newexpr->opretset = expr->opretset; + newexpr->args = args; + return (Node *) newexpr; + } + if (IsA(node, DistinctExpr)) + { + DistinctExpr *expr = (DistinctExpr *) node; + List *args; + List *arg; + bool has_null_input = false; + bool all_null_input = true; + bool has_nonconst_input = false; + Expr *simple; + DistinctExpr *newexpr; + + /* + * Reduce constants in the DistinctExpr's arguments. We know args is * either NIL or a List node, so we can call * expression_tree_mutator directly rather than recursing to self. */ @@ -1239,76 +1273,83 @@ eval_const_expressions_mutator(Node *node, List *active_fns) eval_const_expressions_mutator, (void *) active_fns); - switch (expr->opType) + /* + * We must do our own check for NULLs because + * DistinctExpr has different results for NULL input + * than the underlying operator does. + */ + foreach(arg, args) { - case OP_EXPR: - case FUNC_EXPR: + if (IsA(lfirst(arg), Const)) + { + has_null_input |= ((Const *) lfirst(arg))->constisnull; + all_null_input &= ((Const *) lfirst(arg))->constisnull; + } + else + has_nonconst_input = true; + } - /* - * Code for op/func case is pretty bulky, so split it out - * as a separate function. - */ - newexpr = simplify_op_or_func(expr, args, - true, active_fns); - if (newexpr) /* successfully simplified it */ - return (Node *) newexpr; + /* all constants? then can optimize this out */ + if (!has_nonconst_input) + { + /* all nulls? then not distinct */ + if (all_null_input) + return MAKEBOOLCONST(false, false); - /* - * else fall out to build new Expr node with simplified - * args - */ - break; - case DISTINCT_EXPR: - { - List *arg; - bool has_null_input = false; - bool all_null_input = true; - bool has_nonconst_input = false; + /* one null? then distinct */ + if (has_null_input) + return MAKEBOOLCONST(true, false); - /* - * We must do our own check for NULLs because - * DISTINCT_EXPR has different results for NULL input - * than the underlying operator does. - */ - foreach(arg, args) - { - if (IsA(lfirst(arg), Const)) - { - has_null_input |= ((Const *) lfirst(arg))->constisnull; - all_null_input &= ((Const *) lfirst(arg))->constisnull; - } - else - has_nonconst_input = true; - } + /* otherwise try to evaluate the '=' operator */ + /* (NOT okay to try to inline it, though!) */ - /* all constants? then can optimize this out */ - if (!has_nonconst_input) - { - /* all nulls? then not distinct */ - if (all_null_input) - return MAKEBOOLCONST(false, false); - - /* one null? then distinct */ - if (has_null_input) - return MAKEBOOLCONST(true, false); - - /* otherwise try to evaluate the '=' operator */ - /* (NOT okay to try to inline it, though!) */ - newexpr = simplify_op_or_func(expr, args, - false, active_fns); - if (newexpr) /* successfully simplified it */ - return (Node *) newexpr; - } + /* + * Need to get OID of underlying function. Okay to scribble on + * input to this extent. + */ + set_opfuncid((OpExpr *) expr); /* rely on struct equivalence */ + /* + * Code for op/func reduction is pretty bulky, so split it out + * as a separate function. + */ + simple = simplify_function(expr->opfuncid, args, + false, active_fns); + if (simple) /* successfully simplified it */ + return (Node *) simple; + } - /* - * else fall out to build new Expr node with simplified - * args - */ - break; - } + /* + * The expression cannot be simplified any further, so build and + * return a replacement DistinctExpr node using the + * possibly-simplified arguments. + */ + newexpr = makeNode(DistinctExpr); + newexpr->opno = expr->opno; + newexpr->opfuncid = expr->opfuncid; + newexpr->opresulttype = expr->opresulttype; + newexpr->opretset = expr->opretset; + newexpr->args = args; + return (Node *) newexpr; + } + if (IsA(node, BoolExpr)) + { + BoolExpr *expr = (BoolExpr *) node; + List *args; + Const *const_input; + + /* + * Reduce constants in the BoolExpr's arguments. We know args is + * either NIL or a List node, so we can call + * expression_tree_mutator directly rather than recursing to self. + */ + args = (List *) expression_tree_mutator((Node *) expr->args, + eval_const_expressions_mutator, + (void *) active_fns); + + switch (expr->boolop) + { case OR_EXPR: { - /*---------- * OR arguments are handled as follows: * non constant: keep @@ -1361,7 +1402,6 @@ eval_const_expressions_mutator(Node *node, List *active_fns) } case AND_EXPR: { - /*---------- * AND arguments are handled as follows: * non constant: keep @@ -1414,47 +1454,34 @@ eval_const_expressions_mutator(Node *node, List *active_fns) } case NOT_EXPR: Assert(length(args) == 1); - if (!IsA(lfirst(args), Const)) - break; - const_input = (Const *) lfirst(args); - /* NOT NULL => NULL */ - if (const_input->constisnull) - return MAKEBOOLCONST(false, true); - /* otherwise pretty easy */ - return MAKEBOOLCONST(!DatumGetBool(const_input->constvalue), - false); - case SUBPLAN_EXPR: - - /* - * Return a SubPlan unchanged --- too late to do anything - * with it. The arglist simplification above was wasted - * work (the list probably only contains Var nodes - * anyway). - * - * XXX should we elog() here instead? Probably this routine - * should never be invoked after SubPlan creation. - */ - return (Node *) expr; + if (IsA(lfirst(args), Const)) + { + const_input = (Const *) lfirst(args); + /* NOT NULL => NULL */ + if (const_input->constisnull) + return MAKEBOOLCONST(false, true); + /* otherwise pretty easy */ + return MAKEBOOLCONST(!DatumGetBool(const_input->constvalue), + false); + } + /* Else we still need a NOT node */ + return (Node *) make_notclause(lfirst(args)); default: - elog(ERROR, "eval_const_expressions: unexpected opType %d", - (int) expr->opType); + elog(ERROR, "eval_const_expressions: unexpected boolop %d", + (int) expr->boolop); break; } - + } + if (IsA(node, SubPlanExpr)) + { /* - * If we break out of the above switch on opType, then the - * expression cannot be simplified any further, so build and - * return a replacement Expr node using the possibly-simplified - * arguments and the original oper node. Can't use make_clause() - * here because we want to be sure the typeOid field is - * preserved... + * Return a SubPlanExpr unchanged --- too late to do anything + * with it. + * + * XXX should we elog() here instead? Probably this routine + * should never be invoked after SubPlanExpr creation. */ - newexpr = makeNode(Expr); - newexpr->typeOid = expr->typeOid; - newexpr->opType = expr->opType; - newexpr->oper = expr->oper; - newexpr->args = args; - return (Node *) newexpr; + return node; } if (IsA(node, RelabelType)) { @@ -1466,14 +1493,15 @@ eval_const_expressions_mutator(Node *node, List *active_fns) RelabelType *relabel = (RelabelType *) node; Node *arg; - arg = eval_const_expressions_mutator(relabel->arg, active_fns); + arg = eval_const_expressions_mutator((Node *) relabel->arg, + active_fns); /* * If we find stacked RelabelTypes (eg, from foo :: int :: oid) we * can discard all but the top one. */ while (arg && IsA(arg, RelabelType)) - arg = ((RelabelType *) arg)->arg; + arg = (Node *) ((RelabelType *) arg)->arg; if (arg && IsA(arg, Const)) { @@ -1493,7 +1521,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns) { RelabelType *newrelabel = makeNode(RelabelType); - newrelabel->arg = arg; + newrelabel->arg = (Expr *) arg; newrelabel->resulttype = relabel->resulttype; newrelabel->resulttypmod = relabel->resulttypmod; return (Node *) newrelabel; @@ -1545,7 +1573,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns) * alternative, the CASE reduces to just this alternative. */ if (newargs == NIL) - return casewhen->result; + return (Node *) casewhen->result; /* * Otherwise, add it to the list, and drop all the rest. @@ -1555,7 +1583,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns) } /* Simplify the default result */ - defresult = eval_const_expressions_mutator(caseexpr->defresult, + defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult, active_fns); /* @@ -1569,7 +1597,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns) newcase->casetype = caseexpr->casetype; newcase->arg = NULL; newcase->args = newargs; - newcase->defresult = defresult; + newcase->defresult = (Expr *) defresult; return (Node *) newcase; } @@ -1585,19 +1613,18 @@ eval_const_expressions_mutator(Node *node, List *active_fns) } /* - * Subroutine for eval_const_expressions: try to simplify an op or func + * Subroutine for eval_const_expressions: try to simplify a function call + * (which might originally have been an operator; we don't care) * - * Inputs are the op or func Expr node, and the pre-simplified argument list; + * Inputs are the function OID and the pre-simplified argument list; * also a list of already-active inline function expansions. * * Returns a simplified expression if successful, or NULL if cannot - * simplify the op/func. + * simplify the function call. */ static Expr * -simplify_op_or_func(Expr *expr, List *args, bool allow_inline, - List *active_fns) +simplify_function(Oid funcid, List *args, bool allow_inline, List *active_fns) { - Oid funcid; HeapTuple func_tuple; Expr *newexpr; @@ -1609,30 +1636,16 @@ simplify_op_or_func(Expr *expr, List *args, bool allow_inline, * to the function's pg_proc tuple, so fetch it just once to use in both * attempts. */ - if (expr->opType == FUNC_EXPR) - { - Func *func = (Func *) expr->oper; - - funcid = func->funcid; - } - else /* OP_EXPR or DISTINCT_EXPR */ - { - Oper *oper = (Oper *) expr->oper; - - replace_opid(oper); /* OK to scribble on input to this extent */ - funcid = oper->opid; - } - func_tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0); if (!HeapTupleIsValid(func_tuple)) elog(ERROR, "Function OID %u does not exist", funcid); - newexpr = evaluate_op_or_func(expr, args, func_tuple); + newexpr = evaluate_function(funcid, args, func_tuple); if (!newexpr && allow_inline) - newexpr = inline_op_or_func(expr, args, func_tuple, active_fns); + newexpr = inline_function(funcid, args, func_tuple, active_fns); ReleaseSysCache(func_tuple); @@ -1640,17 +1653,17 @@ simplify_op_or_func(Expr *expr, List *args, bool allow_inline, } /* - * evaluate_op_or_func: try to pre-evaluate an op or func + * evaluate_function: try to pre-evaluate a function call * * We can do this if the function is strict and has any constant-null inputs * (just return a null constant), or if the function is immutable and has all * constant inputs (call it and return the result as a Const node). * * Returns a simplified expression if successful, or NULL if cannot - * simplify the op/func. + * simplify the function. */ static Expr * -evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple) +evaluate_function(Oid funcid, List *args, HeapTuple func_tuple) { Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple); Oid result_typeid = funcform->prorettype; @@ -1658,7 +1671,7 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple) bool resultTypByVal; bool has_nonconst_input = false; bool has_null_input = false; - Expr *newexpr; + FuncExpr *newexpr; ExprContext *econtext; Datum const_val; bool const_is_null; @@ -1705,21 +1718,20 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple) * We use the executor's routine ExecEvalExpr() to avoid duplication of * code and ensure we get the same result as the executor would get. * - * Build a new Expr node containing the already-simplified arguments. - * The only other setup needed here is the replace_opid() that - * simplify_op_or_func already did for the OP_EXPR/DISTINCT_EXPR case. + * Build a new FuncExpr node containing the already-simplified arguments. */ - newexpr = makeNode(Expr); - newexpr->typeOid = expr->typeOid; - newexpr->opType = expr->opType; - newexpr->oper = expr->oper; + newexpr = makeNode(FuncExpr); + newexpr->funcid = funcid; + newexpr->funcresulttype = result_typeid; + newexpr->funcretset = false; + newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */ newexpr->args = args; /* Get info needed about result datatype */ get_typlenbyval(result_typeid, &resultTypLen, &resultTypByVal); /* - * It is OK to pass a dummy econtext because none of the + * It is OK to use a dummy econtext because none of the * ExecEvalExpr() code used in this situation will use econtext. That * might seem fortuitous, but it's not so unreasonable --- a constant * expression does not depend on context, by definition, n'est ce pas? @@ -1745,7 +1757,7 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple) } /* - * inline_op_or_func: try to expand inline an op or func + * inline_function: try to expand a function call inline * * If the function is a sufficiently simple SQL-language function * (just "SELECT expression"), then we can inline it and avoid the rather @@ -1763,14 +1775,13 @@ evaluate_op_or_func(Expr *expr, List *args, HeapTuple func_tuple) * functions by inlining them. * * Returns a simplified expression if successful, or NULL if cannot - * simplify the op/func. + * simplify the function. */ static Expr * -inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple, - List *active_fns) +inline_function(Oid funcid, List *args, HeapTuple func_tuple, + List *active_fns) { Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple); - Oid funcid = HeapTupleGetOid(func_tuple); Oid result_typeid = funcform->prorettype; char result_typtype; char *src; @@ -1816,7 +1827,7 @@ inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple, * stuff that parsing might create. */ mycxt = AllocSetContextCreate(CurrentMemoryContext, - "inline_op_or_func", + "inline_function", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); @@ -1828,7 +1839,7 @@ inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple, Anum_pg_proc_prosrc, &isNull); if (isNull) - elog(ERROR, "inline_op_or_func: null prosrc for procedure %u", + elog(ERROR, "inline_function: null prosrc for procedure %u", funcid); src = DatumGetCString(DirectFunctionCall1(textout, tmp)); @@ -1877,7 +1888,7 @@ inline_op_or_func(Expr *expr, List *args, HeapTuple func_tuple, length(querytree->targetList) != 1) goto fail; - newexpr = ((TargetEntry *) lfirst(querytree->targetList))->expr; + newexpr = (Node *) ((TargetEntry *) lfirst(querytree->targetList))->expr; /* * Additional validity checks on the expression. It mustn't return a @@ -2065,17 +2076,17 @@ substitute_actual_parameters_mutator(Node *node, * FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query * jointrees and setOperation trees can be processed without additional code. * - * expression_tree_walker will handle SubLink and SubPlan nodes by recursing - * normally into the "lefthand" arguments (which belong to the outer plan). - * It will also call the walker on the sub-Query node; however, when - * expression_tree_walker itself is called on a Query node, it does nothing - * and returns "false". The net effect is that unless the walker does - * something special at a Query node, sub-selects will not be visited - * during an expression tree walk. This is exactly the behavior wanted - * in many cases --- and for those walkers that do want to recurse into - * sub-selects, special behavior is typically needed anyway at the entry - * to a sub-select (such as incrementing a depth counter). A walker that - * wants to examine sub-selects should include code along the lines of: + * expression_tree_walker will handle SubLink and SubPlanExpr nodes by + * recursing normally into the "lefthand" arguments (which are expressions + * belonging to the outer plan). It will also call the walker on the + * sub-Query node; however, when expression_tree_walker itself is called on a + * Query node, it does nothing and returns "false". The net effect is that + * unless the walker does something special at a Query node, sub-selects will + * not be visited during an expression tree walk. This is exactly the behavior + * wanted in many cases --- and for those walkers that do want to recurse into + * sub-selects, special behavior is typically needed anyway at the entry to a + * sub-select (such as incrementing a depth counter). A walker that wants to + * examine sub-selects should include code along the lines of: * * if (IsA(node, Query)) * { @@ -2115,29 +2126,12 @@ expression_tree_walker(Node *node, return false; switch (nodeTag(node)) { - case T_Const: case T_Var: + case T_Const: case T_Param: case T_RangeTblRef: /* primitive node types with no subnodes */ break; - case T_Expr: - { - Expr *expr = (Expr *) node; - - if (expr->opType == SUBPLAN_EXPR) - { - /* recurse to the SubLink node (skipping SubPlan!) */ - if (walker((Node *) ((SubPlan *) expr->oper)->sublink, - context)) - return true; - } - /* for all Expr node types, examine args list */ - if (expression_tree_walker((Node *) expr->args, - walker, context)) - return true; - } - break; case T_Aggref: return walker(((Aggref *) node)->target, context); case T_ArrayRef: @@ -2158,41 +2152,41 @@ expression_tree_walker(Node *node, return true; } break; - case T_FieldSelect: - return walker(((FieldSelect *) node)->arg, context); - case T_RelabelType: - return walker(((RelabelType *) node)->arg, context); - case T_CaseExpr: + case T_FuncExpr: { - CaseExpr *caseexpr = (CaseExpr *) node; + FuncExpr *expr = (FuncExpr *) node; - /* we assume walker doesn't care about CaseWhens, either */ - foreach(temp, caseexpr->args) - { - CaseWhen *when = (CaseWhen *) lfirst(temp); + if (expression_tree_walker((Node *) expr->args, + walker, context)) + return true; + } + break; + case T_OpExpr: + { + OpExpr *expr = (OpExpr *) node; - Assert(IsA(when, CaseWhen)); - if (walker(when->expr, context)) - return true; - if (walker(when->result, context)) - return true; - } - /* caseexpr->arg should be null, but we'll check it anyway */ - if (walker(caseexpr->arg, context)) + if (expression_tree_walker((Node *) expr->args, + walker, context)) return true; - if (walker(caseexpr->defresult, context)) + } + break; + case T_DistinctExpr: + { + DistinctExpr *expr = (DistinctExpr *) node; + + if (expression_tree_walker((Node *) expr->args, + walker, context)) return true; } break; - case T_NullTest: - return walker(((NullTest *) node)->arg, context); - case T_BooleanTest: - return walker(((BooleanTest *) node)->arg, context); - case T_ConstraintTest: - if (walker(((ConstraintTest *) node)->arg, context)) - return true; - return walker(((ConstraintTest *) node)->check_expr, context); - case T_ConstraintTestValue: + case T_BoolExpr: + { + BoolExpr *expr = (BoolExpr *) node; + + if (expression_tree_walker((Node *) expr->args, + walker, context)) + return true; + } break; case T_SubLink: { @@ -2202,7 +2196,7 @@ expression_tree_walker(Node *node, * If the SubLink has already been processed by * subselect.c, it will have lefthand=NIL, and we need to * scan the oper list. Otherwise we only need to look at - * the lefthand list (the incomplete Oper nodes in the + * the lefthand list (the incomplete OpExpr nodes in the * oper list are deemed uninteresting, perhaps even * confusing). */ @@ -2224,6 +2218,57 @@ expression_tree_walker(Node *node, return walker(sublink->subselect, context); } break; + case T_SubPlanExpr: + { + SubPlanExpr *expr = (SubPlanExpr *) node; + + /* recurse to the SubLink node, but not into the Plan */ + if (walker((Node *) expr->sublink, context)) + return true; + /* also examine args list */ + if (expression_tree_walker((Node *) expr->args, + walker, context)) + return true; + } + break; + case T_FieldSelect: + return walker(((FieldSelect *) node)->arg, context); + case T_RelabelType: + return walker(((RelabelType *) node)->arg, context); + case T_CaseExpr: + { + CaseExpr *caseexpr = (CaseExpr *) node; + + /* we assume walker doesn't care about CaseWhens, either */ + foreach(temp, caseexpr->args) + { + CaseWhen *when = (CaseWhen *) lfirst(temp); + + Assert(IsA(when, CaseWhen)); + if (walker(when->expr, context)) + return true; + if (walker(when->result, context)) + return true; + } + /* caseexpr->arg should be null, but we'll check it anyway */ + if (walker(caseexpr->arg, context)) + return true; + if (walker(caseexpr->defresult, context)) + return true; + } + break; + case T_NullTest: + return walker(((NullTest *) node)->arg, context); + case T_BooleanTest: + return walker(((BooleanTest *) node)->arg, context); + case T_ConstraintTest: + if (walker(((ConstraintTest *) node)->arg, context)) + return true; + return walker(((ConstraintTest *) node)->check_expr, context); + case T_ConstraintTestValue: + break; + case T_TargetEntry: + return walker(((TargetEntry *) node)->expr, context); case T_Query: /* Do nothing with a sub-Query, per discussion above */ break; @@ -2234,8 +2279,6 @@ expression_tree_walker(Node *node, return true; } break; - case T_TargetEntry: - return walker(((TargetEntry *) node)->expr, context); case T_FromExpr: { FromExpr *from = (FromExpr *) node; @@ -2387,14 +2430,14 @@ query_tree_walker(Query *query, * expression_tree_mutator include all those normally found in target lists * and qualifier clauses during the planning stage. * - * expression_tree_mutator will handle a SUBPLAN_EXPR node by recursing into - * the args and slink->oper lists (which belong to the outer plan), but it + * expression_tree_mutator will handle a SubPlanExpr node by recursing into + * the args and sublink->oper lists (which belong to the outer plan), but it * will simply copy the link to the inner plan, since that's typically what * expression tree mutators want. A mutator that wants to modify the subplan * can force appropriate behavior by recognizing subplan expression nodes * and doing the right thing. * - * Bare SubLink nodes (without a SUBPLAN_EXPR) are handled by recursing into + * Bare SubLink nodes (without a SubPlanExpr) are handled by recursing into * the "lefthand" argument list only. (A bare SubLink should be seen only if * the tree has not yet been processed by subselect.c.) Again, this can be * overridden by the mutator, but it seems to be the most useful default @@ -2428,61 +2471,19 @@ expression_tree_mutator(Node *node, return NULL; switch (nodeTag(node)) { - case T_Const: case T_Var: + case T_Const: case T_Param: case T_RangeTblRef: /* primitive node types with no subnodes */ return (Node *) copyObject(node); - case T_Expr: - { - Expr *expr = (Expr *) node; - Expr *newnode; - - FLATCOPY(newnode, expr, Expr); - - if (expr->opType == SUBPLAN_EXPR) - { - SubLink *oldsublink = ((SubPlan *) expr->oper)->sublink; - SubPlan *newsubplan; - - /* flat-copy the oper node, which is a SubPlan */ - CHECKFLATCOPY(newsubplan, expr->oper, SubPlan); - newnode->oper = (Node *) newsubplan; - /* likewise its SubLink node */ - CHECKFLATCOPY(newsubplan->sublink, oldsublink, SubLink); - - /* - * transform args list (params to be passed to - * subplan) - */ - MUTATE(newnode->args, expr->args, List *); - /* transform sublink's oper list as well */ - MUTATE(newsubplan->sublink->oper, oldsublink->oper, List *); - - /* - * but not the subplan itself, which is referenced - * as-is - */ - } - else - { - /* - * for other Expr node types, just transform args - * list, linking to original oper node (OK?) - */ - MUTATE(newnode->args, expr->args, List *); - } - return (Node *) newnode; - } - break; case T_Aggref: { Aggref *aggref = (Aggref *) node; Aggref *newnode; FLATCOPY(newnode, aggref, Aggref); - MUTATE(newnode->target, aggref->target, Node *); + MUTATE(newnode->target, aggref->target, Expr *); return (Node *) newnode; } break; @@ -2497,9 +2498,81 @@ expression_tree_mutator(Node *node, MUTATE(newnode->reflowerindexpr, arrayref->reflowerindexpr, List *); MUTATE(newnode->refexpr, arrayref->refexpr, - Node *); + Expr *); MUTATE(newnode->refassgnexpr, arrayref->refassgnexpr, - Node *); + Expr *); + return (Node *) newnode; + } + break; + case T_FuncExpr: + { + FuncExpr *expr = (FuncExpr *) node; + FuncExpr *newnode; + + FLATCOPY(newnode, expr, FuncExpr); + MUTATE(newnode->args, expr->args, List *); + return (Node *) newnode; + } + break; + case T_OpExpr: + { + OpExpr *expr = (OpExpr *) node; + OpExpr *newnode; + + FLATCOPY(newnode, expr, OpExpr); + MUTATE(newnode->args, expr->args, List *); + return (Node *) newnode; + } + break; + case T_DistinctExpr: + { + DistinctExpr *expr = (DistinctExpr *) node; + DistinctExpr *newnode; + + FLATCOPY(newnode, expr, DistinctExpr); + MUTATE(newnode->args, expr->args, List *); + return (Node *) newnode; + } + break; + case T_BoolExpr: + { + BoolExpr *expr = (BoolExpr *) node; + BoolExpr *newnode; + + FLATCOPY(newnode, expr, BoolExpr); + MUTATE(newnode->args, expr->args, List *); + return (Node *) newnode; + } + break; + case T_SubLink: + { + /* + * A "bare" SubLink (note we will not come here if we + * found a SubPlanExpr node above it). Transform the + * lefthand side, but not the oper list nor the subquery. + */ + SubLink *sublink = (SubLink *) node; + SubLink *newnode; + + FLATCOPY(newnode, sublink, SubLink); + MUTATE(newnode->lefthand, sublink->lefthand, List *); + return (Node *) newnode; + } + break; + case T_SubPlanExpr: + { + SubPlanExpr *expr = (SubPlanExpr *) node; + SubLink *oldsublink = expr->sublink; + SubPlanExpr *newnode; + + FLATCOPY(newnode, expr, SubPlanExpr); + /* flat-copy the SubLink node */ + CHECKFLATCOPY(newnode->sublink, oldsublink, SubLink); + /* transform args list (params to be passed to subplan) */ + MUTATE(newnode->args, expr->args, List *); + /* transform sublink's oper list as well */ + MUTATE(newnode->sublink->oper, oldsublink->oper, List *); + /* but not the subplan itself, which is referenced as-is */ return (Node *) newnode; } break; @@ -2509,7 +2582,7 @@ expression_tree_mutator(Node *node, FieldSelect *newnode; FLATCOPY(newnode, fselect, FieldSelect); - MUTATE(newnode->arg, fselect->arg, Node *); + MUTATE(newnode->arg, fselect->arg, Expr *); return (Node *) newnode; } break; @@ -2519,7 +2592,7 @@ expression_tree_mutator(Node *node, RelabelType *newnode; FLATCOPY(newnode, relabel, RelabelType); - MUTATE(newnode->arg, relabel->arg, Node *); + MUTATE(newnode->arg, relabel->arg, Expr *); return (Node *) newnode; } break; @@ -2531,8 +2604,8 @@ expression_tree_mutator(Node *node, FLATCOPY(newnode, caseexpr, CaseExpr); MUTATE(newnode->args, caseexpr->args, List *); /* caseexpr->arg should be null, but we'll check it anyway */ - MUTATE(newnode->arg, caseexpr->arg, Node *); - MUTATE(newnode->defresult, caseexpr->defresult, Node *); + MUTATE(newnode->arg, caseexpr->arg, Expr *); + MUTATE(newnode->defresult, caseexpr->defresult, Expr *); return (Node *) newnode; } break; @@ -2542,8 +2615,8 @@ expression_tree_mutator(Node *node, CaseWhen *newnode; FLATCOPY(newnode, casewhen, CaseWhen); - MUTATE(newnode->expr, casewhen->expr, Node *); - MUTATE(newnode->result, casewhen->result, Node *); + MUTATE(newnode->expr, casewhen->expr, Expr *); + MUTATE(newnode->result, casewhen->result, Expr *); return (Node *) newnode; } break; @@ -2553,7 +2626,7 @@ expression_tree_mutator(Node *node, NullTest *newnode; FLATCOPY(newnode, ntest, NullTest); - MUTATE(newnode->arg, ntest->arg, Node *); + MUTATE(newnode->arg, ntest->arg, Expr *); return (Node *) newnode; } break; @@ -2563,7 +2636,7 @@ expression_tree_mutator(Node *node, BooleanTest *newnode; FLATCOPY(newnode, btest, BooleanTest); - MUTATE(newnode->arg, btest->arg, Node *); + MUTATE(newnode->arg, btest->arg, Expr *); return (Node *) newnode; } break; @@ -2573,8 +2646,8 @@ expression_tree_mutator(Node *node, ConstraintTest *newnode; FLATCOPY(newnode, ctest, ConstraintTest); - MUTATE(newnode->arg, ctest->arg, Node *); - MUTATE(newnode->check_expr, ctest->check_expr, Node *); + MUTATE(newnode->arg, ctest->arg, Expr *); + MUTATE(newnode->check_expr, ctest->check_expr, Expr *); return (Node *) newnode; } break; @@ -2587,18 +2660,17 @@ expression_tree_mutator(Node *node, return (Node *) newnode; } break; - case T_SubLink: + case T_TargetEntry: { /* - * A "bare" SubLink (note we will not come here if we - * found a SUBPLAN_EXPR node above it). Transform the - * lefthand side, but not the oper list nor the subquery. + * We mutate the expression, but not the resdom, by + * default. */ - SubLink *sublink = (SubLink *) node; - SubLink *newnode; + TargetEntry *targetentry = (TargetEntry *) node; + TargetEntry *newnode; - FLATCOPY(newnode, sublink, SubLink); - MUTATE(newnode->lefthand, sublink->lefthand, List *); + FLATCOPY(newnode, targetentry, TargetEntry); + MUTATE(newnode->expr, targetentry->expr, Expr *); return (Node *) newnode; } break; @@ -2622,20 +2694,6 @@ expression_tree_mutator(Node *node, return (Node *) resultlist; } break; - case T_TargetEntry: - { - /* - * We mutate the expression, but not the resdom, by - * default. - */ - TargetEntry *targetentry = (TargetEntry *) node; - TargetEntry *newnode; - - FLATCOPY(newnode, targetentry, TargetEntry); - MUTATE(newnode->expr, targetentry->expr, Node *); - return (Node *) newnode; - } - break; case T_FromExpr: { FromExpr *from = (FromExpr *) node; diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index fa8c89862f4d0b3d1376e4816c0feb1da9ebdff0..0d268b8e40cb66750be062131f96edb62471827b 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.52 2002/06/20 20:29:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.53 2002/12/12 15:49:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -110,7 +110,7 @@ create_tl_element(Var *var, int resdomno) var->vartypmod, NULL, false), - (Node *) var); + (Expr *) var); } /***************************************************************************** @@ -253,5 +253,5 @@ get_sortgroupclause_expr(SortClause *sortClause, List *targetList) { TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList); - return tle->expr; + return (Node *) tle->expr; } diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 23b824dbcb019d239ee32ba79c3b44198645220c..8d22aa26b9144147956423135e9a41271c679c3d 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.40 2002/09/11 14:48:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.41 2002/12/12 15:49:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -65,7 +65,7 @@ static Node *flatten_join_alias_vars_mutator(Node *node, * NOTE: this is used on not-yet-planned expressions. It may therefore find * bare SubLinks, and if so it needs to recurse into them to look for uplevel * references to the desired rtable level! But when we find a completed - * SubPlan, we only need to look at the parameters passed to the subplan. + * SubPlanExpr, we only need to look at the parameters passed to the subplan. */ List * pull_varnos(Node *node) @@ -111,12 +111,12 @@ pull_varnos_walker(Node *node, pull_varnos_context *context) * executed by the outer query. But short-circuit recursion into * the subquery itself, which would be a waste of effort. */ - Expr *expr = (Expr *) node; + SubPlanExpr *subplan = (SubPlanExpr *) node; - if (pull_varnos_walker((Node *) ((SubPlan *) expr->oper)->sublink->oper, + if (pull_varnos_walker((Node *) subplan->sublink->oper, context)) return true; - if (pull_varnos_walker((Node *) expr->args, + if (pull_varnos_walker((Node *) subplan->args, context)) return true; return false; @@ -146,7 +146,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context) * NOTE: this is used on not-yet-planned expressions. It may therefore find * bare SubLinks, and if so it needs to recurse into them to look for uplevel * references to the desired rtable entry! But when we find a completed - * SubPlan, we only need to look at the parameters passed to the subplan. + * SubPlanExpr, we only need to look at the parameters passed to the subplan. */ bool contain_var_reference(Node *node, int varno, int varattno, int levelsup) @@ -194,12 +194,12 @@ contain_var_reference_walker(Node *node, * executed by the outer query. But short-circuit recursion into * the subquery itself, which would be a waste of effort. */ - Expr *expr = (Expr *) node; + SubPlanExpr *subplan = (SubPlanExpr *) node; - if (contain_var_reference_walker((Node *) ((SubPlan *) expr->oper)->sublink->oper, + if (contain_var_reference_walker((Node *) subplan->sublink->oper, context)) return true; - if (contain_var_reference_walker((Node *) expr->args, + if (contain_var_reference_walker((Node *) subplan->args, context)) return true; return false; diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 18144f7b94136c904258afdf9e31e3ce8529b696..56f0fdd955a4f79ecca798a55624d36ead4f5569 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.254 2002/11/15 02:50:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.255 2002/12/12 15:49:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -479,14 +479,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, { TargetEntry *tle = (TargetEntry *) lfirst(tl); Resdom *resnode = tle->resdom; - Node *expr; + Expr *expr; if (resnode->resjunk) continue; if (tle->expr && IsA(tle->expr, Const)) expr = tle->expr; else - expr = (Node *) makeVar(rtr->rtindex, + expr = (Expr *) makeVar(rtr->rtindex, resnode->resno, resnode->restype, resnode->restypmod, @@ -1807,14 +1807,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom; char *colName = pstrdup(leftResdom->resname); Resdom *resdom; - Node *expr; + Expr *expr; resdom = makeResdom((AttrNumber) pstate->p_last_resno++, colType, -1, colName, false); - expr = (Node *) makeVar(1, + expr = (Expr *) makeVar(1, leftResdom->resno, colType, -1, @@ -2424,7 +2424,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt) format_type_be(given_type_id), format_type_be(expected_type_id)); - fix_opids(expr); + fix_opfuncids(expr); lfirst(l) = expr; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index b3edb3b5505e43461390a5c18181f141ae0179e5..53e1a5999fed52e5a032f11057b35c2460331c29 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.386 2002/12/06 05:00:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.387 2002/12/12 15:49:36 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -5755,70 +5755,70 @@ a_expr: c_expr { $$ = $1; } | a_expr ISNULL { NullTest *n = makeNode(NullTest); - n->arg = $1; + n->arg = (Expr *) $1; n->nulltesttype = IS_NULL; $$ = (Node *)n; } | a_expr IS NULL_P { NullTest *n = makeNode(NullTest); - n->arg = $1; + n->arg = (Expr *) $1; n->nulltesttype = IS_NULL; $$ = (Node *)n; } | a_expr NOTNULL { NullTest *n = makeNode(NullTest); - n->arg = $1; + n->arg = (Expr *) $1; n->nulltesttype = IS_NOT_NULL; $$ = (Node *)n; } | a_expr IS NOT NULL_P { NullTest *n = makeNode(NullTest); - n->arg = $1; + n->arg = (Expr *) $1; n->nulltesttype = IS_NOT_NULL; $$ = (Node *)n; } | a_expr IS TRUE_P { BooleanTest *b = makeNode(BooleanTest); - b->arg = $1; + b->arg = (Expr *) $1; b->booltesttype = IS_TRUE; $$ = (Node *)b; } | a_expr IS NOT TRUE_P { BooleanTest *b = makeNode(BooleanTest); - b->arg = $1; + b->arg = (Expr *) $1; b->booltesttype = IS_NOT_TRUE; $$ = (Node *)b; } | a_expr IS FALSE_P { BooleanTest *b = makeNode(BooleanTest); - b->arg = $1; + b->arg = (Expr *) $1; b->booltesttype = IS_FALSE; $$ = (Node *)b; } | a_expr IS NOT FALSE_P { BooleanTest *b = makeNode(BooleanTest); - b->arg = $1; + b->arg = (Expr *) $1; b->booltesttype = IS_NOT_FALSE; $$ = (Node *)b; } | a_expr IS UNKNOWN { BooleanTest *b = makeNode(BooleanTest); - b->arg = $1; + b->arg = (Expr *) $1; b->booltesttype = IS_UNKNOWN; $$ = (Node *)b; } | a_expr IS NOT UNKNOWN { BooleanTest *b = makeNode(BooleanTest); - b->arg = $1; + b->arg = (Expr *) $1; b->booltesttype = IS_NOT_UNKNOWN; $$ = (Node *)b; } @@ -6640,9 +6640,9 @@ in_expr: select_with_parens case_expr: CASE case_arg when_clause_list case_default END_TRANS { CaseExpr *c = makeNode(CaseExpr); - c->arg = $2; + c->arg = (Expr *) $2; c->args = $3; - c->defresult = $4; + c->defresult = (Expr *) $4; $$ = (Node *)c; } | NULLIF '(' a_expr ',' a_expr ')' @@ -6650,10 +6650,10 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS CaseExpr *c = makeNode(CaseExpr); CaseWhen *w = makeNode(CaseWhen); - w->expr = (Node *) makeSimpleA_Expr(OP, "=", $3, $5); + w->expr = (Expr *) makeSimpleA_Expr(OP, "=", $3, $5); /* w->result is left NULL */ c->args = makeList1(w); - c->defresult = $3; + c->defresult = (Expr *) $3; $$ = (Node *)c; } | COALESCE '(' expr_list ')' @@ -6666,7 +6666,7 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS NullTest *n = makeNode(NullTest); n->arg = lfirst(l); n->nulltesttype = IS_NOT_NULL; - w->expr = (Node *) n; + w->expr = (Expr *) n; w->result = lfirst(l); c->args = lappend(c->args, w); } @@ -6684,8 +6684,8 @@ when_clause: WHEN a_expr THEN a_expr { CaseWhen *w = makeNode(CaseWhen); - w->expr = $2; - w->result = $4; + w->expr = (Expr *) $2; + w->result = (Expr *) $4; $$ = (Node *)w; } ; @@ -7594,20 +7594,17 @@ static Node * makeRowNullTest(NullTestType test, List *args) { Node *expr = NULL; - Node *arg; NullTest *n; if (lnext(args) != NIL) expr = makeRowNullTest(test, lnext(args)); - arg = lfirst(args); - n = makeNode(NullTest); - n->arg = arg; + n->arg = (Expr *) lfirst(args); n->nulltesttype = test; if (expr == NULL) - expr = (Node *)n; + expr = (Node *) n; else if (test == IS_NOT_NULL) expr = (Node *) makeA_Expr(OR, NIL, expr, (Node *)n); else diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index ca398b4e3b31d4f50b4db0cd87e5ed409c7d19e0..6f05ee329cd1127ffd06f5760452ff92f291f358 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * 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"); } - /* - * 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. */ @@ -876,7 +865,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar) outcoltype, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); else if (l_colvar->vartypmod != outcoltypmod) - l_node = (Node *) makeRelabelType((Node *) l_colvar, + l_node = (Node *) makeRelabelType((Expr *) l_colvar, outcoltype, outcoltypmod, COERCE_IMPLICIT_CAST); else @@ -887,7 +876,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar) outcoltype, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); else if (r_colvar->vartypmod != outcoltypmod) - r_node = (Node *) makeRelabelType((Node *) r_colvar, + r_node = (Node *) makeRelabelType((Expr *) r_colvar, outcoltype, outcoltypmod, COERCE_IMPLICIT_CAST); else @@ -928,13 +917,13 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar) CaseWhen *w = makeNode(CaseWhen); NullTest *n = makeNode(NullTest); - n->arg = l_node; + n->arg = (Expr *) l_node; n->nulltesttype = IS_NOT_NULL; - w->expr = (Node *) n; - w->result = l_node; + w->expr = (Expr *) n; + w->result = (Expr *) l_node; c->casetype = outcoltype; c->args = makeList1(w); - c->defresult = r_node; + c->defresult = (Expr *) r_node; res_node = (Node *) c; break; } diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 6d3524c5d6c148406bdc8bef0cd573121b33c649..3856939d404a87d83ded1857a4c37120fec36587 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * 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); /* Need a RelabelType if no typmod coercion is performed */ if (targettypmod < 0) - expr = (Node *) makeRelabelType(expr, targettype, -1, + expr = (Node *) makeRelabelType((Expr *) expr, + targettype, -1, cformat); } else @@ -190,7 +191,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, cformat); /* We might now need a RelabelType. */ if (exprType(result) != targetTypeId) - result = (Node *) makeRelabelType(result, targetTypeId, -1, + result = (Node *) makeRelabelType((Expr *) result, + targetTypeId, -1, cformat); } @@ -227,7 +229,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, { result = coerce_type_constraints(result, targetTypeId, cformat); - result = (Node *) makeRelabelType(result, targetTypeId, -1, + result = (Node *) makeRelabelType((Expr *) result, + targetTypeId, -1, cformat); } @@ -266,7 +269,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, * typmod, which is likely but not certain (wrong if target is * a domain, in any case). */ - result = (Node *) makeRelabelType(result, targetTypeId, -1, + result = (Node *) makeRelabelType((Expr *) result, + targetTypeId, -1, cformat); } } @@ -277,7 +281,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, * except relabel the type. This is binary compatibility for * complex types. */ - result = (Node *) makeRelabelType(node, targetTypeId, -1, + result = (Node *) makeRelabelType((Expr *) node, + targetTypeId, -1, cformat); } else @@ -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", NameStr(typTup->typname), NameStr(c->conname)); - r->arg = arg; + r->arg = (Expr *) arg; r->testtype = CONSTR_TEST_CHECK; r->name = NameStr(c->conname); r->domname = NameStr(typTup->typname); @@ -492,7 +497,7 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat) { ConstraintTest *r = makeNode(ConstraintTest); - r->arg = arg; + r->arg = (Expr *) arg; r->testtype = CONSTR_TEST_NOTNULL; r->name = "NOT NULL"; r->domname = notNull; @@ -1140,21 +1145,14 @@ find_typmod_coercion_function(Oid typeId, int *nargs) static Node * build_func_call(Oid funcid, Oid rettype, List *args, CoercionForm fformat) { - Func *funcnode; - Expr *expr; - - funcnode = makeNode(Func); - funcnode->funcid = funcid; - funcnode->funcresulttype = rettype; - funcnode->funcretset = false; /* only possible case here */ - funcnode->funcformat = fformat; - funcnode->func_fcache = NULL; - - expr = makeNode(Expr); - expr->typeOid = rettype; - expr->opType = FUNC_EXPR; - expr->oper = (Node *) funcnode; - expr->args = args; - - return (Node *) expr; + FuncExpr *funcexpr; + + funcexpr = makeNode(FuncExpr); + funcexpr->funcid = funcid; + funcexpr->funcresulttype = rettype; + funcexpr->funcretset = false; /* only possible case here */ + funcexpr->funcformat = fformat; + funcexpr->args = args; + + return (Node *) funcexpr; } diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 41e669428597176b3052ab53ab79f1e2f7de372a..7dcbf59a4e397a77ee7773a61c71352476892208 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * 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; if (exprIsNullConstant(a->lexpr)) - n->arg = a->rexpr; + n->arg = (Expr *) a->rexpr; else - n->arg = a->lexpr; + n->arg = (Expr *) a->lexpr; result = transformExpr(pstate, (Node *) n, domVal); @@ -225,15 +225,13 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) a->lexpr, domVal); Node *rexpr = transformExpr(pstate, a->rexpr, domVal); - Expr *expr = makeNode(Expr); lexpr = coerce_to_boolean(lexpr, "AND"); rexpr = coerce_to_boolean(rexpr, "AND"); - expr->typeOid = BOOLOID; - expr->opType = AND_EXPR; - expr->args = makeList2(lexpr, rexpr); - result = (Node *) expr; + result = (Node *) makeBoolExpr(AND_EXPR, + makeList2(lexpr, + rexpr)); } break; case OR: @@ -242,29 +240,24 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) a->lexpr, domVal); Node *rexpr = transformExpr(pstate, a->rexpr, domVal); - Expr *expr = makeNode(Expr); lexpr = coerce_to_boolean(lexpr, "OR"); rexpr = coerce_to_boolean(rexpr, "OR"); - expr->typeOid = BOOLOID; - expr->opType = OR_EXPR; - expr->args = makeList2(lexpr, rexpr); - result = (Node *) expr; + result = (Node *) makeBoolExpr(OR_EXPR, + makeList2(lexpr, + rexpr)); } break; case NOT: { Node *rexpr = transformExpr(pstate, a->rexpr, domVal); - Expr *expr = makeNode(Expr); rexpr = coerce_to_boolean(rexpr, "NOT"); - expr->typeOid = BOOLOID; - expr->opType = NOT_EXPR; - expr->args = makeList1(rexpr); - result = (Node *) expr; + result = (Node *) makeBoolExpr(NOT_EXPR, + makeList1(rexpr)); } break; case DISTINCT: @@ -277,9 +270,12 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) result = (Node *) make_op(a->name, lexpr, rexpr); - if (((Expr *) result)->typeOid != BOOLOID) + if (((OpExpr *) result)->opresulttype != BOOLOID) elog(ERROR, "IS DISTINCT FROM requires = operator to yield boolean"); - ((Expr *) result)->opType = DISTINCT_EXPR; + /* + * We rely on DistinctExpr and OpExpr being same struct + */ + NodeSetTag(result, T_DistinctExpr); } break; case OF: @@ -433,7 +429,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) Node *lexpr; Operator optup; Form_pg_operator opform; - Oper *newop; + OpExpr *newop; right_list = lnext(right_list); if (tent->resdom->resjunk) @@ -451,7 +447,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) */ optup = oper(op, exprType(lexpr), - exprType(tent->expr), + exprType((Node *) tent->expr), false); opform = (Form_pg_operator) GETSTRUCT(optup); @@ -466,11 +462,15 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) " to be used with quantified predicate subquery", opname); - newop = makeOper(oprid(optup), /* opno */ - InvalidOid, /* opid */ - opform->oprresult, - false); + newop = makeNode(OpExpr); + newop->opno = oprid(optup); + newop->opfuncid = InvalidOid; + newop->opresulttype = opform->oprresult; + newop->opretset = false; + newop->args = NIL; /* for now */ + sublink->oper = lappend(sublink->oper, newop); + ReleaseSysCache(optup); } if (left_list != NIL) @@ -499,22 +499,24 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) Assert(IsA(w, CaseWhen)); - warg = w->expr; + warg = (Node *) w->expr; if (c->arg != NULL) { /* shorthand form was specified, so expand... */ warg = (Node *) makeSimpleA_Expr(OP, "=", - c->arg, warg); + (Node *) c->arg, + warg); } - neww->expr = transformExpr(pstate, warg, domVal); + neww->expr = (Expr *) transformExpr(pstate, warg, domVal); - neww->expr = coerce_to_boolean(neww->expr, "CASE/WHEN"); + neww->expr = (Expr *) coerce_to_boolean((Node *) neww->expr, + "CASE/WHEN"); /* * result is NULL for NULLIF() construct - thomas * 1998-11-11 */ - warg = w->result; + warg = (Node *) w->result; if (warg == NULL) { A_Const *n = makeNode(A_Const); @@ -522,10 +524,10 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) n->val.type = T_Null; warg = (Node *) n; } - neww->result = transformExpr(pstate, warg, domVal); + neww->result = (Expr *) transformExpr(pstate, warg, domVal); newargs = lappend(newargs, neww); - typeids = lappendi(typeids, exprType(neww->result)); + typeids = lappendi(typeids, exprType((Node *) neww->result)); } newc->args = newargs; @@ -538,7 +540,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) newc->arg = NULL; /* transform the default clause */ - defresult = c->defresult; + defresult = (Node *) c->defresult; if (defresult == NULL) { A_Const *n = makeNode(A_Const); @@ -546,7 +548,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) n->val.type = T_Null; defresult = (Node *) n; } - newc->defresult = transformExpr(pstate, defresult, domVal); + newc->defresult = (Expr *) transformExpr(pstate, defresult, domVal); /* * Note: default result is considered the most significant @@ -554,24 +556,26 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) * code worked before, but it seems a little bogus to me * --- tgl */ - typeids = lconsi(exprType(newc->defresult), typeids); + typeids = lconsi(exprType((Node *) newc->defresult), typeids); ptype = select_common_type(typeids, "CASE"); newc->casetype = ptype; /* Convert default result clause, if necessary */ - newc->defresult = coerce_to_common_type(newc->defresult, - ptype, - "CASE/ELSE"); + newc->defresult = (Expr *) + coerce_to_common_type((Node *) newc->defresult, + ptype, + "CASE/ELSE"); /* Convert when-clause results, if necessary */ foreach(args, newc->args) { CaseWhen *w = (CaseWhen *) lfirst(args); - w->result = coerce_to_common_type(w->result, - ptype, - "CASE/WHEN"); + w->result = (Expr *) + coerce_to_common_type((Node *) w->result, + ptype, + "CASE/WHEN"); } result = (Node *) newc; @@ -582,7 +586,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) { NullTest *n = (NullTest *) expr; - n->arg = transformExpr(pstate, n->arg, domVal); + n->arg = (Expr *) transformExpr(pstate, (Node *) n->arg, domVal); /* the argument can be any type, so don't coerce it */ result = expr; break; @@ -619,9 +623,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) clausename = NULL; /* keep compiler quiet */ } - b->arg = transformExpr(pstate, b->arg, domVal); + b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg, domVal); - b->arg = coerce_to_boolean(b->arg, clausename); + b->arg = (Expr *) coerce_to_boolean((Node *) b->arg, clausename); result = expr; break; @@ -885,36 +889,39 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) Oid exprType(Node *expr) { - Oid type = (Oid) InvalidOid; + Oid type; if (!expr) - return type; + return InvalidOid; switch (nodeTag(expr)) { case T_Var: type = ((Var *) expr)->vartype; break; - case T_Expr: - type = ((Expr *) expr)->typeOid; - break; case T_Const: type = ((Const *) expr)->consttype; break; - case T_ArrayRef: - type = ((ArrayRef *) expr)->refrestype; + case T_Param: + type = ((Param *) expr)->paramtype; break; case T_Aggref: type = ((Aggref *) expr)->aggtype; break; - case T_Param: - type = ((Param *) expr)->paramtype; + case T_ArrayRef: + type = ((ArrayRef *) expr)->refrestype; break; - case T_FieldSelect: - type = ((FieldSelect *) expr)->resulttype; + case T_FuncExpr: + type = ((FuncExpr *) expr)->funcresulttype; break; - case T_RelabelType: - type = ((RelabelType *) expr)->resulttype; + case T_OpExpr: + type = ((OpExpr *) expr)->opresulttype; + break; + case T_DistinctExpr: + type = ((DistinctExpr *) expr)->opresulttype; + break; + case T_BoolExpr: + type = BOOLOID; break; case T_SubLink: { @@ -938,11 +945,17 @@ exprType(Node *expr) } } break; + case T_FieldSelect: + type = ((FieldSelect *) expr)->resulttype; + break; + case T_RelabelType: + type = ((RelabelType *) expr)->resulttype; + break; case T_CaseExpr: type = ((CaseExpr *) expr)->casetype; break; case T_CaseWhen: - type = exprType(((CaseWhen *) expr)->result); + type = exprType((Node *) ((CaseWhen *) expr)->result); break; case T_NullTest: type = BOOLOID; @@ -951,7 +964,7 @@ exprType(Node *expr) type = BOOLOID; break; case T_ConstraintTest: - type = exprType(((ConstraintTest *) expr)->arg); + type = exprType((Node *) ((ConstraintTest *) expr)->arg); break; case T_ConstraintTestValue: type = ((ConstraintTestValue *) expr)->typeId; @@ -959,6 +972,7 @@ exprType(Node *expr) default: elog(ERROR, "exprType: Do not know how to get type for %d node", nodeTag(expr)); + type = InvalidOid; /* keep compiler quiet */ break; } return type; @@ -995,7 +1009,7 @@ exprTypmod(Node *expr) } } break; - case T_Expr: + case T_FuncExpr: { int32 coercedTypmod; @@ -1021,9 +1035,9 @@ exprTypmod(Node *expr) if (!cexpr->defresult) return -1; - if (exprType(cexpr->defresult) != casetype) + if (exprType((Node *) cexpr->defresult) != casetype) return -1; - typmod = exprTypmod(cexpr->defresult); + typmod = exprTypmod((Node *) cexpr->defresult); if (typmod < 0) return -1; /* no point in trying harder */ foreach(arg, cexpr->args) @@ -1031,16 +1045,16 @@ exprTypmod(Node *expr) CaseWhen *w = (CaseWhen *) lfirst(arg); Assert(IsA(w, CaseWhen)); - if (exprType(w->result) != casetype) + if (exprType((Node *) w->result) != casetype) return -1; - if (exprTypmod(w->result) != typmod) + if (exprTypmod((Node *) w->result) != typmod) return -1; } return typmod; } break; case T_ConstraintTest: - return exprTypmod(((ConstraintTest *) expr)->arg); + return exprTypmod((Node *) ((ConstraintTest *) expr)->arg); default: break; @@ -1059,7 +1073,7 @@ exprTypmod(Node *expr) bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) { - Func *func; + FuncExpr *func; int nargs; Const *second_arg; @@ -1067,12 +1081,9 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) *coercedTypmod = -1; /* default result on failure */ /* Is it a function-call at all? */ - if (expr == NULL || - !IsA(expr, Expr) || - ((Expr *) expr)->opType != FUNC_EXPR) + if (expr == NULL || !IsA(expr, FuncExpr)) return false; - func = (Func *) (((Expr *) expr)->oper); - Assert(IsA(func, Func)); + func = (FuncExpr *) expr; /* * If it didn't come from a coercion context, reject. @@ -1086,11 +1097,11 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) * argument being an int4 constant, it can't have been created from a * length coercion (it must be a type coercion, instead). */ - nargs = length(((Expr *) expr)->args); + nargs = length(func->args); if (nargs < 2 || nargs > 3) return false; - second_arg = (Const *) lsecond(((Expr *) expr)->args); + second_arg = (Const *) lsecond(func->args); if (!IsA(second_arg, Const) || second_arg->consttype != INT4OID || second_arg->constisnull) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 46d1bb0755c1e934e1a743cc6810ab28b8c5a682..4a2eb27d7ccc9dac1cc7c7d6957edf56f86cd4a7 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * 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 */ if (fdresult == FUNCDETAIL_NORMAL) { - Expr *expr = makeNode(Expr); - Func *funcnode = makeNode(Func); + FuncExpr *funcexpr = makeNode(FuncExpr); - funcnode->funcid = funcid; - funcnode->funcresulttype = rettype; - funcnode->funcretset = retset; - funcnode->funcformat = COERCE_EXPLICIT_CALL; - funcnode->func_fcache = NULL; + funcexpr->funcid = funcid; + funcexpr->funcresulttype = rettype; + funcexpr->funcretset = retset; + funcexpr->funcformat = COERCE_EXPLICIT_CALL; + funcexpr->args = fargs; - expr->typeOid = rettype; - expr->opType = FUNC_EXPR; - expr->oper = (Node *) funcnode; - expr->args = fargs; - - retval = (Node *) expr; + retval = (Node *) funcexpr; } else { @@ -1182,7 +1176,7 @@ setup_field_select(Node *input, char *attname, Oid relid) elog(ERROR, "Relation \"%s\" has no column \"%s\"", get_rel_name(relid), attname); - fselect->arg = input; + fselect->arg = (Expr *) input; fselect->fieldnum = attno; fselect->resulttype = get_atttype(relid, attno); fselect->resulttypmod = get_atttypmod(relid, attno); diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 088aaafb0b32c8cee87716977ec3ecab76d979eb..a246344c7bd6a6c2a15efe956f7f139f89f07884 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * 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; Operator tup; Form_pg_operator opform; - Oper *newop; Node *left, *right; - Expr *result; + OpExpr *result; ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree); rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree); @@ -124,15 +123,11 @@ make_op(List *opname, Node *ltree, Node *rtree) right = make_operand(rtree, rtypeId, opform->oprright); } - newop = makeOper(oprid(tup), /* opno */ - InvalidOid, /* opid */ - opform->oprresult, /* opresulttype */ - get_func_retset(opform->oprcode)); /* opretset */ - - result = makeNode(Expr); - result->typeOid = opform->oprresult; - result->opType = OP_EXPR; - result->oper = (Node *) newop; + result = makeNode(OpExpr); + result->opno = oprid(tup); + result->opfuncid = InvalidOid; + result->opresulttype = opform->oprresult; + result->opretset = get_func_retset(opform->oprcode); if (!left) result->args = makeList1(right); @@ -143,7 +138,7 @@ make_op(List *opname, Node *ltree, Node *rtree) ReleaseSysCache(tup); - return result; + return (Expr *) result; } /* make_op() */ @@ -343,8 +338,8 @@ transformArraySubscripts(ParseState *pstate, aref->refelemalign = type_struct_element->typalign; aref->refupperindexpr = upperIndexpr; aref->reflowerindexpr = lowerIndexpr; - aref->refexpr = arrayBase; - aref->refassgnexpr = assignFrom; + aref->refexpr = (Expr *) arrayBase; + aref->refassgnexpr = (Expr *) assignFrom; ReleaseSysCache(type_tuple_array); ReleaseSysCache(type_tuple_element); diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 65c386a937c9c19f4309f289cafbdfb97b2232a4..4ae3bf23153229616db8ae6e7debafe33508ae32 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * 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), label, false); - te->expr = varnode; + te->expr = (Expr *) varnode; te_list = lappend(te_list, te); names = lnext(names); diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 1a2da6da1eb354fe1723a90e20951056314b4961..5e4e23db920686f1106eecf0229aa6034c134198 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * 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, resjunk); - return makeTargetEntry(resnode, expr); + return makeTargetEntry(resnode, (Expr *) expr); } @@ -225,7 +225,7 @@ updateTargetListEntry(ParseState *pstate, int attrno, List *indirection) { - Oid type_id = exprType(tle->expr); /* type of value provided */ + Oid type_id = exprType((Node *) tle->expr); /* type of value provided */ Oid attrtype; /* type of target column */ int32 attrtypmod; Resdom *resnode = tle->resdom; @@ -277,8 +277,8 @@ updateTargetListEntry(ParseState *pstate, attrtypmod, indirection, pstate->p_is_insert, - tle->expr); - tle->expr = (Node *) aref; + (Node *) tle->expr); + tle->expr = (Expr *) aref; } else { @@ -289,10 +289,11 @@ updateTargetListEntry(ParseState *pstate, */ if (type_id != InvalidOid) { - tle->expr = coerce_to_target_type(tle->expr, type_id, - attrtype, attrtypmod, - COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST); + tle->expr = (Expr *) + coerce_to_target_type((Node *) tle->expr, type_id, + attrtype, attrtypmod, + COERCION_ASSIGNMENT, + COERCE_IMPLICIT_CAST); if (tle->expr == NULL) elog(ERROR, "column \"%s\" is of type %s" " but expression is of type %s" @@ -501,7 +502,7 @@ FigureColnameInternal(Node *node, char **name) } break; case T_CaseExpr: - strength = FigureColnameInternal(((CaseExpr *) node)->defresult, + strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult, name); if (strength <= 1) { diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index bb58db8e8a5584deaf07dc47a51105e8ad0cbb63..d0badcc154f960f75c15db6cae898fc7d776a7be 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.113 2002/10/20 00:58:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.114 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -304,7 +304,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation) att_tup->atttypmod, pstrdup(NameStr(att_tup->attname)), false), - new_expr); + (Expr *) new_expr); } 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 * once. */ - priorbottom = ((ArrayRef *) prior_tle->expr)->refexpr; + priorbottom = (Node *) ((ArrayRef *) prior_tle->expr)->refexpr; while (priorbottom != NULL && IsA(priorbottom, ArrayRef) && ((ArrayRef *) priorbottom)->refassgnexpr != NULL) - priorbottom = ((ArrayRef *) priorbottom)->refexpr; + priorbottom = (Node *) ((ArrayRef *) priorbottom)->refexpr; if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr)) elog(ERROR, "Multiple assignments to same attribute \"%s\"", resdom->resname); @@ -404,7 +404,7 @@ process_matched_tle(TargetEntry *src_tle, memcpy(newexpr, src_tle->expr, sizeof(ArrayRef)); newexpr->refexpr = prior_tle->expr; - return makeTargetEntry(resdom, (Node *) newexpr); + return makeTargetEntry(resdom, (Expr *) newexpr); } diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 94a940648c002bae6b628f03664b767652f506b0..22e7eee306c50f395602c6fb4de187345307596b 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,7 +7,7 @@ * * * 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... */ invqual = makeNode(BooleanTest); - invqual->arg = qual; + invqual->arg = (Expr *) qual; invqual->booltesttype = IS_NOT_TRUE; AddQual(parsetree, (Node *) invqual); @@ -724,7 +724,7 @@ FindMatchingNew(List *tlist, int attno) TargetEntry *tle = lfirst(i); if (tle->resdom->resno == attno) - return tle->expr; + return (Node *) tle->expr; } return NULL; } diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index b8189e8cc11018a0d0872a60fc19cd16af07c5aa..104f93a355c216e4daea2f6bf629fb5880c41027 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -17,7 +17,7 @@ * * 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 "commands/trigger.h" #include "executor/spi_priv.h" +#include "optimizer/planmain.h" #include "parser/parse_oper.h" #include "utils/lsyscache.h" #include "miscadmin.h" @@ -2747,6 +2748,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS) nth(defval[j].adnum - 1, spi_plan->targetlist); spi_qptle->expr = stringToNode(defval[j].adbin); + fix_opfuncids((Node *) spi_qptle->expr); break; } @@ -3037,6 +3039,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS) nth(defval[j].adnum - 1, spi_plan->targetlist); spi_qptle->expr = stringToNode(defval[j].adbin); + fix_opfuncids((Node *) spi_qptle->expr); break; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index c5a0f0d75d853fa8d70399c8c317acfc090e4535..92f69a32a829ecd6bde51148ab6dff96846de3ea 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.127 2002/11/26 03:01:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.128 2002/12/12 15:49:40 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -149,13 +149,13 @@ static RangeTblEntry *find_rte_by_refname(const char *refname, deparse_context *context); static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit); -static void get_oper_expr(Expr *expr, deparse_context *context); -static void get_func_expr(Expr *expr, deparse_context *context, +static void get_oper_expr(OpExpr *expr, deparse_context *context); +static void get_func_expr(FuncExpr *expr, deparse_context *context, bool showimplicit); static void get_agg_expr(Aggref *aggref, deparse_context *context); static Node *strip_type_coercion(Node *expr, Oid resultType); static void get_const_expr(Const *constval, deparse_context *context); -static void get_sublink_expr(Node *node, deparse_context *context); +static void get_sublink_expr(SubLink *sublink, deparse_context *context); static void get_from_clause(Query *query, deparse_context *context); static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context); @@ -1434,7 +1434,7 @@ get_basic_select_query(Query *query, deparse_context *context, sep = ", "; colno++; - get_rule_expr(tle->expr, context, true); + get_rule_expr((Node *) tle->expr, context, true); /* * Figure out what the result column should be called. In the @@ -1565,7 +1565,7 @@ get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno, Node *expr; tle = get_sortgroupclause_tle(srt, tlist); - expr = tle->expr; + expr = (Node *) tle->expr; /* * Use column-number form if requested by caller or if expression is a @@ -1647,7 +1647,7 @@ get_insert_query_def(Query *query, deparse_context *context) appendStringInfo(buf, sep); sep = ", "; - get_rule_expr(tle->expr, context, false); + get_rule_expr((Node *) tle->expr, context, false); } appendStringInfoChar(buf, ')'); } @@ -1697,7 +1697,7 @@ get_update_query_def(Query *query, deparse_context *context) if (!tleIsArrayAssign(tle)) appendStringInfo(buf, "%s = ", quote_identifier(tle->resdom->resname)); - get_rule_expr(tle->expr, context, false); + get_rule_expr((Node *) tle->expr, context, false); } /* Add the FROM clause if needed */ @@ -1924,10 +1924,6 @@ get_rule_expr(Node *node, deparse_context *context, */ switch (nodeTag(node)) { - case T_Const: - get_const_expr((Const *) node, context); - break; - case T_Var: { Var *var = (Var *) node; @@ -1958,82 +1954,26 @@ get_rule_expr(Node *node, deparse_context *context, } break; - case T_Expr: + case T_Const: + get_const_expr((Const *) node, context); + break; + + case T_Param: { - Expr *expr = (Expr *) node; - List *args = expr->args; + Param *param = (Param *) node; - /* - * Expr nodes have to be handled a bit detailed - */ - switch (expr->opType) + switch (param->paramkind) { - case OP_EXPR: - get_oper_expr(expr, context); - break; - - case DISTINCT_EXPR: - appendStringInfoChar(buf, '('); - Assert(length(args) == 2); - { - /* binary operator */ - Node *arg1 = (Node *) lfirst(args); - Node *arg2 = (Node *) lsecond(args); - - get_rule_expr(arg1, context, true); - appendStringInfo(buf, " IS DISTINCT FROM "); - get_rule_expr(arg2, context, true); - } - appendStringInfoChar(buf, ')'); - break; - - case FUNC_EXPR: - get_func_expr(expr, context, showimplicit); - break; - - case OR_EXPR: - appendStringInfoChar(buf, '('); - get_rule_expr((Node *) lfirst(args), context, false); - while ((args = lnext(args)) != NIL) - { - appendStringInfo(buf, " OR "); - get_rule_expr((Node *) lfirst(args), context, - false); - } - appendStringInfoChar(buf, ')'); - break; - - case AND_EXPR: - appendStringInfoChar(buf, '('); - get_rule_expr((Node *) lfirst(args), context, false); - while ((args = lnext(args)) != NIL) - { - appendStringInfo(buf, " AND "); - get_rule_expr((Node *) lfirst(args), context, - false); - } - appendStringInfoChar(buf, ')'); - break; - - case NOT_EXPR: - appendStringInfo(buf, "(NOT "); - get_rule_expr((Node *) lfirst(args), context, false); - appendStringInfoChar(buf, ')'); + case PARAM_NAMED: + appendStringInfo(buf, "$%s", param->paramname); break; - - case SUBPLAN_EXPR: - - /* - * We cannot see an already-planned subplan in - * rule deparsing, only while EXPLAINing a query - * plan. For now, just punt. - */ - appendStringInfo(buf, "(subplan)"); + case PARAM_NUM: + case PARAM_EXEC: + appendStringInfo(buf, "$%d", param->paramid); break; - default: - elog(ERROR, "get_rule_expr: expr opType %d not supported", - expr->opType); + appendStringInfo(buf, "(param)"); + break; } } break; @@ -2058,7 +1998,7 @@ get_rule_expr(Node *node, deparse_context *context, */ if (aref->refassgnexpr) context->varprefix = false; - get_rule_expr(aref->refexpr, context, showimplicit); + get_rule_expr((Node *) aref->refexpr, context, showimplicit); context->varprefix = savevarprefix; lowlist = aref->reflowerindexpr; foreach(uplist, aref->refupperindexpr) @@ -2077,15 +2017,103 @@ get_rule_expr(Node *node, deparse_context *context, if (aref->refassgnexpr) { appendStringInfo(buf, " = "); - get_rule_expr(aref->refassgnexpr, context, showimplicit); + get_rule_expr((Node *) aref->refassgnexpr, context, + showimplicit); + } + } + break; + + case T_FuncExpr: + get_func_expr((FuncExpr *) node, context, showimplicit); + break; + + case T_OpExpr: + get_oper_expr((OpExpr *) node, context); + break; + + case T_DistinctExpr: + { + DistinctExpr *expr = (DistinctExpr *) node; + List *args = expr->args; + + Assert(length(args) == 2); + { + /* binary operator */ + Node *arg1 = (Node *) lfirst(args); + Node *arg2 = (Node *) lsecond(args); + + appendStringInfoChar(buf, '('); + get_rule_expr(arg1, context, true); + appendStringInfo(buf, " IS DISTINCT FROM "); + get_rule_expr(arg2, context, true); + appendStringInfoChar(buf, ')'); } } break; + case T_BoolExpr: + { + BoolExpr *expr = (BoolExpr *) node; + List *args = expr->args; + + switch (expr->boolop) + { + case AND_EXPR: + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) lfirst(args), context, false); + while ((args = lnext(args)) != NIL) + { + appendStringInfo(buf, " AND "); + get_rule_expr((Node *) lfirst(args), context, + false); + } + appendStringInfoChar(buf, ')'); + break; + + case OR_EXPR: + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) lfirst(args), context, false); + while ((args = lnext(args)) != NIL) + { + appendStringInfo(buf, " OR "); + get_rule_expr((Node *) lfirst(args), context, + false); + } + appendStringInfoChar(buf, ')'); + break; + + case NOT_EXPR: + appendStringInfo(buf, "(NOT "); + get_rule_expr((Node *) lfirst(args), context, false); + appendStringInfoChar(buf, ')'); + break; + + default: + elog(ERROR, "get_rule_expr: unknown boolop %d", + (int) expr->boolop); + } + } + break; + + case T_SubLink: + get_sublink_expr((SubLink *) node, context); + break; + + case T_SubPlanExpr: + { + /* + * We cannot see an already-planned subplan in + * rule deparsing, only while EXPLAINing a query + * plan. For now, just punt. + */ + appendStringInfo(buf, "(subplan)"); + } + break; + case T_FieldSelect: { FieldSelect *fselect = (FieldSelect *) node; - Oid argType = exprType(fselect->arg); + Oid argType = exprType((Node *) fselect->arg); Oid typrelid; char *fieldname; @@ -2103,7 +2131,7 @@ get_rule_expr(Node *node, deparse_context *context, * are *not* simple. So, always use parenthesized syntax. */ appendStringInfoChar(buf, '('); - get_rule_expr(fselect->arg, context, true); + get_rule_expr((Node *) fselect->arg, context, true); appendStringInfo(buf, ").%s", quote_identifier(fieldname)); } break; @@ -2111,7 +2139,7 @@ get_rule_expr(Node *node, deparse_context *context, case T_RelabelType: { RelabelType *relabel = (RelabelType *) node; - Node *arg = relabel->arg; + Node *arg = (Node *) relabel->arg; if (relabel->relabelformat == COERCE_IMPLICIT_CAST && !showimplicit) @@ -2149,12 +2177,12 @@ get_rule_expr(Node *node, deparse_context *context, CaseWhen *when = (CaseWhen *) lfirst(temp); appendStringInfo(buf, " WHEN "); - get_rule_expr(when->expr, context, false); + get_rule_expr((Node *) when->expr, context, false); appendStringInfo(buf, " THEN "); - get_rule_expr(when->result, context, true); + get_rule_expr((Node *) when->result, context, true); } appendStringInfo(buf, " ELSE "); - get_rule_expr(caseexpr->defresult, context, true); + get_rule_expr((Node *) caseexpr->defresult, context, true); appendStringInfo(buf, " END"); } break; @@ -2164,7 +2192,7 @@ get_rule_expr(Node *node, deparse_context *context, NullTest *ntest = (NullTest *) node; appendStringInfo(buf, "("); - get_rule_expr(ntest->arg, context, true); + get_rule_expr((Node *) ntest->arg, context, true); switch (ntest->nulltesttype) { case IS_NULL: @@ -2185,7 +2213,7 @@ get_rule_expr(Node *node, deparse_context *context, BooleanTest *btest = (BooleanTest *) node; appendStringInfo(buf, "("); - get_rule_expr(btest->arg, context, false); + get_rule_expr((Node *) btest->arg, context, false); switch (btest->booltesttype) { case IS_TRUE: @@ -2221,38 +2249,12 @@ get_rule_expr(Node *node, deparse_context *context, * We assume that the operations of the constraint node * need not be explicitly represented in the output. */ - get_rule_expr(ctest->arg, context, showimplicit); + get_rule_expr((Node *) ctest->arg, context, showimplicit); } break; case T_ConstraintTestValue: - { - appendStringInfo(buf, "VALUE"); - } - break; - - case T_SubLink: - get_sublink_expr(node, context); - break; - - case T_Param: - { - Param *param = (Param *) node; - - switch (param->paramkind) - { - case PARAM_NAMED: - appendStringInfo(buf, "$%s", param->paramname); - break; - case PARAM_NUM: - case PARAM_EXEC: - appendStringInfo(buf, "$%d", param->paramid); - break; - default: - appendStringInfo(buf, "(param)"); - break; - } - } + appendStringInfo(buf, "VALUE"); break; default: @@ -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 -get_oper_expr(Expr *expr, deparse_context *context) +get_oper_expr(OpExpr *expr, deparse_context *context) { StringInfo buf = context->buf; - Oid opno = ((Oper *) expr->oper)->opno; + Oid opno = expr->opno; List *args = expr->args; appendStringInfoChar(buf, '('); @@ -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 -get_func_expr(Expr *expr, deparse_context *context, +get_func_expr(FuncExpr *expr, deparse_context *context, bool showimplicit) { StringInfo buf = context->buf; - Func *func = (Func *) (expr->oper); - Oid funcoid = func->funcid; + Oid funcoid = expr->funcid; Oid argtypes[FUNC_MAX_ARGS]; int nargs; List *l; @@ -2342,7 +2343,7 @@ get_func_expr(Expr *expr, deparse_context *context, * If the function call came from an implicit coercion, then just show * the first argument --- unless caller wants to see implicit coercions. */ - if (func->funcformat == COERCE_IMPLICIT_CAST && !showimplicit) + if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit) { get_rule_expr((Node *) lfirst(expr->args), context, showimplicit); return; @@ -2352,11 +2353,11 @@ get_func_expr(Expr *expr, deparse_context *context, * If the function call came from a cast, then show * the first argument plus an explicit cast operation. */ - if (func->funcformat == COERCE_EXPLICIT_CAST || - func->funcformat == COERCE_IMPLICIT_CAST) + if (expr->funcformat == COERCE_EXPLICIT_CAST || + expr->funcformat == COERCE_IMPLICIT_CAST) { Node *arg = lfirst(expr->args); - Oid rettype = expr->typeOid; + Oid rettype = expr->funcresulttype; int32 coercedTypmod; /* Get the typmod if this is a length-coercion function */ @@ -2410,7 +2411,7 @@ static void get_agg_expr(Aggref *aggref, deparse_context *context) { StringInfo buf = context->buf; - Oid argtype = exprType(aggref->target); + Oid argtype = exprType((Node *) aggref->target); appendStringInfo(buf, "%s(%s", generate_function_name(aggref->aggfnoid, 1, &argtype), @@ -2418,7 +2419,7 @@ get_agg_expr(Aggref *aggref, deparse_context *context) if (aggref->aggstar) appendStringInfo(buf, "*"); else - get_rule_expr(aggref->target, context, true); + get_rule_expr((Node *) aggref->target, context, true); appendStringInfoChar(buf, ')'); } @@ -2442,14 +2443,12 @@ strip_type_coercion(Node *expr, Oid resultType) if (IsA(expr, RelabelType) && ((RelabelType *) expr)->resulttypmod == -1) - return ((RelabelType *) expr)->arg; + return (Node *) ((RelabelType *) expr)->arg; - if (IsA(expr, Expr) && - ((Expr *) expr)->opType == FUNC_EXPR) + if (IsA(expr, FuncExpr)) { - Func *func = (Func *) (((Expr *) expr)->oper); + FuncExpr *func = (FuncExpr *) expr; - Assert(IsA(func, Func)); if (func->funcformat != COERCE_EXPLICIT_CAST && func->funcformat != COERCE_IMPLICIT_CAST) return expr; /* don't absorb into upper coercion */ @@ -2457,7 +2456,7 @@ strip_type_coercion(Node *expr, Oid resultType) if (exprIsLengthCoercion(expr, NULL)) return expr; - return (Node *) lfirst(((Expr *) expr)->args); + return (Node *) lfirst(func->args); } return expr; @@ -2609,14 +2608,13 @@ get_const_expr(Const *constval, deparse_context *context) * ---------- */ static void -get_sublink_expr(Node *node, deparse_context *context) +get_sublink_expr(SubLink *sublink, deparse_context *context) { StringInfo buf = context->buf; - SubLink *sublink = (SubLink *) node; Query *query = (Query *) (sublink->subselect); List *l; char *sep; - Oper *oper; + OpExpr *oper; bool need_paren; appendStringInfoChar(buf, '('); @@ -2657,17 +2655,17 @@ get_sublink_expr(Node *node, deparse_context *context) break; case ANY_SUBLINK: - oper = (Oper *) lfirst(sublink->oper); + oper = (OpExpr *) lfirst(sublink->oper); appendStringInfo(buf, "%s ANY ", get_opname(oper->opno)); break; case ALL_SUBLINK: - oper = (Oper *) lfirst(sublink->oper); + oper = (OpExpr *) lfirst(sublink->oper); appendStringInfo(buf, "%s ALL ", get_opname(oper->opno)); break; case MULTIEXPR_SUBLINK: - oper = (Oper *) lfirst(sublink->oper); + oper = (OpExpr *) lfirst(sublink->oper); appendStringInfo(buf, "%s ", get_opname(oper->opno)); break; diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 827b000d229bf92097af0a2ff97793264bc20005..c378f8b50e38461247e782edb9b859408c915cdd 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * 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) */ if (IsA(arg, RelabelType)) - arg = ((RelabelType *) arg)->arg; + arg = (Node *) ((RelabelType *) arg)->arg; if (IsA(arg, Var) &&(varRelid == 0 || varRelid == ((Var *) arg)->varno)) var = (Var *) arg; @@ -1246,7 +1246,7 @@ nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid) * Ignore any binary-compatible relabeling */ if (IsA(arg, RelabelType)) - arg = ((RelabelType *) arg)->arg; + arg = (Node *) ((RelabelType *) arg)->arg; if (IsA(arg, Var) && (varRelid == 0 || varRelid == ((Var *) arg)->varno)) @@ -1753,14 +1753,15 @@ mergejoinscansel(Query *root, Node *clause, /* Deconstruct the merge clause */ if (!is_opclause(clause)) return; /* shouldn't happen */ - opno = ((Oper *) ((Expr *) clause)->oper)->opno; + opno = ((OpExpr *) clause)->opno; left = get_leftop((Expr *) clause); right = get_rightop((Expr *) clause); if (!right) return; /* shouldn't happen */ /* Can't do anything if inputs are not Vars */ - if (!IsA(left, Var) ||!IsA(right, Var)) + if (!IsA(left, Var) || + !IsA(right, Var)) return; /* Verify mergejoinability and get left and right "<" operators */ @@ -2842,9 +2843,9 @@ get_restriction_var(List *args, /* Ignore any binary-compatible relabeling */ if (IsA(left, RelabelType)) - left = ((RelabelType *) left)->arg; + left = (Node *) ((RelabelType *) left)->arg; if (IsA(right, RelabelType)) - right = ((RelabelType *) right)->arg; + right = (Node *) ((RelabelType *) right)->arg; /* Look for the var */ @@ -2895,9 +2896,9 @@ get_join_vars(List *args, Var **var1, Var **var2) /* Ignore any binary-compatible relabeling */ if (IsA(left, RelabelType)) - left = ((RelabelType *) left)->arg; + left = (Node *) ((RelabelType *) left)->arg; if (IsA(right, RelabelType)) - right = ((RelabelType *) right)->arg; + right = (Node *) ((RelabelType *) right)->arg; if (IsA(left, Var)) *var1 = (Var *) left; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 8cb41a9290b80fe485ad08d046daabc34f9b9250..fa3131873300e5f530cf0a44e8ebeacebac84da9 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.168 2002/12/06 05:20:24 momjian Exp $ + * $Id: catversion.h,v 1.169 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200212061 +#define CATALOG_VERSION_NO 200212101 #endif diff --git a/src/include/executor/nodeSubplan.h b/src/include/executor/nodeSubplan.h index c573cf900dfc6561040fb16c6b51ed427d7e6a16..e025c9de696167107259d7816af5c3fd18aec649 100644 --- a/src/include/executor/nodeSubplan.h +++ b/src/include/executor/nodeSubplan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodeSubplan.h,v 1.12 2002/12/05 15:50:38 tgl Exp $ + * $Id: nodeSubplan.h,v 1.13 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,7 @@ #include "nodes/execnodes.h" -extern SubPlanState *ExecInitSubPlan(SubPlan *node, EState *estate); +extern SubPlanState *ExecInitSubPlan(SubPlanExpr *node, EState *estate); extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext, bool *isNull); extern void ExecEndSubPlan(SubPlanState *node); diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 68f0dcda49a215e41fcdc08309ca66ba0f651663..d1f4ebfc4002c8404e99ffd5ff8b2c285133d50b 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: makefuncs.h,v 1.42 2002/11/25 21:29:42 tgl Exp $ + * $Id: makefuncs.h,v 1.43 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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, Node *lexpr, Node *rexpr); -extern Oper *makeOper(Oid opno, - Oid opid, - Oid opresulttype, - bool opretset); - extern Var *makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Index varlevelsup); -extern TargetEntry *makeTargetEntry(Resdom *resdom, Node *expr); +extern TargetEntry *makeTargetEntry(Resdom *resdom, Expr *expr); extern Resdom *makeResdom(AttrNumber resno, Oid restype, @@ -49,9 +44,11 @@ extern Const *makeConst(Oid consttype, extern Const *makeNullConst(Oid consttype); +extern Expr *makeBoolExpr(BoolExprType boolop, List *args); + extern Alias *makeAlias(const char *aliasname, List *colnames); -extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod, +extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat); extern RangeVar *makeRangeVar(char *schemaname, char *relname); diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h index 7db0525bad8875f6451f660c871f33f356db392b..99e1a62542c965a453b9c0406ee0614795b3051e 100644 --- a/src/include/nodes/nodeFuncs.h +++ b/src/include/nodes/nodeFuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodeFuncs.h,v 1.17 2002/06/20 20:29:51 momjian Exp $ + * $Id: nodeFuncs.h,v 1.18 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern bool single_node(Node *node); extern bool var_is_outer(Var *var); extern bool var_is_rel(Var *var); -extern Oper *replace_opid(Oper *oper); +extern void set_opfuncid(OpExpr *opexpr); #endif /* NODEFUNCS_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 2f3e71407aaadb82dfd5035527a3224a40a10b9e..aacdf60dd9ad396373fc8ca4507f01106541dcd8 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.129 2002/12/06 05:00:31 momjian Exp $ + * $Id: nodes.h,v 1.130 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -62,7 +62,6 @@ typedef enum NodeTag T_Hash, T_SetOp, T_Limit, - T_SubPlan, /* * TAGS FOR PLAN STATE NODES (execnodes.h) @@ -96,21 +95,32 @@ typedef enum NodeTag * TAGS FOR PRIMITIVE NODES (primnodes.h) */ T_Resdom = 300, - T_Fjoin, + T_Alias, + T_RangeVar, T_Expr, T_Var, - T_Oper, T_Const, T_Param, T_Aggref, + T_ArrayRef, + T_FuncExpr, + T_OpExpr, + T_DistinctExpr, + T_BoolExpr, T_SubLink, - T_Func, + T_SubPlanExpr, T_FieldSelect, - T_ArrayRef, T_RelabelType, + T_CaseExpr, + T_CaseWhen, + T_NullTest, + T_BooleanTest, + T_ConstraintTest, + T_ConstraintTestValue, + T_TargetEntry, T_RangeTblRef, - T_FromExpr, T_JoinExpr, + T_FromExpr, /* * TAGS FOR PLANNER NODES (relation.h) @@ -183,7 +193,6 @@ typedef enum NodeTag T_ViewStmt, T_LoadStmt, T_CreateDomainStmt, - T_DomainConstraintValue, T_CreatedbStmt, T_DropdbStmt, T_VacuumStmt, @@ -228,30 +237,22 @@ typedef enum NodeTag T_ResTarget, T_TypeCast, T_SortGroupBy, - T_Alias, - T_RangeVar, T_RangeSubselect, T_RangeFunction, T_TypeName, - T_IndexElem, T_ColumnDef, + T_IndexElem, T_Constraint, T_DefElem, - T_TargetEntry, T_RangeTblEntry, T_SortClause, T_GroupClause, - T_NullTest, - T_BooleanTest, - T_ConstraintTest, - T_ConstraintTestValue, - T_CaseExpr, - T_CaseWhen, T_FkConstraint, T_PrivGrantee, T_FuncWithArgs, T_PrivTarget, T_InsertDefault, + T_DomainConstraintValue, T_CreateOpClassItem, T_CompositeTypeStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 5201e1bb0e7287055b2f3c2af55ef90db81f1a2f..f2d92431b71e993121713004b70f1bdd99fb3591 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.221 2002/12/06 05:00:32 momjian Exp $ + * $Id: parsenodes.h,v 1.222 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,7 @@ typedef enum QuerySource /* * Query - - * all statments are turned into a Query tree (via transformStmt) + * all statements are turned into a Query tree (via transformStmt) * for further processing by the optimizer * utility statements (i.e. non-optimizable statements) * have the *utilityStmt field set. @@ -201,145 +201,6 @@ typedef struct TypeCast TypeName *typename; /* the target type */ } TypeCast; -/* - * CaseExpr - a CASE expression - */ -typedef struct CaseExpr -{ - NodeTag type; - Oid casetype; - Node *arg; /* implicit equality comparison argument */ - List *args; /* the arguments (list of WHEN clauses) */ - Node *defresult; /* the default result (ELSE clause) */ -} CaseExpr; - -/* - * CaseWhen - an argument to a CASE expression - */ -typedef struct CaseWhen -{ - NodeTag type; - Node *expr; /* comparison expression */ - Node *result; /* substitution result */ -} CaseWhen; - -/* ---------------- - * NullTest - * - * NullTest represents the operation of testing a value for NULLness. - * Currently, we only support scalar input values, but eventually a - * row-constructor input should be supported. - * The appropriate test is performed and returned as a boolean Datum. - * ---------------- - */ - -typedef enum NullTestType -{ - IS_NULL, IS_NOT_NULL -} NullTestType; - -typedef struct NullTest -{ - NodeTag type; - Node *arg; /* input expression */ - NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ -} NullTest; - -/* - * BooleanTest - * - * BooleanTest represents the operation of determining whether a boolean - * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations - * are supported. Note that a NULL input does *not* cause a NULL result. - * The appropriate test is performed and returned as a boolean Datum. - */ - -typedef enum BoolTestType -{ - IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN -} BoolTestType; - -typedef struct BooleanTest -{ - NodeTag type; - Node *arg; /* input expression */ - BoolTestType booltesttype; /* test type */ -} BooleanTest; - -/* - * ConstraintTest - * - * ConstraintTest represents the operation of testing a value to see whether - * it meets a constraint. If so, the input value is returned as the result; - * if not, an error is raised. - */ - -typedef enum ConstraintTestType -{ - CONSTR_TEST_NOTNULL, - CONSTR_TEST_CHECK -} ConstraintTestType; - -typedef struct ConstraintTest -{ - NodeTag type; - Node *arg; /* input expression */ - ConstraintTestType testtype; /* test type */ - char *name; /* name of constraint (for error msgs) */ - char *domname; /* name of domain (for error messages) */ - Node *check_expr; /* for CHECK test, a boolean expression */ -} ConstraintTest; - -/* - * Placeholder node for the value to be processed by a domains - * check constraint. - */ -typedef struct DomainConstraintValue -{ - NodeTag type; -} DomainConstraintValue; - -typedef struct ConstraintTestValue -{ - NodeTag type; - Oid typeId; - int32 typeMod; -} ConstraintTestValue; - -/* - * ColumnDef - column definition (used in various creates) - * - * If the column has a default value, we may have the value expression - * in either "raw" form (an untransformed parse tree) or "cooked" form - * (the nodeToString representation of an executable expression tree), - * depending on how this ColumnDef node was created (by parsing, or by - * inheritance from an existing relation). We should never have both - * in the same node! - * - * The constraints list may contain a CONSTR_DEFAULT item in a raw - * parsetree produced by gram.y, but transformCreateStmt will remove - * the item and set raw_default instead. CONSTR_DEFAULT items - * should not appear in any subsequent processing. - * - * The "support" field, if not null, denotes a supporting relation that - * should be linked by an internal dependency to the column. Currently - * this is only used to link a SERIAL column's sequence to the column. - */ -typedef struct ColumnDef -{ - NodeTag type; - char *colname; /* name of column */ - TypeName *typename; /* type of column */ - int inhcount; /* number of times column is inherited */ - bool is_local; /* column has local (non-inherited) def'n */ - bool is_not_null; /* NOT NULL constraint specified? */ - Node *raw_default; /* default value (untransformed parse - * tree) */ - char *cooked_default; /* nodeToString representation */ - List *constraints; /* other constraints on column */ - RangeVar *support; /* supporting relation, if any */ -} ColumnDef; - /* * FuncCall - a function or aggregate invocation * @@ -414,6 +275,15 @@ typedef struct InsertDefault NodeTag type; } InsertDefault; +/* + * Empty node used as raw-parse-tree representation of VALUE keyword + * for domain check constraints. + */ +typedef struct DomainConstraintValue +{ + NodeTag type; +} DomainConstraintValue; + /* * SortGroupBy - for ORDER BY clause */ @@ -446,6 +316,40 @@ typedef struct RangeFunction * assignment of RECORD TupleDesc */ } RangeFunction; +/* + * ColumnDef - column definition (used in various creates) + * + * If the column has a default value, we may have the value expression + * in either "raw" form (an untransformed parse tree) or "cooked" form + * (the nodeToString representation of an executable expression tree), + * depending on how this ColumnDef node was created (by parsing, or by + * inheritance from an existing relation). We should never have both + * in the same node! + * + * The constraints list may contain a CONSTR_DEFAULT item in a raw + * parsetree produced by gram.y, but transformCreateStmt will remove + * the item and set raw_default instead. CONSTR_DEFAULT items + * should not appear in any subsequent processing. + * + * The "support" field, if not null, denotes a supporting relation that + * should be linked by an internal dependency to the column. Currently + * this is only used to link a SERIAL column's sequence to the column. + */ +typedef struct ColumnDef +{ + NodeTag type; + char *colname; /* name of column */ + TypeName *typename; /* type of column */ + int inhcount; /* number of times column is inherited */ + bool is_local; /* column has local (non-inherited) def'n */ + bool is_not_null; /* NOT NULL constraint specified? */ + Node *raw_default; /* default value (untransformed parse + * tree) */ + char *cooked_default; /* nodeToString representation */ + List *constraints; /* other constraints on column */ + RangeVar *support; /* supporting relation, if any */ +} ColumnDef; + /* * IndexElem - index parameters (used in CREATE INDEX) * @@ -479,21 +383,6 @@ typedef struct DefElem * 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 - * (( expr) ( expr) ...) - */ -typedef struct TargetEntry -{ - NodeTag type; - Resdom *resdom; /* fjoin overload this to be a list?? */ - Fjoin *fjoin; - Node *expr; -} TargetEntry; - /*-------------------- * RangeTblEntry - * A range table is a List of RangeTblEntry nodes. diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 097f8d93b1334bcb117ece115e0f358b172fb058..67a4d48782f1c072f2964ef74307cfefaadc36c5 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: plannodes.h,v 1.62 2002/12/05 15:50:39 tgl Exp $ + * $Id: plannodes.h,v 1.63 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -375,31 +375,4 @@ typedef struct Limit Node *limitCount; /* COUNT parameter, or NULL if none */ } Limit; -/* --------------------- - * SubPlan node - * - * XXX Perhaps does not belong in this file? It's not really a Plan node. - * Should we make it inherit from Plan anyway? - * --------------------- - */ -typedef struct SubPlan -{ - NodeTag type; - Plan *plan; /* subselect plan itself */ - int plan_id; /* dummy thing because of we haven't equal - * funcs for plan nodes... actually, we - * could put *plan itself somewhere else - * (TopPlan node ?)... */ - List *rtable; /* range table for subselect */ - /* setParam and parParam are lists of integers (param IDs) */ - List *setParam; /* non-correlated EXPR & EXISTS subqueries - * have to set some Params for paren Plan */ - List *parParam; /* indices of corr. Vars from parent plan */ - SubLink *sublink; /* SubLink node from parser; holds info - * about what to do with subselect's - * results */ - - struct SubPlanState *pstate; /* XXX TEMPORARY HACK */ -} SubPlan; - #endif /* PLANNODES_H */ diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 11e74a8d92b83b4205ca34975b12af4866cf3e4d..ec0ad4235c96fb0a9d30d6dfee30a09859c27479 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.71 2002/11/30 21:25:06 tgl Exp $ + * $Id: primnodes.h,v 1.72 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -67,31 +67,6 @@ typedef struct Resdom * from final target list */ } Resdom; -/* - * Fjoin - */ -typedef struct Fjoin -{ - NodeTag type; - bool fj_initialized; /* true if the Fjoin has already been - * initialized for the current target list - * evaluation */ - int fj_nNodes; /* The number of Iter nodes returning sets - * that the node will flatten */ - List *fj_innerNode; /* exactly one Iter node. We eval every - * node in the outerList once then eval - * the inner node to completion pair the - * outerList result vector with each inner - * result to form the full result. When - * the inner has been exhausted, we get - * the next outer result vector and reset - * the inner. */ - DatumPtr fj_results; /* The complete (flattened) result vector */ - BoolPtr fj_alwaysDone; /* a null vector to indicate sets with a - * cardinality of 0, we treat them as the - * set {NULL}. */ -} Fjoin; - /* * Alias - @@ -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 - * allow more casts than earlier ones. + * All node types that are used in executable expression trees should derive + * from Expr (that is, have Expr as their first field). Since Expr only + * contains NodeTag, this is a formality, but it is an easy form of + * documentation. See also the ExprState node types in execnodes.h. */ -typedef enum CoercionContext -{ - COERCION_IMPLICIT, /* coercion in context of expression */ - COERCION_ASSIGNMENT, /* coercion in context of assignment */ - COERCION_EXPLICIT /* explicit cast operation */ -} CoercionContext; - -/* - * CoercionForm - information showing how to display a function-call node - */ -typedef enum CoercionForm -{ - COERCE_EXPLICIT_CALL, /* display as a function call */ - COERCE_EXPLICIT_CAST, /* display as an explicit cast */ - COERCE_IMPLICIT_CAST, /* implicit cast, so hide it */ - COERCE_DONTCARE /* special case for pathkeys */ -} CoercionForm; - -/* - * Expr - * - * Note: DISTINCT_EXPR implements the "x IS DISTINCT FROM y" construct. - * This is similar to an OP_EXPR, except for its handling of NULL inputs. - * The oper field is always an Oper node for the "=" operator for x and y. - * (We use "=", not the more obvious "<>", because more datatypes have "=" - * than "<>". This means the executor must invert the operator result.) - */ -typedef enum OpType -{ - OP_EXPR, DISTINCT_EXPR, FUNC_EXPR, - OR_EXPR, AND_EXPR, NOT_EXPR, SUBPLAN_EXPR -} OpType; - typedef struct Expr { NodeTag type; - Oid typeOid; /* oid of the type of this expression */ - OpType opType; /* kind of expression */ - Node *oper; /* operator node if needed (Oper, Func, or - * SubPlan) */ - List *args; /* arguments to this expression */ } Expr; /* - * Oper - Expr subnode for an OP_EXPR (or DISTINCT_EXPR) - * - * NOTE: in the good old days 'opno' used to be both (or either, or - * neither) the pg_operator oid, and/or the pg_proc oid depending - * on the postgres module in question (parser->pg_operator, - * executor->pg_proc, planner->both), the mood of the programmer, - * and the phase of the moon (rumors that it was also depending on the day - * of the week are probably false). To make things even more postgres-like - * (i.e. a mess) some comments were referring to 'opno' using the name - * 'opid'. Anyway, now we have two separate fields, and of course that - * immediately removes all bugs from the code... [ sp :-) ]. - * - * Note also that opid is not necessarily filled in immediately on creation - * of the node. The planner makes sure it is valid before passing the node - * tree to the executor, but during parsing/planning opid is typically 0. - */ -typedef struct Oper -{ - NodeTag type; - Oid opno; /* PG_OPERATOR OID of the operator */ - Oid opid; /* PG_PROC OID of underlying function */ - Oid opresulttype; /* PG_TYPE OID of result value */ - bool opretset; /* true if operator returns set */ - FunctionCachePtr op_fcache; /* runtime state, else NULL */ -} Oper; - -/* - * Func - Expr subnode for a FUNC_EXPR - */ -typedef struct Func -{ - NodeTag type; - Oid funcid; /* PG_PROC OID of the function */ - Oid funcresulttype; /* PG_TYPE OID of result value */ - bool funcretset; /* true if function returns set */ - CoercionForm funcformat; /* how to display this function call */ - FunctionCachePtr func_fcache; /* runtime state, or NULL */ -} Func; - -/* - * Var + * Var - expression node representing a variable (ie, a table column) * * Note: during parsing/planning, varnoold/varoattno are always just copies * of varno/varattno. At the tail end of planning, Var nodes appearing in @@ -248,7 +147,7 @@ typedef struct Func typedef struct Var { - NodeTag type; + Expr xpr; Index varno; /* index of this var's relation in the * range table (could also be INNER or * OUTER) */ @@ -272,7 +171,7 @@ typedef struct Var */ typedef struct Const { - NodeTag type; + Expr xpr; Oid consttype; /* PG_TYPE OID of the constant's datatype */ int constlen; /* typlen of the constant's datatype */ Datum constvalue; /* the constant's value */ @@ -300,12 +199,11 @@ typedef struct Const * * PARAM_EXEC: The parameter is an internal executor parameter. * It has a number contained in the `paramid' field. - * * ---------------- */ typedef struct Param { - NodeTag type; + Expr xpr; int paramkind; /* kind of parameter. See above */ AttrNumber paramid; /* numeric ID for parameter ("$1") */ char *paramname; /* name for parameter ("$.foo") */ @@ -317,15 +215,156 @@ typedef struct Param */ typedef struct Aggref { - NodeTag type; + Expr xpr; Oid aggfnoid; /* pg_proc Oid of the aggregate */ Oid aggtype; /* type Oid of result of the aggregate */ - Node *target; /* expression we are aggregating on */ + Expr *target; /* expression we are aggregating on */ bool aggstar; /* TRUE if argument was really '*' */ bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */ + + /* XXX this should move to AggrefExprState: */ int aggno; /* workspace for executor (see nodeAgg.c) */ } Aggref; +/* ---------------- + * ArrayRef: describes an array subscripting operation + * + * An ArrayRef can describe fetching a single element from an array, + * fetching a subarray (array slice), storing a single element into + * an array, or storing a slice. The "store" cases work with an + * initial array value and a source value that is inserted into the + * appropriate part of the array; the result of the operation is an + * entire new modified array value. + * + * If reflowerindexpr = NIL, then we are fetching or storing a single array + * element at the subscripts given by refupperindexpr. Otherwise we are + * fetching or storing an array slice, that is a rectangular subarray + * with lower and upper bounds given by the index expressions. + * reflowerindexpr must be the same length as refupperindexpr when it + * is not NIL. + * + * Note: array types can be fixed-length (refattrlength > 0), but only + * when the element type is itself fixed-length. Otherwise they are + * varlena structures and have refattrlength = -1. In any case, + * an array type is never pass-by-value. + * + * Note: refrestype is NOT the element type, but the array type, + * when doing subarray fetch or either type of store. It might be a good + * idea to include a refelemtype field as well. + * ---------------- + */ +typedef struct ArrayRef +{ + Expr xpr; + Oid refrestype; /* type of the result of the ArrayRef + * operation */ + int refattrlength; /* typlen of array type */ + int refelemlength; /* typlen of the array element type */ + bool refelembyval; /* is the element type pass-by-value? */ + char refelemalign; /* typalign of the element type */ + List *refupperindexpr;/* expressions that evaluate to upper + * array indexes */ + List *reflowerindexpr;/* expressions that evaluate to lower + * array indexes */ + Expr *refexpr; /* the expression that evaluates to an + * array value */ + Expr *refassgnexpr; /* expression for the source value, or + * NULL if fetch */ +} ArrayRef; + +/* + * CoercionContext - distinguishes the allowed set of type casts + * + * NB: ordering of the alternatives is significant; later (larger) values + * allow more casts than earlier ones. + */ +typedef enum CoercionContext +{ + COERCION_IMPLICIT, /* coercion in context of expression */ + COERCION_ASSIGNMENT, /* coercion in context of assignment */ + COERCION_EXPLICIT /* explicit cast operation */ +} CoercionContext; + +/* + * CoercionForm - information showing how to display a function-call node + */ +typedef enum CoercionForm +{ + COERCE_EXPLICIT_CALL, /* display as a function call */ + COERCE_EXPLICIT_CAST, /* display as an explicit cast */ + COERCE_IMPLICIT_CAST, /* implicit cast, so hide it */ + COERCE_DONTCARE /* special case for pathkeys */ +} CoercionForm; + +/* + * FuncExpr - expression node for a function call + */ +typedef struct FuncExpr +{ + Expr xpr; + Oid funcid; /* PG_PROC OID of the function */ + Oid funcresulttype; /* PG_TYPE OID of result value */ + bool funcretset; /* true if function returns set */ + CoercionForm funcformat; /* how to display this function call */ + List *args; /* arguments to the function */ + + FunctionCachePtr func_fcache; /* XXX runtime state, or NULL */ +} FuncExpr; + +/* + * OpExpr - expression node for an operator invocation + * + * Semantically, this is essentially the same as a function call. + * + * Note that opfuncid is not necessarily filled in immediately on creation + * of the node. The planner makes sure it is valid before passing the node + * tree to the executor, but during parsing/planning opfuncid is typically 0. + */ +typedef struct OpExpr +{ + Expr xpr; + Oid opno; /* PG_OPERATOR OID of the operator */ + Oid opfuncid; /* PG_PROC OID of underlying function */ + Oid opresulttype; /* PG_TYPE OID of result value */ + bool opretset; /* true if operator returns set */ + List *args; /* arguments to the operator (1 or 2) */ + + FunctionCachePtr op_fcache; /* XXX runtime state, else NULL */ +} OpExpr; + +/* + * DistinctExpr - expression node for "x IS DISTINCT FROM y" + * + * Except for the nodetag, this is represented identically to an OpExpr + * referencing the "=" operator for x and y. + * We use "=", not the more obvious "<>", because more datatypes have "=" + * than "<>". This means the executor must invert the operator result. + * Note that the operator function won't be called at all if either input + * is NULL, since then the result can be determined directly. + */ +typedef OpExpr DistinctExpr; + +/* + * BoolExpr - expression node for the basic Boolean operators AND, OR, NOT + * + * Notice the arguments are given as a List. For NOT, of course the list + * must always have exactly one element. For AND and OR, the executor can + * handle any number of arguments. The parser treats AND and OR as binary + * and so it only produces two-element lists, but the optimizer will flatten + * trees of AND and OR nodes to produce longer lists when possible. + */ +typedef enum BoolExprType +{ + AND_EXPR, OR_EXPR, NOT_EXPR +} BoolExprType; + +typedef struct BoolExpr +{ + Expr xpr; + BoolExprType boolop; + List *args; /* arguments to this expression */ +} BoolExpr; + /* ---------------- * SubLink * @@ -348,19 +387,23 @@ typedef struct Aggref * depending on the "useor" flag. ALL and ANY combine the per-row results * using AND and OR semantics respectively. * + * SubLink is classed as an Expr node, but it is not actually executable; + * it must be replaced in the expression tree by a SubPlanExpr node during + * planning. + * * NOTE: lefthand and oper have varying meanings depending on where you look * in the parse/plan pipeline: * 1. gram.y delivers a list of the (untransformed) lefthand expressions in * lefthand, and sets oper to a single A_Expr (not a list!) containing * the string name of the operator, but no arguments. * 2. The parser's expression transformation transforms lefthand normally, - * and replaces oper with a list of Oper nodes, one per lefthand + * and replaces oper with a list of OpExpr nodes, one per lefthand * expression. These nodes represent the parser's resolution of exactly * which operator to apply to each pair of lefthand and targetlist - * expressions. However, we have not constructed actual Expr trees for - * these operators yet. This is the representation seen in saved rules - * and in the rewriter. - * 3. Finally, the planner converts the oper list to a list of normal Expr + * expressions. However, we have not constructed complete Expr trees for + * these operations yet: the args fields of the OpExpr nodes are NIL. + * This is the representation seen in saved rules and in the rewriter. + * 3. Finally, the planner converts the oper list to a list of normal OpExpr * nodes representing the application of the operator(s) to the lefthand * expressions and values from the inner targetlist. The inner * targetlist items are represented by placeholder Param nodes. @@ -370,7 +413,7 @@ typedef struct Aggref * Planner routines that might see either representation 2 or 3 can tell * the difference by checking whether lefthand is NIL or not. Also, * representation 2 appears in a "bare" SubLink, while representation 3 is - * found in SubLinks that are children of SubPlan nodes. + * found in SubLinks that are children of SubPlanExpr nodes. * * In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are * always NIL. useor is not significant either for these sublink types. @@ -384,62 +427,45 @@ typedef enum SubLinkType typedef struct SubLink { - NodeTag type; + Expr xpr; SubLinkType subLinkType; /* EXISTS, ALL, ANY, MULTIEXPR, EXPR */ bool useor; /* TRUE to combine column results with * "OR" not "AND" */ List *lefthand; /* list of outer-query expressions on the * left */ - List *oper; /* list of Oper nodes for combining - * operators */ + List *oper; /* list of OpExpr nodes for combining + * operators, or final list of executable + * expressions */ Node *subselect; /* subselect as Query* or parsetree */ } SubLink; -/* ---------------- - * ArrayRef: describes an array subscripting operation - * - * An ArrayRef can describe fetching a single element from an array, - * fetching a subarray (array slice), storing a single element into - * an array, or storing a slice. The "store" cases work with an - * initial array value and a source value that is inserted into the - * appropriate part of the array; the result of the operation is an - * entire new modified array value. - * - * If reflowerindexpr = NIL, then we are fetching or storing a single array - * element at the subscripts given by refupperindexpr. Otherwise we are - * fetching or storing an array slice, that is a rectangular subarray - * with lower and upper bounds given by the index expressions. - * reflowerindexpr must be the same length as refupperindexpr when it - * is not NIL. - * - * Note: array types can be fixed-length (refattrlength > 0), but only - * when the element type is itself fixed-length. Otherwise they are - * varlena structures and have refattrlength = -1. In any case, - * an array type is never pass-by-value. +/* + * SubPlanExpr - executable expression node for a subplan (sub-SELECT) * - * Note: refrestype is NOT the element type, but the array type, - * when doing subarray fetch or either type of store. It might be a good - * idea to include a refelemtype field as well. - * ---------------- + * The planner replaces SubLink nodes in expression trees with SubPlanExpr + * nodes after it has finished planning the subquery. See notes above. */ -typedef struct ArrayRef +typedef struct SubPlanExpr { - NodeTag type; - Oid refrestype; /* type of the result of the ArrayRef - * operation */ - int refattrlength; /* typlen of array type */ - int refelemlength; /* typlen of the array element type */ - bool refelembyval; /* is the element type pass-by-value? */ - char refelemalign; /* typalign of the element type */ - List *refupperindexpr;/* expressions that evaluate to upper - * array indexes */ - List *reflowerindexpr;/* expressions that evaluate to lower - * array indexes */ - Node *refexpr; /* the expression that evaluates to an - * array value */ - Node *refassgnexpr; /* expression for the source value, or - * NULL if fetch */ -} ArrayRef; + Expr xpr; + Oid typeOid; /* PG_TYPE OID of the expression result */ + struct Plan *plan; /* subselect plan itself */ + int plan_id; /* dummy thing because of we haven't equal + * funcs for plan nodes... actually, we + * could put *plan itself somewhere else + * (TopPlan node ?)... */ + List *rtable; /* range table for subselect */ + /* setParam and parParam are lists of integers (param IDs) */ + List *setParam; /* non-correlated EXPR & EXISTS subqueries + * have to set some Params for paren Plan */ + List *parParam; /* indices of input Params from parent plan */ + List *args; /* exprs to pass as parParam values */ + SubLink *sublink; /* SubLink node from parser; holds info + * about what to do with subselect's + * results */ + + struct SubPlanState *pstate; /* XXX TEMPORARY HACK */ +} SubPlanExpr; /* ---------------- * FieldSelect @@ -453,8 +479,8 @@ typedef struct ArrayRef typedef struct FieldSelect { - NodeTag type; - Node *arg; /* input expression */ + Expr xpr; + Expr *arg; /* input expression */ AttrNumber fieldnum; /* attribute number of field to extract */ Oid resulttype; /* type of the field (result type of this * node) */ @@ -476,13 +502,134 @@ typedef struct FieldSelect typedef struct RelabelType { - NodeTag type; - Node *arg; /* input expression */ + Expr xpr; + Expr *arg; /* input expression */ Oid resulttype; /* output type of coercion expression */ int32 resulttypmod; /* output typmod (usually -1) */ CoercionForm relabelformat; /* how to display this node */ } RelabelType; +/* + * CaseExpr - a CASE expression + */ +typedef struct CaseExpr +{ + Expr xpr; + Oid casetype; /* type of expression result */ + Expr *arg; /* implicit equality comparison argument */ + List *args; /* the arguments (list of WHEN clauses) */ + Expr *defresult; /* the default result (ELSE clause) */ +} CaseExpr; + +/* + * CaseWhen - an argument to a CASE expression + */ +typedef struct CaseWhen +{ + Expr xpr; + Expr *expr; /* condition expression */ + Expr *result; /* substitution result */ +} CaseWhen; + +/* ---------------- + * NullTest + * + * NullTest represents the operation of testing a value for NULLness. + * Currently, we only support scalar input values, but eventually a + * row-constructor input should be supported. + * The appropriate test is performed and returned as a boolean Datum. + * ---------------- + */ + +typedef enum NullTestType +{ + IS_NULL, IS_NOT_NULL +} NullTestType; + +typedef struct NullTest +{ + Expr xpr; + Expr *arg; /* input expression */ + NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ +} NullTest; + +/* + * BooleanTest + * + * BooleanTest represents the operation of determining whether a boolean + * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations + * are supported. Note that a NULL input does *not* cause a NULL result. + * The appropriate test is performed and returned as a boolean Datum. + */ + +typedef enum BoolTestType +{ + IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN +} BoolTestType; + +typedef struct BooleanTest +{ + Expr xpr; + Expr *arg; /* input expression */ + BoolTestType booltesttype; /* test type */ +} BooleanTest; + +/* + * ConstraintTest + * + * ConstraintTest represents the operation of testing a value to see whether + * it meets a constraint. If so, the input value is returned as the result; + * if not, an error is raised. + */ + +typedef enum ConstraintTestType +{ + CONSTR_TEST_NOTNULL, + CONSTR_TEST_CHECK +} ConstraintTestType; + +typedef struct ConstraintTest +{ + Expr xpr; + Expr *arg; /* input expression */ + ConstraintTestType testtype; /* test type */ + char *name; /* name of constraint (for error msgs) */ + char *domname; /* name of domain (for error messages) */ + Expr *check_expr; /* for CHECK test, a boolean expression */ +} ConstraintTest; + +/* + * Placeholder node for the value to be processed by a domains + * check constraint. This is effectively like a Param; could we use + * a Param node instead? + */ +typedef struct ConstraintTestValue +{ + Expr xpr; + Oid typeId; + int32 typeMod; +} ConstraintTestValue; + + +/* + * TargetEntry - + * a target entry (used in query target lists) + * + * Strictly speaking, a TargetEntry isn't an expression node (since it can't + * be evaluated by ExecEvalExpr). But we treat it as one anyway, since in + * very many places it's convenient to process a whole query targetlist as a + * single expression tree. + * + * The separation between TargetEntry and Resdom is historical. One of these + * days, Resdom should probably get folded into TargetEntry. + */ +typedef struct TargetEntry +{ + Expr xpr; + Resdom *resdom; /* descriptor for targetlist item */ + Expr *expr; /* expression to evaluate */ +} TargetEntry; + /* ---------------------------------------------------------------- * node types for join trees diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 333ca0b695b497572943cccdc2e8cc3c14237273..6da47683e6e23f21e44c7875776693b4a9ece905 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: relation.h,v 1.73 2002/12/05 15:50:39 tgl Exp $ + * $Id: relation.h,v 1.74 2002/12/12 15:49:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -295,7 +295,7 @@ typedef struct PathKeyItem /* * key typically points to a Var node, ie a relation attribute, but it - * can also point to a Func clause representing the value indexed by a + * can also point to a FuncExpr clause representing the value indexed by a * functional index. Someday we might allow arbitrary expressions as * path keys, so don't assume more than you must. */ diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index da0fe4c5102e5b6aa64d4443a8a1549e0851b640..8da7a8688efb9667179f3a72a25d59f64801f723 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: clauses.h,v 1.56 2002/12/01 21:05:14 tgl Exp $ + * $Id: clauses.h,v 1.57 2002/12/12 15:49:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,23 +16,28 @@ #include "nodes/relation.h" -extern Expr *make_clause(int type, Node *oper, List *args); -extern bool is_opclause(Node *clause); -extern Expr *make_opclause(Oper *op, Var *leftop, Var *rightop); + +#define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr)) +#define is_funcclause(clause) ((clause) != NULL && IsA(clause, FuncExpr)) +#define is_subplan(clause) ((clause) != NULL && IsA(clause, SubPlanExpr)) + + +extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset, + Expr *leftop, Expr *rightop); extern Var *get_leftop(Expr *clause); extern Var *get_rightop(Expr *clause); -extern bool is_funcclause(Node *clause); -extern Expr *make_funcclause(Func *func, List *funcargs); - -extern bool or_clause(Node *clause); -extern Expr *make_orclause(List *orclauses); +extern Expr *make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset, + CoercionForm funcformat, List *funcargs); extern bool not_clause(Node *clause); extern Expr *make_notclause(Expr *notclause); extern Expr *get_notclausearg(Expr *notclause); +extern bool or_clause(Node *clause); +extern Expr *make_orclause(List *orclauses); + extern bool and_clause(Node *clause); extern Expr *make_andclause(List *andclauses); extern Node *make_and_qual(Node *qual1, Node *qual2); @@ -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 int NumRelids(Node *clause); -extern void CommuteClause(Expr *clause); +extern void CommuteClause(OpExpr *clause); 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) (), void *context, int flags); -#define is_subplan(clause) ((clause) != NULL && \ - IsA(clause, Expr) && \ - ((Expr *) (clause))->opType == SUBPLAN_EXPR) - #endif /* CLAUSES_H */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index b03ce0453e6dd0c765cafdf3740b571730633b26..06f585f722007b011fcf65651a1ace7c211bd2cc 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: paths.h,v 1.61 2002/11/24 21:52:15 tgl Exp $ + * $Id: paths.h,v 1.62 2002/12/12 15:49:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,8 +42,6 @@ extern void debug_print_rel(Query *root, RelOptInfo *rel); extern void create_index_paths(Query *root, RelOptInfo *rel); extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel, Relids outer_relids, JoinType jointype); -extern Oid indexable_operator(Expr *clause, Oid opclass, - bool indexkey_on_left); extern List *extract_or_indexqual_conditions(RelOptInfo *rel, IndexOptInfo *index, Expr *orsubclause); diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index ecd7bca604246765eb75a0c0d60a288483adb882..134adad9b604c99f35225bf6042a7cebd9036f78 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: planmain.h,v 1.63 2002/11/21 00:42:19 tgl Exp $ + * $Id: planmain.h,v 1.64 2002/12/12 15:49:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -68,6 +68,6 @@ extern void set_plan_references(Plan *plan, List *rtable); extern List *join_references(List *clauses, List *rtable, List *outer_tlist, List *inner_tlist, Index acceptable_rel); -extern void fix_opids(Node *node); +extern void fix_opfuncids(Node *node); #endif /* PLANMAIN_H */ diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 007a3ffbe7955060583d5d9d3c3a6f9a89b58dfd..23d457263e82d85978e5948e557c6d8cc56a114e 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.72 2002/12/05 15:50:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.73 2002/12/12 15:49:42 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -3499,44 +3499,130 @@ exec_cast_value(Datum value, Oid valtype, static bool exec_simple_check_node(Node *node) { + if (node == NULL) + return TRUE; + switch (nodeTag(node)) { - case T_Expr: + case T_Const: + return TRUE; + + case T_Param: + return TRUE; + + case T_ArrayRef: { - Expr *expr = (Expr *) node; - List *l; + ArrayRef *expr = (ArrayRef *) node; - switch (expr->opType) - { - case OP_EXPR: - case DISTINCT_EXPR: - case FUNC_EXPR: - case OR_EXPR: - case AND_EXPR: - case NOT_EXPR: - break; + if (!exec_simple_check_node((Node *) expr->refupperindexpr)) + return FALSE; + if (!exec_simple_check_node((Node *) expr->reflowerindexpr)) + return FALSE; + if (!exec_simple_check_node((Node *) expr->refexpr)) + return FALSE; + if (!exec_simple_check_node((Node *) expr->refassgnexpr)) + return FALSE; - default: - return FALSE; - } + return TRUE; + } - foreach(l, expr->args) - { - if (!exec_simple_check_node(lfirst(l))) - return FALSE; - } + case T_FuncExpr: + { + FuncExpr *expr = (FuncExpr *) node; + + if (expr->funcretset) + return FALSE; + if (!exec_simple_check_node((Node *) expr->args)) + return FALSE; return TRUE; } - case T_Param: - return TRUE; + case T_OpExpr: + { + OpExpr *expr = (OpExpr *) node; - case T_Const: - return TRUE; + if (expr->opretset) + return FALSE; + if (!exec_simple_check_node((Node *) expr->args)) + return FALSE; + + return TRUE; + } + + case T_DistinctExpr: + { + DistinctExpr *expr = (DistinctExpr *) node; + + if (expr->opretset) + return FALSE; + if (!exec_simple_check_node((Node *) expr->args)) + return FALSE; + + return TRUE; + } + + case T_BoolExpr: + { + BoolExpr *expr = (BoolExpr *) node; + + if (!exec_simple_check_node((Node *) expr->args)) + return FALSE; + + return TRUE; + } + + case T_FieldSelect: + return exec_simple_check_node((Node *) ((FieldSelect *) node)->arg); case T_RelabelType: - return exec_simple_check_node(((RelabelType *) node)->arg); + return exec_simple_check_node((Node *) ((RelabelType *) node)->arg); + + case T_CaseExpr: + { + CaseExpr *expr = (CaseExpr *) node; + + if (!exec_simple_check_node((Node *) expr->arg)) + return FALSE; + if (!exec_simple_check_node((Node *) expr->args)) + return FALSE; + if (!exec_simple_check_node((Node *) expr->defresult)) + return FALSE; + + return TRUE; + } + + case T_CaseWhen: + { + CaseWhen *when = (CaseWhen *) node; + + if (!exec_simple_check_node((Node *) when->expr)) + return FALSE; + if (!exec_simple_check_node((Node *) when->result)) + return FALSE; + + return TRUE; + } + + case T_NullTest: + return exec_simple_check_node((Node *) ((NullTest *) node)->arg); + + case T_BooleanTest: + return exec_simple_check_node((Node *) ((BooleanTest *) node)->arg); + + case T_List: + { + List *expr = (List *) node; + List *l; + + foreach(l, expr) + { + if (!exec_simple_check_node(lfirst(l))) + return FALSE; + } + + return TRUE; + } default: return FALSE; @@ -3596,18 +3682,17 @@ exec_simple_check_plan(PLpgSQL_expr * expr) tle = (TargetEntry *) lfirst(plan->targetlist); /* - * 5. Check that all the nodes in the expression are one of Expr, - * Param or Const. + * 5. Check that all the nodes in the expression are non-scary. */ - if (!exec_simple_check_node(tle->expr)) + if (!exec_simple_check_node((Node *) tle->expr)) return; /* * Yes - this is a simple expression. Remember the expression and the * return type */ - expr->plan_simple_expr = tle->expr; - expr->plan_simple_type = exprType(tle->expr); + expr->plan_simple_expr = (Node *) tle->expr; + expr->plan_simple_type = exprType((Node *) tle->expr); } /*