@@ -370,36 +370,55 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
370
370
}
371
371
372
372
/*
373
- * find entry with lowest penalty
373
+ * Search an upper index page for the entry with lowest penalty for insertion
374
+ * of the new index key contained in "it".
375
+ *
376
+ * Returns the index of the page entry to insert into.
374
377
*/
375
378
OffsetNumber
376
379
gistchoose (Relation r , Page p , IndexTuple it , /* it has compressed entry */
377
380
GISTSTATE * giststate )
378
381
{
382
+ OffsetNumber result ;
379
383
OffsetNumber maxoff ;
380
384
OffsetNumber i ;
381
- OffsetNumber which ;
382
- float sum_grow ,
383
- which_grow [INDEX_MAX_KEYS ];
385
+ float best_penalty [INDEX_MAX_KEYS ];
384
386
GISTENTRY entry ,
385
387
identry [INDEX_MAX_KEYS ];
386
388
bool isnull [INDEX_MAX_KEYS ];
387
389
388
- maxoff = PageGetMaxOffsetNumber (p );
389
- * which_grow = -1.0 ;
390
- which = InvalidOffsetNumber ;
391
- sum_grow = 1 ;
390
+ Assert (!GistPageIsLeaf (p ));
391
+
392
392
gistDeCompressAtt (giststate , r ,
393
393
it , NULL , (OffsetNumber ) 0 ,
394
394
identry , isnull );
395
395
396
+ /* we'll return FirstOffsetNumber if page is empty (shouldn't happen) */
397
+ result = FirstOffsetNumber ;
398
+
399
+ /*
400
+ * The index may have multiple columns, and there's a penalty value for
401
+ * each column. The penalty associated with a column that appears earlier
402
+ * in the index definition is strictly more important than the penalty of
403
+ * a column that appears later in the index definition.
404
+ *
405
+ * best_penalty[j] is the best penalty we have seen so far for column j,
406
+ * or -1 when we haven't yet examined column j. Array entries to the
407
+ * right of the first -1 are undefined.
408
+ */
409
+ best_penalty [0 ] = -1 ;
410
+
411
+ /*
412
+ * Loop over tuples on page.
413
+ */
414
+ maxoff = PageGetMaxOffsetNumber (p );
396
415
Assert (maxoff >= FirstOffsetNumber );
397
- Assert (!GistPageIsLeaf (p ));
398
416
399
- for (i = FirstOffsetNumber ; i <= maxoff && sum_grow ; i = OffsetNumberNext (i ))
417
+ for (i = FirstOffsetNumber ; i <= maxoff ; i = OffsetNumberNext (i ))
400
418
{
401
- int j ;
402
419
IndexTuple itup = (IndexTuple ) PageGetItem (p , PageGetItemId (p , i ));
420
+ bool zero_penalty ;
421
+ int j ;
403
422
404
423
if (!GistPageIsLeaf (p ) && GistTupleIsInvalid (itup ))
405
424
{
@@ -409,41 +428,70 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
409
428
continue ;
410
429
}
411
430
412
- sum_grow = 0 ;
431
+ zero_penalty = true;
432
+
433
+ /* Loop over index attributes. */
413
434
for (j = 0 ; j < r -> rd_att -> natts ; j ++ )
414
435
{
415
436
Datum datum ;
416
437
float usize ;
417
438
bool IsNull ;
418
439
440
+ /* Compute penalty for this column. */
419
441
datum = index_getattr (itup , j + 1 , giststate -> tupdesc , & IsNull );
420
442
gistdentryinit (giststate , j , & entry , datum , r , p , i ,
421
443
FALSE, IsNull );
422
444
usize = gistpenalty (giststate , j , & entry , IsNull ,
423
445
& identry [j ], isnull [j ]);
446
+ if (usize > 0 )
447
+ zero_penalty = false;
424
448
425
- if (which_grow [j ] < 0 || usize < which_grow [j ])
449
+ if (best_penalty [j ] < 0 || usize < best_penalty [j ])
450
+ {
451
+ /*
452
+ * New best penalty for column. Tentatively select this tuple
453
+ * as the target, and record the best penalty. Then reset the
454
+ * next column's penalty to "unknown" (and indirectly, the
455
+ * same for all the ones to its right). This will force us to
456
+ * adopt this tuple's penalty values as the best for all the
457
+ * remaining columns during subsequent loop iterations.
458
+ */
459
+ result = i ;
460
+ best_penalty [j ] = usize ;
461
+
462
+ if (j < r -> rd_att -> natts - 1 )
463
+ best_penalty [j + 1 ] = -1 ;
464
+ }
465
+ else if (best_penalty [j ] == usize )
426
466
{
427
- which = i ;
428
- which_grow [ j ] = usize ;
429
- if ( j < r -> rd_att -> natts - 1 && i == FirstOffsetNumber )
430
- which_grow [ j + 1 ] = -1 ;
431
- sum_grow += which_grow [ j ];
467
+ /*
468
+ * The current tuple is exactly as good for this column as the
469
+ * best tuple seen so far. The next iteration of this loop
470
+ * will compare the next column.
471
+ */
432
472
}
433
- else if (which_grow [j ] == usize )
434
- sum_grow += usize ;
435
473
else
436
474
{
437
- sum_grow = 1 ;
475
+ /*
476
+ * The current tuple is worse for this column than the best
477
+ * tuple seen so far. Skip the remaining columns and move on
478
+ * to the next tuple, if any.
479
+ */
480
+ zero_penalty = false; /* so outer loop won't exit */
438
481
break ;
439
482
}
440
483
}
441
- }
442
484
443
- if (which == InvalidOffsetNumber )
444
- which = FirstOffsetNumber ;
485
+ /*
486
+ * If we find a tuple with zero penalty for all columns, there's no
487
+ * need to examine remaining tuples; just break out of the loop and
488
+ * return it.
489
+ */
490
+ if (zero_penalty )
491
+ break ;
492
+ }
445
493
446
- return which ;
494
+ return result ;
447
495
}
448
496
449
497
/*
0 commit comments