@@ -112,8 +112,9 @@ gistkillitems(IndexScanDesc scan)
112112 * Similarly, *recheck_distances_p is set to indicate whether the distances
113113 * need to be rechecked, and it is also ignored for non-leaf entries.
114114 *
115- * If we are doing an ordered scan, so->distances[] is filled with distance
116- * data from the distance() functions before returning success.
115+ * If we are doing an ordered scan, so->distancesValues[] and
116+ * so->distancesNulls[] is filled with distance data from the distance()
117+ * functions before returning success.
117118 *
118119 * We must decompress the key in the IndexTuple before passing it to the
119120 * sk_funcs (which actually are the opclass Consistent or Distance methods).
@@ -134,7 +135,8 @@ gistindex_keytest(IndexScanDesc scan,
134135GISTSTATE * giststate = so -> giststate ;
135136ScanKey key = scan -> keyData ;
136137int keySize = scan -> numberOfKeys ;
137- double * distance_p ;
138+ double * distance_value_p ;
139+ bool * distance_null_p ;
138140Relation r = scan -> indexRelation ;
139141
140142* recheck_p = false;
@@ -152,7 +154,10 @@ gistindex_keytest(IndexScanDesc scan,
152154if (GistPageIsLeaf (page ))/* shouldn't happen */
153155elog (ERROR ,"invalid GiST tuple found on leaf page" );
154156for (i = 0 ;i < scan -> numberOfOrderBys ;i ++ )
155- so -> distances [i ]= - get_float8_infinity ();
157+ {
158+ so -> distanceValues [i ]= - get_float8_infinity ();
159+ so -> distanceNulls [i ]= false;
160+ }
156161return true;
157162}
158163
@@ -235,7 +240,8 @@ gistindex_keytest(IndexScanDesc scan,
235240
236241/* OK, it passes --- now let's compute the distances */
237242key = scan -> orderByData ;
238- distance_p = so -> distances ;
243+ distance_value_p = so -> distanceValues ;
244+ distance_null_p = so -> distanceNulls ;
239245keySize = scan -> numberOfOrderBys ;
240246while (keySize > 0 )
241247{
@@ -249,8 +255,9 @@ gistindex_keytest(IndexScanDesc scan,
249255
250256if ((key -> sk_flags & SK_ISNULL )|| isNull )
251257{
252- /* Assume distance computes as null and sorts to the end */
253- * distance_p = get_float8_infinity ();
258+ /* Assume distance computes as null */
259+ * distance_value_p = 0.0 ;
260+ * distance_null_p = true;
254261}
255262else
256263{
@@ -287,11 +294,13 @@ gistindex_keytest(IndexScanDesc scan,
287294ObjectIdGetDatum (key -> sk_subtype ),
288295PointerGetDatum (& recheck ));
289296* recheck_distances_p |=recheck ;
290- * distance_p = DatumGetFloat8 (dist );
297+ * distance_value_p = DatumGetFloat8 (dist );
298+ * distance_null_p = false;
291299}
292300
293301key ++ ;
294- distance_p ++ ;
302+ distance_value_p ++ ;
303+ distance_null_p ++ ;
295304keySize -- ;
296305}
297306
@@ -304,7 +313,8 @@ gistindex_keytest(IndexScanDesc scan,
304313 *
305314 * scan: index scan we are executing
306315 * pageItem: search queue item identifying an index page to scan
307- * myDistances: distances array associated with pageItem, or NULL at the root
316+ * myDistanceValues: distances array associated with pageItem, or NULL at the root
317+ * myDistanceNulls: null flags for myDistanceValues array, or NULL at the root
308318 * tbm: if not NULL, gistgetbitmap's output bitmap
309319 * ntids: if not NULL, gistgetbitmap's output tuple counter
310320 *
@@ -321,7 +331,8 @@ gistindex_keytest(IndexScanDesc scan,
321331 * sibling will be processed next.
322332 */
323333static void
324- gistScanPage (IndexScanDesc scan ,GISTSearchItem * pageItem ,double * myDistances ,
334+ gistScanPage (IndexScanDesc scan ,GISTSearchItem * pageItem ,
335+ double * myDistanceValues ,bool * myDistanceNulls ,
325336TIDBitmap * tbm ,int64 * ntids )
326337{
327338GISTScanOpaque so = (GISTScanOpaque )scan -> opaque ;
@@ -359,7 +370,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
359370GISTSearchItem * item ;
360371
361372/* This can't happen when starting at the root */
362- Assert (myDistances != NULL );
373+ Assert (myDistanceValues != NULL && myDistanceNulls != NULL );
363374
364375oldcxt = MemoryContextSwitchTo (so -> queueCxt );
365376
@@ -369,8 +380,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
369380item -> data .parentlsn = pageItem -> data .parentlsn ;
370381
371382/* Insert it into the queue using same distances as for this page */
372- memcpy (item -> distances ,myDistances ,
373- sizeof (double )* scan -> numberOfOrderBys );
383+ memcpy (GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
384+ myDistanceValues ,sizeof (double )* scan -> numberOfOrderBys );
385+ memcpy (GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
386+ myDistanceNulls ,sizeof (bool )* scan -> numberOfOrderBys );
374387
375388pairingheap_add (so -> queue ,& item -> phNode );
376389
@@ -479,6 +492,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
479492 * search.
480493 */
481494GISTSearchItem * item ;
495+ int nOrderBys = scan -> numberOfOrderBys ;
482496
483497oldcxt = MemoryContextSwitchTo (so -> queueCxt );
484498
@@ -513,8 +527,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
513527}
514528
515529/* Insert it into the queue using new distance data */
516- memcpy (item -> distances ,so -> distances ,
517- sizeof (double )* scan -> numberOfOrderBys );
530+ memcpy (GISTSearchItemDistanceValues (item ,nOrderBys ),
531+ so -> distanceValues ,sizeof (double )* nOrderBys );
532+ memcpy (GISTSearchItemDistanceNulls (item ,nOrderBys ),
533+ so -> distanceNulls ,sizeof (bool )* nOrderBys );
518534
519535pairingheap_add (so -> queue ,& item -> phNode );
520536
@@ -579,7 +595,8 @@ getNextNearest(IndexScanDesc scan)
579595scan -> xs_recheck = item -> data .heap .recheck ;
580596
581597index_store_float8_orderby_distances (scan ,so -> orderByTypes ,
582- item -> distances ,
598+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
599+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
583600item -> data .heap .recheckDistances );
584601
585602/* in an index-only scan, also return the reconstructed tuple. */
@@ -592,7 +609,10 @@ getNextNearest(IndexScanDesc scan)
592609/* visit an index page, extract its items into queue */
593610CHECK_FOR_INTERRUPTS ();
594611
595- gistScanPage (scan ,item ,item -> distances ,NULL ,NULL );
612+ gistScanPage (scan ,item ,
613+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
614+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
615+ NULL ,NULL );
596616}
597617
598618pfree (item );
@@ -630,7 +650,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
630650
631651fakeItem .blkno = GIST_ROOT_BLKNO ;
632652memset (& fakeItem .data .parentlsn ,0 ,sizeof (GistNSN ));
633- gistScanPage (scan ,& fakeItem ,NULL ,NULL ,NULL );
653+ gistScanPage (scan ,& fakeItem ,NULL ,NULL ,NULL , NULL );
634654}
635655
636656if (scan -> numberOfOrderBys > 0 )
@@ -724,7 +744,10 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
724744 * this page, we fall out of the inner "do" and loop around to
725745 * return them.
726746 */
727- gistScanPage (scan ,item ,item -> distances ,NULL ,NULL );
747+ gistScanPage (scan ,item ,
748+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
749+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
750+ NULL ,NULL );
728751
729752pfree (item );
730753}while (so -> nPageData == 0 );
@@ -755,7 +778,7 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
755778
756779fakeItem .blkno = GIST_ROOT_BLKNO ;
757780memset (& fakeItem .data .parentlsn ,0 ,sizeof (GistNSN ));
758- gistScanPage (scan ,& fakeItem ,NULL ,tbm ,& ntids );
781+ gistScanPage (scan ,& fakeItem ,NULL ,NULL , tbm ,& ntids );
759782
760783/*
761784 * While scanning a leaf page, ItemPointers of matching heap tuples will
@@ -770,7 +793,10 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
770793
771794CHECK_FOR_INTERRUPTS ();
772795
773- gistScanPage (scan ,item ,item -> distances ,tbm ,& ntids );
796+ gistScanPage (scan ,item ,
797+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
798+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
799+ tbm ,& ntids );
774800
775801pfree (item );
776802}