Remove 'func_tlist' from Func expression nodes, likewise 'param_tlist'

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.
This commit is contained in:
Tom Lane 2000-08-08 15:43:12 +00:00
parent 8fc32374be
commit 62e29fe2e7
31 changed files with 378 additions and 476 deletions

View 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,

View 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);
/*
* 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 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
{
/* XXX is this right? Return whole tuple slot?? */
value = PointerGetDatum(resSlot);
fcinfo->isnull = false;
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;
}
/*

View 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;

View 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;

View 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
@ -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;
}

View 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;

View 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)

View 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);

View 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)
{

View 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);

View 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);

View 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));
}

View 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;

View 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;

View 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)));

View 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);

View 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;

View 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);
fselect->arg = input;
fselect->fieldnum = attno;
fselect->resulttype = get_atttype(relid, attno);
fselect->resulttypmod = 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);
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;
}

View 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;

View 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);

View 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);

View 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);

View 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;

View 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

View 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

View 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 $
*
*-------------------------------------------------------------------------
*/
@ -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 */

View 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,

View 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,

View 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

View 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,

View 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! */