(unnamed)
text/plain
Filename: (unnamed)
Type: text/plain
Part: 0
*** src/backend/parser/parse_func.c.orig Fri Dec 15 14:22:03 2000
--- src/backend/parser/parse_func.c Tue Dec 26 14:17:09 2000
***************
*** 442,451 ****
/*
* for func(relname), the param to the function is the tuple
! * under consideration. we build a special VarNode to reflect
* this -- it has varno set to the correct range table entry,
* but has varattno == 0 to signal that the whole tuple is the
! * argument.
*/
if (rte->relname == NULL)
elog(ERROR,
--- 442,453 ----
/*
* for func(relname), the param to the function is the tuple
! * under consideration. We build a special VarNode to reflect
* this -- it has varno set to the correct range table entry,
* but has varattno == 0 to signal that the whole tuple is the
! * argument. Also, it has typmod set to sizeof(Pointer) to
! * signal that the runtime representation will be a pointer
! * not an Oid.
*/
if (rte->relname == NULL)
elog(ERROR,
***************
*** 453,459 ****
toid = typenameTypeId(rte->relname);
/* replace it in the arg list */
! lfirst(i) = makeVar(vnum, 0, toid, -1, sublevels_up);
}
else if (!attisset)
toid = exprType(arg);
--- 455,465 ----
toid = typenameTypeId(rte->relname);
/* replace it in the arg list */
! lfirst(i) = makeVar(vnum,
! InvalidAttrNumber,
! toid,
! sizeof(Pointer),
! sublevels_up);
}
else if (!attisset)
toid = exprType(arg);
*** src/backend/access/common/tupdesc.c.orig Thu Nov 16 17:30:15 2000
--- src/backend/access/common/tupdesc.c Tue Dec 26 14:16:06 2000
***************
*** 352,358 ****
AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
-
/* ----------------
* allocate storage for this attribute
* ----------------
--- 352,357 ----
***************
*** 362,368 ****
desc->attrs[attributeNumber - 1] = att;
/* ----------------
! * initialize some of the attribute fields
* ----------------
*/
att->attrelid = 0; /* dummy value */
--- 361,367 ----
desc->attrs[attributeNumber - 1] = att;
/* ----------------
! * initialize the attribute fields
* ----------------
*/
att->attrelid = 0; /* dummy value */
***************
*** 372,378 ****
else
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
-
att->attdispersion = 0; /* dummy value */
att->attcacheoff = -1;
att->atttypmod = typmod;
--- 371,376 ----
***************
*** 414,421 ****
att->atttypid = InvalidOid;
att->attlen = (int16) 0;
att->attbyval = (bool) 0;
- att->attstorage = 'p';
att->attalign = 'i';
return false;
}
--- 412,419 ----
att->atttypid = InvalidOid;
att->attlen = (int16) 0;
att->attbyval = (bool) 0;
att->attalign = 'i';
+ att->attstorage = 'p';
return false;
}
***************
*** 427,468 ****
typeForm = (Form_pg_type) GETSTRUCT(tuple);
att->atttypid = tuple->t_data->t_oid;
- att->attalign = typeForm->typalign;
! /* ------------------------
! If this attribute is a set, what is really stored in the
! attribute is the OID of a tuple in the pg_proc catalog.
! The pg_proc tuple contains the query string which defines
! this set - i.e., the query to run to get the set.
! So the atttypid (just assigned above) refers to the type returned
! by this query, but the actual length of this attribute is the
! length (size) of an OID.
!
! Why not just make the atttypid point to the OID type, instead
! of the type the query returns? Because the executor uses the atttypid
! to tell the front end what type will be returned (in BeginCommand),
! and in the end the type returned will be the result of the query, not
! an OID.
!
! Why not wait until the return type of the set is known (i.e., the
! recursive call to the executor to execute the set has returned)
! before telling the front end what the return type will be? Because
! the executor is a delicate thing, and making sure that the correct
! order of front-end commands is maintained is messy, especially
! considering that target lists may change as inherited attributes
! are considered, etc. Ugh.
! -----------------------------------------
! */
if (attisset)
{
att->attlen = sizeof(Oid);
att->attbyval = true;
att->attstorage = 'p';
}
else
{
att->attlen = typeForm->typlen;
att->attbyval = typeForm->typbyval;
att->attstorage = typeForm->typstorage;
}
--- 425,487 ----
typeForm = (Form_pg_type) GETSTRUCT(tuple);
att->atttypid = tuple->t_data->t_oid;
! /*------------------------
! * There are a couple of cases where we must override the information
! * stored in pg_type.
! *
! * First: if this attribute is a set, what is really stored in the
! * attribute is the OID of a tuple in the pg_proc catalog.
! * The pg_proc tuple contains the query string which defines
! * this set - i.e., the query to run to get the set.
! * So the atttypid (just assigned above) refers to the type returned
! * by this query, but the actual length of this attribute is the
! * length (size) of an OID.
! *
! * (Why not just make the atttypid point to the OID type, instead
! * of the type the query returns? Because the executor uses the atttypid
! * to tell the front end what type will be returned (in BeginCommand),
! * and in the end the type returned will be the result of the query, not
! * an OID.)
! *
! * (Why not wait until the return type of the set is known (i.e., the
! * recursive call to the executor to execute the set has returned)
! * before telling the front end what the return type will be? Because
! * the executor is a delicate thing, and making sure that the correct
! * order of front-end commands is maintained is messy, especially
! * considering that target lists may change as inherited attributes
! * are considered, etc. Ugh.)
! *
! * Second: if we are dealing with a complex type (a tuple type), then
! * pg_type will say that the representation is the same as Oid. But
! * if typmod is sizeof(Pointer) then the internal representation is
! * actually a pointer to a TupleTableSlot, and we have to substitute
! * that information.
! *
! * A set of complex type is first and foremost a set, so its
! * representation is Oid not pointer. So, test that case first.
! *-----------------------------------------
! */
if (attisset)
{
att->attlen = sizeof(Oid);
att->attbyval = true;
+ att->attalign = 'i';
+ att->attstorage = 'p';
+ }
+ else if (typeForm->typtype == 'c' && typmod == sizeof(Pointer))
+ {
+ att->attlen = sizeof(Pointer);
+ att->attbyval = true;
+ att->attalign = 'd'; /* kluge to work with 8-byte pointers */
+ /* XXX ought to have a separate attalign value for pointers ... */
att->attstorage = 'p';
}
else
{
att->attlen = typeForm->typlen;
att->attbyval = typeForm->typbyval;
+ att->attalign = typeForm->typalign;
att->attstorage = typeForm->typstorage;
}
*** src/backend/executor/execTuples.c.orig Sat Nov 11 19:36:57 2000
--- src/backend/executor/execTuples.c Tue Dec 26 14:17:30 2000
***************
*** 835,841 ****
return tupType;
}
! /*
TupleDesc
ExecCopyTupType(TupleDesc td, int natts)
{
--- 835,841 ----
return tupType;
}
! #ifdef NOT_USED
TupleDesc
ExecCopyTupType(TupleDesc td, int natts)
{
***************
*** 852,881 ****
}
return newTd;
}
! */
/* ----------------------------------------------------------------
* ExecTypeFromTL
*
* Currently there are about 4 different places where we create
* TupleDescriptors. They should all be merged, or perhaps
* be rewritten to call BuildDesc().
- *
- * old comments
- * Forms attribute type info from the target list in the node.
- * It assumes all domains are individually specified in the target list.
- * It fails if the target list contains something like Emp.all
- * which represents all the attributes from EMP relation.
- *
- * Conditions:
- * The inner and outer subtrees should be initialized because it
- * might be necessary to know the type infos of the subtrees.
* ----------------------------------------------------------------
*/
TupleDesc
ExecTypeFromTL(List *targetList)
{
! List *tlcdr;
TupleDesc typeInfo;
Resdom *resdom;
Oid restype;
--- 852,874 ----
}
return newTd;
}
! #endif
/* ----------------------------------------------------------------
* ExecTypeFromTL
*
+ * Generate a tuple descriptor for the result tuple of a targetlist.
+ * Note that resjunk columns, if any, are included in the result.
+ *
* Currently there are about 4 different places where we create
* TupleDescriptors. They should all be merged, or perhaps
* be rewritten to call BuildDesc().
* ----------------------------------------------------------------
*/
TupleDesc
ExecTypeFromTL(List *targetList)
{
! List *tlitem;
TupleDesc typeInfo;
Resdom *resdom;
Oid restype;
***************
*** 897,910 ****
typeInfo = CreateTemplateTupleDesc(len);
/* ----------------
! * notes: get resdom from (resdom expr)
! * get_typbyval comes from src/lib/l-lisp/lsyscache.c
* ----------------
*/
! tlcdr = targetList;
! while (tlcdr != NIL)
{
! TargetEntry *tle = lfirst(tlcdr);
if (tle->resdom != NULL)
{
--- 890,901 ----
typeInfo = CreateTemplateTupleDesc(len);
/* ----------------
! * scan list, generate type info for each entry
* ----------------
*/
! foreach(tlitem, targetList)
{
! TargetEntry *tle = lfirst(tlitem);
if (tle->resdom != NULL)
{
***************
*** 920,926 ****
0,
false);
! /*
ExecSetTypeInfo(resdom->resno - 1,
typeInfo,
(Oid) restype,
--- 911,917 ----
0,
false);
! #ifdef NOT_USED
ExecSetTypeInfo(resdom->resno - 1,
typeInfo,
(Oid) restype,
***************
*** 929,941 ****
NameStr(*resdom->resname),
get_typbyval(restype),
get_typalign(restype));
! */
}
else
{
Resdom *fjRes;
List *fjTlistP;
! List *fjList = lfirst(tlcdr);
#ifdef SETS_FIXED
TargetEntry *tle;
--- 920,933 ----
NameStr(*resdom->resname),
get_typbyval(restype),
get_typalign(restype));
! #endif
}
else
{
+ /* XXX this branch looks fairly broken ... tgl 12/2000 */
Resdom *fjRes;
List *fjTlistP;
! List *fjList = lfirst(tlitem);
#ifdef SETS_FIXED
TargetEntry *tle;
***************
*** 953,959 ****
fjRes->restypmod,
0,
false);
! /*
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) restype,
--- 945,951 ----
fjRes->restypmod,
0,
false);
! #ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) restype,
***************
*** 962,968 ****
(char *) fjRes->resname,
get_typbyval(restype),
get_typalign(restype));
! */
foreach(fjTlistP, lnext(fjList))
{
--- 954,960 ----
(char *) fjRes->resname,
get_typbyval(restype),
get_typalign(restype));
! #endif
foreach(fjTlistP, lnext(fjList))
{
***************
*** 978,984 ****
0,
false);
! /*
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) fjRes->restype,
--- 970,976 ----
0,
false);
! #ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) fjRes->restype,
***************
*** 987,997 ****
(char *) fjRes->resname,
get_typbyval(fjRes->restype),
get_typalign(fjRes->restype));
! */
}
}
-
- tlcdr = lnext(tlcdr);
}
return typeInfo;
--- 979,987 ----
(char *) fjRes->resname,
get_typbyval(fjRes->restype),
get_typalign(fjRes->restype));
! #endif
}
}
}
return typeInfo;
*** src/backend/executor/execUtils.c.orig Thu Nov 16 17:30:20 2000
--- src/backend/executor/execUtils.c Tue Dec 26 14:17:26 2000
***************
*** 274,289 ****
{
List *targetList;
TupleDesc tupDesc;
- int len;
targetList = node->targetlist;
tupDesc = ExecTypeFromTL(targetList);
! len = ExecTargetListLength(targetList);
!
! if (len > 0)
! ExecAssignResultType(commonstate, tupDesc);
! else
! ExecAssignResultType(commonstate, (TupleDesc) NULL);
}
/* ----------------
--- 274,283 ----
{
List *targetList;
TupleDesc tupDesc;
targetList = node->targetlist;
tupDesc = ExecTypeFromTL(targetList);
! ExecAssignResultType(commonstate, tupDesc);
}
/* ----------------
***************
*** 582,589 ****
}
/* ----------------
! * ExecFreeTypeInfo frees the array of attrbutes
! * created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
* ----------------
*/
void
--- 576,583 ----
}
/* ----------------
! * ExecFreeTypeInfo frees the array of attributes
! * created by ExecMakeTypeInfo and returned by ExecTypeFromTL
* ----------------
*/
void