88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.61 2000/02/18 09:28:53 inoue Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.62 2000/02/21 03:36:49 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
1515#include "postgres.h"
16+
1617#include "access/genam.h"
18+ #include "access/hash.h"
1719#include "access/heapam.h"
1820#include "access/valid.h"
1921#include "catalog/pg_operator.h"
2830static void CatCacheRemoveCTup (CatCache * cache , Dlelem * e );
2931static Index CatalogCacheComputeHashIndex (struct catcache * cacheInP );
3032static Index CatalogCacheComputeTupleHashIndex (struct catcache * cacheInOutP ,
31- Relation relation , HeapTuple tuple );
33+ Relation relation ,
34+ HeapTuple tuple );
3235static void CatalogCacheInitializeCache (struct catcache * cache ,
33- Relation relation );
34- static long comphash ( long l , char * v );
36+ Relation relation );
37+ static uint32 cc_hashname ( NameData * n );
3538
3639/* ----------------
3740 * variables, macros and other stuff
@@ -63,14 +66,15 @@ GlobalMemory CacheCxt; /* context in which caches are allocated */
6366/* ----------------
6467 * EQPROC is used in CatalogCacheInitializeCache to find the equality
6568 * functions for system types that are used as cache key fields.
69+ * See also GetCCHashFunc, which should support the same set of types.
6670 *
6771 * XXX this should be replaced by catalog lookups,
6872 * but that seems to pose considerable risk of circularity...
6973 * ----------------
7074 */
7175static const Oid eqproc [] = {
7276 F_BOOLEQ , InvalidOid , F_CHAREQ , F_NAMEEQ , InvalidOid ,
73- F_INT2EQ , F_KEYFIRSTEQ , F_INT4EQ , F_OIDEQ , F_TEXTEQ ,
77+ F_INT2EQ , F_INT2VECTOREQ , F_INT4EQ , F_OIDEQ , F_TEXTEQ ,
7478 F_OIDEQ , InvalidOid , InvalidOid , InvalidOid , F_OIDVECTOREQ
7579};
7680
@@ -80,6 +84,54 @@ static const Oid eqproc[] = {
8084 * internal support functions
8185 * ----------------------------------------------------------------
8286 */
87+
88+ static CCHashFunc
89+ GetCCHashFunc (Oid keytype )
90+ {
91+ switch (keytype )
92+ {
93+ case BOOLOID :
94+ case CHAROID :
95+ return (CCHashFunc ) hashchar ;
96+ case NAMEOID :
97+ return (CCHashFunc ) cc_hashname ;
98+ case INT2OID :
99+ return (CCHashFunc ) hashint2 ;
100+ case INT2VECTOROID :
101+ return (CCHashFunc ) hashint2vector ;
102+ case INT4OID :
103+ return (CCHashFunc ) hashint4 ;
104+ case TEXTOID :
105+ return (CCHashFunc ) hashtext ;
106+ case REGPROCOID :
107+ case OIDOID :
108+ return (CCHashFunc ) hashoid ;
109+ case OIDVECTOROID :
110+ return (CCHashFunc ) hashoidvector ;
111+ default :
112+ elog (FATAL , "GetCCHashFunc: type %u unsupported as catcache key" ,
113+ keytype );
114+ return NULL ;
115+ }
116+ }
117+
118+ static uint32
119+ cc_hashname (NameData * n )
120+ {
121+ /*
122+ * We need our own variant of hashname because we want to accept
123+ * null-terminated C strings as search values for name fields.
124+ * So, we have to make sure the data is correctly padded before
125+ * we compute the hash value.
126+ */
127+ NameData my_n ;
128+
129+ namestrcpy (& my_n , NameStr (* n ));
130+
131+ return hashname (& my_n );
132+ }
133+
134+
83135/* --------------------------------
84136 * CatalogCacheInitializeCache
85137 * --------------------------------
@@ -190,31 +242,20 @@ CatalogCacheInitializeCache(struct catcache * cache,
190242
191243 if (cache -> cc_key [i ] > 0 )
192244 {
245+ Oid keytype = tupdesc -> attrs [cache -> cc_key [i ] - 1 ]-> atttypid ;
193246
194- /*
195- * Yoiks. The implementation of the hashing code and the
196- * implementation of int2vector's are at loggerheads. The right
197- * thing to do is to throw out the implementation of int2vector's
198- * altogether; until that happens, we do the right thing here
199- * to guarantee that the hash key generator doesn't try to
200- * dereference an int2 by mistake.
201- */
247+ cache -> cc_hashfunc [i ] = GetCCHashFunc (keytype );
202248
203- if (tupdesc -> attrs [cache -> cc_key [i ] - 1 ]-> atttypid == INT2VECTOROID )
204- cache -> cc_klen [i ] = sizeof (short );
205- else
206- cache -> cc_klen [i ] = tupdesc -> attrs [cache -> cc_key [i ] - 1 ]-> attlen ;
207-
208- cache -> cc_skey [i ].sk_procedure = EQPROC (tupdesc -> attrs [cache -> cc_key [i ] - 1 ]-> atttypid );
249+ /* If GetCCHashFunc liked the type, safe to index into eqproc[] */
250+ cache -> cc_skey [i ].sk_procedure = EQPROC (keytype );
209251
210252 fmgr_info (cache -> cc_skey [i ].sk_procedure ,
211253 & cache -> cc_skey [i ].sk_func );
212254 cache -> cc_skey [i ].sk_nargs = cache -> cc_skey [i ].sk_func .fn_nargs ;
213255
214- CACHE5_elog (DEBUG , "CatalogCacheInit %s %d %d %x" ,
256+ CACHE4_elog (DEBUG , "CatalogCacheInit %s %d %x" ,
215257 RelationGetRelationName (relation ),
216258 i ,
217- tupdesc -> attrs [cache -> cc_key [i ] - 1 ]-> attlen ,
218259 cache );
219260 }
220261 }
@@ -255,94 +296,44 @@ CatalogCacheInitializeCache(struct catcache * cache,
255296 MemoryContextSwitchTo (oldcxt );
256297}
257298
258- /* ----------------
259- * comphash
260- * Compute a hash value, somehow.
261- *
262- * XXX explain algorithm here.
263- *
264- * l is length of the attribute value, v
265- * v is the attribute value ("Datum")
266- * ----------------
267- */
268- static long
269- comphash (long l , char * v )
270- {
271- long i ;
272- NameData n ;
273-
274- CACHE3_elog (DEBUG , "comphash (%d,%x)" , l , v );
275-
276- switch (l )
277- {
278- case 1 :
279- case 2 :
280- case 4 :
281- return (long ) v ;
282- }
283-
284- if (l == NAMEDATALEN )
285- {
286-
287- /*
288- * if it's a name, make sure that the values are null-padded.
289- *
290- * Note that this other fixed-length types can also have the same
291- * typelen so this may break them - XXX
292- */
293- namestrcpy (& n , v );
294- v = NameStr (n );
295- }
296- else if (l < 0 )
297- l = VARSIZE (v );
298-
299- i = 0 ;
300- while (l -- )
301- i += * v ++ ;
302- return i ;
303- }
304-
305299/* --------------------------------
306300 * CatalogCacheComputeHashIndex
307301 * --------------------------------
308302 */
309303static Index
310304CatalogCacheComputeHashIndex (struct catcache * cacheInP )
311305{
312- Index hashIndex ;
306+ uint32 hashIndex = 0 ;
313307
314- hashIndex = 0x0 ;
315- CACHE6_elog (DEBUG , "CatalogCacheComputeHashIndex %s %d %d %d %x" ,
308+ CACHE4_elog (DEBUG , "CatalogCacheComputeHashIndex %s %d %x" ,
316309 cacheInP -> cc_relname ,
317310 cacheInP -> cc_nkeys ,
318- cacheInP -> cc_klen [0 ],
319- cacheInP -> cc_klen [1 ],
320311 cacheInP );
321312
322313 switch (cacheInP -> cc_nkeys )
323314 {
324315 case 4 :
325- hashIndex ^= comphash ( cacheInP -> cc_klen [ 3 ],
326- ( char * ) cacheInP -> cc_skey [3 ].sk_argument ) << 9 ;
316+ hashIndex ^=
317+ ( * cacheInP -> cc_hashfunc [ 3 ])( cacheInP -> cc_skey [3 ].sk_argument ) << 9 ;
327318 /* FALLTHROUGH */
328319 case 3 :
329- hashIndex ^= comphash ( cacheInP -> cc_klen [ 2 ],
330- ( char * ) cacheInP -> cc_skey [2 ].sk_argument ) << 6 ;
320+ hashIndex ^=
321+ ( * cacheInP -> cc_hashfunc [ 2 ])( cacheInP -> cc_skey [2 ].sk_argument ) << 6 ;
331322 /* FALLTHROUGH */
332323 case 2 :
333- hashIndex ^= comphash ( cacheInP -> cc_klen [ 1 ],
334- ( char * ) cacheInP -> cc_skey [1 ].sk_argument ) << 3 ;
324+ hashIndex ^=
325+ ( * cacheInP -> cc_hashfunc [ 1 ])( cacheInP -> cc_skey [1 ].sk_argument ) << 3 ;
335326 /* FALLTHROUGH */
336327 case 1 :
337- hashIndex ^= comphash ( cacheInP -> cc_klen [ 0 ],
338- ( char * ) cacheInP -> cc_skey [0 ].sk_argument );
328+ hashIndex ^=
329+ ( * cacheInP -> cc_hashfunc [ 0 ])( cacheInP -> cc_skey [0 ].sk_argument );
339330 break ;
340331 default :
341332 elog (FATAL , "CCComputeHashIndex: %d cc_nkeys" , cacheInP -> cc_nkeys );
342333 break ;
343334 }
344- hashIndex %= cacheInP -> cc_size ;
345- return hashIndex ;
335+ hashIndex %= ( uint32 ) cacheInP -> cc_size ;
336+ return ( Index ) hashIndex ;
346337}
347338
348339/* --------------------------------
@@ -645,8 +636,8 @@ do { \
645636 cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \
646637 for (i = 0; i < nkeys; i += 1) \
647638 { \
648- elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \
649- cp->cc_key[i], cp->cc_klen[i], \
639+ elog(DEBUG, "InitSysCache: key=%d skey=[%d %d %d %d]\n", \
640+ cp->cc_key[i], \
650641 cp->cc_skey[i].sk_flags, \
651642 cp->cc_skey[i].sk_attno, \
652643 cp->cc_skey[i].sk_procedure, \
@@ -742,7 +733,8 @@ InitSysCache(char *relname,
742733 cp -> cc_iscanfunc = iScanfuncP ;
743734
744735 /* ----------------
745- * initialize the cache's key information
736+ * partially initialize the cache's key information
737+ * CatalogCacheInitializeCache() will do the rest
746738 * ----------------
747739 */
748740 for (i = 0 ; i < nkeys ; ++ i )
@@ -756,15 +748,7 @@ InitSysCache(char *relname,
756748 elog (FATAL , "InitSysCache: called with %d key[%d]" , key [i ], i );
757749 else
758750 {
759- cp -> cc_klen [i ] = sizeof (Oid );
760-
761- /*
762- * ScanKeyEntryData and struct skey are equivalent. It
763- * looks like a move was made to obsolete struct skey, but
764- * it didn't reach this file. Someday we should clean up
765- * this code and consolidate to ScanKeyEntry - mer 10 Nov
766- * 1991
767- */
751+ cp -> cc_hashfunc [i ] = GetCCHashFunc (OIDOID );
768752 ScanKeyEntryInitialize (& cp -> cc_skey [i ],
769753 (bits16 ) 0 ,
770754 (AttrNumber ) key [i ],
0 commit comments