Tom Lane <[EMAIL PROTECTED]> writes:
> That would be okay with me. It might be a good idea to change the
> name completely (perhaps CopyTupleDesc() ?) as a means of catching
> places that aren't correctly updated.
Done, and done -- a revised patch is attached.
-Neil
Index: src/backend/access/common/tupdesc.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/access/common/tupdesc.c,v
retrieving revision 1.100
diff -c -r1.100 tupdesc.c
*** src/backend/access/common/tupdesc.c 25 Sep 2003 06:57:56 -0000 1.100
--- src/backend/access/common/tupdesc.c 20 Nov 2003 21:43:47 -0000
***************
*** 96,204 ****
}
/* ----------------------------------------------------------------
! * CreateTupleDescCopy
*
! * This function creates a new TupleDesc by copying from an existing
! * TupleDesc
! *
! * !!! Constraints are not copied !!!
* ----------------------------------------------------------------
*/
TupleDesc
! CreateTupleDescCopy(TupleDesc tupdesc)
{
! TupleDesc desc;
! int i,
! size;
! desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
! desc->natts = tupdesc->natts;
! if (desc->natts > 0)
! {
! size = desc->natts * sizeof(Form_pg_attribute);
! desc->attrs = (Form_pg_attribute *) palloc(size);
! for (i = 0; i < desc->natts; i++)
! {
! desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
! memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
! desc->attrs[i]->attnotnull = false;
! desc->attrs[i]->atthasdef = false;
! }
! }
! else
! desc->attrs = NULL;
! desc->constr = NULL;
! desc->tdhasoid = tupdesc->tdhasoid;
! return desc;
! }
!
! /* ----------------------------------------------------------------
! * CreateTupleDescCopyConstr
! *
! * This function creates a new TupleDesc by copying from an existing
! * TupleDesc (with Constraints)
! * ----------------------------------------------------------------
! */
! TupleDesc
! CreateTupleDescCopyConstr(TupleDesc tupdesc)
! {
! TupleDesc desc;
! TupleConstr *constr = tupdesc->constr;
! int i,
! size;
! desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
! desc->natts = tupdesc->natts;
! if (desc->natts > 0)
! {
! size = desc->natts * sizeof(Form_pg_attribute);
! desc->attrs = (Form_pg_attribute *) palloc(size);
! for (i = 0; i < desc->natts; i++)
{
! desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
! memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
}
}
else
! desc->attrs = NULL;
! if (constr)
{
! TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
! cpy->has_not_null = constr->has_not_null;
! if ((cpy->num_defval = constr->num_defval) > 0)
{
! cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
! memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
! for (i = cpy->num_defval - 1; i >= 0; i--)
{
if (constr->defval[i].adbin)
! cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
}
}
! if ((cpy->num_check = constr->num_check) > 0)
{
! cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
! memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
! for (i = cpy->num_check - 1; i >= 0; i--)
{
if (constr->check[i].ccname)
! cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
if (constr->check[i].ccbin)
! cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
}
}
! desc->constr = cpy;
}
- else
- desc->constr = NULL;
! desc->tdhasoid = tupdesc->tdhasoid;
! return desc;
}
void
--- 96,183 ----
}
/* ----------------------------------------------------------------
! * CopyTupleDesc
*
! * This function creates a new TupleDesc by copying from an
! * existing TupleDesc. Iff 'copyConstr' is true, the constraints
! * on the input TupleDesc are also copied.
* ----------------------------------------------------------------
*/
TupleDesc
! CopyTupleDesc(TupleDesc tupDesc, bool copyConstr)
{
! TupleDesc result;
! int i;
! result = (TupleDesc) palloc(sizeof(*result));
! result->natts = tupDesc->natts;
! result->tdhasoid = tupDesc->tdhasoid;
! result->constr = NULL;
! if (result->natts > 0)
! {
! int size;
! size = result->natts * sizeof(Form_pg_attribute);
! result->attrs = (Form_pg_attribute *) palloc(size);
! for (i = 0; i < result->natts; i++)
{
! result->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
! memcpy(result->attrs[i], tupDesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
!
! /*
! * If we're not copying constraints, fix up the attributes
! * to remove NOT NULL or DEFAULT indicators.
! */
! if (!copyConstr)
! {
! result->attrs[i]->attnotnull = false;
! result->attrs[i]->atthasdef = false;
! }
}
}
else
! result->attrs = NULL;
!
! if (copyConstr && tupDesc->constr)
{
! TupleConstr *constr;
! constr = (TupleConstr *) palloc(sizeof(*constr));
! memcpy(constr, tupDesc->constr, sizeof(*constr));
! constr->defval = NULL;
! constr->check = NULL;
! if (constr->num_defval > 0)
{
! constr->defval = (AttrDefault *) palloc(constr->num_defval * sizeof(AttrDefault));
! memcpy(constr->defval, tupDesc->constr->defval,
! constr->num_defval * sizeof(AttrDefault));
! for (i = constr->num_defval - 1; i >= 0; i--)
{
if (constr->defval[i].adbin)
! constr->defval[i].adbin = pstrdup(constr->defval[i].adbin);
}
}
! if (constr->num_check > 0)
{
! constr->check = (ConstrCheck *) palloc(constr->num_check * sizeof(ConstrCheck));
! memcpy(constr->check, tupDesc->constr->check,
! constr->num_check * sizeof(ConstrCheck));
! for (i = constr->num_check - 1; i >= 0; i--)
{
if (constr->check[i].ccname)
! constr->check[i].ccname = pstrdup(constr->check[i].ccname);
if (constr->check[i].ccbin)
! constr->check[i].ccbin = pstrdup(constr->check[i].ccbin);
}
}
! result->constr = constr;
}
! return result;
}
void
***************
*** 607,613 ****
relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
relvar = makeRangeVarFromNameList(relname_list);
rel = relation_openrv(relvar, AccessShareLock);
! tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock);
return tupdesc;
--- 586,592 ----
relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
relvar = makeRangeVarFromNameList(relname_list);
rel = relation_openrv(relvar, AccessShareLock);
! tupdesc = CopyTupleDesc(RelationGetDescr(rel), false);
relation_close(rel, AccessShareLock);
return tupdesc;
***************
*** 644,650 ****
elog(ERROR, "invalid typrelid for complex type %u", typeoid);
rel = relation_open(relid, AccessShareLock);
! tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
natts = tupdesc->natts;
relation_close(rel, AccessShareLock);
/* XXX should we hold the lock to ensure table doesn't change? */
--- 623,629 ----
elog(ERROR, "invalid typrelid for complex type %u", typeoid);
rel = relation_open(relid, AccessShareLock);
! tupdesc = CopyTupleDesc(RelationGetDescr(rel), false);
natts = tupdesc->natts;
relation_close(rel, AccessShareLock);
/* XXX should we hold the lock to ensure table doesn't change? */
Index: src/backend/commands/cluster.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/commands/cluster.c,v
retrieving revision 1.118
diff -c -r1.118 cluster.c
*** src/backend/commands/cluster.c 12 Nov 2003 21:15:49 -0000 1.118
--- src/backend/commands/cluster.c 20 Nov 2003 21:19:36 -0000
***************
*** 494,500 ****
* Need to make a copy of the tuple descriptor, since
* heap_create_with_catalog modifies it.
*/
! tupdesc = CreateTupleDescCopyConstr(OldHeapDesc);
OIDNewHeap = heap_create_with_catalog(NewName,
RelationGetNamespace(OldHeap),
--- 494,500 ----
* Need to make a copy of the tuple descriptor, since
* heap_create_with_catalog modifies it.
*/
! tupdesc = CopyTupleDesc(OldHeapDesc, true);
OIDNewHeap = heap_create_with_catalog(NewName,
RelationGetNamespace(OldHeap),
Index: src/backend/commands/portalcmds.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/commands/portalcmds.c,v
retrieving revision 1.24
diff -c -r1.24 portalcmds.c
*** src/backend/commands/portalcmds.c 24 Aug 2003 21:02:43 -0000 1.24
--- src/backend/commands/portalcmds.c 20 Nov 2003 21:27:24 -0000
***************
*** 295,301 ****
*/
oldcxt = MemoryContextSwitchTo(portal->holdContext);
! portal->tupDesc = CreateTupleDescCopy(portal->tupDesc);
MemoryContextSwitchTo(oldcxt);
--- 295,301 ----
*/
oldcxt = MemoryContextSwitchTo(portal->holdContext);
! portal->tupDesc = CopyTupleDesc(portal->tupDesc, false);
MemoryContextSwitchTo(oldcxt);
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/executor/execMain.c,v
retrieving revision 1.221
diff -c -r1.221 execMain.c
*** src/backend/executor/execMain.c 6 Nov 2003 22:08:14 -0000 1.221
--- src/backend/executor/execMain.c 20 Nov 2003 21:29:16 -0000
***************
*** 804,810 ****
/*
* have to copy tupType to get rid of constraints
*/
! tupdesc = CreateTupleDescCopy(tupType);
intoRelationId = heap_create_with_catalog(intoName,
namespaceId,
--- 804,810 ----
/*
* have to copy tupType to get rid of constraints
*/
! tupdesc = CopyTupleDesc(tupType, false);
intoRelationId = heap_create_with_catalog(intoName,
namespaceId,
Index: src/backend/executor/execQual.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/executor/execQual.c,v
retrieving revision 1.150
diff -c -r1.150 execQual.c
*** src/backend/executor/execQual.c 13 Oct 2003 22:47:15 -0000 1.150
--- src/backend/executor/execQual.c 20 Nov 2003 21:29:58 -0000
***************
*** 1074,1080 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function returning row did not return a valid tuple slot")));
! tupdesc = CreateTupleDescCopy(slot->ttc_tupleDescriptor);
returnsTuple = true;
}
else
--- 1074,1080 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function returning row did not return a valid tuple slot")));
! tupdesc = CopyTupleDesc(slot->ttc_tupleDescriptor, false);
returnsTuple = true;
}
else
Index: src/backend/executor/functions.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/executor/functions.c,v
retrieving revision 1.75
diff -c -r1.75 functions.c
*** src/backend/executor/functions.c 25 Sep 2003 18:58:35 -0000 1.75
--- src/backend/executor/functions.c 20 Nov 2003 21:30:17 -0000
***************
*** 389,395 ****
*/
if (funcSlot->ttc_tupleDescriptor == NULL)
{
! resultTd = CreateTupleDescCopy(resultSlot->ttc_tupleDescriptor);
ExecSetSlotDescriptor(funcSlot, resultTd, true);
ExecSetSlotDescriptorIsNew(funcSlot, true);
}
--- 389,395 ----
*/
if (funcSlot->ttc_tupleDescriptor == NULL)
{
! resultTd = CopyTupleDesc(resultSlot->ttc_tupleDescriptor, false);
ExecSetSlotDescriptor(funcSlot, resultTd, true);
ExecSetSlotDescriptorIsNew(funcSlot, true);
}
Index: src/backend/executor/nodeFunctionscan.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/executor/nodeFunctionscan.c,v
retrieving revision 1.22
diff -c -r1.22 nodeFunctionscan.c
*** src/backend/executor/nodeFunctionscan.c 25 Sep 2003 23:02:12 -0000 1.22
--- src/backend/executor/nodeFunctionscan.c 20 Nov 2003 21:30:35 -0000
***************
*** 205,211 ****
elog(ERROR, "invalid typrelid for complex type %u",
funcrettype);
rel = relation_open(funcrelid, AccessShareLock);
! tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock);
}
else if (functyptype == 'b' || functyptype == 'd')
--- 205,211 ----
elog(ERROR, "invalid typrelid for complex type %u",
funcrettype);
rel = relation_open(funcrelid, AccessShareLock);
! tupdesc = CopyTupleDesc(RelationGetDescr(rel), false);
relation_close(rel, AccessShareLock);
}
else if (functyptype == 'b' || functyptype == 'd')
Index: src/backend/executor/spi.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/executor/spi.c,v
retrieving revision 1.107
diff -c -r1.107 spi.c
*** src/backend/executor/spi.c 1 Oct 2003 21:30:52 -0000 1.107
--- src/backend/executor/spi.c 20 Nov 2003 21:31:30 -0000
***************
*** 386,392 ****
oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
}
! ctupdesc = CreateTupleDescCopy(tupdesc);
if (oldcxt)
MemoryContextSwitchTo(oldcxt);
--- 386,392 ----
oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
}
! ctupdesc = CopyTupleDesc(tupdesc, false);
if (oldcxt)
MemoryContextSwitchTo(oldcxt);
***************
*** 416,422 ****
}
ctuple = heap_copytuple(tuple);
! ctupdesc = CreateTupleDescCopy(tupdesc);
cslot = MakeTupleTableSlot();
ExecSetSlotDescriptor(cslot, ctupdesc, true);
--- 416,422 ----
}
ctuple = heap_copytuple(tuple);
! ctupdesc = CopyTupleDesc(tupdesc, false);
cslot = MakeTupleTableSlot();
ExecSetSlotDescriptor(cslot, ctupdesc, true);
***************
*** 950,956 ****
tuptable->tuptabcxt = tuptabcxt;
tuptable->alloced = tuptable->free = 128;
tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
! tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
MemoryContextSwitchTo(oldcxt);
}
--- 950,956 ----
tuptable->tuptabcxt = tuptabcxt;
tuptable->alloced = tuptable->free = 128;
tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
! tuptable->tupdesc = CopyTupleDesc(typeinfo, false);
MemoryContextSwitchTo(oldcxt);
}
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/tcop/utility.c,v
retrieving revision 1.208
diff -c -r1.208 utility.c
*** src/backend/tcop/utility.c 2 Oct 2003 06:34:04 -0000 1.208
--- src/backend/tcop/utility.c 20 Nov 2003 21:31:51 -0000
***************
*** 1119,1125 ****
portal = GetPortalByName(stmt->portalname);
if (!PortalIsValid(portal))
return NULL; /* not our business to raise error */
! return CreateTupleDescCopy(portal->tupDesc);
}
case T_ExecuteStmt:
--- 1119,1125 ----
portal = GetPortalByName(stmt->portalname);
if (!PortalIsValid(portal))
return NULL; /* not our business to raise error */
! return CopyTupleDesc(portal->tupDesc, false);
}
case T_ExecuteStmt:
Index: src/backend/utils/cache/catcache.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/cache/catcache.c,v
retrieving revision 1.110
diff -c -r1.110 catcache.c
*** src/backend/utils/cache/catcache.c 12 Nov 2003 21:15:55 -0000 1.110
--- src/backend/utils/cache/catcache.c 20 Nov 2003 21:37:56 -0000
***************
*** 913,919 ****
/*
* copy the relcache's tuple descriptor to permanent cache storage
*/
! tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
/*
* get the relation's OID and relisshared flag, too
--- 913,919 ----
/*
* copy the relcache's tuple descriptor to permanent cache storage
*/
! tupdesc = CopyTupleDesc(RelationGetDescr(relation), true);
/*
* get the relation's OID and relisshared flag, too
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/cache/relcache.c,v
retrieving revision 1.192
diff -c -r1.192 relcache.c
*** src/backend/utils/cache/relcache.c 12 Nov 2003 21:15:56 -0000 1.192
--- src/backend/utils/cache/relcache.c 20 Nov 2003 21:32:12 -0000
***************
*** 2132,2138 ****
* multiple system catalogs. We can copy attnotnull constraints here,
* however.
*/
! rel->rd_att = CreateTupleDescCopy(tupDesc);
has_not_null = false;
for (i = 0; i < natts; i++)
{
--- 2132,2138 ----
* multiple system catalogs. We can copy attnotnull constraints here,
* however.
*/
! rel->rd_att = CopyTupleDesc(tupDesc, false);
has_not_null = false;
for (i = 0; i < natts; i++)
{
Index: src/include/access/tupdesc.h
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/include/access/tupdesc.h,v
retrieving revision 1.41
diff -c -r1.41 tupdesc.h
*** src/include/access/tupdesc.h 11 Aug 2003 23:04:50 -0000 1.41
--- src/include/access/tupdesc.h 20 Nov 2003 21:18:21 -0000
***************
*** 60,68 ****
extern TupleDesc CreateTupleDesc(int natts, bool hasoid,
Form_pg_attribute *attrs);
! extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc);
!
! extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc);
extern void FreeTupleDesc(TupleDesc tupdesc);
--- 60,66 ----
extern TupleDesc CreateTupleDesc(int natts, bool hasoid,
Form_pg_attribute *attrs);
! extern TupleDesc CopyTupleDesc(TupleDesc tupdesc, bool copyConstr);
extern void FreeTupleDesc(TupleDesc tupdesc);
Index: src/pl/plpgsql/src/pl_comp.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/pl/plpgsql/src/pl_comp.c,v
retrieving revision 1.69
diff -c -r1.69 pl_comp.c
*** src/pl/plpgsql/src/pl_comp.c 30 Sep 2003 00:59:51 -0000 1.69
--- src/pl/plpgsql/src/pl_comp.c 20 Nov 2003 21:33:44 -0000
***************
*** 1494,1500 ****
* memory context ...
*/
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
! row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
MemoryContextSwitchTo(oldcxt);
row->nfields = classStruct->relnatts;
--- 1494,1500 ----
* memory context ...
*/
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
! row->rowtupdesc = CopyTupleDesc(RelationGetDescr(rel), false);
MemoryContextSwitchTo(oldcxt);
row->nfields = classStruct->relnatts;
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.93
diff -c -r1.93 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c 1 Oct 2003 21:47:42 -0000 1.93
--- src/pl/plpgsql/src/pl_exec.c 20 Nov 2003 21:34:54 -0000
***************
*** 352,358 ****
MemoryContext oldcxt;
oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
! rsi->setDesc = CreateTupleDescCopy(estate.rettupdesc);
MemoryContextSwitchTo(oldcxt);
}
}
--- 352,358 ----
MemoryContext oldcxt;
oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
! rsi->setDesc = CopyTupleDesc(estate.rettupdesc, false);
MemoryContextSwitchTo(oldcxt);
}
}
***************
*** 3390,3396 ****
if (tupdesc)
{
! rec->tupdesc = CreateTupleDescCopy(tupdesc);
rec->freetupdesc = true;
}
else
--- 3390,3396 ----
if (tupdesc)
{
! rec->tupdesc = CopyTupleDesc(tupdesc, false);
rec->freetupdesc = true;
}
else
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faqs/FAQ.html