]> granicus.if.org Git - postgresql/commitdiff
Get rid of long-since-vestigial Iter node type, in favor of adding a
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 12 May 2002 23:43:04 +0000 (23:43 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 12 May 2002 23:43:04 +0000 (23:43 +0000)
returns-set boolean field in Func and Oper nodes.  This allows cleaner,
more reliable tests for expressions returning sets in the planner and
parser.  For example, a WHERE clause returning a set is now detected
and complained of in the parser, not only at runtime.

33 files changed:
src/backend/catalog/heap.c
src/backend/commands/tablecmds.c
src/backend/executor/Makefile
src/backend/executor/execFlatten.c [deleted file]
src/backend/executor/execQual.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/makefuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/README
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/pathkeys.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/prep/prepqual.c
src/backend/optimizer/util/clauses.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_func.c
src/backend/parser/parse_node.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/lsyscache.c
src/include/catalog/catversion.h
src/include/executor/execFlatten.h [deleted file]
src/include/nodes/makefuncs.h
src/include/nodes/nodes.h
src/include/nodes/primnodes.h
src/include/optimizer/clauses.h
src/include/parser/parse_coerce.h
src/include/utils/lsyscache.h

index e0301094d16a96333ee503a234467ba8f7cbc9ee..df6c44f5bc5a735092520a8ef2c72c03667bcc48 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.198 2002/05/03 04:11:08 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.199 2002/05/12 23:43:02 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -49,6 +49,7 @@
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
 #include "optimizer/var.h"
+#include "parser/parse_coerce.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
 #include "parser/parse_target.h"
@@ -1626,9 +1627,7 @@ AddRelationRawConstraints(Relation rel,
                /*
                 * Make sure it yields a boolean result.
                 */
-               if (exprType(expr) != BOOLOID)
-                       elog(ERROR, "CHECK constraint expression '%s' does not yield boolean result",
-                                ccname);
+               expr = coerce_to_boolean(expr, "CHECK");
 
                /*
                 * Make sure no outside relations are referred to.
@@ -1764,6 +1763,12 @@ cookDefault(ParseState *pstate,
        if (contain_var_clause(expr))
                elog(ERROR, "cannot use column references in DEFAULT clause");
 
+       /*
+        * It can't return a set either.
+        */
+       if (expression_returns_set(expr))
+               elog(ERROR, "DEFAULT clause must not return a set");
+
        /*
         * No subplans or aggregates, either...
         */
index 79b54aa7a5aeb5a92f20da5667647677ab9cc157..885b760a51208c36d1656458b5005077468c1d32 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.12 2002/04/27 21:24:34 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.13 2002/05/12 23:43:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,6 +37,7 @@
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
 #include "parser/parse.h"
+#include "parser/parse_coerce.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
 #include "parser/parse_type.h"
@@ -2461,9 +2462,7 @@ AlterTableAddConstraint(Oid myrelid,
                                                                /*
                                                                 * Make sure it yields a boolean result.
                                                                 */
-                                                               if (exprType(expr) != BOOLOID)
-                                                                       elog(ERROR, "CHECK '%s' does not yield boolean result",
-                                                                                name);
+                                                               expr = coerce_to_boolean(expr, "CHECK");
 
                                                                /*
                                                                 * Make sure no outside relations are
@@ -2473,6 +2472,14 @@ AlterTableAddConstraint(Oid myrelid,
                                                                        elog(ERROR, "Only relation '%s' can be referenced in CHECK",
                                                                                 RelationGetRelationName(rel));
 
+                                                               /*
+                                                                * No subplans or aggregates, either...
+                                                                */
+                                                               if (contain_subplans(expr))
+                                                                       elog(ERROR, "cannot use subselect in CHECK constraint expression");
+                                                               if (contain_agg_clause(expr))
+                                                                       elog(ERROR, "cannot use aggregate function in CHECK constraint expression");
+
                                                                /*
                                                                 * Might as well try to reduce any
                                                                 * constant expressions.
index 0a66e1be03e08ae0ef9fb1bad32ccf1e706c60b5..b875259bc1a6c294301ad982acfa0e8c4ce46f49 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for executor
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/executor/Makefile,v 1.18 2002/05/12 20:10:02 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/executor/Makefile,v 1.19 2002/05/12 23:43:02 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/executor
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = execAmi.o execFlatten.o execJunk.o execMain.o \
+OBJS = execAmi.o execJunk.o execMain.o \
        execProcnode.o execQual.o execScan.o execTuples.o \
        execUtils.o functions.o instrument.o nodeAppend.o nodeAgg.o nodeHash.o \
        nodeHashjoin.o nodeIndexscan.o nodeMaterial.o nodeMergejoin.o \
diff --git a/src/backend/executor/execFlatten.c b/src/backend/executor/execFlatten.c
deleted file mode 100644 (file)
index ecbe7b5..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * execFlatten.c
- *       This file handles the nodes associated with flattening sets in the
- *       target list of queries containing functions returning sets.
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/Attic/execFlatten.c,v 1.16 2001/10/28 06:25:43 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-/*
- * ExecEvalIter() -
- *      Iterate through the all return tuples/base types from a function one
- *      at time (i.e. one per ExecEvalIter call).      Not really needed for
- *      postquel functions, but for reasons of orthogonality, these nodes
- *      exist above pq functions as well as c functions.
- *
- * ExecEvalFjoin() -
- *      Given N Iter nodes return a vector of all combinations of results
- *      one at a time (i.e. one result vector per ExecEvalFjoin call).  This
- *      node does the actual flattening work.
- */
-#include "postgres.h"
-#include "executor/execFlatten.h"
-#include "executor/executor.h"
-
-#ifdef SETS_FIXED
-static bool FjoinBumpOuterNodes(TargetEntry *tlist, ExprContext *econtext,
-                                       DatumPtr results, char *nulls);
-#endif
-
-
-Datum
-ExecEvalIter(Iter *iterNode,
-                        ExprContext *econtext,
-                        bool *isNull,
-                        ExprDoneCond *isDone)
-{
-       Node       *expression;
-
-       expression = iterNode->iterexpr;
-
-       /*
-        * Really Iter nodes are only needed for C functions, postquel
-        * function by their nature return 1 result at a time.  For now we are
-        * only worrying about postquel functions, c functions will come
-        * later.
-        */
-       return ExecEvalExpr(expression, econtext, isNull, isDone);
-}
-
-void
-ExecEvalFjoin(TargetEntry *tlist,
-                         ExprContext *econtext,
-                         bool *isNullVect,
-                         ExprDoneCond *fj_isDone)
-{
-
-#ifdef SETS_FIXED
-       bool            isDone;
-       int                     curNode;
-       List       *tlistP;
-
-       Fjoin      *fjNode = tlist->fjoin;
-       DatumPtr        resVect = fjNode->fj_results;
-       BoolPtr         alwaysDone = fjNode->fj_alwaysDone;
-
-       if (fj_isDone)
-               *fj_isDone = ExprMultipleResult;
-
-       /*
-        * For the next tuple produced by the plan, we need to re-initialize
-        * the Fjoin node.
-        */
-       if (!fjNode->fj_initialized)
-       {
-               /*
-                * Initialize all of the Outer nodes
-                */
-               curNode = 1;
-               foreach(tlistP, lnext(tlist))
-               {
-                       TargetEntry *tle = lfirst(tlistP);
-
-                       resVect[curNode] = ExecEvalIter((Iter *) tle->expr,
-                                                                                       econtext,
-                                                                                       &isNullVect[curNode],
-                                                                                       &isDone);
-                       if (isDone)
-                               isNullVect[curNode] = alwaysDone[curNode] = true;
-                       else
-                               alwaysDone[curNode] = false;
-
-                       curNode++;
-               }
-
-               /*
-                * Initialize the inner node
-                */
-               resVect[0] = ExecEvalIter((Iter *) fjNode->fj_innerNode->expr,
-                                                                 econtext,
-                                                                 &isNullVect[0],
-                                                                 &isDone);
-               if (isDone)
-                       isNullVect[0] = alwaysDone[0] = true;
-               else
-                       alwaysDone[0] = false;
-
-               /*
-                * Mark the Fjoin as initialized now.
-                */
-               fjNode->fj_initialized = TRUE;
-
-               /*
-                * If the inner node is always done, then we are done for now
-                */
-               if (isDone)
-                       return;
-       }
-       else
-       {
-               /*
-                * If we're already initialized, all we need to do is get the next
-                * inner result and pair it up with the existing outer node result
-                * vector.      Watch out for the degenerate case, where the inner
-                * node never returns results.
-                */
-
-               /*
-                * Fill in nulls for every function that is always done.
-                */
-               for (curNode = fjNode->fj_nNodes - 1; curNode >= 0; curNode--)
-                       isNullVect[curNode] = alwaysDone[curNode];
-
-               if (alwaysDone[0] == true)
-               {
-                       *fj_isDone = FjoinBumpOuterNodes(tlist,
-                                                                                        econtext,
-                                                                                        resVect,
-                                                                                        isNullVect);
-                       return;
-               }
-               else
-                       resVect[0] = ExecEvalIter((Iter *) fjNode->fj_innerNode->expr,
-                                                                         econtext,
-                                                                         &isNullVect[0],
-                                                                         &isDone);
-       }
-
-       /*
-        * if the inner node is done
-        */
-       if (isDone)
-       {
-               *fj_isDone = FjoinBumpOuterNodes(tlist,
-                                                                                econtext,
-                                                                                resVect,
-                                                                                isNullVect);
-               if (*fj_isDone)
-                       return;
-
-               resVect[0] = ExecEvalIter((Iter *) fjNode->fj_innerNode->expr,
-                                                                 econtext,
-                                                                 &isNullVect[0],
-                                                                 &isDone);
-
-       }
-#endif
-       return;
-}
-
-#ifdef SETS_FIXED
-static bool
-FjoinBumpOuterNodes(TargetEntry *tlist,
-                                       ExprContext *econtext,
-                                       DatumPtr results,
-                                       char *nulls)
-{
-       bool            funcIsDone = true;
-       Fjoin      *fjNode = tlist->fjoin;
-       char       *alwaysDone = fjNode->fj_alwaysDone;
-       List       *outerList = lnext(tlist);
-       List       *trailers = lnext(tlist);
-       int                     trailNode = 1;
-       int                     curNode = 1;
-
-       /*
-        * Run through list of functions until we get to one that isn't yet
-        * done returning values.  Watch out for funcs that are always done.
-        */
-       while ((funcIsDone == true) && (outerList != NIL))
-       {
-               TargetEntry *tle = lfirst(outerList);
-
-               if (alwaysDone[curNode] == true)
-                       nulls[curNode] = 'n';
-               else
-                       results[curNode] = ExecEvalIter((Iter) tle->expr,
-                                                                                       econtext,
-                                                                                       &nulls[curNode],
-                                                                                       &funcIsDone);
-               curNode++;
-               outerList = lnext(outerList);
-       }
-
-       /*
-        * If every function is done, then we are done flattening. Mark the
-        * Fjoin node uninitialized, it is time to get the next tuple from the
-        * plan and redo all of the flattening.
-        */
-       if (funcIsDone)
-       {
-               set_fj_initialized(fjNode, false);
-               return true;
-       }
-
-       /*
-        * We found a function that wasn't done.  Now re-run every function
-        * before it.  As usual watch out for functions that are always done.
-        */
-       trailNode = 1;
-       while (trailNode != curNode - 1)
-       {
-               TargetEntry *tle = lfirst(trailers);
-
-               if (alwaysDone[trailNode] != true)
-                       results[trailNode] = ExecEvalIter((Iter) tle->expr,
-                                                                                         econtext,
-                                                                                         &nulls[trailNode],
-                                                                                         &funcIsDone);
-               trailNode++;
-               trailers = lnext(trailers);
-       }
-       return false;
-}
-
-#endif
index bebb664f29901679ba9adc02bdb7b1e65a6a9041..cc9bebd1feddb6c2f5ba2e5b72937877f8d46625 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.92 2002/05/12 20:10:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.93 2002/05/12 23:43:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,7 +35,6 @@
 #include "postgres.h"
 
 #include "access/heapam.h"
-#include "executor/execFlatten.h"
 #include "executor/execdebug.h"
 #include "executor/functions.h"
 #include "executor/nodeSubplan.h"
@@ -1336,12 +1335,6 @@ ExecEvalExpr(Node *expression,
                case T_Param:
                        retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
                        break;
-               case T_Iter:
-                       retDatum = ExecEvalIter((Iter *) expression,
-                                                                       econtext,
-                                                                       isNull,
-                                                                       isDone);
-                       break;
                case T_Aggref:
                        retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
                        break;
index cfcf00a4d47a8694d91e188e70e8b1c2550554b6..3801d409cf156f21e39554caf66101af70ec8689 100644 (file)
@@ -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.183 2002/05/12 20:10:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.184 2002/05/12 23:43:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -764,6 +764,7 @@ _copyOper(Oper *from)
        newnode->opno = from->opno;
        newnode->opid = from->opid;
        newnode->opresulttype = from->opresulttype;
+       newnode->opretset = from->opretset;
        /* Do not copy the run-time state, if any */
        newnode->op_fcache = NULL;
 
@@ -852,7 +853,8 @@ _copyFunc(Func *from)
         * copy remainder of node
         */
        newnode->funcid = from->funcid;
-       newnode->functype = from->functype;
+       newnode->funcresulttype = from->funcresulttype;
+       newnode->funcretset = from->funcretset;
        /* Do not copy the run-time state, if any */
        newnode->func_fcache = NULL;
 
@@ -1433,17 +1435,6 @@ _copyJoinInfo(JoinInfo *from)
        return newnode;
 }
 
-static Iter *
-_copyIter(Iter *from)
-{
-       Iter       *newnode = makeNode(Iter);
-
-       Node_Copy(from, newnode, iterexpr);
-       newnode->itertype = from->itertype;
-
-       return newnode;
-}
-
 static Stream *
 _copyStream(Stream *from)
 {
@@ -2729,9 +2720,6 @@ copyObject(void *from)
                case T_ArrayRef:
                        retval = _copyArrayRef(from);
                        break;
-               case T_Iter:
-                       retval = _copyIter(from);
-                       break;
                case T_FieldSelect:
                        retval = _copyFieldSelect(from);
                        break;
index 185a16beb5a9df6d542cb75df6c172688bd05841..cf203243f1120364b53a7227d47052f8141080a4 100644 (file)
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.131 2002/05/12 20:10:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.132 2002/05/12 23:43:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -130,6 +130,8 @@ _equalOper(Oper *a, Oper *b)
                return false;
        if (a->opresulttype != b->opresulttype)
                return false;
+       if (a->opretset != b->opretset)
+               return false;
 
        /*
         * We do not examine opid or op_fcache, since these are logically
@@ -139,7 +141,8 @@ _equalOper(Oper *a, Oper *b)
         * (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 either...
+        * It's probably not really necessary to check opresulttype or opretset,
+        * either...
         */
 
        return true;
@@ -210,7 +213,9 @@ _equalFunc(Func *a, Func *b)
 {
        if (a->funcid != b->funcid)
                return false;
-       if (a->functype != b->functype)
+       if (a->funcresulttype != b->funcresulttype)
+               return false;
+       if (a->funcretset != b->funcretset)
                return false;
        /* Note we do not look at func_fcache; see notes for _equalOper */
 
@@ -538,12 +543,6 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
        return true;
 }
 
-static bool
-_equalIter(Iter *a, Iter *b)
-{
-       return equal(a->iterexpr, b->iterexpr);
-}
-
 static bool
 _equalStream(Stream *a, Stream *b)
 {
@@ -1884,9 +1883,6 @@ equal(void *a, void *b)
                case T_ArrayRef:
                        retval = _equalArrayRef(a, b);
                        break;
-               case T_Iter:
-                       retval = _equalIter(a, b);
-                       break;
                case T_RelabelType:
                        retval = _equalRelabelType(a, b);
                        break;
index 65f4ffcca379678c2ed68629e4a0f49ba5b986d1..54d9e06190803f71e5289b0a792416f61d3ad6d7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.31 2002/04/16 23:08:10 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.32 2002/05/12 23:43:02 tgl Exp $
  */
 #include "postgres.h"
 
@@ -56,13 +56,15 @@ makeSimpleA_Expr(int oper, const char *name,
 Oper *
 makeOper(Oid opno,
                 Oid opid,
-                Oid opresulttype)
+                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;
 }
index 698beb5d999a597d56a1a912da33a1c1238f9461..8ee69d1a7020cc4b90dd13264fcd4214e79ce5d6 100644 (file)
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.158 2002/05/12 20:10:03 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.159 2002/05/12 23:43:02 tgl Exp $
  *
  * NOTES
  *       Every (plan) node in POSTGRES has an associated "out" routine which
@@ -850,9 +850,11 @@ _outArrayRef(StringInfo str, ArrayRef *node)
 static void
 _outFunc(StringInfo str, Func *node)
 {
-       appendStringInfo(str, " FUNC :funcid %u :functype %u ",
+       appendStringInfo(str,
+                                        " FUNC :funcid %u :funcresulttype %u :funcretset %s ",
                                         node->funcid,
-                                        node->functype);
+                                        node->funcresulttype,
+                                        booltostr(node->funcretset));
 }
 
 /*
@@ -862,10 +864,11 @@ static void
 _outOper(StringInfo str, Oper *node)
 {
        appendStringInfo(str,
-                                        " OPER :opno %u :opid %u :opresulttype %u ",
+                                        " OPER :opno %u :opid %u :opresulttype %u :opretset %s ",
                                         node->opno,
                                         node->opid,
-                                        node->opresulttype);
+                                        node->opresulttype,
+                                        booltostr(node->opretset));
 }
 
 /*
@@ -1246,13 +1249,6 @@ _outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
        }
 }
 
-static void
-_outIter(StringInfo str, Iter *node)
-{
-       appendStringInfo(str, " ITER :iterexpr ");
-       _outNode(str, node->iterexpr);
-}
-
 static void
 _outStream(StringInfo str, Stream *node)
 {
@@ -1731,9 +1727,6 @@ _outNode(StringInfo str, void *obj)
                        case T_JoinInfo:
                                _outJoinInfo(str, obj);
                                break;
-                       case T_Iter:
-                               _outIter(str, obj);
-                               break;
                        case T_Stream:
                                _outStream(str, obj);
                                break;
index 27604dcb4be0ee0d894ed3bec840aad87663cfb0..98aab14b911677473356c44ba152b1d7330fa56b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.121 2002/05/12 20:10:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.122 2002/05/12 23:43:02 tgl Exp $
  *
  * NOTES
  *       Most of the read functions for plan nodes are tested. (In fact, they
@@ -1083,9 +1083,13 @@ _readFunc(void)
        token = pg_strtok(&length); /* now read it */
        local_node->funcid = atooid(token);
 
-       token = pg_strtok(&length); /* get :functype */
+       token = pg_strtok(&length); /* get :funcresulttype */
        token = pg_strtok(&length); /* now read it */
-       local_node->functype = atooid(token);
+       local_node->funcresulttype = atooid(token);
+
+       token = pg_strtok(&length); /* get :funcretset */
+       token = pg_strtok(&length); /* now read it */
+       local_node->funcretset = strtobool(token);
 
        local_node->func_fcache = NULL;
 
@@ -1119,6 +1123,10 @@ _readOper(void)
        token = pg_strtok(&length); /* now read it */
        local_node->opresulttype = atooid(token);
 
+       token = pg_strtok(&length); /* get :opretset */
+       token = pg_strtok(&length); /* now read it */
+       local_node->opretset = strtobool(token);
+
        local_node->op_fcache = NULL;
 
        return local_node;
@@ -1991,26 +1999,6 @@ _readJoinInfo(void)
        return local_node;
 }
 
-/* ----------------
- *             _readIter()
- *
- * ----------------
- */
-static Iter *
-_readIter(void)
-{
-       Iter       *local_node;
-       char       *token;
-       int                     length;
-
-       local_node = makeNode(Iter);
-
-       token = pg_strtok(&length); /* eat :iterexpr */
-       local_node->iterexpr = nodeRead(true);          /* now read it */
-
-       return local_node;
-}
-
 
 /* ----------------
  *             parsePlanString
@@ -2124,8 +2112,6 @@ parsePlanString(void)
                return_value = _readRestrictInfo();
        else if (length == 8 && strncmp(token, "JOININFO", length) == 0)
                return_value = _readJoinInfo();
-       else if (length == 4 && strncmp(token, "ITER", length) == 0)
-               return_value = _readIter();
        else if (length == 5 && strncmp(token, "QUERY", length) == 0)
                return_value = _readQuery();
        else if (length == 6 && strncmp(token, "NOTIFY", length) == 0)
index 472efbcd9cc9cb7b88b8d15d3acbd4e86aa1fc2d..14e3990922022ed121d43b0e2dae845f6d9dcd08 100644 (file)
@@ -42,7 +42,8 @@ base rels of the query.
 Possible Paths for a primitive table relation include plain old sequential
 scan, plus index scans for any indexes that exist on the table.  A subquery
 base relation just has one Path, a "SubqueryScan" path (which links to the
-subplan that was built by a recursive invocation of the planner).
+subplan that was built by a recursive invocation of the planner).  Likewise
+a function-RTE base relation has only one possible Path.
 
 Joins always occur using two RelOptInfos.  One is outer, the other inner.
 Outers drive lookups of values in the inner.  In a nested loop, lookups of
index 1e9074186c297139883e7b6262500cd8c4ae63db..27b6d110bc91022eb936e5f65381763c153da4da 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.84 2002/05/12 20:10:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.85 2002/05/12 23:43:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -312,8 +312,8 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
         * checking that seems more work than it's worth.  In any case, a
         * plain DISTINCT is safe to push down past.)
         *
-        * 3. If the subquery has any ITER nodes (ie, functions returning sets)
-        * in its target list, we do not push down any quals, since the quals
+        * 3. If the subquery has any functions returning sets in its target list,
+        * we do not push down any quals, since the quals
         * might refer to those tlist items, which would mean we'd introduce
         * functions-returning-sets into the subquery's WHERE/HAVING quals.
         * (It'd be sufficient to not push down quals that refer to those
@@ -333,7 +333,7 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
                subquery->limitOffset == NULL &&
                subquery->limitCount == NULL &&
                !has_distinct_on_clause(subquery) &&
-               !contain_iter_clause((Node *) subquery->targetList))
+               !expression_returns_set((Node *) subquery->targetList))
        {
                /* OK to consider pushing down individual quals */
                List       *upperrestrictlist = NIL;
index 21599b08bd7b02db5a679981750963394b180dd6..6ec1d5af8fa66ab9777c501a1e211bb8f28fc631 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.116 2002/04/16 23:08:10 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.117 2002/05/12 23:43:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1316,7 +1316,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
         */
        test_oper = makeOper(test_op,           /* opno */
                                                 InvalidOid,    /* opid */
-                                                BOOLOID);              /* opresulttype */
+                                                BOOLOID,               /* opresulttype */
+                                                false);                /* opretset */
        replace_opid(test_oper);
        test_expr = make_opclause(test_oper,
                                                          (Var *) clause_const,
@@ -2020,7 +2021,7 @@ 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);
+               op = makeOper(oproid, InvalidOid, BOOLOID, false);
                expr = make_opclause(op, leftop, (Var *) con);
                result = makeList1(expr);
                return result;
@@ -2035,7 +2036,7 @@ 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);
+       op = makeOper(oproid, InvalidOid, BOOLOID, false);
        expr = make_opclause(op, leftop, (Var *) con);
        result = makeList1(expr);
 
@@ -2051,7 +2052,7 @@ prefix_quals(Var *leftop, Oid expr_op,
                if (oproid == InvalidOid)
                        elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
                con = string_to_const(greaterstr, datatype);
-               op = makeOper(oproid, InvalidOid, BOOLOID);
+               op = makeOper(oproid, InvalidOid, BOOLOID, false);
                expr = make_opclause(op, leftop, (Var *) con);
                result = lappend(result, expr);
                pfree(greaterstr);
@@ -2116,7 +2117,7 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
 
        opr1right = network_scan_first(rightop);
 
-       op = makeOper(opr1oid, InvalidOid, BOOLOID);
+       op = makeOper(opr1oid, InvalidOid, BOOLOID, false);
        expr = make_opclause(op, leftop,
                                                 (Var *) makeConst(datatype, -1, opr1right,
                                                                                   false, false, false, false));
@@ -2131,7 +2132,7 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
 
        opr2right = network_scan_last(rightop);
 
-       op = makeOper(opr2oid, InvalidOid, BOOLOID);
+       op = makeOper(opr2oid, InvalidOid, BOOLOID, false);
        expr = make_opclause(op, leftop,
                                                 (Var *) makeConst(datatype, -1, opr2right,
                                                                                   false, false, false, false));
index 60e05ca340f3e79adcaa6970484e7f3bcf307be6..a35e86375a2aa181240c97601832a273e62c4699 100644 (file)
@@ -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.37 2002/03/12 00:51:44 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.38 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -518,7 +518,8 @@ build_index_pathkeys(Query *root,
                List       *funcargs = NIL;
 
                funcnode->funcid = index->indproc;
-               funcnode->functype = get_func_rettype(index->indproc);
+               funcnode->funcresulttype = get_func_rettype(index->indproc);
+               funcnode->funcretset = false; /* can never be a set */
                funcnode->func_fcache = NULL;
 
                while (*indexkeys != 0)
index 2410651d6831c46400097e87ac16bc4d4ddca2ae..5d35d1b230ac6369c899f386291f7710c01b69af 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.69 2002/04/28 19:54:28 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.70 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -764,9 +764,10 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
        clause = makeNode(Expr);
        clause->typeOid = BOOLOID;
        clause->opType = OP_EXPR;
-       clause->oper = (Node *) makeOper(oprid(eq_operator),            /* opno */
+       clause->oper = (Node *) makeOper(oprid(eq_operator),/* opno */
                                                                         InvalidOid,            /* opid */
-                                                                        BOOLOID);      /* operator result type */
+                                                                        BOOLOID,                       /* opresulttype */
+                                                                        false);                        /* opretset */
        clause->args = makeList2(item1, item2);
 
        ReleaseSysCache(eq_operator);
index 5eb17f3b05cf070230f0c15df13a6324c8cf40e4..500297f2155fd87dc238b8078b93d499603e9265 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.116 2002/04/28 19:54:28 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.117 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -498,7 +498,7 @@ is_simple_subquery(Query *subquery)
         * set-returning functions into places where they mustn't go,
         * such as quals of higher queries.
         */
-       if (contain_iter_clause((Node *) subquery->targetList))
+       if (expression_returns_set((Node *) subquery->targetList))
                return false;
 
        /*
index a7773040d796804d2db513778701ba1df5926339..069563ec18ec83350f49878aa00bf20d918a6460 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.30 2001/10/25 05:49:33 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.31 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -502,7 +502,8 @@ push_nots(Expr *qual)
                {
                        Oper       *op = (Oper *) makeOper(negator,
                                                                                           InvalidOid,
-                                                                                          oper->opresulttype);
+                                                                                          oper->opresulttype,
+                                                                                          oper->opretset);
 
                        return make_opclause(op, get_leftop(qual), get_rightop(qual));
                }
index 1a278e9ca2e46721a6fe0c3dbfc80bffcceeb7e0..972c7f94633df4d93b76810eec2a678a56dbb02a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.98 2002/05/12 20:10:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.99 2002/05/12 23:43:03 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -47,7 +47,7 @@ typedef struct
 
 static bool contain_agg_clause_walker(Node *node, void *context);
 static bool pull_agg_clause_walker(Node *node, List **listptr);
-static bool contain_iter_clause_walker(Node *node, void *context);
+static bool expression_returns_set_walker(Node *node, void *context);
 static bool contain_subplans_walker(Node *node, void *context);
 static bool pull_subplans_walker(Node *node, List **listptr);
 static bool check_subplans_for_ungrouped_vars_walker(Node *node,
@@ -74,7 +74,7 @@ make_clause(int type, Node *oper, List *args)
                        expr->typeOid = ((Oper *) oper)->opresulttype;
                        break;
                case FUNC_EXPR:
-                       expr->typeOid = ((Func *) oper)->functype;
+                       expr->typeOid = ((Func *) oper)->funcresulttype;
                        break;
                default:
                        elog(ERROR, "make_clause: unsupported type %d", type);
@@ -195,7 +195,7 @@ make_funcclause(Func *func, List *funcargs)
 {
        Expr       *expr = makeNode(Expr);
 
-       expr->typeOid = func->functype;
+       expr->typeOid = func->funcresulttype;
        expr->opType = FUNC_EXPR;
        expr->oper = (Node *) func;
        expr->args = funcargs;
@@ -453,36 +453,61 @@ pull_agg_clause_walker(Node *node, List **listptr)
 
 
 /*****************************************************************************
- *             Iter clause manipulation
+ *             Support for expressions returning sets
  *****************************************************************************/
 
 /*
- * contain_iter_clause
- *       Recursively search for Iter nodes within a clause.
+ * expression_returns_set
+ *       Test whethe an expression returns a set result.
  *
- *       Returns true if any Iter found.
- *
- * XXX Iter is a crock.  It'd be better to look directly at each function
- * or operator to see if it can return a set.  However, that would require
- * a lot of extra cycles as things presently stand.  The return-type info
- * for function and operator nodes should be extended to include whether
- * the return is a set.
+ * Because we use expression_tree_walker(), this can also be applied to
+ * whole targetlists; it'll produce TRUE if any one of the tlist items
+ * returns a set.
  */
 bool
-contain_iter_clause(Node *clause)
+expression_returns_set(Node *clause)
 {
-       return contain_iter_clause_walker(clause, NULL);
+       return expression_returns_set_walker(clause, NULL);
 }
 
 static bool
-contain_iter_clause_walker(Node *node, void *context)
+expression_returns_set_walker(Node *node, void *context)
 {
        if (node == NULL)
                return false;
-       if (IsA(node, Iter))
-               return true;                    /* abort the tree traversal and return
-                                                                * true */
-       return expression_tree_walker(node, contain_iter_clause_walker, context);
+       if (IsA(node, Expr))
+       {
+               Expr   *expr = (Expr *) node;
+
+               switch (expr->opType)
+               {
+                       case OP_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;
+               }
+       }
+       /* Avoid recursion for some other cases that can't return a set */
+       if (IsA(node, Aggref))
+               return false;
+       if (IsA(node, SubLink))
+               return false;
+       return expression_tree_walker(node, expression_returns_set_walker,
+                                                                 context);
 }
 
 /*****************************************************************************
@@ -1043,7 +1068,8 @@ CommuteClause(Expr *clause)
 
        commu = makeOper(optup->t_data->t_oid,
                                         commuTup->oprcode,
-                                        commuTup->oprresult);
+                                        commuTup->oprresult,
+                                        ((Oper *) clause->oper)->opretset);
 
        ReleaseSysCache(optup);
 
@@ -1073,8 +1099,7 @@ CommuteClause(Expr *clause)
  * results even with constant inputs, "nextval()" being the classic
  * example.  Functions that are not marked "immutable" in pg_proc
  * will not be pre-evaluated here, although we will reduce their
- * arguments as far as possible.  Functions that are the arguments
- * of Iter nodes are also not evaluated.
+ * arguments as far as possible.
  *
  * We assume that the tree has already been type-checked and contains
  * only operators and functions that are reasonable to try to execute.
@@ -1398,37 +1423,6 @@ eval_const_expressions_mutator(Node *node, void *context)
                newcase->defresult = defresult;
                return (Node *) newcase;
        }
-       if (IsA(node, Iter))
-       {
-               /*
-                * The argument of an Iter is normally a function call. We must
-                * not try to eliminate the function, but we can try to simplify
-                * its arguments.  If, by chance, the arg is NOT a function then
-                * we go ahead and try to simplify it (by falling into
-                * expression_tree_mutator). Is that the right thing?
-                */
-               Iter       *iter = (Iter *) node;
-
-               if (is_funcclause(iter->iterexpr))
-               {
-                       Expr       *func = (Expr *) iter->iterexpr;
-                       Expr       *newfunc;
-                       Iter       *newiter;
-
-                       newfunc = makeNode(Expr);
-                       newfunc->typeOid = func->typeOid;
-                       newfunc->opType = func->opType;
-                       newfunc->oper = func->oper;
-                       newfunc->args = (List *)
-                               expression_tree_mutator((Node *) func->args,
-                                                                               eval_const_expressions_mutator,
-                                                                               (void *) context);
-                       newiter = makeNode(Iter);
-                       newiter->iterexpr = (Node *) newfunc;
-                       newiter->itertype = iter->itertype;
-                       return (Node *) newiter;
-               }
-       }
 
        /*
         * For any node type not handled above, we recurse using
@@ -1501,8 +1495,9 @@ simplify_op_or_func(Expr *expr, List *args)
         * Get the function procedure's OID and look to see whether it is
         * marked immutable.
         *
-        * XXX would it be better to take the result type from the pg_proc tuple,
-        * rather than the Oper or Func node?
+        * Note we take the result type from the Oper or Func node, not the
+        * pg_proc tuple; probably necessary for binary-compatibility cases.
+        *
         */
        if (expr->opType == OP_EXPR)
        {
@@ -1517,7 +1512,7 @@ simplify_op_or_func(Expr *expr, List *args)
                Func       *func = (Func *) expr->oper;
 
                funcid = func->funcid;
-               result_typeid = func->functype;
+               result_typeid = func->funcresulttype;
        }
 
        /*
@@ -1747,8 +1742,6 @@ expression_tree_walker(Node *node,
                        break;
                case T_Aggref:
                        return walker(((Aggref *) node)->target, context);
-               case T_Iter:
-                       return walker(((Iter *) node)->iterexpr, context);
                case T_ArrayRef:
                        {
                                ArrayRef   *aref = (ArrayRef *) node;
@@ -2083,16 +2076,6 @@ expression_tree_mutator(Node *node,
                                return (Node *) newnode;
                        }
                        break;
-               case T_Iter:
-                       {
-                               Iter       *iter = (Iter *) node;
-                               Iter       *newnode;
-
-                               FLATCOPY(newnode, iter, Iter);
-                               MUTATE(newnode->iterexpr, iter->iterexpr, Node *);
-                               return (Node *) newnode;
-                       }
-                       break;
                case T_ArrayRef:
                        {
                                ArrayRef   *arrayref = (ArrayRef *) node;
index 19aa688ff949d9609eba31e8eab968678e34b5c3..a41182e9398636e9db4dd3d13cb8ac9929e35e0a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.91 2002/05/12 20:10:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.92 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -285,14 +285,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
         */
        result = transformExpr(pstate, result);
 
-       /*
-        * We expect the result to yield bool directly, otherwise complain. We
-        * could try coerce_to_boolean() here, but it seems likely that an "="
-        * operator that doesn't return bool is wrong anyway.
-        */
-       if (exprType(result) != BOOLOID)
-               elog(ERROR, "JOIN/USING clause must return type boolean, not type %s",
-                        format_type_be(exprType(result)));
+       result = coerce_to_boolean(result, "JOIN/USING");
 
        return result;
 }      /* transformJoinUsingClause() */
@@ -326,9 +319,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
        /* This part is just like transformWhereClause() */
        result = transformExpr(pstate, j->quals);
 
-       if (!coerce_to_boolean(pstate, &result))
-               elog(ERROR, "JOIN/ON clause must return type boolean, not type %s",
-                        format_type_be(exprType(result)));
+       result = coerce_to_boolean(result, "JOIN/ON");
 
        pstate->p_namespace = save_namespace;
 
@@ -486,14 +477,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
                elog(ERROR, "cannot use subselect in FROM function expression");
 
        /*
-        * Remove any Iter nodes added by parse_func.c.  We oughta get rid of
-        * Iter completely ...
-        */
-       while (funcexpr && IsA(funcexpr, Iter))
-               funcexpr = ((Iter *) funcexpr)->iterexpr;
-
-       /*
-        * Insist we now have a bare function call (explain.c is the only place
+        * 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.
         */
@@ -947,9 +931,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
 
        qual = transformExpr(pstate, clause);
 
-       if (!coerce_to_boolean(pstate, &qual))
-               elog(ERROR, "WHERE clause must return type boolean, not type %s",
-                        format_type_be(exprType(qual)));
+       qual = coerce_to_boolean(qual, "WHERE");
 
        return qual;
 }
index 57aad4dbf5845a5be64997db2447ca990f5da907..716cbcbb756496e3d6d25417f8ca6c12e2625cfc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.71 2002/04/25 02:56:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.72 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -313,26 +313,37 @@ coerce_type_typmod(ParseState *pstate, Node *node,
 
 /* coerce_to_boolean()
  *             Coerce an argument of a construct that requires boolean input
- *             (AND, OR, NOT, etc).
+ *             (AND, OR, NOT, etc).  Also check that input is not a set.
  *
- * If successful, update *pnode to be the transformed argument (if any
- * transformation is needed), and return TRUE. If fail, return FALSE.
- * (The caller must check for FALSE and emit a suitable error message.)
+ * Returns the possibly-transformed node tree.
  */
-bool
-coerce_to_boolean(ParseState *pstate, Node **pnode)
+Node *
+coerce_to_boolean(Node *node, const char *constructName)
 {
-       Oid                     inputTypeId = exprType(*pnode);
+       Oid                     inputTypeId = exprType(node);
        Oid                     targetTypeId;
 
-       if (inputTypeId == BOOLOID)
-               return true;                    /* no work */
-       targetTypeId = BOOLOID;
-       if (!can_coerce_type(1, &inputTypeId, &targetTypeId, false))
-               return false;                   /* fail, but let caller choose error msg */
-       *pnode = coerce_type(pstate, *pnode, inputTypeId, targetTypeId, -1,
-                                                false);
-       return true;
+       if (inputTypeId != BOOLOID)
+       {
+               targetTypeId = BOOLOID;
+               if (!can_coerce_type(1, &inputTypeId, &targetTypeId, false))
+               {
+                       /* translator: first %s is name of a SQL construct, eg WHERE */
+                       elog(ERROR, "Argument of %s must be type boolean, not type %s",
+                                constructName, format_type_be(inputTypeId));
+               }
+               node = coerce_type(NULL, node, inputTypeId, targetTypeId, -1,
+                                                  false);
+       }
+
+       if (expression_returns_set(node))
+       {
+               /* translator: %s is name of a SQL construct, eg WHERE */
+               elog(ERROR, "Argument of %s must not be a set function",
+                        constructName);
+       }
+
+       return node;
 }
 
 
@@ -782,7 +793,8 @@ build_func_call(Oid funcid, Oid rettype, List *args)
 
        funcnode = makeNode(Func);
        funcnode->funcid = funcid;
-       funcnode->functype = rettype;
+       funcnode->funcresulttype = rettype;
+       funcnode->funcretset = false; /* only possible case here */
        funcnode->func_fcache = NULL;
 
        expr = makeNode(Expr);
index 100bf9a7b49e92cb42d1851235791ff4eac0a8f1..e29d5ca4b5c5e7c1b940a8cd114d8b5a0808f377 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.116 2002/04/28 00:49:12 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.117 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,6 +31,7 @@
 #include "parser/parse_target.h"
 #include "parser/parse_type.h"
 #include "utils/builtins.h"
+#include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
 
@@ -230,15 +231,8 @@ transformExpr(ParseState *pstate, Node *expr)
                                                                                                                          a->rexpr);
                                                        Expr       *expr = makeNode(Expr);
 
-                                                       if (!coerce_to_boolean(pstate, &lexpr))
-                                                               elog(ERROR, "left-hand side of AND is type '%s', not '%s'",
-                                                                        format_type_be(exprType(lexpr)),
-                                                                        format_type_be(BOOLOID));
-
-                                                       if (!coerce_to_boolean(pstate, &rexpr))
-                                                               elog(ERROR, "right-hand side of AND is type '%s', not '%s'",
-                                                                        format_type_be(exprType(rexpr)),
-                                                                        format_type_be(BOOLOID));
+                                                       lexpr = coerce_to_boolean(lexpr, "AND");
+                                                       rexpr = coerce_to_boolean(rexpr, "AND");
 
                                                        expr->typeOid = BOOLOID;
                                                        expr->opType = AND_EXPR;
@@ -254,15 +248,8 @@ transformExpr(ParseState *pstate, Node *expr)
                                                                                                                          a->rexpr);
                                                        Expr       *expr = makeNode(Expr);
 
-                                                       if (!coerce_to_boolean(pstate, &lexpr))
-                                                               elog(ERROR, "left-hand side of OR is type '%s', not '%s'",
-                                                                        format_type_be(exprType(lexpr)),
-                                                                        format_type_be(BOOLOID));
-
-                                                       if (!coerce_to_boolean(pstate, &rexpr))
-                                                               elog(ERROR, "right-hand side of OR is type '%s', not '%s'",
-                                                                        format_type_be(exprType(rexpr)),
-                                                                        format_type_be(BOOLOID));
+                                                       lexpr = coerce_to_boolean(lexpr, "OR");
+                                                       rexpr = coerce_to_boolean(rexpr, "OR");
 
                                                        expr->typeOid = BOOLOID;
                                                        expr->opType = OR_EXPR;
@@ -276,10 +263,7 @@ transformExpr(ParseState *pstate, Node *expr)
                                                                                                                          a->rexpr);
                                                        Expr       *expr = makeNode(Expr);
 
-                                                       if (!coerce_to_boolean(pstate, &rexpr))
-                                                               elog(ERROR, "argument to NOT is type '%s', not '%s'",
-                                                                        format_type_be(exprType(rexpr)),
-                                                                        format_type_be(BOOLOID));
+                                                       rexpr = coerce_to_boolean(rexpr, "NOT");
 
                                                        expr->typeOid = BOOLOID;
                                                        expr->opType = NOT_EXPR;
@@ -426,9 +410,15 @@ transformExpr(ParseState *pstate, Node *expr)
                                                                 opname, typeidTypeName(opform->oprresult),
                                                                 typeidTypeName(BOOLOID));
 
+                                               if (get_func_retset(opform->oprcode))
+                                                       elog(ERROR, "'%s' must not return a set"
+                                                                " to be used with quantified predicate subquery",
+                                                                opname);
+
                                                newop = makeOper(oprid(optup),  /* opno */
                                                                                 InvalidOid,    /* opid */
-                                                                                opform->oprresult);
+                                                                                opform->oprresult,
+                                                                                false);
                                                sublink->oper = lappend(sublink->oper, newop);
                                                ReleaseSysCache(optup);
                                        }
@@ -467,8 +457,7 @@ transformExpr(ParseState *pstate, Node *expr)
                                        }
                                        neww->expr = transformExpr(pstate, warg);
 
-                                       if (!coerce_to_boolean(pstate, &neww->expr))
-                                               elog(ERROR, "WHEN clause must have a boolean result");
+                                       neww->expr = coerce_to_boolean(neww->expr, "CASE/WHEN");
 
                                        /*
                                         * result is NULL for NULLIF() construct - thomas
@@ -553,42 +542,38 @@ transformExpr(ParseState *pstate, Node *expr)
                case T_BooleanTest:
                        {
                                BooleanTest *b = (BooleanTest *) expr;
+                               const char *clausename;
 
-                               b->arg = transformExpr(pstate, b->arg);
-
-                               if (!coerce_to_boolean(pstate, &b->arg))
+                               switch (b->booltesttype)
                                {
-                                       const char *clausename;
+                                       case IS_TRUE:
+                                               clausename = "IS TRUE";
+                                               break;
+                                       case IS_NOT_TRUE:
+                                               clausename = "IS NOT TRUE";
+                                               break;
+                                       case IS_FALSE:
+                                               clausename = "IS FALSE";
+                                               break;
+                                       case IS_NOT_FALSE:
+                                               clausename = "IS NOT FALSE";
+                                               break;
+                                       case IS_UNKNOWN:
+                                               clausename = "IS UNKNOWN";
+                                               break;
+                                       case IS_NOT_UNKNOWN:
+                                               clausename = "IS NOT UNKNOWN";
+                                               break;
+                                       default:
+                                               elog(ERROR, "transformExpr: unexpected booltesttype %d",
+                                                        (int) b->booltesttype);
+                                               clausename = NULL;      /* keep compiler quiet */
+                               }
 
-                                       switch (b->booltesttype)
-                                       {
-                                               case IS_TRUE:
-                                                       clausename = "IS TRUE";
-                                                       break;
-                                               case IS_NOT_TRUE:
-                                                       clausename = "IS NOT TRUE";
-                                                       break;
-                                               case IS_FALSE:
-                                                       clausename = "IS FALSE";
-                                                       break;
-                                               case IS_NOT_FALSE:
-                                                       clausename = "IS NOT FALSE";
-                                                       break;
-                                               case IS_UNKNOWN:
-                                                       clausename = "IS UNKNOWN";
-                                                       break;
-                                               case IS_NOT_UNKNOWN:
-                                                       clausename = "IS NOT UNKNOWN";
-                                                       break;
-                                               default:
-                                                       elog(ERROR, "transformExpr: unexpected booltesttype %d",
-                                                                (int) b->booltesttype);
-                                                       clausename = NULL;      /* keep compiler quiet */
-                                       }
+                               b->arg = transformExpr(pstate, b->arg);
+
+                               b->arg = coerce_to_boolean(b->arg, clausename);
 
-                                       elog(ERROR, "Argument of %s must be boolean",
-                                                clausename);
-                               }
                                result = expr;
                                break;
                        }
@@ -833,12 +818,6 @@ exprType(Node *expr)
 
        switch (nodeTag(expr))
        {
-               case T_Func:
-                       type = ((Func *) expr)->functype;
-                       break;
-               case T_Iter:
-                       type = ((Iter *) expr)->itertype;
-                       break;
                case T_Var:
                        type = ((Var *) expr)->vartype;
                        break;
index 339577f39ca09273c2e633a83d8538bae6952972..1912ab4e0724578c98e3d19312b72cdccc852ba8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.128 2002/05/12 20:10:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.129 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -280,7 +280,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
                Func       *funcnode = makeNode(Func);
 
                funcnode->funcid = funcid;
-               funcnode->functype = rettype;
+               funcnode->funcresulttype = rettype;
+               funcnode->funcretset = retset;
                funcnode->func_fcache = NULL;
 
                expr->typeOid = rettype;
@@ -289,21 +290,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
                expr->args = fargs;
 
                retval = (Node *) expr;
-
-               /*
-                * if the function returns a set of values, then we need to iterate
-                * over all the returned values in the executor, so we stick an iter
-                * node here.  if it returns a singleton, then we don't need the iter
-                * node.
-                */
-               if (retset)
-               {
-                       Iter       *iter = makeNode(Iter);
-
-                       iter->itertype = rettype;
-                       iter->iterexpr = retval;
-                       retval = (Node *) iter;
-               }
        }
        else
        {
@@ -1186,26 +1172,6 @@ ParseComplexProjection(ParseState *pstate,
         */
        switch (nodeTag(first_arg))
        {
-               case T_Iter:
-                       {
-                               Iter       *iter = (Iter *) first_arg;
-
-                               /*
-                                * If it's an Iter, we stick the FieldSelect
-                                * *inside* the Iter --- this is klugy, but necessary
-                                * because ExecTargetList() currently does the right thing
-                                * only when the Iter node is at the top level of a
-                                * targetlist item.
-                                *
-                                * XXX Iter should go away altogether...
-                                */
-                               fselect = setup_field_select(iter->iterexpr,
-                                                                                        funcname, argrelid);
-                               iter->iterexpr = (Node *) fselect;
-                               iter->itertype = fselect->resulttype;
-                               return (Node *) iter;
-                               break;
-                       }
                case T_Var:
                        {
                                Var                *var = (Var *) first_arg;
index 2c4467035a5c3b4ff234f518c136caed8dce2cc8..e4b0766c63f556258a52cd7cdd9fbea37bbaa33a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.64 2002/05/01 19:26:07 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.65 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -135,7 +135,8 @@ make_op(List *opname, Node *ltree, Node *rtree)
 
        newop = makeOper(oprid(tup),    /* opno */
                                         InvalidOid,    /* opid */
-                                        opform->oprresult);            /* operator result type */
+                                        opform->oprresult,     /* opresulttype */
+                                        get_func_retset(opform->oprcode));     /* opretset */
 
        result = makeNode(Expr);
        result->typeOid = opform->oprresult;
index b4bd3b2f5145f7ec6f0fafbd023a49154f3b80b4..78cb6306e02993fade598c792c64ca73a1da2e08 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.103 2002/05/12 20:10:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.104 2002/05/12 23:43:03 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1673,10 +1673,6 @@ get_rule_expr(Node *node, deparse_context *context)
                        get_agg_expr((Aggref *) node, context);
                        break;
 
-               case T_Iter:
-                       get_rule_expr(((Iter *) node)->iterexpr, context);
-                       break;
-
                case T_ArrayRef:
                        {
                                ArrayRef   *aref = (ArrayRef *) node;
index ca3bd80e8a7e58366a5ab4a0e4c1295984ebd73e..e695f533b02f450b62e6a2cc2b406ebe7bf9aa08 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.72 2002/04/30 01:26:26 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.73 2002/05/12 23:43:03 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -612,6 +612,27 @@ get_func_rettype(Oid funcid)
        return result;
 }
 
+/*
+ * get_func_retset
+ *             Given procedure id, return the function's proretset flag.
+ */
+bool
+get_func_retset(Oid funcid)
+{
+       HeapTuple       tp;
+       bool            result;
+
+       tp = SearchSysCache(PROCOID,
+                                               ObjectIdGetDatum(funcid),
+                                               0, 0, 0);
+       if (!HeapTupleIsValid(tp))
+               elog(ERROR, "Function OID %u does not exist", funcid);
+
+       result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
+       ReleaseSysCache(tp);
+       return result;
+}
+
 /*
  * func_volatile
  *             Given procedure id, return the function's provolatile flag.
index 3120fb5fae0c34e7bffad96579db4e5d239ba64b..ca61cb51a76f773eb4c9c1d6db25f9b38e828987 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.130 2002/05/12 20:10:04 tgl Exp $
+ * $Id: catversion.h,v 1.131 2002/05/12 23:43:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200205121
+#define CATALOG_VERSION_NO     200205122
 
 #endif
diff --git a/src/include/executor/execFlatten.h b/src/include/executor/execFlatten.h
deleted file mode 100644 (file)
index 1795ed1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * execFlatten.h
- *       prototypes for execFlatten.c.
- *
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $Id: execFlatten.h,v 1.16 2001/11/05 17:46:33 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef EXECFLATTEN_H
-#define EXECFLATTEN_H
-
-#include "nodes/execnodes.h"
-#include "nodes/parsenodes.h"
-
-
-extern Datum ExecEvalIter(Iter *iterNode, ExprContext *econtext,
-                        bool *isNull, ExprDoneCond *isDone);
-
-extern void ExecEvalFjoin(TargetEntry *tlist, ExprContext *econtext,
-                         bool *isNullVect, ExprDoneCond *fj_isDone);
-
-#endif   /* EXECFLATTEN_H */
index 4096c2d9fb3fad5b775924dcf54d3259af17d734..e3b6a164377d9beea7a315d81b4f043a0e0a282f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: makefuncs.h,v 1.35 2002/04/16 23:08:12 tgl Exp $
+ * $Id: makefuncs.h,v 1.36 2002/05/12 23:43:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,8 +22,9 @@ extern A_Expr *makeSimpleA_Expr(int oper, const char *name,
                                                                Node *lexpr, Node *rexpr);
 
 extern Oper *makeOper(Oid opno,
-                Oid opid,
-                Oid opresulttype);
+                                         Oid opid,
+                                         Oid opresulttype,
+                                         bool opretset);
 
 extern Var *makeVar(Index varno,
                AttrNumber varattno,
index 492619e194d06bdfdaff02237d43b1602d2b2ad2..7de647d1362bcf2bb0dddc55c28ad4dfbdd4b72c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.106 2002/05/12 20:10:04 tgl Exp $
+ * $Id: nodes.h,v 1.107 2002/05/12 23:43:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,7 +66,6 @@ typedef enum NodeTag
        T_Func,
        T_FieldSelect,
        T_ArrayRef,
-       T_Iter,
        T_RelabelType,
        T_RangeTblRef,
        T_FromExpr,
index 6eed89a70424e409dd4e1f605c874c07e947ffd4..342ac11bb5bd13f369a52c7c3b5f3c17910d4c5c 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.62 2002/05/12 20:10:05 tgl Exp $
+ * $Id: primnodes.h,v 1.63 2002/05/12 23:43:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -151,12 +151,51 @@ typedef struct Expr
 {
        NodeTag         type;
        Oid                     typeOid;                /* oid of the type of this expression */
-       OpType          opType;                 /* 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
+ *
+ * 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 */
+       FunctionCachePtr func_fcache; /* runtime state, or NULL */
+} Func;
+
 /*
  * Var
  *
@@ -196,37 +235,6 @@ typedef struct Var
        AttrNumber      varoattno;              /* original value of varattno */
 } Var;
 
-/*--------------------
- * Oper
- *
- * 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 for the operator's
-                                                                * underlying function */
-       Oid                     opresulttype;
-       /* PG_TYPE OID of the operator's return value */
-       FunctionCachePtr op_fcache;
-       /* runtime state while running the function */
-} Oper;
-
-
 /*
  * Const
  */
@@ -283,39 +291,6 @@ typedef struct Param
        Oid                     paramtype;              /* PG_TYPE OID of the parameter's value */
 } Param;
 
-
-/*
- * Func
- */
-typedef struct Func
-{
-       NodeTag         type;
-       Oid                     funcid;                 /* PG_PROC OID of the function */
-       Oid                     functype;               /* PG_TYPE OID of the function's return
-                                                                * value */
-       FunctionCachePtr func_fcache;
-
-       /*
-        * runtime state while running this function. Where we are in the
-        * execution of the function if it returns more than one value, etc.
-        * See utils/fcache.h
-        */
-} Func;
-
-/* ----------------
- * Iter
- *             can anyone explain what this is for?  Seems to have something to do
- *             with evaluation of functions that return sets...
- * ----------------
- */
-typedef struct Iter
-{
-       NodeTag         type;
-       Node       *iterexpr;
-       Oid                     itertype;               /* type of the iter expr (use for type
-                                                                * checking) */
-} Iter;
-
 /*
  * Aggref
  */
index 69596c1779a843022e42173cabb830f0dc9abd76..376e8cc77aa69a882f3f1c91e47ae7e26a4573d0 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: clauses.h,v 1.51 2002/04/05 00:31:35 tgl Exp $
+ * $Id: clauses.h,v 1.52 2002/05/12 23:43:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,7 +42,7 @@ extern List *make_ands_implicit(Expr *clause);
 extern bool contain_agg_clause(Node *clause);
 extern List *pull_agg_clause(Node *clause);
 
-extern bool contain_iter_clause(Node *clause);
+extern bool expression_returns_set(Node *clause);
 
 extern bool contain_subplans(Node *clause);
 extern List *pull_subplans(Node *clause);
index 47ce9b61c1619ff34b5dbf6b34edbf7f9ec21ef0..a7eb56a50929b901d7c3d8d8497ee3e3eaf463d4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_coerce.h,v 1.42 2002/04/11 20:00:15 tgl Exp $
+ * $Id: parse_coerce.h,v 1.43 2002/05/12 23:43:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,7 +45,7 @@ extern Node *coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 extern Node *coerce_type_typmod(ParseState *pstate, Node *node,
                                   Oid targetTypeId, int32 atttypmod);
 
-extern bool coerce_to_boolean(ParseState *pstate, Node **pnode);
+extern Node *coerce_to_boolean(Node *node, const char *constructName);
 
 extern Oid     select_common_type(List *typeids, const char *context);
 extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
index 9f8122567375f22ecfebc5e2b2ab94c957ab81c6..eaff98448d32510adaad645d9f7d8c5abf7a0c2b 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.51 2002/04/30 01:26:26 tgl Exp $
+ * $Id: lsyscache.h,v 1.52 2002/05/12 23:43:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,7 @@ extern RegProcedure get_oprrest(Oid opno);
 extern RegProcedure get_oprjoin(Oid opno);
 extern char *get_func_name(Oid funcid);
 extern Oid     get_func_rettype(Oid funcid);
+extern bool    get_func_retset(Oid funcid);
 extern char func_volatile(Oid funcid);
 extern Oid     get_relname_relid(const char *relname, Oid relnamespace);
 extern char *get_rel_name(Oid relid);