aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execQual.c93
-rw-r--r--src/backend/executor/functions.c82
-rw-r--r--src/backend/nodes/copyfuncs.c44
-rw-r--r--src/backend/nodes/equalfuncs.c33
-rw-r--r--src/backend/nodes/makefuncs.c21
-rw-r--r--src/backend/nodes/outfuncs.c36
-rw-r--r--src/backend/nodes/readfuncs.c70
-rw-r--r--src/backend/optimizer/path/indxpath.c12
-rw-r--r--src/backend/optimizer/path/pathkeys.c7
-rw-r--r--src/backend/optimizer/plan/initsplan.c6
-rw-r--r--src/backend/optimizer/plan/planner.c6
-rw-r--r--src/backend/optimizer/prep/prepqual.c5
-rw-r--r--src/backend/optimizer/prep/preptlist.c8
-rw-r--r--src/backend/optimizer/util/clauses.c18
-rw-r--r--src/backend/optimizer/util/tlist.c6
-rw-r--r--src/backend/parser/analyze.c4
-rw-r--r--src/backend/parser/parse_expr.c14
-rw-r--r--src/backend/parser/parse_func.c226
-rw-r--r--src/backend/parser/parse_node.c6
-rw-r--r--src/backend/parser/parse_relation.c4
-rw-r--r--src/backend/parser/parse_target.c4
-rw-r--r--src/backend/rewrite/rewriteHandler.c6
-rw-r--r--src/backend/utils/adt/ruleutils.c28
-rw-r--r--src/backend/utils/cache/fcache.c34
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/executor/functions.h6
-rw-r--r--src/include/nodes/makefuncs.h8
-rw-r--r--src/include/nodes/nodes.h4
-rw-r--r--src/include/nodes/primnodes.h48
-rw-r--r--src/include/parser/parse_func.h4
-rw-r--r--src/include/utils/fcache.h7
31 files changed, 378 insertions, 476 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index a445a57d9cf..6e934a17725 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.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
@@ -1215,6 +1162,34 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
}
/* ----------------------------------------------------------------
+ * 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
*
* Recursively evaluate a targetlist or qualification expression.
@@ -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,
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index a92811d0342..001feb267ff 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -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;
}
/*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 2def370e9fb..33b630c7934 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -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;
}
@@ -873,6 +863,27 @@ _copySubLink(SubLink *from)
}
/* ----------------
+ * _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;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index b85c410c253..701e6511e44 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -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;
}
@@ -282,6 +272,20 @@ _equalSubLink(SubLink *a, SubLink *b)
}
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)
{
if (!equal(a->arg, b->arg))
@@ -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;
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 4bad2008d77..45e1c03738c 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -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
@@ -29,17 +29,14 @@
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;
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 155aae37ad2..14f2ab106c7 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -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
@@ -758,6 +758,19 @@ _outSubLink(StringInfo str, SubLink *node)
}
/*
+ * 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
*/
static void
@@ -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;
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index c663ba304fc..17e0396e5fe 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.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;
}
@@ -1122,6 +1093,39 @@ _readSubLink()
}
/* ----------------
+ * _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
*
* RelabelType is a subclass of Node
@@ -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)
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 44305558abb..13bf65e6990 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.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);
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index e9906bfef25..6d7b67bee3d 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.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)
{
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 8b95deca587..d2bbff7e600 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.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);
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 42545750d39..1a9a7d36fa6 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.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);
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index c13cc598485..d77e138f193 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.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));
}
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index a782203cd9b..e3b9803d0ab 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.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;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index d3a813fb86c..adda68b636a 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.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;
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index d55c5177089..93b3fc6f568 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.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)));
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 5824c300d7c..09f90fe3bc3 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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);
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 8c3e64d6d86..7976f5e7795 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.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;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index d1a5e44f873..44a750c166e 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.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,43 +669,12 @@ 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
* when we have no way to check for side-effects of user-defined fns?
@@ -724,6 +692,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *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
* node here. if it returns a singleton, then we don't need the 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;
}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 273dc0ef644..2bda101538c 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.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;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 7a3e3c2d6ad..802299c8966 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.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);
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 2f076028cc9..1564f976b04 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.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);
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index acd62c9c70e..1f4073f9fcf 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -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);
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 502df7713d6..6d4da07207a 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -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;
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c
index ba34dfd03dc..15ac990e31d 100644
--- a/src/backend/utils/cache/fcache.c
+++ b/src/backend/utils/cache/fcache.c
@@ -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
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index d0c0b8e2bf9..e69b5753e3a 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -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
diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h
index 26f2daac535..0e55be1980e 100644
--- a/src/include/executor/functions.h
+++ b/src/include/executor/functions.h
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -17,12 +17,8 @@
#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 */
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 3b470b150a2..1ec37fc7b6f 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -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,
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 08a44675fc8..27de4d54ebf 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -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,
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 47de5779ae5..1ad9a3d082a 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -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;
/* ----------------
@@ -440,6 +431,29 @@ typedef struct ArrayRef
} 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
* resulttype - output type of coercion expression
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index 836626486b7..79b193a2b51 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -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,
diff --git a/src/include/utils/fcache.h b/src/include/utils/fcache.h
index 59f35867a72..efae7613959 100644
--- a/src/include/utils/fcache.h
+++ b/src/include/utils/fcache.h
@@ -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! */