@@ -190,54 +190,63 @@ gtrgm_consistent(PG_FUNCTION_ARGS)
190190TRGM * key = (TRGM * )DatumGetPointer (entry -> key );
191191TRGM * qtrg ;
192192bool res ;
193+ Size querysize = VARSIZE (query );
193194char * cache = (char * )fcinfo -> flinfo -> fn_extra ,
194- * cacheContents = cache + MAXALIGN (sizeof (StrategyNumber ));
195+ * cachedQuery = cache + MAXALIGN (sizeof (StrategyNumber ));
195196
196197/*
197198 * Store both the strategy number and extracted trigrams in cache, because
198199 * trigram extraction is relatively CPU-expensive.We must include
199200 * strategy number because trigram extraction depends on strategy.
201+ *
202+ * The cached structure contains the strategy number, then the input
203+ * query (starting at a MAXALIGN boundary), then the TRGM value (also
204+ * starting at a MAXALIGN boundary).
200205 */
201- if (cache == NULL || strategy != * ((StrategyNumber * )cache )||
202- VARSIZE (cacheContents )!= VARSIZE (query )||
203- memcmp (cacheContents ,query ,VARSIZE (query ))!= 0 )
206+ if (cache == NULL ||
207+ strategy != * ((StrategyNumber * )cache )||
208+ VARSIZE (cachedQuery )!= querysize ||
209+ memcmp (cachedQuery ,query ,querysize )!= 0 )
204210{
211+ char * newcache ;
212+
205213switch (strategy )
206214{
207215case SimilarityStrategyNumber :
208- qtrg = generate_trgm (VARDATA (query ),VARSIZE (query )- VARHDRSZ );
216+ qtrg = generate_trgm (VARDATA (query ),
217+ querysize - VARHDRSZ );
209218break ;
210219case ILikeStrategyNumber :
211220#ifndef IGNORECASE
212221elog (ERROR ,"cannot handle ~~* with case-sensitive trigrams" );
213222#endif
214223/* FALL THRU */
215224case LikeStrategyNumber :
216- qtrg = generate_wildcard_trgm (VARDATA (query ),VARSIZE (query )- VARHDRSZ );
225+ qtrg = generate_wildcard_trgm (VARDATA (query ),
226+ querysize - VARHDRSZ );
217227break ;
218228default :
219229elog (ERROR ,"unrecognized strategy number: %d" ,strategy );
220230qtrg = NULL ;/* keep compiler quiet */
221231break ;
222232}
223233
234+ newcache = MemoryContextAlloc (fcinfo -> flinfo -> fn_mcxt ,
235+ MAXALIGN (sizeof (StrategyNumber ))+
236+ MAXALIGN (querysize )+
237+ VARSIZE (qtrg ));
238+ cachedQuery = newcache + MAXALIGN (sizeof (StrategyNumber ));
239+
240+ * ((StrategyNumber * )newcache )= strategy ;
241+ memcpy (cachedQuery ,query ,querysize );
242+ memcpy (cachedQuery + MAXALIGN (querysize ),qtrg ,VARSIZE (qtrg ));
243+
224244if (cache )
225245pfree (cache );
226-
227- fcinfo -> flinfo -> fn_extra =
228- MemoryContextAlloc (fcinfo -> flinfo -> fn_mcxt ,
229- MAXALIGN (sizeof (StrategyNumber ))+
230- MAXALIGN (VARSIZE (query ))+
231- VARSIZE (qtrg ));
232- cache = (char * )fcinfo -> flinfo -> fn_extra ;
233- cacheContents = cache + MAXALIGN (sizeof (StrategyNumber ));
234-
235- * ((StrategyNumber * )cache )= strategy ;
236- memcpy (cacheContents ,query ,VARSIZE (query ));
237- memcpy (cacheContents + MAXALIGN (VARSIZE (query )),qtrg ,VARSIZE (qtrg ));
246+ fcinfo -> flinfo -> fn_extra = newcache ;
238247}
239248
240- qtrg = (TRGM * ) (cacheContents + MAXALIGN (VARSIZE ( query ) ));
249+ qtrg = (TRGM * ) (cachedQuery + MAXALIGN (querysize ));
241250
242251switch (strategy )
243252{
@@ -328,24 +337,35 @@ gtrgm_distance(PG_FUNCTION_ARGS)
328337TRGM * key = (TRGM * )DatumGetPointer (entry -> key );
329338TRGM * qtrg ;
330339float8 res ;
340+ Size querysize = VARSIZE (query );
331341char * cache = (char * )fcinfo -> flinfo -> fn_extra ;
332342
333- if (cache == NULL || VARSIZE (cache )!= VARSIZE (query )|| memcmp (cache ,query ,VARSIZE (query ))!= 0 )
343+ /*
344+ * Cache the generated trigrams across multiple calls with the same
345+ * query.
346+ */
347+ if (cache == NULL ||
348+ VARSIZE (cache )!= querysize ||
349+ memcmp (cache ,query ,querysize )!= 0 )
334350{
335- qtrg = generate_trgm ( VARDATA ( query ), VARSIZE ( query ) - VARHDRSZ ) ;
351+ char * newcache ;
336352
337- if (cache )
338- pfree (cache );
353+ qtrg = generate_trgm (VARDATA (query ),querysize - VARHDRSZ );
354+
355+ newcache = MemoryContextAlloc (fcinfo -> flinfo -> fn_mcxt ,
356+ MAXALIGN (querysize )+
357+ VARSIZE (qtrg ));
339358
340- fcinfo -> flinfo -> fn_extra = MemoryContextAlloc (fcinfo -> flinfo -> fn_mcxt ,
341- MAXALIGN (VARSIZE (query ))+ VARSIZE (qtrg ));
342- cache = (char * )fcinfo -> flinfo -> fn_extra ;
359+ memcpy (newcache ,query ,querysize );
360+ memcpy (newcache + MAXALIGN (querysize ),qtrg ,VARSIZE (qtrg ));
343361
344- memcpy (cache ,query ,VARSIZE (query ));
345- memcpy (cache + MAXALIGN (VARSIZE (query )),qtrg ,VARSIZE (qtrg ));
362+ if (cache )
363+ pfree (cache );
364+ fcinfo -> flinfo -> fn_extra = newcache ;
365+ cache = newcache ;
346366}
347367
348- qtrg = (TRGM * ) (cache + MAXALIGN (VARSIZE ( query ) ));
368+ qtrg = (TRGM * ) (cache + MAXALIGN (querysize ));
349369
350370switch (strategy )
351371{
@@ -552,9 +572,36 @@ gtrgm_penalty(PG_FUNCTION_ARGS)
552572
553573if (ISARRKEY (newval ))
554574{
555- BITVEC sign ;
575+ char * cache = (char * )fcinfo -> flinfo -> fn_extra ;
576+ TRGM * cachedVal = (TRGM * ) (cache + MAXALIGN (sizeof (BITVEC )));
577+ Size newvalsize = VARSIZE (newval );
578+ BITVECP sign ;
579+
580+ /*
581+ * Cache the sign data across multiple calls with the same newval.
582+ */
583+ if (cache == NULL ||
584+ VARSIZE (cachedVal )!= newvalsize ||
585+ memcmp (cachedVal ,newval ,newvalsize )!= 0 )
586+ {
587+ char * newcache ;
588+
589+ newcache = MemoryContextAlloc (fcinfo -> flinfo -> fn_mcxt ,
590+ MAXALIGN (sizeof (BITVEC ))+
591+ newvalsize );
592+
593+ makesign ((BITVECP )newcache ,newval );
556594
557- makesign (sign ,newval );
595+ cachedVal = (TRGM * ) (newcache + MAXALIGN (sizeof (BITVEC )));
596+ memcpy (cachedVal ,newval ,newvalsize );
597+
598+ if (cache )
599+ pfree (cache );
600+ fcinfo -> flinfo -> fn_extra = newcache ;
601+ cache = newcache ;
602+ }
603+
604+ sign = (BITVECP )cache ;
558605
559606if (ISALLTRUE (origval ))
560607* penalty = ((float ) (SIGLENBIT - sizebitvec (sign ))) / (float ) (SIGLENBIT + 1 );
@@ -643,20 +690,16 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
643690CACHESIGN * cache ;
644691SPLITCOST * costvector ;
645692
646- nbytes = (maxoff + 2 )* sizeof (OffsetNumber );
647- v -> spl_left = (OffsetNumber * )palloc (nbytes );
648- v -> spl_right = (OffsetNumber * )palloc (nbytes );
649-
693+ /* cache the sign data for each existing item */
650694cache = (CACHESIGN * )palloc (sizeof (CACHESIGN )* (maxoff + 2 ));
651- fillcache (& cache [FirstOffsetNumber ],GETENTRY (entryvec ,FirstOffsetNumber ));
695+ for (k = FirstOffsetNumber ;k <=maxoff ;k = OffsetNumberNext (k ))
696+ fillcache (& cache [k ],GETENTRY (entryvec ,k ));
652697
698+ /* now find the two furthest-apart items */
653699for (k = FirstOffsetNumber ;k < maxoff ;k = OffsetNumberNext (k ))
654700{
655701for (j = OffsetNumberNext (k );j <=maxoff ;j = OffsetNumberNext (j ))
656702{
657- if (k == FirstOffsetNumber )
658- fillcache (& cache [j ],GETENTRY (entryvec ,j ));
659-
660703size_waste = hemdistcache (& (cache [j ]),& (cache [k ]));
661704if (size_waste > waste )
662705{
@@ -667,17 +710,20 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
667710}
668711}
669712
670- left = v -> spl_left ;
671- v -> spl_nleft = 0 ;
672- right = v -> spl_right ;
673- v -> spl_nright = 0 ;
674-
713+ /* just in case we didn't make a selection ... */
675714if (seed_1 == 0 || seed_2 == 0 )
676715{
677716seed_1 = 1 ;
678717seed_2 = 2 ;
679718}
680719
720+ /* initialize the result vectors */
721+ nbytes = (maxoff + 2 )* sizeof (OffsetNumber );
722+ v -> spl_left = left = (OffsetNumber * )palloc (nbytes );
723+ v -> spl_right = right = (OffsetNumber * )palloc (nbytes );
724+ v -> spl_nleft = 0 ;
725+ v -> spl_nright = 0 ;
726+
681727/* form initial .. */
682728if (cache [seed_1 ].allistrue )
683729{