Remove 'func_tlist' from Func expression nodes, likewise 'param_tlist'
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 8 Aug 2000 15:43:12 +0000 (15:43 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 8 Aug 2000 15:43:12 +0000 (15:43 +0000)
from Param nodes, per discussion a few days ago on pghackers.  Add new
expression node type FieldSelect that implements the functionality where
it's actually needed.  Clean up some other unused fields in Func nodes
as well.
NOTE: initdb forced due to change in stored expression trees for rules.

31 files changed:
src/backend/executor/execQual.c
src/backend/executor/functions.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/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/prep/preptlist.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/tlist.c
src/backend/parser/analyze.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_func.c
src/backend/parser/parse_node.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/rewrite/rewriteHandler.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/fcache.c
src/include/catalog/catversion.h
src/include/executor/functions.h
src/include/nodes/makefuncs.h
src/include/nodes/nodes.h
src/include/nodes/primnodes.h
src/include/parser/parse_func.h
src/include/utils/fcache.h

index a445a57d9cf6e6ecbb70e2940b046ad076314ce1..6e934a177251004bb706c2d08419c330a5b8e8bb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.76 2000/07/23 01:35:58 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.77 2000/08/08 15:41:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -294,8 +294,6 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
    AttrNumber  attnum;
    HeapTuple   heapTuple;
    TupleDesc   tuple_type;
-   bool        byval;
-   int16       len;
 
    /*
     * get the slot we want
@@ -363,36 +361,6 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
                          tuple_type,   /* tuple descriptor of tuple */
                          isNull);      /* return: is attribute null? */
 
-   /*
-    * return null if att is null
-    */
-   if (*isNull)
-       return (Datum) 0;
-
-   /*
-    * get length and type information.. ??? what should we do about
-    * variable length attributes - variable length attributes have their
-    * length stored in the first 4 bytes of the memory pointed to by the
-    * returned value.. If we can determine that the type is a variable
-    * length type, we can do the right thing. -cim 9/15/89
-    */
-   if (attnum < 0)
-   {
-
-       /*
-        * If this is a pseudo-att, we get the type and fake the length.
-        * There ought to be a routine to return the real lengths, so
-        * we'll mark this one ... XXX -mao
-        */
-       len = heap_sysattrlen(attnum);  /* XXX see -mao above */
-       byval = heap_sysattrbyval(attnum);      /* XXX see -mao above */
-   }
-   else
-   {
-       len = tuple_type->attrs[attnum - 1]->attlen;
-       byval = tuple_type->attrs[attnum - 1]->attbyval ? true : false;
-   }
-
    return result;
 }
 
@@ -519,25 +487,7 @@ ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
    /*
     * return the value.
     */
-   if (paramList->isnull)
-   {
-       *isNull = true;
-       return (Datum) 0;
-   }
-
-   if (expression->param_tlist != NIL)
-   {
-       HeapTuple   tup;
-       Datum       value;
-       List       *tlist = expression->param_tlist;
-       TargetEntry *tle = (TargetEntry *) lfirst(tlist);
-       TupleTableSlot *slot = (TupleTableSlot *) paramList->value;
-
-       tup = slot->val;
-       value = ProjectAttribute(slot->ttc_tupleDescriptor,
-                                tle, tup, isNull);
-       return value;
-   }
+   *isNull = paramList->isnull;
    return paramList->value;
 }
 
@@ -686,7 +636,6 @@ ExecMakeFunctionResult(Node *node,
 {
    FunctionCallInfoData    fcinfo;
    FunctionCachePtr        fcache;
-   List                   *ftlist;
    bool                    funcisset;
    Datum                   result;
    bool                    argDone;
@@ -702,13 +651,11 @@ ExecMakeFunctionResult(Node *node,
    if (IsA(node, Func))
    {
        fcache = ((Func *) node)->func_fcache;
-       ftlist = ((Func *) node)->func_tlist;
        funcisset = (((Func *) node)->funcid == F_SETEVAL);
    }
    else
    {
        fcache = ((Oper *) node)->op_fcache;
-       ftlist = NIL;
        funcisset = false;
    }
 
@@ -822,7 +769,7 @@ ExecMakeFunctionResult(Node *node,
 
            if (callit)
            {
-               result = postquel_function(&fcinfo, fcache, ftlist, isDone);
+               result = postquel_function(&fcinfo, fcache, isDone);
                *isNull = fcinfo.isnull;
            }
            else
@@ -1214,6 +1161,34 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
    return (Datum) 0;
 }
 
+/* ----------------------------------------------------------------
+ *     ExecEvalFieldSelect
+ *
+ *     Evaluate a FieldSelect node.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalFieldSelect(FieldSelect *fselect,
+                   ExprContext *econtext,
+                   bool *isNull,
+                   bool *isDone)
+{
+   Datum           result;
+   TupleTableSlot *resSlot;
+
+   result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
+   if (*isNull)
+       return result;
+   /* XXX what about isDone? */
+   resSlot = (TupleTableSlot *) DatumGetPointer(result);
+   Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
+   result = heap_getattr(resSlot->val,
+                         fselect->fieldnum,
+                         resSlot->ttc_tupleDescriptor,
+                         isNull);
+   return result;
+}
+
 /* ----------------------------------------------------------------
  *     ExecEvalExpr
  *
@@ -1319,6 +1294,12 @@ ExecEvalExpr(Node *expression,
                }
                break;
            }
+       case T_FieldSelect:
+           retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
+                                          econtext,
+                                          isNull,
+                                          isDone);
+           break;
        case T_RelabelType:
            retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
                                    econtext,
index a92811d0342a0409d6f6c2c6a409c09ec53e29d9..001feb267ffe02e0b65f14228ae3f8dc902f0430 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.36 2000/07/12 02:37:03 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.37 2000/08/08 15:41:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,24 +47,21 @@ static void postquel_end(execution_state *es);
 static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo);
 static Datum postquel_execute(execution_state *es,
                              FunctionCallInfo fcinfo,
-                             FunctionCachePtr fcache,
-                             List *func_tlist);
+                             FunctionCachePtr fcache);
 
 
-Datum
-ProjectAttribute(TupleDesc TD,
-                TargetEntry *tlist,
-                HeapTuple tup,
+static Datum
+ProjectAttribute(HeapTuple tup,
+                AttrNumber attrno,
+                TupleDesc TD,
                 bool *isnullP)
 {
    Datum       val;
-   Var        *attrVar = (Var *) tlist->expr;
-   AttrNumber  attrno = attrVar->varattno;
 
    val = heap_getattr(tup, attrno, TD, isnullP);
 
    if (*isnullP)
-       return (Datum) 0;
+       return val;
 
    return datumCopy(val,
                     TD->attrs[attrno - 1]->attbyval,
@@ -216,39 +213,29 @@ copy_function_result(FunctionCachePtr fcache,
 {
    TupleTableSlot *funcSlot;
    TupleDesc   resultTd;
+   HeapTuple   resultTuple;
    HeapTuple   newTuple;
-   HeapTuple   oldTuple;
 
    Assert(!TupIsNull(resultSlot));
-   oldTuple = resultSlot->val;
+   resultTuple = resultSlot->val;
 
    funcSlot = (TupleTableSlot *) fcache->funcSlot;
 
    if (funcSlot == (TupleTableSlot *) NULL)
        return resultSlot;
 
-   resultTd = resultSlot->ttc_tupleDescriptor;
-
    /*
-    * When the funcSlot is NULL we have to initialize the funcSlot's
+    * If first time through, we have to initialize the funcSlot's
     * tuple descriptor.
     */
    if (TupIsNull(funcSlot))
    {
-       int         i = 0;
-       TupleDesc   funcTd = funcSlot->ttc_tupleDescriptor;
-
-       while (i < oldTuple->t_data->t_natts)
-       {
-           funcTd->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
-           memmove(funcTd->attrs[i],
-                   resultTd->attrs[i],
-                   ATTRIBUTE_TUPLE_SIZE);
-           i++;
-       }
+       resultTd = resultSlot->ttc_tupleDescriptor;
+       funcSlot->ttc_tupleDescriptor = CreateTupleDescCopy(resultTd);
+       funcSlot->ttc_descIsNew = true;
    }
 
-   newTuple = heap_copytuple(oldTuple);
+   newTuple = heap_copytuple(resultTuple);
 
    return ExecStoreTuple(newTuple, funcSlot, InvalidBuffer, true);
 }
@@ -256,8 +243,7 @@ copy_function_result(FunctionCachePtr fcache,
 static Datum
 postquel_execute(execution_state *es,
                 FunctionCallInfo fcinfo,
-                FunctionCachePtr fcache,
-                List *func_tlist)
+                FunctionCachePtr fcache)
 {
    TupleTableSlot *slot;
    Datum       value;
@@ -305,27 +291,35 @@ postquel_execute(execution_state *es,
         * logic and code redundancy here.
         */
        resSlot = copy_function_result(fcache, slot);
-       if (func_tlist != NIL)
-       {
-           TargetEntry *tle = lfirst(func_tlist);
 
-           value = ProjectAttribute(resSlot->ttc_tupleDescriptor,
-                                    tle,
-                                    resSlot->val,
-                                    &fcinfo->isnull);
-       }
-       else
+       /*
+        * If we are supposed to return a tuple, we return the tuple slot
+        * pointer converted to Datum.  If we are supposed to return a simple
+        * value, then project out the first attribute of the result tuple
+        * (ie, take the first result column of the final SELECT).
+        */
+       if (fcache->returnsTuple)
        {
-           /* XXX is this right?  Return whole tuple slot?? */
+           /*
+            * XXX do we need to remove junk attrs from the result tuple?
+            * Probably OK to leave them, as long as they are at the end.
+            */
            value = PointerGetDatum(resSlot);
            fcinfo->isnull = false;
        }
+       else
+       {
+           value = ProjectAttribute(resSlot->val,
+                                    1,
+                                    resSlot->ttc_tupleDescriptor,
+                                    &fcinfo->isnull);
+       }
 
        /*
         * If this is a single valued function we have to end the function
         * execution now.
         */
-       if (fcache->oneResult)
+       if (!fcache->returnsSet)
        {
            postquel_end(es);
            es->status = F_EXEC_DONE;
@@ -346,7 +340,6 @@ postquel_execute(execution_state *es,
 Datum
 postquel_function(FunctionCallInfo fcinfo,
                  FunctionCachePtr fcache,
-                 List *func_tlist,
                  bool *isDone)
 {
    MemoryContext oldcontext;
@@ -388,10 +381,7 @@ postquel_function(FunctionCallInfo fcinfo,
     */
    while (es != (execution_state *) NULL)
    {
-       result = postquel_execute(es,
-                                 fcinfo,
-                                 fcache,
-                                 func_tlist);
+       result = postquel_execute(es, fcinfo, fcache);
        if (es->status != F_EXEC_DONE)
            break;
        es = es->next;
@@ -423,7 +413,7 @@ postquel_function(FunctionCallInfo fcinfo,
         */
        *isDone = true;
        MemoryContextSwitchTo(oldcontext);
-       return (fcache->oneResult) ? result : (Datum) NULL;
+       return (fcache->returnsSet) ? (Datum) NULL : result;
    }
 
    /*
index 2def370e9fb36d432514138652937de5f616ae34..33b630c7934d100244561e30e8bb6ad984be7b7a 100644 (file)
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.118 2000/07/22 04:22:46 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.119 2000/08/08 15:41:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -717,14 +717,8 @@ _copyOper(Oper *from)
    newnode->opno = from->opno;
    newnode->opid = from->opid;
    newnode->opresulttype = from->opresulttype;
-   newnode->opsize = from->opsize;
-
-   /*
-    * NOTE: shall we copy the cache structure or just the pointer ?
-    * Alternatively we can set 'op_fcache' to NULL, in which case the
-    * executor will initialize it when it needs it...
-    */
-   newnode->op_fcache = from->op_fcache;
+   /* Do not copy the run-time state, if any */
+   newnode->op_fcache = NULL;
 
    return newnode;
 }
@@ -797,7 +791,6 @@ _copyParam(Param *from)
    if (from->paramname != NULL)
        newnode->paramname = pstrdup(from->paramname);
    newnode->paramtype = from->paramtype;
-   Node_Copy(from, newnode, param_tlist);
 
    return newnode;
 }
@@ -817,11 +810,8 @@ _copyFunc(Func *from)
     */
    newnode->funcid = from->funcid;
    newnode->functype = from->functype;
-   newnode->funcisindex = from->funcisindex;
-   newnode->funcsize = from->funcsize;
-   newnode->func_fcache = from->func_fcache;
-   Node_Copy(from, newnode, func_tlist);
-   Node_Copy(from, newnode, func_planlist);
+   /* Do not copy the run-time state, if any */
+   newnode->func_fcache = NULL;
 
    return newnode;
 }
@@ -872,6 +862,27 @@ _copySubLink(SubLink *from)
    return newnode;
 }
 
+/* ----------------
+ *     _copyFieldSelect
+ * ----------------
+ */
+static FieldSelect *
+_copyFieldSelect(FieldSelect *from)
+{
+   FieldSelect *newnode = makeNode(FieldSelect);
+
+   /* ----------------
+    *  copy remainder of node
+    * ----------------
+    */
+   Node_Copy(from, newnode, arg);
+   newnode->fieldnum = from->fieldnum;
+   newnode->resulttype = from->resulttype;
+   newnode->resulttypmod = from->resulttypmod;
+
+   return newnode;
+}
+
 /* ----------------
  *     _copyRelabelType
  * ----------------
@@ -1710,6 +1721,9 @@ copyObject(void *from)
        case T_Iter:
            retval = _copyIter(from);
            break;
+       case T_FieldSelect:
+           retval = _copyFieldSelect(from);
+           break;
        case T_RelabelType:
            retval = _copyRelabelType(from);
            break;
index b85c410c253fbec3564983078de0d8eec25735bd..701e6511e4441e344504dd0b2628cdce26b198d1 100644 (file)
@@ -24,7 +24,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.70 2000/07/22 04:22:46 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.71 2000/08/08 15:41:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -154,7 +154,7 @@ _equalOper(Oper *a, Oper *b)
        return false;
 
    /*
-    * We do not examine opid, opsize, or op_fcache, since these are
+    * 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.
     *
@@ -195,8 +195,6 @@ _equalParam(Param *a, Param *b)
        return false;
    if (a->paramtype != b->paramtype)
        return false;
-   if (!equal(a->param_tlist, b->param_tlist))
-       return false;
 
    switch (a->paramkind)
    {
@@ -233,15 +231,7 @@ _equalFunc(Func *a, Func *b)
        return false;
    if (a->functype != b->functype)
        return false;
-   if (a->funcisindex != b->funcisindex)
-       return false;
-   if (a->funcsize != b->funcsize)
-       return false;
-   /* Note we do not look at func_fcache */
-   if (!equal(a->func_tlist, b->func_tlist))
-       return false;
-   if (!equal(a->func_planlist, b->func_planlist))
-       return false;
+   /* Note we do not look at func_fcache; see notes for _equalOper */
 
    return true;
 }
@@ -281,6 +271,20 @@ _equalSubLink(SubLink *a, SubLink *b)
    return true;
 }
 
+static bool
+_equalFieldSelect(FieldSelect *a, FieldSelect *b)
+{
+   if (!equal(a->arg, b->arg))
+       return false;
+   if (a->fieldnum != b->fieldnum)
+       return false;
+   if (a->resulttype != b->resulttype)
+       return false;
+   if (a->resulttypmod != b->resulttypmod)
+       return false;
+   return true;
+}
+
 static bool
 _equalRelabelType(RelabelType *a, RelabelType *b)
 {
@@ -787,6 +791,9 @@ equal(void *a, void *b)
        case T_Iter:
            retval = _equalIter(a, b);
            break;
+       case T_FieldSelect:
+           retval = _equalFieldSelect(a, b);
+           break;
        case T_RelabelType:
            retval = _equalRelabelType(a, b);
            break;
index 4bad2008d77a8dd206440fc85af9111fdeeb2c18..45e1c03738c6de3aac16578707e0ef32eb4578ac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.21 2000/04/12 17:15:16 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.22 2000/08/08 15:41:24 tgl Exp $
  *
  * NOTES
  *   Creator functions in POSTGRES 4.2 are generated automatically. Most of
 Oper *
 makeOper(Oid opno,
         Oid opid,
-        Oid opresulttype,
-        int opsize,
-        FunctionCachePtr op_fcache)
+        Oid opresulttype)
 {
    Oper       *oper = makeNode(Oper);
 
    oper->opno = opno;
    oper->opid = opid;
    oper->opresulttype = opresulttype;
-   oper->opsize = opsize;
-   oper->op_fcache = op_fcache;
+   oper->op_fcache = NULL;
    return oper;
 }
 
@@ -99,8 +96,6 @@ makeResdom(AttrNumber resno,
           Oid restype,
           int32 restypmod,
           char *resname,
-          Index reskey,
-          Oid reskeyop,
           bool resjunk)
 {
    Resdom     *resdom = makeNode(Resdom);
@@ -111,12 +106,14 @@ makeResdom(AttrNumber resno,
    resdom->resname = resname;
 
    /*
-    * For historical reasons, ressortgroupref defaults to 0 while
-    * reskey/reskeyop are passed in explicitly.  This is pretty silly.
+    * We always set the sorting/grouping fields to 0.  If the caller wants
+    * to change them he must do so explicitly.  Few if any callers should
+    * be doing that, so omitting these arguments reduces the chance of error.
     */
    resdom->ressortgroupref = 0;
-   resdom->reskey = reskey;
-   resdom->reskeyop = reskeyop;
+   resdom->reskey = 0;
+   resdom->reskeyop = InvalidOid;
+
    resdom->resjunk = resjunk;
    return resdom;
 }
index 155aae37ad2f7026c74455d3e4a9a24d6466310f..14f2ab106c73e1e4d6a0fa2d87f508ac91075530 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.124 2000/07/22 04:22:46 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.125 2000/08/08 15:41:26 tgl Exp $
  *
  * NOTES
  *   Every (plan) node in POSTGRES has an associated "out" routine which
@@ -757,6 +757,19 @@ _outSubLink(StringInfo str, SubLink *node)
    _outNode(str, node->subselect);
 }
 
+/*
+ * FieldSelect
+ */
+static void
+_outFieldSelect(StringInfo str, FieldSelect *node)
+{
+   appendStringInfo(str, " FIELDSELECT :arg ");
+   _outNode(str, node->arg);
+
+   appendStringInfo(str, " :fieldnum %d :resulttype %u :resulttypmod %d ",
+                    node->fieldnum, node->resulttype, node->resulttypmod);
+}
+
 /*
  * RelabelType
  */
@@ -802,19 +815,9 @@ _outArrayRef(StringInfo str, ArrayRef *node)
 static void
 _outFunc(StringInfo str, Func *node)
 {
-   appendStringInfo(str,
-          " FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
+   appendStringInfo(str, " FUNC :funcid %u :functype %u ",
                     node->funcid,
-                    node->functype,
-                    node->funcisindex ? "true" : "false",
-                    node->funcsize);
-
-   appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
-                    (int) node->func_fcache);
-   _outNode(str, node->func_tlist);
-
-   appendStringInfo(str, " :func_planlist ");
-   _outNode(str, node->func_planlist);
+                    node->functype);
 }
 
 /*
@@ -840,9 +843,7 @@ _outParam(StringInfo str, Param *node)
                     node->paramkind,
                     node->paramid);
    _outToken(str, node->paramname);
-   appendStringInfo(str, " :paramtype %u :param_tlist ",
-                    node->paramtype);
-   _outNode(str, node->param_tlist);
+   appendStringInfo(str, " :paramtype %u ", node->paramtype);
 }
 
 /*
@@ -1482,6 +1483,9 @@ _outNode(StringInfo str, void *obj)
            case T_SubLink:
                _outSubLink(str, obj);
                break;
+           case T_FieldSelect:
+               _outFieldSelect(str, obj);
+               break;
            case T_RelabelType:
                _outRelabelType(str, obj);
                break;
index c663ba304fc285c591b5a17b3a014666ce5783db..17e0396e5fee4f4d7e67a611b22f1575116835bf 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.94 2000/07/22 04:22:46 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.95 2000/08/08 15:41:27 tgl Exp $
  *
  * NOTES
  *   Most of the read functions for plan nodes are tested. (In fact, they
@@ -942,29 +942,7 @@ _readFunc()
    token = lsptok(NULL, &length);      /* now read it */
    local_node->functype = (Oid) atol(token);
 
-   token = lsptok(NULL, &length);      /* get :funcisindex */
-   token = lsptok(NULL, &length);      /* now read it */
-
-   if (!strncmp(token, "true", 4))
-       local_node->funcisindex = true;
-   else
-       local_node->funcisindex = false;
-
-   token = lsptok(NULL, &length);      /* get :funcsize */
-   token = lsptok(NULL, &length);      /* now read it */
-   local_node->funcsize = atol(token);
-
-   token = lsptok(NULL, &length);      /* get :func_fcache */
-   token = lsptok(NULL, &length);      /* get @ */
-   token = lsptok(NULL, &length);      /* now read it */
-
-   local_node->func_fcache = (FunctionCache *) NULL;
-
-   token = lsptok(NULL, &length);      /* get :func_tlist */
-   local_node->func_tlist = nodeRead(true);    /* now read it */
-
-   token = lsptok(NULL, &length);      /* get :func_planlist */
-   local_node->func_planlist = nodeRead(true); /* now read it */
+   local_node->func_fcache = NULL;
 
    return local_node;
 }
@@ -996,11 +974,7 @@ _readOper()
    token = lsptok(NULL, &length);      /* now read it */
    local_node->opresulttype = (Oid) atol(token);
 
-   /*
-    * NOTE: Alternatively we can call 'replace_opid' which initializes
-    * both 'opid' and 'op_fcache'.
-    */
-   local_node->op_fcache = (FunctionCache *) NULL;
+   local_node->op_fcache = NULL;
 
    return local_node;
 }
@@ -1039,9 +1013,6 @@ _readParam()
    token = lsptok(NULL, &length);      /* now read it */
    local_node->paramtype = (Oid) atol(token);
 
-   token = lsptok(NULL, &length);      /* get :param_tlist */
-   local_node->param_tlist = nodeRead(true);   /* now read it */
-
    return local_node;
 }
 
@@ -1121,6 +1092,39 @@ _readSubLink()
    return local_node;
 }
 
+/* ----------------
+ *     _readFieldSelect
+ *
+ * FieldSelect is a subclass of Node
+ * ----------------
+ */
+static FieldSelect *
+_readFieldSelect()
+{
+   FieldSelect *local_node;
+   char       *token;
+   int         length;
+
+   local_node = makeNode(FieldSelect);
+
+   token = lsptok(NULL, &length);      /* eat :arg */
+   local_node->arg = nodeRead(true);   /* now read it */
+
+   token = lsptok(NULL, &length);      /* eat :fieldnum */
+   token = lsptok(NULL, &length);      /* get fieldnum */
+   local_node->fieldnum = (AttrNumber) atoi(token);
+
+   token = lsptok(NULL, &length);      /* eat :resulttype */
+   token = lsptok(NULL, &length);      /* get resulttype */
+   local_node->resulttype = (Oid) atol(token);
+
+   token = lsptok(NULL, &length);      /* eat :resulttypmod */
+   token = lsptok(NULL, &length);      /* get resulttypmod */
+   local_node->resulttypmod = atoi(token);
+
+   return local_node;
+}
+
 /* ----------------
  *     _readRelabelType
  *
@@ -1781,6 +1785,8 @@ parsePlanString(void)
        return_value = _readAggref();
    else if (length == 7 && strncmp(token, "SUBLINK", length) == 0)
        return_value = _readSubLink();
+   else if (length == 11 && strncmp(token, "FIELDSELECT", length) == 0)
+       return_value = _readFieldSelect();
    else if (length == 11 && strncmp(token, "RELABELTYPE", length) == 0)
        return_value = _readRelabelType();
    else if (length == 3 && strncmp(token, "AGG", length) == 0)
index 44305558abb3e580c9a622cf191ba5486da96caa..13bf65e699040fc90ec98083694efafa1658cd4c 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.91 2000/08/03 16:34:12 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.92 2000/08/08 15:41:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1339,9 +1339,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
     */
    test_oper = makeOper(test_op,       /* opno */
                         InvalidOid,    /* opid */
-                        BOOLOID,       /* opresulttype */
-                        0,     /* opsize */
-                        NULL); /* op_fcache */
+                        BOOLOID);      /* opresulttype */
    replace_opid(test_oper);
 
    test_expr = make_opclause(test_oper,
@@ -1934,7 +1932,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, 0, NULL);
+       op = makeOper(oproid, InvalidOid, BOOLOID);
        expr = make_opclause(op, leftop, (Var *) con);
        result = lcons(expr, NIL);
        return result;
@@ -1949,7 +1947,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, 0, NULL);
+   op = makeOper(oproid, InvalidOid, BOOLOID);
    expr = make_opclause(op, leftop, (Var *) con);
    result = lcons(expr, NIL);
 
@@ -1964,7 +1962,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, 0, NULL);
+       op = makeOper(oproid, InvalidOid, BOOLOID);
        expr = make_opclause(op, leftop, (Var *) con);
        result = lappend(result, expr);
        pfree(greaterstr);
index e9906bfef2549b45f129d7bea8d8bd67d21dd475..6d7b67bee3df6a359f54bdc05a29ba4965ff527b 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.23 2000/07/24 03:10:56 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.24 2000/08/08 15:41:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -436,12 +436,7 @@ build_index_pathkeys(Query *root,
 
        funcnode->funcid = index->indproc;
        funcnode->functype = get_func_rettype(index->indproc);
-       funcnode->funcisindex = false;
-       funcnode->funcsize = 0;
        funcnode->func_fcache = NULL;
-       /* we assume here that the function returns a base type... */
-       funcnode->func_tlist = setup_base_tlist(funcnode->functype);
-       funcnode->func_planlist = NIL;
 
        while (*indexkeys != 0)
        {
index 8b95deca5874d3eee2634d69674704d1171e6669..d2bbff7e6006c532fffac5268ac53b44d55b898c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.47 2000/07/24 03:11:01 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.48 2000/08/08 15:41:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -382,9 +382,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
    clause->opType = OP_EXPR;
    clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */
                                     InvalidOid, /* opid */
-                                    BOOLOID, /* operator result type */
-                                    0,
-                                    NULL);
+                                    BOOLOID); /* operator result type */
    clause->args = lcons(item1, lcons(item2, NIL));
 
    add_restrict_and_join_to_rel(root, (Node *) clause);
index 42545750d393a695952341c29236050056bb9612..1a9a7d36fa6de7d022fdfd3933392dd4458c7d0a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.86 2000/07/27 23:15:57 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.87 2000/08/08 15:41:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -373,8 +373,6 @@ union_planner(Query *parse,
                                    TIDOID,
                                    -1,
                                    resname,
-                                   0,
-                                   0,
                                    true);
 
                var = makeVar(rowmark->rti, -1, TIDOID, -1, 0);
@@ -761,8 +759,6 @@ make_subplanTargetList(Query *parse,
                                                exprType(groupexpr),
                                                exprTypmod(groupexpr),
                                                NULL,
-                                               (Index) 0,
-                                               (Oid) 0,
                                                false),
                                     groupexpr);
                sub_tlist = lappend(sub_tlist, te);
index c13cc598485ef1a0e439b4a13eced745c4df08fa..d77e138f193a279efd744bd64954e168fca1f813 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.26 2000/06/08 22:37:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.27 2000/08/08 15:41:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -504,8 +504,7 @@ push_nots(Expr *qual)
        {
            Oper       *op = (Oper *) makeOper(negator,
                                               InvalidOid,
-                                              oper->opresulttype,
-                                              0, NULL);
+                                              oper->opresulttype);
 
            return make_opclause(op, get_leftop(qual), get_rightop(qual));
        }
index a782203cd9b95595f4913c5fe30a7eb5de0072f4..e3b9803d0ab0c19232b0be7904700b265c532342 100644 (file)
@@ -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.37 2000/07/22 06:19:04 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.38 2000/08/08 15:41:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,8 +75,6 @@ preprocess_targetlist(List *tlist,
                            TIDOID,
                            -1,
                            pstrdup("ctid"),
-                           0,
-                           0,
                            true);
 
        var = makeVar(result_relation, SelfItemPointerAttributeNumber,
@@ -219,8 +217,6 @@ expand_targetlist(List *tlist, int command_type,
                                                             atttype,
                                                             -1,
                                                       pstrdup(attrname),
-                                                            0,
-                                                            (Oid) 0,
                                                             false),
                                                  (Node *) temp_const);
                        break;
@@ -251,8 +247,6 @@ expand_targetlist(List *tlist, int command_type,
                                                             atttype,
                                                             atttypmod,
                                                             pstrdup(attrname),
-                                                            0,
-                                                            (Oid) 0,
                                                             false),
                                                  (Node *) temp_var);
                        break;
index d3a813fb86c134f9f4c1ef21e64edb05fd2cf481..adda68b636aaf9d4b4bf7f0593d02af232ea65e1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.69 2000/07/12 02:37:11 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.70 2000/08/08 15:41:53 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -910,9 +910,7 @@ CommuteClause(Expr *clause)
 
    commu = makeOper(heapTup->t_data->t_oid,
                     commuTup->oprcode,
-                    commuTup->oprresult,
-                    ((Oper *) clause->oper)->opsize,
-                    NULL);
+                    commuTup->oprresult);
 
    /*
     * re-form the clause in-place!
@@ -1596,6 +1594,8 @@ bool
                    return true;
            }
            break;
+       case T_FieldSelect:
+           return walker(((FieldSelect *) node)->arg, context);
        case T_RelabelType:
            return walker(((RelabelType *) node)->arg, context);
        case T_CaseExpr:
@@ -1824,6 +1824,16 @@ Node *
                return (Node *) newnode;
            }
            break;
+       case T_FieldSelect:
+           {
+               FieldSelect *fselect = (FieldSelect *) node;
+               FieldSelect *newnode;
+
+               FLATCOPY(newnode, fselect, FieldSelect);
+               MUTATE(newnode->arg, fselect->arg, Node *);
+               return (Node *) newnode;
+           }
+           break;
        case T_RelabelType:
            {
                RelabelType *relabel = (RelabelType *) node;
index d55c5177089df41632cb196d823729ec4539b564..93b3fc6f568e87b33e82dd4af13cf68cfa2370c9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.46 2000/06/08 22:37:16 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.47 2000/08/08 15:41:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -110,8 +110,6 @@ create_tl_element(Var *var, int resdomno)
                                      var->vartype,
                                      var->vartypmod,
                                      NULL,
-                                     (Index) 0,
-                                     (Oid) 0,
                                      false),
                           (Node *) var);
 }
@@ -199,8 +197,6 @@ add_to_flat_tlist(List *tlist, List *vars)
                           var->vartype,
                           var->vartypmod,
                           NULL,
-                          (Index) 0,
-                          (Oid) 0,
                           false);
            tlist = lappend(tlist,
                            makeTargetEntry(r, copyObject(var)));
index 5824c300d7c85c7dbaeae35891599413c5ca8d35..09f90fe3bc3080abdeff0610d58103457e2ea453 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: analyze.c,v 1.152 2000/08/03 16:35:08 tgl Exp $
+ * $Id: analyze.c,v 1.153 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -470,7 +470,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
                                            thisatt->atttypid,
                                            thisatt->atttypmod,
                                      pstrdup(NameStr(thisatt->attname)),
-                                           0, 0, false),
+                                           false),
                                 stringToNode(defval[ndef].adbin));
            qry->targetList = lappend(qry->targetList, te);
 
index 8c3e64d6d863c1b3f07db4c4aa4cbc7539237e0a..7976f5e779590ee41d59a98209ba5dc4b631d379 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.81 2000/06/15 03:32:20 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.82 2000/08/08 15:42:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -133,7 +133,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
                param->paramid = (AttrNumber) paramno;
                param->paramname = "<unnamed>";
                param->paramtype = toid;
-               param->param_tlist = NIL;
                result = transformIndirection(pstate, (Node *) param,
                                              pno->indirection);
                /* cope with typecast applied to param */
@@ -381,9 +380,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
 
                        newop = makeOper(oprid(optup),  /* opno */
                                         InvalidOid,    /* opid */
-                                        opform->oprresult,
-                                        0,
-                                        NULL);
+                                        opform->oprresult);
                        sublink->oper = lappend(sublink->oper, newop);
                    }
                    if (left_list != NIL)
@@ -579,6 +576,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
        case T_Param:
        case T_Aggref:
        case T_ArrayRef:
+       case T_FieldSelect:
        case T_RelabelType:
            {
                result = (Node *) expr;
@@ -690,6 +688,9 @@ exprType(Node *expr)
        case T_Param:
            type = ((Param *) expr)->paramtype;
            break;
+       case T_FieldSelect:
+           type = ((FieldSelect *) expr)->resulttype;
+           break;
        case T_RelabelType:
            type = ((RelabelType *) expr)->resulttype;
            break;
@@ -773,6 +774,9 @@ exprTypmod(Node *expr)
                    return coercedTypmod;
            }
            break;
+       case T_FieldSelect:
+           return ((FieldSelect *) expr)->resulttypmod;
+           break;
        case T_RelabelType:
            return ((RelabelType *) expr)->resulttypmod;
            break;
index d1a5e44f8735a2ab88f22a921ab189022091e0a3..44a750c166e38756934b8766a8bd720e367d2fed 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.86 2000/08/03 19:19:34 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.87 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,7 @@ static int match_argtypes(int nargs,
               Oid *input_typeids,
               CandidateList function_typeids,
               CandidateList *candidates);
-static List *setup_tlist(char *attname, Oid relid);
+static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
 static Oid *func_select_candidate(int nargs, Oid *input_typeids,
                      CandidateList candidates);
 static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
@@ -394,10 +394,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
                argrelid = typeidTypeRelid(toid);
 
                /*
-                * A projection contains either an attribute name or "*".
+                * A projection must match an attribute name of the rel.
                 */
-               if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
-                   && strcmp(funcname, "*"))
+               if (get_attnum(argrelid, funcname) == InvalidAttrNumber)
                    elog(ERROR, "Functions on sets are not yet supported");
            }
 
@@ -670,42 +669,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
    funcnode = makeNode(Func);
    funcnode->funcid = funcid;
    funcnode->functype = rettype;
-   funcnode->funcisindex = false;
-   funcnode->funcsize = 0;
    funcnode->func_fcache = NULL;
-   funcnode->func_tlist = NIL;
-   funcnode->func_planlist = NIL;
 
-   /* perform the necessary typecasting */
+   /* perform the necessary typecasting of arguments */
    make_arguments(pstate, nargs, fargs, oid_array, true_oid_array);
 
-   /*
-    * for functions returning base types, we want to project out the
-    * return value.  set up a target list to do that.  the executor will
-    * ignore these for c functions, and do the right thing for postquel
-    * functions.
-    */
-
-   if (typeidTypeRelid(rettype) == InvalidOid)
-       funcnode->func_tlist = setup_base_tlist(rettype);
-
-   /*
-    * For sets, we want to make a targetlist to project out this
-    * attribute of the set tuples.
-    */
-   if (attisset)
-   {
-       if (!strcmp(funcname, "*"))
-           funcnode->func_tlist = expandAll(pstate, relname,
-                                            makeAttr(refname, NULL),
-                                            curr_resno);
-       else
-       {
-           funcnode->func_tlist = setup_tlist(funcname, argrelid);
-           rettype = get_atttype(argrelid, get_attnum(argrelid, funcname));
-       }
-   }
-
    /*
     * Special checks to disallow sequence functions with side-effects
     * in WHERE clauses.  This is pretty much of a hack; why disallow these
@@ -723,6 +691,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
    expr->args = fargs;
    retval = (Node *) expr;
 
+   /*
+    * For sets, we want to project out the desired attribute of the tuples.
+    */
+   if (attisset)
+   {
+       FieldSelect    *fselect;
+
+       fselect = setup_field_select(retval, funcname, argrelid);
+       rettype = fselect->resulttype;
+       retval = (Node *) fselect;
+   }
+
    /*
     * 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
@@ -1524,66 +1504,30 @@ make_arguments(ParseState *pstate,
 }
 
 /*
- ** setup_tlist
- **        Build a tlist that says which attribute to project to.
- **        This routine is called by ParseFuncOrColumn() to set up a target list
- **        on a tuple parameter or return value.  Due to a bug in 4.0,
- **        it's not possible to refer to system attributes in this case.
+ ** setup_field_select
+ **        Build a FieldSelect node that says which attribute to project to.
+ **        This routine is called by ParseFuncOrColumn() when we have found
+ **        a projection on a function result or parameter.
  */
-static List *
-setup_tlist(char *attname, Oid relid)
+static FieldSelect *
+setup_field_select(Node *input, char *attname, Oid relid)
 {
-   TargetEntry *tle;
-   Resdom     *resnode;
-   Var        *varnode;
-   Oid         typeid;
-   int32       type_mod;
-   int         attno;
+   FieldSelect *fselect = makeNode(FieldSelect);
+   AttrNumber  attno;
 
    attno = get_attnum(relid, attname);
+
+   /* XXX Is there still a reason for this restriction? */
    if (attno < 0)
        elog(ERROR, "Cannot reference attribute '%s'"
             " of tuple params/return values for functions", attname);
 
-   typeid = get_atttype(relid, attno);
-   type_mod = get_atttypmod(relid, attno);
-
-   resnode = makeResdom(1,
-                        typeid,
-                        type_mod,
-                        get_attname(relid, attno),
-                        0,
-                        InvalidOid,
-                        false);
-   varnode = makeVar(-1, attno, typeid, type_mod, 0);
+   fselect->arg = input;
+   fselect->fieldnum = attno;
+   fselect->resulttype = get_atttype(relid, attno);
+   fselect->resulttypmod = get_atttypmod(relid, attno);
 
-   tle = makeTargetEntry(resnode, (Node *) varnode);
-   return lcons(tle, NIL);
-}
-
-/*
- ** setup_base_tlist
- **        Build a tlist that extracts a base type from the tuple
- **        returned by the executor.
- */
-List *
-setup_base_tlist(Oid typeid)
-{
-   TargetEntry *tle;
-   Resdom     *resnode;
-   Var        *varnode;
-
-   resnode = makeResdom(1,
-                        typeid,
-                        -1,
-                        "<noname>",
-                        0,
-                        InvalidOid,
-                        false);
-   varnode = makeVar(-1, 1, typeid, -1, 0);
-   tle = makeTargetEntry(resnode, (Node *) varnode);
-
-   return lcons(tle, NIL);
+   return fselect;
 }
 
 /*
@@ -1599,51 +1543,32 @@ ParseComplexProjection(ParseState *pstate,
 {
    Oid         argtype;
    Oid         argrelid;
-   Relation    rd;
-   Oid         relid;
-   int         attnum;
+   FieldSelect *fselect;
 
    switch (nodeTag(first_arg))
    {
        case T_Iter:
            {
-               Func       *func;
-               Iter       *iter;
+               Iter       *iter = (Iter *) first_arg;
 
-               iter = (Iter *) first_arg;
-               func = (Func *) ((Expr *) iter->iterexpr)->oper;
-               argtype = get_func_rettype(func->funcid);
+               /*
+                * If the argument of the Iter returns a tuple,
+                * funcname may be a projection.  If so, 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.
+                */
+               argtype = iter->itertype;
                argrelid = typeidTypeRelid(argtype);
                if (argrelid &&
-                   ((attnum = get_attnum(argrelid, funcname))
-                    != InvalidAttrNumber))
+                   get_attnum(argrelid, funcname) != InvalidAttrNumber)
                {
-
-                   /*
-                    * the argument is a function returning a tuple, so
-                    * funcname may be a projection
-                    */
-
-                   /* add a tlist to the func node and return the Iter */
-                   rd = heap_openr_nofail(typeidTypeName(argtype));
-                   if (RelationIsValid(rd))
-                   {
-                       relid = RelationGetRelid(rd);
-                       func->func_tlist = setup_tlist(funcname, argrelid);
-                       iter->itertype = attnumTypeId(rd, attnum);
-                       heap_close(rd, NoLock);
-                       return (Node *) iter;
-                   }
-                   else
-                   {
-                       elog(ERROR, "Function '%s' has bad return type %d",
-                            funcname, argtype);
-                   }
-               }
-               else
-               {
-                   /* drop through */
-                   ;
+                   fselect = setup_field_select(iter->iterexpr,
+                                                funcname, argrelid);
+                   iter->iterexpr = (Node *) fselect;
+                   iter->itertype = fselect->resulttype;
+                   return (Node *) iter;
                }
                break;
            }
@@ -1665,38 +1590,20 @@ ParseComplexProjection(ParseState *pstate,
                if (expr->opType != FUNC_EXPR)
                    break;
 
-               funcnode = (Func *) expr->oper;
-               argtype = get_func_rettype(funcnode->funcid);
-               argrelid = typeidTypeRelid(argtype);
-
                /*
-                * the argument is a function returning a tuple, so
+                * If the argument is a function returning a tuple,
                 * funcname may be a projection
                 */
+               funcnode = (Func *) expr->oper;
+               argtype = funcnode->functype;
+               argrelid = typeidTypeRelid(argtype);
                if (argrelid &&
-                   (attnum = get_attnum(argrelid, funcname))
-                   != InvalidAttrNumber)
+                   get_attnum(argrelid, funcname) != InvalidAttrNumber)
                {
-                   Expr       *newexpr;
-
-                   /* add a tlist to the func node */
-                   rd = heap_openr(typeidTypeName(argtype), NoLock);
-
-                   relid = RelationGetRelid(rd);
-                   funcnode->func_tlist = setup_tlist(funcname, argrelid);
-                   funcnode->functype = attnumTypeId(rd, attnum);
-
-                   newexpr = makeNode(Expr);
-                   newexpr->typeOid = funcnode->functype;
-                   newexpr->opType = FUNC_EXPR;
-                   newexpr->oper = (Node *) funcnode;
-                   newexpr->args = expr->args;
-
-                   heap_close(rd, NoLock);
-
-                   return (Node *) newexpr;
+                   fselect = setup_field_select((Node *) expr,
+                                                funcname, argrelid);
+                   return (Node *) fselect;
                }
-
                break;
            }
        case T_Param:
@@ -1707,19 +1614,14 @@ ParseComplexProjection(ParseState *pstate,
                 * If the Param is a complex type, this could be a
                 * projection
                 */
-               rd = heap_openr_nofail(typeidTypeName(param->paramtype));
-               if (RelationIsValid(rd))
+               argtype = param->paramtype;
+               argrelid = typeidTypeRelid(argtype);
+               if (argrelid &&
+                   get_attnum(argrelid, funcname) != InvalidAttrNumber)
                {
-                   relid = RelationGetRelid(rd);
-                   if ((attnum = get_attnum(relid, funcname))
-                       != InvalidAttrNumber)
-                   {
-                       param->paramtype = attnumTypeId(rd, attnum);
-                       param->param_tlist = setup_tlist(funcname, relid);
-                       heap_close(rd, NoLock);
-                       return (Node *) param;
-                   }
-                   heap_close(rd, NoLock);
+                   fselect = setup_field_select((Node *) param,
+                                                funcname, argrelid);
+                   return (Node *) fselect;
                }
                break;
            }
index 273dc0ef64414d4f5d4035c4d0fdb5a5d4af621c..2bda101538ce88af27123b4df1649b75e393d97e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.43 2000/07/05 23:11:32 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.44 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -161,9 +161,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
 
    newop = makeOper(oprid(tup),/* opno */
                     InvalidOid,/* opid */
-                    opform->oprresult, /* operator result type */
-                    0,
-                    NULL);
+                    opform->oprresult); /* operator result type */
 
    result = makeNode(Expr);
    result->typeOid = opform->oprresult;
index 7a3e3c2d6ad0435d196a73626290185044c4dd17..802299c8966856265f752fd30d4b80664c679fa7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.45 2000/07/02 22:00:41 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.46 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -412,8 +412,6 @@ expandAll(ParseState *pstate, char *relname, Attr *ref, int *this_resno)
                                varnode->vartype,
                                varnode->vartypmod,
                                label,
-                               (Index) 0,
-                               (Oid) 0,
                                false);
        te->expr = (Node *) varnode;
        te_list = lappend(te_list, te);
index 2f076028cc9f11e79a0e543eecf096b99f78520f..1564f976b042b0ef13154b5640b51e76ecacbda0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.60 2000/06/15 03:32:20 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.61 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,8 +71,6 @@ transformTargetEntry(ParseState *pstate,
                         type_id,
                         type_mod,
                         colname,
-                        (Index) 0,
-                        (Oid) InvalidOid,
                         resjunk);
 
    return makeTargetEntry(resnode, expr);
index acd62c9c70e9082065b795b5c11418a5e9d2c455..1f4073f9fcf9683d9589cf3bae9f172b2a71cd32 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.77 2000/06/30 07:04:22 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.78 2000/08/08 15:42:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1882,9 +1882,7 @@ Except_Intersect_Rewrite(Query *parsetree)
 
                newop = makeOper(oprid(optup),  /* opno */
                                 InvalidOid,    /* opid */
-                                opform->oprresult,
-                                0,
-                                NULL);
+                                opform->oprresult);
 
                n->oper = lappend(n->oper, newop);
 
index 502df7713d64d41e1057e3527b6fd80a011f9d26..6d4da07207af6a09e00f36e9ccf93cd32c30792b 100644 (file)
@@ -3,7 +3,7 @@
  *           out of its tuple
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.57 2000/07/06 23:03:37 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.58 2000/08/08 15:42:21 tgl Exp $
  *
  *   This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1430,6 +1430,32 @@ get_rule_expr(Node *node, deparse_context *context)
            }
            break;
 
+       case T_FieldSelect:
+           {
+               FieldSelect *fselect = (FieldSelect *) node;
+               HeapTuple   typetup;
+               Form_pg_type typeStruct;
+               Oid         typrelid;
+               char       *fieldname;
+
+               /* we do NOT parenthesize the arg expression, for now */
+               get_rule_expr(fselect->arg, context);
+               typetup = SearchSysCacheTuple(TYPEOID,
+                                  ObjectIdGetDatum(exprType(fselect->arg)),
+                                             0, 0, 0);
+               if (!HeapTupleIsValid(typetup))
+                   elog(ERROR, "cache lookup of type %u failed",
+                        exprType(fselect->arg));
+               typeStruct = (Form_pg_type) GETSTRUCT(typetup);
+               typrelid = typeStruct->typrelid;
+               if (!OidIsValid(typrelid))
+                   elog(ERROR, "Argument type %s of FieldSelect is not a tuple type",
+                        NameStr(typeStruct->typname));
+               fieldname = get_attribute_name(typrelid, fselect->fieldnum);
+               appendStringInfo(buf, ".%s", quote_identifier(fieldname));
+           }
+           break;
+
        case T_RelabelType:
            {
                RelabelType *relabel = (RelabelType *) node;
index ba34dfd03dc9448f40bf78800396d3c405828870..15ac990e31d7376c44088d6ef6ead47cf3763e65 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.34 2000/07/12 02:37:20 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.35 2000/08/08 15:42:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,6 +50,9 @@ GetDynamicFuncArgType(Var *arg, ExprContext *econtext)
        elog(ERROR, "Lookup failed on type tuple for class %s",
             relname);
 
+   /* TEST: I bet this routine is unnecessary ... */
+   Assert(arg->vartype == tup->t_data->t_oid);
+
    return tup->t_data->t_oid;
 }
 
@@ -116,22 +119,25 @@ init_fcache(Oid foid,
    {
        /* The return type is not a relation, so just use byval */
        retval->typbyval = typeStruct->typbyval;
+       retval->returnsTuple = false;
    }
    else
    {
 
        /*
         * This is a hack.  We assume here that any function returning a
-        * relation returns it by reference.  This needs to be fixed.
+        * tuple returns it by reference.  This needs to be fixed, since
+        * actually the mechanism isn't quite like return-by-reference.
         */
        retval->typbyval = false;
+       retval->returnsTuple = true;
    }
    retval->foid = foid;
    retval->language = procedureStruct->prolang;
+   retval->returnsSet = procedureStruct->proretset;
+   retval->hasSetArg = false;
    retval->func_state = (char *) NULL;
    retval->setArg = (Datum) 0;
-   retval->hasSetArg = false;
-   retval->oneResult = !procedureStruct->proretset;
 
    /*
     * If we are returning exactly one result then we have to copy tuples
@@ -140,12 +146,9 @@ init_fcache(Oid foid,
     * allocated by the executor (i.e. slots and tuples) is freed.
     */
    if ((retval->language == SQLlanguageId) &&
-       retval->oneResult &&
+       !retval->returnsSet &&
        !retval->typbyval)
    {
-       Form_pg_class relationStruct;
-       HeapTuple   relationTuple;
-       TupleDesc   td;
        TupleTableSlot *slot;
 
        slot = makeNode(TupleTableSlot);
@@ -155,21 +158,6 @@ init_fcache(Oid foid,
        slot->ttc_buffer = InvalidBuffer;
        slot->ttc_whichplan = -1;
 
-       relationTuple =
-           SearchSysCacheTuple(RELNAME,
-                               PointerGetDatum(&typeStruct->typname),
-                               0, 0, 0);
-
-       if (relationTuple)
-       {
-           relationStruct = (Form_pg_class) GETSTRUCT(relationTuple);
-           td = CreateTemplateTupleDesc(relationStruct->relnatts);
-       }
-       else
-           td = CreateTemplateTupleDesc(1);
-
-       slot->ttc_tupleDescriptor = td;
-
        retval->funcSlot = (Pointer) slot;
    }
    else
index d0c0b8e2bf9a01e2c6e2c0ec790e3a00f2af5bc5..e69b5753e3a212d71b07ce94d45bd3edcedd0977 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.40 2000/08/06 18:06:13 thomas Exp $
+ * $Id: catversion.h,v 1.41 2000/08/08 15:42:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200008061
+#define CATALOG_VERSION_NO 200008071
 
 #endif
index 26f2daac535eb7a0fd3103151145d67fc474b774..0e55be1980ed24fc6d6a9a1bfbe605ffe45a68f3 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: functions.h,v 1.12 2000/05/28 17:56:18 tgl Exp $
+ * $Id: functions.h,v 1.13 2000/08/08 15:42:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "nodes/parsenodes.h"
 #include "utils/syscache.h"
 
-extern Datum ProjectAttribute(TupleDesc TD, TargetEntry *tlist,
-                             HeapTuple tup, bool *isnullP);
-
 extern Datum postquel_function(FunctionCallInfo fcinfo,
                               FunctionCachePtr fcache,
-                              List *func_tlist,
                               bool *isDone);
 
 #endif  /* FUNCTIONS_H */
index 3b470b150a29fae8721200a08a19865ea5778498..1ec37fc7b6fefad4ff05faf308ae8186067442ea 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: makefuncs.h,v 1.24 2000/04/12 17:16:40 momjian Exp $
+ * $Id: makefuncs.h,v 1.25 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,9 +18,7 @@
 
 extern Oper *makeOper(Oid opno,
         Oid opid,
-        Oid opresulttype,
-        int opsize,
-        FunctionCachePtr op_fcache);
+        Oid opresulttype);
 
 extern Var *makeVar(Index varno,
        AttrNumber varattno,
@@ -34,8 +32,6 @@ extern Resdom *makeResdom(AttrNumber resno,
           Oid restype,
           int32 restypmod,
           char *resname,
-          Index reskey,
-          Oid reskeyop,
           bool resjunk);
 
 extern Const *makeConst(Oid consttype,
index 08a44675fc8c9d03758bd10dda9181256dec9504..27de4d54ebfea7072d7a8f9f299155d83ad51dee 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.72 2000/07/22 04:22:47 tgl Exp $
+ * $Id: nodes.h,v 1.73 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,7 @@ typedef enum NodeTag
    T_Aggref,
    T_SubLink,
    T_Func,
-   T_ArrayXXX,                 /* not used anymore; this tag# is available */
+   T_FieldSelect,
    T_ArrayRef,
    T_Iter,
    T_RelabelType,
index 47de5779ae57f1e7f23016615bacccaf8ffc89f8..1ad9a3d082ad1bd5ecfbf87771482a910fb7b692 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.45 2000/07/22 04:22:47 tgl Exp $
+ * $Id: primnodes.h,v 1.46 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,10 +160,9 @@ typedef struct Var
 /* ----------------
  * Oper
  *     opno            - PG_OPERATOR OID of the operator
- *     opid            - PG_PROC OID for the operator
+ *     opid            - PG_PROC OID for the operator's underlying function
  *     opresulttype    - PG_TYPE OID of the operator's return value
- *     opsize          - size of return result (cached by executor)
- *     op_fcache       - XXX comment me.
+ *     op_fcache       - runtime state while running the function
  *
  * ----
  * NOTE: in the good old days 'opno' used to be both (or either, or
@@ -175,6 +174,10 @@ typedef struct Var
  * (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
@@ -183,7 +186,6 @@ typedef struct Oper
    Oid         opno;
    Oid         opid;
    Oid         opresulttype;
-   int         opsize;
    FunctionCachePtr op_fcache;
 } Oper;
 
@@ -240,7 +242,6 @@ typedef struct Const
  *     paramid - numeric identifier for literal-constant parameters ("$1")
  *     paramname - attribute name for tuple-substitution parameters ("$.foo")
  *     paramtype - PG_TYPE OID of the parameter's value
- *     param_tlist - allows for projection in a param node.
  * ----------------
  */
 typedef struct Param
@@ -250,23 +251,17 @@ typedef struct Param
    AttrNumber  paramid;
    char       *paramname;
    Oid         paramtype;
-   List       *param_tlist;
 } Param;
 
 
 /* ----------------
  * Func
- *     funcid          - PG_FUNCTION OID of the function
+ *     funcid          - PG_PROC OID of the function
  *     functype        - PG_TYPE OID of the function's return value
- *     funcisindex     - the function can be evaluated by scanning an index
- *                       (set during query optimization)
- *     funcsize        - size of return result (cached by executor)
  *     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_tlist      - projection of functions returning tuples
- *     func_planlist   - result of planning this func, if it's a PQ func
  * ----------------
  */
 typedef struct Func
@@ -274,11 +269,7 @@ typedef struct Func
    NodeTag     type;
    Oid         funcid;
    Oid         functype;
-   bool        funcisindex;
-   int         funcsize;
    FunctionCachePtr func_fcache;
-   List       *func_tlist;
-   List       *func_planlist;
 } Func;
 
 /* ----------------
@@ -439,6 +430,29 @@ typedef struct ArrayRef
    Node       *refassgnexpr;
 } ArrayRef;
 
+/* ----------------
+ * FieldSelect
+ *     arg             - input expression
+ *     fieldnum        - attribute number of field to extract
+ *     resulttype      - type of the field (result type of this node)
+ *     resulttypmod    - output typmod (usually -1)
+ *
+ * FieldSelect represents the operation of extracting one field from a tuple
+ * value.  At runtime, the input expression is expected to yield a Datum
+ * that contains a pointer-to-TupleTableSlot.  The specified field number
+ * is extracted and returned as a Datum.
+ * ----------------
+ */
+
+typedef struct FieldSelect
+{
+   NodeTag     type;
+   Node       *arg;
+   AttrNumber  fieldnum;
+   Oid         resulttype;
+   int32       resulttypmod;
+} FieldSelect;
+
 /* ----------------
  * RelabelType
  *     arg             - input expression
index 836626486b75c5608e458db6ea0ce4f22efc51a7..79b193a2b5117e63d1456c07ba45b099a9df4dd1 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_func.h,v 1.24 2000/04/12 17:16:45 momjian Exp $
+ * $Id: parse_func.h,v 1.25 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,8 +45,6 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
                  bool agg_star, bool agg_distinct,
                  int *curr_resno, int precedence);
 
-extern List *setup_base_tlist(Oid typeid);
-
 extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
 
 extern void func_error(char *caller, char *funcname,
index 59f35867a72b278cc2fd24db1fb450a38cb91dce..efae7613959a75a75491483dd5fd3c91ef73d102 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fcache.h,v 1.12 2000/07/12 02:37:35 tgl Exp $
+ * $Id: fcache.h,v 1.13 2000/08/08 15:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,8 +29,9 @@ typedef struct
    int         typlen;         /* length of the return type */
    bool        typbyval;       /* true if return type is pass by value */
 
-   bool        oneResult;      /* true we only want 1 result from the
-                                * function */
+   bool        returnsTuple;   /* true if return type is a tuple */
+   bool        returnsSet;     /* true if func returns a set (multi rows) */
+
    bool        hasSetArg;      /* true if func is part of a nested dot
                                 * expr whose argument is func returning a
                                 * set ugh! */