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