@@ -112,8 +112,9 @@ gistkillitems(IndexScanDesc scan)
112
112
* Similarly, *recheck_distances_p is set to indicate whether the distances
113
113
* need to be rechecked, and it is also ignored for non-leaf entries.
114
114
*
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.
117
118
*
118
119
* We must decompress the key in the IndexTuple before passing it to the
119
120
* sk_funcs (which actually are the opclass Consistent or Distance methods).
@@ -134,7 +135,8 @@ gistindex_keytest(IndexScanDesc scan,
134
135
GISTSTATE * giststate = so -> giststate ;
135
136
ScanKey key = scan -> keyData ;
136
137
int keySize = scan -> numberOfKeys ;
137
- double * distance_p ;
138
+ double * distance_value_p ;
139
+ bool * distance_null_p ;
138
140
Relation r = scan -> indexRelation ;
139
141
140
142
* recheck_p = false;
@@ -152,7 +154,10 @@ gistindex_keytest(IndexScanDesc scan,
152
154
if (GistPageIsLeaf (page ))/* shouldn't happen */
153
155
elog (ERROR ,"invalid GiST tuple found on leaf page" );
154
156
for (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
+ }
156
161
return true;
157
162
}
158
163
@@ -235,7 +240,8 @@ gistindex_keytest(IndexScanDesc scan,
235
240
236
241
/* OK, it passes --- now let's compute the distances */
237
242
key = scan -> orderByData ;
238
- distance_p = so -> distances ;
243
+ distance_value_p = so -> distanceValues ;
244
+ distance_null_p = so -> distanceNulls ;
239
245
keySize = scan -> numberOfOrderBys ;
240
246
while (keySize > 0 )
241
247
{
@@ -249,8 +255,9 @@ gistindex_keytest(IndexScanDesc scan,
249
255
250
256
if ((key -> sk_flags & SK_ISNULL )|| isNull )
251
257
{
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;
254
261
}
255
262
else
256
263
{
@@ -287,11 +294,13 @@ gistindex_keytest(IndexScanDesc scan,
287
294
ObjectIdGetDatum (key -> sk_subtype ),
288
295
PointerGetDatum (& recheck ));
289
296
* recheck_distances_p |=recheck ;
290
- * distance_p = DatumGetFloat8 (dist );
297
+ * distance_value_p = DatumGetFloat8 (dist );
298
+ * distance_null_p = false;
291
299
}
292
300
293
301
key ++ ;
294
- distance_p ++ ;
302
+ distance_value_p ++ ;
303
+ distance_null_p ++ ;
295
304
keySize -- ;
296
305
}
297
306
@@ -304,7 +313,8 @@ gistindex_keytest(IndexScanDesc scan,
304
313
*
305
314
* scan: index scan we are executing
306
315
* 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
308
318
* tbm: if not NULL, gistgetbitmap's output bitmap
309
319
* ntids: if not NULL, gistgetbitmap's output tuple counter
310
320
*
@@ -321,7 +331,8 @@ gistindex_keytest(IndexScanDesc scan,
321
331
* sibling will be processed next.
322
332
*/
323
333
static void
324
- gistScanPage (IndexScanDesc scan ,GISTSearchItem * pageItem ,double * myDistances ,
334
+ gistScanPage (IndexScanDesc scan ,GISTSearchItem * pageItem ,
335
+ double * myDistanceValues ,bool * myDistanceNulls ,
325
336
TIDBitmap * tbm ,int64 * ntids )
326
337
{
327
338
GISTScanOpaque so = (GISTScanOpaque )scan -> opaque ;
@@ -359,7 +370,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
359
370
GISTSearchItem * item ;
360
371
361
372
/* This can't happen when starting at the root */
362
- Assert (myDistances != NULL );
373
+ Assert (myDistanceValues != NULL && myDistanceNulls != NULL );
363
374
364
375
oldcxt = MemoryContextSwitchTo (so -> queueCxt );
365
376
@@ -369,8 +380,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
369
380
item -> data .parentlsn = pageItem -> data .parentlsn ;
370
381
371
382
/* 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 );
374
387
375
388
pairingheap_add (so -> queue ,& item -> phNode );
376
389
@@ -465,6 +478,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
465
478
* search.
466
479
*/
467
480
GISTSearchItem * item ;
481
+ int nOrderBys = scan -> numberOfOrderBys ;
468
482
469
483
oldcxt = MemoryContextSwitchTo (so -> queueCxt );
470
484
@@ -499,8 +513,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
499
513
}
500
514
501
515
/* Insert it into the queue using new distance data */
502
- memcpy (item -> distances ,so -> distances ,
503
- sizeof (double )* scan -> numberOfOrderBys );
516
+ memcpy (GISTSearchItemDistanceValues (item ,nOrderBys ),
517
+ so -> distanceValues ,sizeof (double )* nOrderBys );
518
+ memcpy (GISTSearchItemDistanceNulls (item ,nOrderBys ),
519
+ so -> distanceNulls ,sizeof (bool )* nOrderBys );
504
520
505
521
pairingheap_add (so -> queue ,& item -> phNode );
506
522
@@ -555,6 +571,8 @@ getNextNearest(IndexScanDesc scan)
555
571
do
556
572
{
557
573
GISTSearchItem * item = getNextGISTSearchItem (so );
574
+ float8 * distanceValues = GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys );
575
+ bool * distanceNulls = GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys );
558
576
559
577
if (!item )
560
578
break ;
@@ -574,8 +592,8 @@ getNextNearest(IndexScanDesc scan)
574
592
if (!scan -> xs_orderbynulls [i ])
575
593
pfree (DatumGetPointer (scan -> xs_orderbyvals [i ]));
576
594
#endif
577
- scan -> xs_orderbyvals [i ]= Float8GetDatum (item -> distances [i ]);
578
- scan -> xs_orderbynulls [i ]= false ;
595
+ scan -> xs_orderbyvals [i ]= Float8GetDatum (distanceValues [i ]);
596
+ scan -> xs_orderbynulls [i ]= distanceNulls [ i ] ;
579
597
}
580
598
else if (so -> orderByTypes [i ]== FLOAT4OID )
581
599
{
@@ -585,8 +603,8 @@ getNextNearest(IndexScanDesc scan)
585
603
if (!scan -> xs_orderbynulls [i ])
586
604
pfree (DatumGetPointer (scan -> xs_orderbyvals [i ]));
587
605
#endif
588
- scan -> xs_orderbyvals [i ]= Float4GetDatum (( float4 ) item -> distances [i ]);
589
- scan -> xs_orderbynulls [i ]= false ;
606
+ scan -> xs_orderbyvals [i ]= Float4GetDatum (distanceValues [i ]);
607
+ scan -> xs_orderbynulls [i ]= distanceNulls [ i ] ;
590
608
}
591
609
else
592
610
{
@@ -614,7 +632,10 @@ getNextNearest(IndexScanDesc scan)
614
632
/* visit an index page, extract its items into queue */
615
633
CHECK_FOR_INTERRUPTS ();
616
634
617
- gistScanPage (scan ,item ,item -> distances ,NULL ,NULL );
635
+ gistScanPage (scan ,item ,
636
+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
637
+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
638
+ NULL ,NULL );
618
639
}
619
640
620
641
pfree (item );
@@ -652,7 +673,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
652
673
653
674
fakeItem .blkno = GIST_ROOT_BLKNO ;
654
675
memset (& fakeItem .data .parentlsn ,0 ,sizeof (GistNSN ));
655
- gistScanPage (scan ,& fakeItem ,NULL ,NULL ,NULL );
676
+ gistScanPage (scan ,& fakeItem ,NULL ,NULL ,NULL , NULL );
656
677
}
657
678
658
679
if (scan -> numberOfOrderBys > 0 )
@@ -746,7 +767,10 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
746
767
* this page, we fall out of the inner "do" and loop around to
747
768
* return them.
748
769
*/
749
- gistScanPage (scan ,item ,item -> distances ,NULL ,NULL );
770
+ gistScanPage (scan ,item ,
771
+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
772
+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
773
+ NULL ,NULL );
750
774
751
775
pfree (item );
752
776
}while (so -> nPageData == 0 );
@@ -777,7 +801,7 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
777
801
778
802
fakeItem .blkno = GIST_ROOT_BLKNO ;
779
803
memset (& fakeItem .data .parentlsn ,0 ,sizeof (GistNSN ));
780
- gistScanPage (scan ,& fakeItem ,NULL ,tbm ,& ntids );
804
+ gistScanPage (scan ,& fakeItem ,NULL ,NULL , tbm ,& ntids );
781
805
782
806
/*
783
807
* While scanning a leaf page, ItemPointers of matching heap tuples will
@@ -792,7 +816,10 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
792
816
793
817
CHECK_FOR_INTERRUPTS ();
794
818
795
- gistScanPage (scan ,item ,item -> distances ,tbm ,& ntids );
819
+ gistScanPage (scan ,item ,
820
+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
821
+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
822
+ tbm ,& ntids );
796
823
797
824
pfree (item );
798
825
}