@@ -133,19 +133,12 @@ typedef struct TypeCacheEnumData
133
133
*
134
134
* Stored record types are remembered in a linear array of TupleDescs,
135
135
* 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.
139
137
*/
140
- #define REC_HASH_KEYS 16 /* use this many columns in hash key */
141
138
142
139
typedef struct RecordCacheEntry
143
140
{
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 ;
149
142
} RecordCacheEntry ;
150
143
151
144
static HTAB * RecordCacheHash = NULL ;
@@ -1297,6 +1290,28 @@ lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
1297
1290
return CreateTupleDescCopyConstr (tmp );
1298
1291
}
1299
1292
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
+ }
1300
1315
1301
1316
/*
1302
1317
* assign_record_type_typmod
@@ -1310,10 +1325,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
1310
1325
{
1311
1326
RecordCacheEntry * recentry ;
1312
1327
TupleDesc entDesc ;
1313
- Oid hashkey [REC_HASH_KEYS ];
1314
1328
bool found ;
1315
- int i ;
1316
- ListCell * l ;
1317
1329
int32 newtypmod ;
1318
1330
MemoryContext oldcxt ;
1319
1331
@@ -1325,45 +1337,31 @@ assign_record_type_typmod(TupleDesc tupDesc)
1325
1337
HASHCTL ctl ;
1326
1338
1327
1339
MemSet (& ctl , 0 , sizeof (ctl ));
1328
- ctl .keysize = REC_HASH_KEYS * sizeof (Oid );
1340
+ ctl .keysize = sizeof (TupleDesc ); /* just the pointer */
1329
1341
ctl .entrysize = sizeof (RecordCacheEntry );
1342
+ ctl .hash = record_type_typmod_hash ;
1343
+ ctl .match = record_type_typmod_compare ;
1330
1344
RecordCacheHash = hash_create ("Record information cache" , 64 ,
1331
- & ctl , HASH_ELEM | HASH_BLOBS );
1345
+ & ctl ,
1346
+ HASH_ELEM | HASH_FUNCTION | HASH_COMPARE );
1332
1347
1333
1348
/* Also make sure CacheMemoryContext exists */
1334
1349
if (!CacheMemoryContext )
1335
1350
CreateCacheMemoryContext ();
1336
1351
}
1337
1352
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 */
1346
1354
recentry = (RecordCacheEntry * ) hash_search (RecordCacheHash ,
1347
- (void * ) hashkey ,
1355
+ (void * ) & tupDesc ,
1348
1356
HASH_ENTER , & found );
1349
- if (! found )
1357
+ if (found && recentry -> tupdesc != NULL )
1350
1358
{
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 ;
1364
1361
}
1365
1362
1366
1363
/* Not present, so need to manufacture an entry */
1364
+ recentry -> tupdesc = NULL ;
1367
1365
oldcxt = MemoryContextSwitchTo (CacheMemoryContext );
1368
1366
1369
1367
if (RecordCacheArray == NULL )
@@ -1382,7 +1380,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
1382
1380
1383
1381
/* if fail in subrs, no damage except possibly some wasted memory... */
1384
1382
entDesc = CreateTupleDescCopy (tupDesc );
1385
- recentry -> tupdescs = lcons ( entDesc , recentry -> tupdescs ) ;
1383
+ recentry -> tupdesc = entDesc ;
1386
1384
/* mark it as a reference-counted tupdesc */
1387
1385
entDesc -> tdrefcount = 1 ;
1388
1386
/* now it's safe to advance NextRecordTypmod */
0 commit comments