@@ -110,8 +110,9 @@ gistkillitems(IndexScanDesc scan)
110
110
* Similarly, *recheck_distances_p is set to indicate whether the distances
111
111
* need to be rechecked, and it is also ignored for non-leaf entries.
112
112
*
113
- * If we are doing an ordered scan, so->distances[] is filled with distance
114
- * data from the distance() functions before returning success.
113
+ * If we are doing an ordered scan, so->distancesValues[] and
114
+ * so->distancesNulls[] is filled with distance data from the distance()
115
+ * functions before returning success.
115
116
*
116
117
* We must decompress the key in the IndexTuple before passing it to the
117
118
* sk_funcs (which actually are the opclass Consistent or Distance methods).
@@ -132,7 +133,8 @@ gistindex_keytest(IndexScanDesc scan,
132
133
GISTSTATE * giststate = so -> giststate ;
133
134
ScanKey key = scan -> keyData ;
134
135
int keySize = scan -> numberOfKeys ;
135
- double * distance_p ;
136
+ double * distance_value_p ;
137
+ bool * distance_null_p ;
136
138
Relation r = scan -> indexRelation ;
137
139
138
140
* recheck_p = false;
@@ -150,7 +152,10 @@ gistindex_keytest(IndexScanDesc scan,
150
152
if (GistPageIsLeaf (page ))/* shouldn't happen */
151
153
elog (ERROR ,"invalid GiST tuple found on leaf page" );
152
154
for (i = 0 ;i < scan -> numberOfOrderBys ;i ++ )
153
- so -> distances [i ]= - get_float8_infinity ();
155
+ {
156
+ so -> distanceValues [i ]= - get_float8_infinity ();
157
+ so -> distanceNulls [i ]= false;
158
+ }
154
159
return true;
155
160
}
156
161
@@ -233,7 +238,8 @@ gistindex_keytest(IndexScanDesc scan,
233
238
234
239
/* OK, it passes --- now let's compute the distances */
235
240
key = scan -> orderByData ;
236
- distance_p = so -> distances ;
241
+ distance_value_p = so -> distanceValues ;
242
+ distance_null_p = so -> distanceNulls ;
237
243
keySize = scan -> numberOfOrderBys ;
238
244
while (keySize > 0 )
239
245
{
@@ -247,8 +253,9 @@ gistindex_keytest(IndexScanDesc scan,
247
253
248
254
if ((key -> sk_flags & SK_ISNULL )|| isNull )
249
255
{
250
- /* Assume distance computes as null and sorts to the end */
251
- * distance_p = get_float8_infinity ();
256
+ /* Assume distance computes as null */
257
+ * distance_value_p = 0.0 ;
258
+ * distance_null_p = true;
252
259
}
253
260
else
254
261
{
@@ -285,11 +292,13 @@ gistindex_keytest(IndexScanDesc scan,
285
292
ObjectIdGetDatum (key -> sk_subtype ),
286
293
PointerGetDatum (& recheck ));
287
294
* recheck_distances_p |=recheck ;
288
- * distance_p = DatumGetFloat8 (dist );
295
+ * distance_value_p = DatumGetFloat8 (dist );
296
+ * distance_null_p = false;
289
297
}
290
298
291
299
key ++ ;
292
- distance_p ++ ;
300
+ distance_value_p ++ ;
301
+ distance_null_p ++ ;
293
302
keySize -- ;
294
303
}
295
304
@@ -302,7 +311,8 @@ gistindex_keytest(IndexScanDesc scan,
302
311
*
303
312
* scan: index scan we are executing
304
313
* pageItem: search queue item identifying an index page to scan
305
- * myDistances: distances array associated with pageItem, or NULL at the root
314
+ * myDistanceValues: distances array associated with pageItem, or NULL at the root
315
+ * myDistanceNulls: null flags for myDistanceValues array, or NULL at the root
306
316
* tbm: if not NULL, gistgetbitmap's output bitmap
307
317
* ntids: if not NULL, gistgetbitmap's output tuple counter
308
318
*
@@ -319,7 +329,8 @@ gistindex_keytest(IndexScanDesc scan,
319
329
* sibling will be processed next.
320
330
*/
321
331
static void
322
- gistScanPage (IndexScanDesc scan ,GISTSearchItem * pageItem ,double * myDistances ,
332
+ gistScanPage (IndexScanDesc scan ,GISTSearchItem * pageItem ,
333
+ double * myDistanceValues ,bool * myDistanceNulls ,
323
334
TIDBitmap * tbm ,int64 * ntids )
324
335
{
325
336
GISTScanOpaque so = (GISTScanOpaque )scan -> opaque ;
@@ -356,7 +367,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
356
367
GISTSearchItem * item ;
357
368
358
369
/* This can't happen when starting at the root */
359
- Assert (myDistances != NULL );
370
+ Assert (myDistanceValues != NULL && myDistanceNulls != NULL );
360
371
361
372
oldcxt = MemoryContextSwitchTo (so -> queueCxt );
362
373
@@ -366,8 +377,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
366
377
item -> data .parentlsn = pageItem -> data .parentlsn ;
367
378
368
379
/* Insert it into the queue using same distances as for this page */
369
- memcpy (item -> distances ,myDistances ,
370
- sizeof (double )* scan -> numberOfOrderBys );
380
+ memcpy (GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
381
+ myDistanceValues ,sizeof (double )* scan -> numberOfOrderBys );
382
+ memcpy (GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
383
+ myDistanceNulls ,sizeof (bool )* scan -> numberOfOrderBys );
371
384
372
385
pairingheap_add (so -> queue ,& item -> phNode );
373
386
@@ -462,6 +475,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
462
475
* search.
463
476
*/
464
477
GISTSearchItem * item ;
478
+ int nOrderBys = scan -> numberOfOrderBys ;
465
479
466
480
oldcxt = MemoryContextSwitchTo (so -> queueCxt );
467
481
@@ -496,8 +510,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
496
510
}
497
511
498
512
/* Insert it into the queue using new distance data */
499
- memcpy (item -> distances ,so -> distances ,
500
- sizeof (double )* scan -> numberOfOrderBys );
513
+ memcpy (GISTSearchItemDistanceValues (item ,nOrderBys ),
514
+ so -> distanceValues ,sizeof (double )* nOrderBys );
515
+ memcpy (GISTSearchItemDistanceNulls (item ,nOrderBys ),
516
+ so -> distanceNulls ,sizeof (bool )* nOrderBys );
501
517
502
518
pairingheap_add (so -> queue ,& item -> phNode );
503
519
@@ -552,6 +568,8 @@ getNextNearest(IndexScanDesc scan)
552
568
do
553
569
{
554
570
GISTSearchItem * item = getNextGISTSearchItem (so );
571
+ float8 * distanceValues = GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys );
572
+ bool * distanceNulls = GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys );
555
573
556
574
if (!item )
557
575
break ;
@@ -571,8 +589,8 @@ getNextNearest(IndexScanDesc scan)
571
589
if (!scan -> xs_orderbynulls [i ])
572
590
pfree (DatumGetPointer (scan -> xs_orderbyvals [i ]));
573
591
#endif
574
- scan -> xs_orderbyvals [i ]= Float8GetDatum (item -> distances [i ]);
575
- scan -> xs_orderbynulls [i ]= false ;
592
+ scan -> xs_orderbyvals [i ]= Float8GetDatum (distanceValues [i ]);
593
+ scan -> xs_orderbynulls [i ]= distanceNulls [ i ] ;
576
594
}
577
595
else if (so -> orderByTypes [i ]== FLOAT4OID )
578
596
{
@@ -582,8 +600,8 @@ getNextNearest(IndexScanDesc scan)
582
600
if (!scan -> xs_orderbynulls [i ])
583
601
pfree (DatumGetPointer (scan -> xs_orderbyvals [i ]));
584
602
#endif
585
- scan -> xs_orderbyvals [i ]= Float4GetDatum (( float4 ) item -> distances [i ]);
586
- scan -> xs_orderbynulls [i ]= false ;
603
+ scan -> xs_orderbyvals [i ]= Float4GetDatum (distanceValues [i ]);
604
+ scan -> xs_orderbynulls [i ]= distanceNulls [ i ] ;
587
605
}
588
606
else
589
607
{
@@ -611,7 +629,10 @@ getNextNearest(IndexScanDesc scan)
611
629
/* visit an index page, extract its items into queue */
612
630
CHECK_FOR_INTERRUPTS ();
613
631
614
- gistScanPage (scan ,item ,item -> distances ,NULL ,NULL );
632
+ gistScanPage (scan ,item ,
633
+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
634
+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
635
+ NULL ,NULL );
615
636
}
616
637
617
638
pfree (item );
@@ -649,7 +670,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
649
670
650
671
fakeItem .blkno = GIST_ROOT_BLKNO ;
651
672
memset (& fakeItem .data .parentlsn ,0 ,sizeof (GistNSN ));
652
- gistScanPage (scan ,& fakeItem ,NULL ,NULL ,NULL );
673
+ gistScanPage (scan ,& fakeItem ,NULL ,NULL ,NULL , NULL );
653
674
}
654
675
655
676
if (scan -> numberOfOrderBys > 0 )
@@ -743,7 +764,10 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
743
764
* this page, we fall out of the inner "do" and loop around to
744
765
* return them.
745
766
*/
746
- gistScanPage (scan ,item ,item -> distances ,NULL ,NULL );
767
+ gistScanPage (scan ,item ,
768
+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
769
+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
770
+ NULL ,NULL );
747
771
748
772
pfree (item );
749
773
}while (so -> nPageData == 0 );
@@ -774,7 +798,7 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
774
798
775
799
fakeItem .blkno = GIST_ROOT_BLKNO ;
776
800
memset (& fakeItem .data .parentlsn ,0 ,sizeof (GistNSN ));
777
- gistScanPage (scan ,& fakeItem ,NULL ,tbm ,& ntids );
801
+ gistScanPage (scan ,& fakeItem ,NULL ,NULL , tbm ,& ntids );
778
802
779
803
/*
780
804
* While scanning a leaf page, ItemPointers of matching heap tuples will
@@ -789,7 +813,10 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
789
813
790
814
CHECK_FOR_INTERRUPTS ();
791
815
792
- gistScanPage (scan ,item ,item -> distances ,tbm ,& ntids );
816
+ gistScanPage (scan ,item ,
817
+ GISTSearchItemDistanceValues (item ,scan -> numberOfOrderBys ),
818
+ GISTSearchItemDistanceNulls (item ,scan -> numberOfOrderBys ),
819
+ tbm ,& ntids );
793
820
794
821
pfree (item );
795
822
}