@@ -133,19 +133,12 @@ typedef struct TypeCacheEnumData
133133 *
134134 * Stored record types are remembered in a linear array of TupleDescs,
135135 * which can be indexed quickly with the assigned typmod. There is also
136- * a hash table to speed searches for matching TupleDescs. The hash key
137- * uses just the first N columns' type OIDs, and so we may have multiple
138- * entries with the same hash key.
136+ * a hash table to speed searches for matching TupleDescs.
139137 */
140- #define REC_HASH_KEYS 16 /* use this many columns in hash key */
141138
142139typedef struct RecordCacheEntry
143140{
144- /* the hash lookup key MUST BE FIRST */
145- Oid hashkey [REC_HASH_KEYS ]; /* column type IDs, zero-filled */
146-
147- /* list of TupleDescs for record types with this hashkey */
148- List * tupdescs ;
141+ TupleDesc tupdesc ;
149142} RecordCacheEntry ;
150143
151144static HTAB * RecordCacheHash = NULL ;
@@ -1297,6 +1290,28 @@ lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
12971290 return CreateTupleDescCopyConstr (tmp );
12981291}
12991292
1293+ /*
1294+ * Hash function for the hash table of RecordCacheEntry.
1295+ */
1296+ static uint32
1297+ record_type_typmod_hash (const void * data , size_t size )
1298+ {
1299+ RecordCacheEntry * entry = (RecordCacheEntry * ) data ;
1300+
1301+ return hashTupleDesc (entry -> tupdesc );
1302+ }
1303+
1304+ /*
1305+ * Match function for the hash table of RecordCacheEntry.
1306+ */
1307+ static int
1308+ record_type_typmod_compare (const void * a , const void * b , size_t size )
1309+ {
1310+ RecordCacheEntry * left = (RecordCacheEntry * ) a ;
1311+ RecordCacheEntry * right = (RecordCacheEntry * ) b ;
1312+
1313+ return equalTupleDescs (left -> tupdesc , right -> tupdesc ) ? 0 : 1 ;
1314+ }
13001315
13011316/*
13021317 * assign_record_type_typmod
@@ -1310,10 +1325,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
13101325{
13111326 RecordCacheEntry * recentry ;
13121327 TupleDesc entDesc ;
1313- Oid hashkey [REC_HASH_KEYS ];
13141328 bool found ;
1315- int i ;
1316- ListCell * l ;
13171329 int32 newtypmod ;
13181330 MemoryContext oldcxt ;
13191331
@@ -1325,45 +1337,31 @@ assign_record_type_typmod(TupleDesc tupDesc)
13251337 HASHCTL ctl ;
13261338
13271339 MemSet (& ctl , 0 , sizeof (ctl ));
1328- ctl .keysize = REC_HASH_KEYS * sizeof (Oid );
1340+ ctl .keysize = sizeof (TupleDesc ); /* just the pointer */
13291341 ctl .entrysize = sizeof (RecordCacheEntry );
1342+ ctl .hash = record_type_typmod_hash ;
1343+ ctl .match = record_type_typmod_compare ;
13301344 RecordCacheHash = hash_create ("Record information cache" , 64 ,
1331- & ctl , HASH_ELEM | HASH_BLOBS );
1345+ & ctl ,
1346+ HASH_ELEM | HASH_FUNCTION | HASH_COMPARE );
13321347
13331348 /* Also make sure CacheMemoryContext exists */
13341349 if (!CacheMemoryContext )
13351350 CreateCacheMemoryContext ();
13361351 }
13371352
1338- /* Find or create a hashtable entry for this hash class */
1339- MemSet (hashkey , 0 , sizeof (hashkey ));
1340- for (i = 0 ; i < tupDesc -> natts ; i ++ )
1341- {
1342- if (i >= REC_HASH_KEYS )
1343- break ;
1344- hashkey [i ] = TupleDescAttr (tupDesc , i )-> atttypid ;
1345- }
1353+ /* Find or create a hashtable entry for this tuple descriptor */
13461354 recentry = (RecordCacheEntry * ) hash_search (RecordCacheHash ,
1347- (void * ) hashkey ,
1355+ (void * ) & tupDesc ,
13481356 HASH_ENTER , & found );
1349- if (! found )
1357+ if (found && recentry -> tupdesc != NULL )
13501358 {
1351- /* New entry ... hash_search initialized only the hash key */
1352- recentry -> tupdescs = NIL ;
1353- }
1354-
1355- /* Look for existing record cache entry */
1356- foreach (l , recentry -> tupdescs )
1357- {
1358- entDesc = (TupleDesc ) lfirst (l );
1359- if (equalTupleDescs (tupDesc , entDesc ))
1360- {
1361- tupDesc -> tdtypmod = entDesc -> tdtypmod ;
1362- return ;
1363- }
1359+ tupDesc -> tdtypmod = recentry -> tupdesc -> tdtypmod ;
1360+ return ;
13641361 }
13651362
13661363 /* Not present, so need to manufacture an entry */
1364+ recentry -> tupdesc = NULL ;
13671365 oldcxt = MemoryContextSwitchTo (CacheMemoryContext );
13681366
13691367 if (RecordCacheArray == NULL )
@@ -1382,7 +1380,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
13821380
13831381 /* if fail in subrs, no damage except possibly some wasted memory... */
13841382 entDesc = CreateTupleDescCopy (tupDesc );
1385- recentry -> tupdescs = lcons ( entDesc , recentry -> tupdescs ) ;
1383+ recentry -> tupdesc = entDesc ;
13861384 /* mark it as a reference-counted tupdesc */
13871385 entDesc -> tdrefcount = 1 ;
13881386 /* now it's safe to advance NextRecordTypmod */
0 commit comments