@ -710,70 +710,122 @@ CheckAttributeType(const char *attname,
}
/*
* InsertPgAttributeTuple
* Construct and insert a new tuple in pg_attribute .
* Cap the maximum amount of bytes allocated for InsertPgAttributeTuples ( )
* slots .
*/
# define MAX_PGATTRIBUTE_INSERT_BYTES 65535
/*
* InsertPgAttributeTuples
* Construct and insert a set of tuples in pg_attribute .
*
* Caller has already opened and locked pg_attribute . new_attribute is the
* attribute to insert . attcacheoff is always initialized to - 1 , attacl ,
* attfdwoptions and attmissingval are always initialized to NULL .
* Caller has already opened and locked pg_attribute . tupdesc contains the
* attributes to insert . attcacheoff is always initialized to - 1 , attacl ,
* attfdwoptions and attmissingval are always initialized to NULL . attoptions
* must contain the same number of elements as tupdesc , or be NULL .
*
* indstate is the index state for CatalogTupleInsertWithInfo . It can be
* passed as NULL , in which case we ' ll fetch the necessary info . ( Don ' t do
* this when inserting multiple attributes , because it ' s a tad more
* expensive . )
*
* new_rel_oid is the relation OID assigned to the attributes inserted .
* If set to InvalidOid , the relation OID from tupdesc is used instead .
*/
void
InsertPgAttributeTuple ( Relation pg_attribute_rel ,
Form_pg_attribute new_attribute ,
Datum attoptions ,
CatalogIndexState indstate )
InsertPgAttributeTuples ( Relation pg_attribute_rel ,
TupleDesc tupdesc ,
Oid new_rel_oid ,
Datum * attoptions ,
CatalogIndexState indstate )
{
Datum values [ Natts_pg_attribute ] ;
bool nulls [ Natts_pg_attribute ] ;
HeapTuple tup ;
TupleTableSlot * * slot ;
TupleDesc td ;
int nslots ;
int natts = 0 ;
int slotCount = 0 ;
bool close_index = false ;
td = RelationGetDescr ( pg_attribute_rel ) ;
/* Initialize the number of slots to use */
nslots = Min ( tupdesc - > natts ,
( MAX_PGATTRIBUTE_INSERT_BYTES / sizeof ( FormData_pg_attribute ) ) ) ;
slot = palloc ( sizeof ( TupleTableSlot * ) * nslots ) ;
for ( int i = 0 ; i < nslots ; i + + )
slot [ i ] = MakeSingleTupleTableSlot ( td , & TTSOpsHeapTuple ) ;
while ( natts < tupdesc - > natts )
{
Form_pg_attribute attrs = TupleDescAttr ( tupdesc , natts ) ;
/* This is a tad tedious, but way cleaner than what we used to do... */
memset ( values , 0 , sizeof ( values ) ) ;
memset ( nulls , false , sizeof ( nulls ) ) ;
ExecClearTuple ( slot [ slotCount ] ) ;
values [ Anum_pg_attribute_attrelid - 1 ] = ObjectIdGetDatum ( new_attribute - > attrelid ) ;
values [ Anum_pg_attribute_attname - 1 ] = NameGetDatum ( & new_attribute - > attname ) ;
values [ Anum_pg_attribute_atttypid - 1 ] = ObjectIdGetDatum ( new_attribute - > atttypid ) ;
values [ Anum_pg_attribute_attstattarget - 1 ] = Int32GetDatum ( new_attribute - > attstattarget ) ;
values [ Anum_pg_attribute_attlen - 1 ] = Int16GetDatum ( new_attribute - > attlen ) ;
values [ Anum_pg_attribute_attnum - 1 ] = Int16GetDatum ( new_attribute - > attnum ) ;
values [ Anum_pg_attribute_attndims - 1 ] = Int32GetDatum ( new_attribute - > attndims ) ;
values [ Anum_pg_attribute_attcacheoff - 1 ] = Int32GetDatum ( - 1 ) ;
values [ Anum_pg_attribute_atttypmod - 1 ] = Int32GetDatum ( new_attribute - > atttypmod ) ;
values [ Anum_pg_attribute_attbyval - 1 ] = BoolGetDatum ( new_attribute - > attbyval ) ;
values [ Anum_pg_attribute_attstorage - 1 ] = CharGetDatum ( new_attribute - > attstorage ) ;
values [ Anum_pg_attribute_attalign - 1 ] = CharGetDatum ( new_attribute - > attalign ) ;
values [ Anum_pg_attribute_attnotnull - 1 ] = BoolGetDatum ( new_attribute - > attnotnull ) ;
values [ Anum_pg_attribute_atthasdef - 1 ] = BoolGetDatum ( new_attribute - > atthasdef ) ;
values [ Anum_pg_attribute_atthasmissing - 1 ] = BoolGetDatum ( new_attribute - > atthasmissing ) ;
values [ Anum_pg_attribute_attidentity - 1 ] = CharGetDatum ( new_attribute - > attidentity ) ;
values [ Anum_pg_attribute_attgenerated - 1 ] = CharGetDatum ( new_attribute - > attgenerated ) ;
values [ Anum_pg_attribute_attisdropped - 1 ] = BoolGetDatum ( new_attribute - > attisdropped ) ;
values [ Anum_pg_attribute_attislocal - 1 ] = BoolGetDatum ( new_attribute - > attislocal ) ;
values [ Anum_pg_attribute_attinhcount - 1 ] = Int32GetDatum ( new_attribute - > attinhcount ) ;
values [ Anum_pg_attribute_attcollation - 1 ] = ObjectIdGetDatum ( new_attribute - > attcollation ) ;
values [ Anum_pg_attribute_attoptions - 1 ] = attoptions ;
/* start out with empty permissions and empty options */
nulls [ Anum_pg_attribute_attacl - 1 ] = true ;
nulls [ Anum_pg_attribute_attoptions - 1 ] = attoptions = = ( Datum ) 0 ;
nulls [ Anum_pg_attribute_attfdwoptions - 1 ] = true ;
nulls [ Anum_pg_attribute_attmissingval - 1 ] = true ;
tup = heap_form_tuple ( RelationGetDescr ( pg_attribute_rel ) , values , nulls ) ;
if ( new_rel_oid ! = InvalidOid )
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attrelid - 1 ] = ObjectIdGetDatum ( new_rel_oid ) ;
else
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attrelid - 1 ] = ObjectIdGetDatum ( attrs - > attrelid ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attname - 1 ] = NameGetDatum ( & attrs - > attname ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_atttypid - 1 ] = ObjectIdGetDatum ( attrs - > atttypid ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attstattarget - 1 ] = Int32GetDatum ( attrs - > attstattarget ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attlen - 1 ] = Int16GetDatum ( attrs - > attlen ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attnum - 1 ] = Int16GetDatum ( attrs - > attnum ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attndims - 1 ] = Int32GetDatum ( attrs - > attndims ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attcacheoff - 1 ] = Int32GetDatum ( - 1 ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_atttypmod - 1 ] = Int32GetDatum ( attrs - > atttypmod ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attbyval - 1 ] = BoolGetDatum ( attrs - > attbyval ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attstorage - 1 ] = CharGetDatum ( attrs - > attstorage ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attalign - 1 ] = CharGetDatum ( attrs - > attalign ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attnotnull - 1 ] = BoolGetDatum ( attrs - > attnotnull ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_atthasdef - 1 ] = BoolGetDatum ( attrs - > atthasdef ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_atthasmissing - 1 ] = BoolGetDatum ( attrs - > atthasmissing ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attidentity - 1 ] = CharGetDatum ( attrs - > attidentity ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attgenerated - 1 ] = CharGetDatum ( attrs - > attgenerated ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attisdropped - 1 ] = BoolGetDatum ( attrs - > attisdropped ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attislocal - 1 ] = BoolGetDatum ( attrs - > attislocal ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attinhcount - 1 ] = Int32GetDatum ( attrs - > attinhcount ) ;
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attcollation - 1 ] = ObjectIdGetDatum ( attrs - > attcollation ) ;
if ( attoptions & & attoptions [ natts ] ! = ( Datum ) 0 )
slot [ slotCount ] - > tts_values [ Anum_pg_attribute_attoptions - 1 ] = attoptions [ natts ] ;
else
slot [ slotCount ] - > tts_isnull [ Anum_pg_attribute_attoptions - 1 ] = true ;
/* finally insert the new tuple, update the indexes, and clean up */
if ( indstate ! = NULL )
CatalogTupleInsertWithInfo ( pg_attribute_rel , tup , indstate ) ;
else
CatalogTupleInsert ( pg_attribute_rel , tup ) ;
/* start out with empty permissions and empty options */
slot [ slotCount ] - > tts_isnull [ Anum_pg_attribute_attacl - 1 ] = true ;
slot [ slotCount ] - > tts_isnull [ Anum_pg_attribute_attfdwoptions - 1 ] = true ;
slot [ slotCount ] - > tts_isnull [ Anum_pg_attribute_attmissingval - 1 ] = true ;
heap_freetuple ( tup ) ;
ExecStoreVirtualTuple ( slot [ slotCount ] ) ;
slotCount + + ;
/*
* If slots are full or the end of processing has been reached , insert
* a batch of tuples .
*/
if ( slotCount = = nslots | | natts = = tupdesc - > natts - 1 )
{
/* fetch index info only when we know we need it */
if ( ! indstate )
{
indstate = CatalogOpenIndexes ( pg_attribute_rel ) ;
close_index = true ;
}
/* insert the new tuples and update the indexes */
CatalogTuplesMultiInsertWithInfo ( pg_attribute_rel , slot , slotCount ,
indstate ) ;
slotCount = 0 ;
}
natts + + ;
}
if ( close_index )
CatalogCloseIndexes ( indstate ) ;
for ( int i = 0 ; i < nslots ; i + + )
ExecDropSingleTupleTableSlot ( slot [ i ] ) ;
pfree ( slot ) ;
}
/* --------------------------------
@ -788,8 +840,6 @@ AddNewAttributeTuples(Oid new_rel_oid,
TupleDesc tupdesc ,
char relkind )
{
Form_pg_attribute attr ;
int i ;
Relation rel ;
CatalogIndexState indstate ;
int natts = tupdesc - > natts ;
@ -803,30 +853,26 @@ AddNewAttributeTuples(Oid new_rel_oid,
indstate = CatalogOpenIndexes ( rel ) ;
/*
* First we add the user attributes . This is also a convenient place to
* add dependencies on their datatypes and collations .
*/
for ( i = 0 ; i < natts ; i + + )
{
attr = TupleDescAttr ( tupdesc , i ) ;
/* Fill in the correct relation OID */
attr - > attrelid = new_rel_oid ;
/* Make sure this is OK, too */
attr - > attstattarget = - 1 ;
InsertPgAttributeTuple ( rel , attr , ( Datum ) 0 , indstate ) ;
/* set stats detail level to a sane default */
for ( int i = 0 ; i < natts ; i + + )
tupdesc - > attrs [ i ] . attstattarget = - 1 ;
InsertPgAttributeTuples ( rel , tupdesc , new_rel_oid , NULL , indstate ) ;
/* add dependencies on their datatypes and collations */
for ( int i = 0 ; i < natts ; i + + )
{
/* Add dependency info */
ObjectAddressSubSet ( myself , RelationRelationId , new_rel_oid , i + 1 ) ;
ObjectAddressSet ( referenced , TypeRelationId , attr - > atttypid ) ;
ObjectAddressSet ( referenced , TypeRelationId ,
tupdesc - > attrs [ i ] . atttypid ) ;
recordDependencyOn ( & myself , & referenced , DEPENDENCY_NORMAL ) ;
/* The default collation is pinned, so don't bother recording it */
if ( OidIsValid ( attr - > attcollation ) & &
attr - > attcollation ! = DEFAULT_COLLATION_OID )
if ( OidIsValid ( tupdesc - > attrs [ i ] . attcollation ) & &
tupdesc - > attrs [ i ] . attcollation ! = DEFAULT_COLLATION_OID )
{
ObjectAddressSet ( referenced , CollationRelationId , attr - > attcollation ) ;
ObjectAddressSet ( referenced , CollationRelationId ,
tupdesc - > attrs [ i ] . attcollation ) ;
recordDependencyOn ( & myself , & referenced , DEPENDENCY_NORMAL ) ;
}
}
@ -838,17 +884,12 @@ AddNewAttributeTuples(Oid new_rel_oid,
*/
if ( relkind ! = RELKIND_VIEW & & relkind ! = RELKIND_COMPOSITE_TYPE )
{
for ( i = 0 ; i < ( int ) lengthof ( SysAtt ) ; i + + )
{
FormData_pg_attribute attStruct ;
TupleDesc td ;
memcpy ( & attStruct , SysAtt [ i ] , sizeof ( FormData_pg_attribute ) ) ;
td = CreateTupleDesc ( lengthof ( SysAtt ) , ( FormData_pg_attribute * * ) & SysAtt ) ;
/* Fill in the correct relation OID in the copied tuple */
attStruct . attrelid = new_rel_oid ;
InsertPgAttributeTuple ( rel , & attStruct , ( Datum ) 0 , indstate ) ;
}
InsertPgAttributeTuples ( rel , td , new_rel_oid , NULL , indstate ) ;
FreeTupleDesc ( td ) ;
}
/*