diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index a445a57d9c..6e934a1772 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 @@ -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, diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index a92811d034..001feb267f 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); + /* + * 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; } /* diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 2def370e9f..33b630c793 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; } @@ -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; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index b85c410c25..701e6511e4 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; } @@ -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; diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 4bad2008d7..45e1c03738 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 155aae37ad..14f2ab106c 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 @@ -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; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index c663ba304f..17e0396e5f 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; } @@ -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) diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 44305558ab..13bf65e699 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 e9906bfef2..6d7b67bee3 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 8b95deca58..d2bbff7e60 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 42545750d3..1a9a7d36fa 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 c13cc59848..d77e138f19 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 a782203cd9..e3b9803d0a 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 d3a813fb86..adda68b636 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 d55c517708..93b3fc6f56 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 5824c300d7..09f90fe3bc 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 8c3e64d6d8..7976f5e779 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 = ""; 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 d1a5e44f87..44a750c166 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,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, - "", - 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 273dc0ef64..2bda101538 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 7a3e3c2d6a..802299c896 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 2f076028cc..1564f976b0 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 acd62c9c70..1f4073f9fc 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 502df7713d..6d4da07207 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 ba34dfd03d..15ac990e31 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 d0c0b8e2bf..e69b5753e3 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 26f2daac53..0e55be1980 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 3b470b150a..1ec37fc7b6 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 08a44675fc..27de4d54eb 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 47de5779ae..1ad9a3d082 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; /* ---------------- @@ -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 diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index 836626486b..79b193a2b5 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 59f35867a7..efae761395 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! */