Coverage Report

Created: 2026-11-09 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/access/nbtree/nbtinsert.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * nbtinsert.c
4
 *    Item insertion in Lehman and Yao btrees for Postgres.
5
 *
6
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *
10
 * IDENTIFICATION
11
 *    src/backend/access/nbtree/nbtinsert.c
12
 *
13
 *-------------------------------------------------------------------------
14
 */
15
16
#include "postgres.h"
17
18
#include "access/nbtree.h"
19
#include "access/nbtxlog.h"
20
#include "access/tableam.h"
21
#include "access/transam.h"
22
#include "access/xloginsert.h"
23
#include "common/int.h"
24
#include "common/pg_prng.h"
25
#include "lib/qunique.h"
26
#include "miscadmin.h"
27
#include "storage/lmgr.h"
28
#include "storage/predicate.h"
29
#include "utils/injection_point.h"
30
31
/* Minimum tree height for application of fastpath optimization */
32
0
#define BTREE_FASTPATH_MIN_LEVEL  2
33
34
35
static BTStack _bt_search_insert(Relation rel, Relation heaprel,
36
                 BTInsertState insertstate);
37
static TransactionId _bt_check_unique(Relation rel, BTInsertState insertstate,
38
                    Relation heapRel,
39
                    IndexUniqueCheck checkUnique, bool *is_unique,
40
                    uint32 *speculativeToken);
41
static OffsetNumber _bt_findinsertloc(Relation rel,
42
                    BTInsertState insertstate,
43
                    bool checkingunique,
44
                    bool indexUnchanged,
45
                    BTStack stack,
46
                    Relation heapRel);
47
static void _bt_stepright(Relation rel, Relation heaprel,
48
              BTInsertState insertstate, BTStack stack);
49
static void _bt_insertonpg(Relation rel, Relation heaprel, BTScanInsert itup_key,
50
               Buffer buf,
51
               Buffer cbuf,
52
               BTStack stack,
53
               IndexTuple itup,
54
               Size itemsz,
55
               OffsetNumber newitemoff,
56
               int postingoff,
57
               bool split_only_page);
58
static Buffer _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key,
59
            Buffer buf, Buffer cbuf, OffsetNumber newitemoff,
60
            Size newitemsz, IndexTuple newitem, IndexTuple orignewitem,
61
            IndexTuple nposting, uint16 postingoff);
62
static void _bt_insert_parent(Relation rel, Relation heaprel, Buffer buf,
63
                Buffer rbuf, BTStack stack, bool isroot, bool isonly);
64
static void _bt_freestack(BTStack stack);
65
static Buffer _bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf);
66
static inline bool _bt_pgaddtup(Page page, Size itemsize, const IndexTupleData *itup,
67
                OffsetNumber itup_off, bool newfirstdataitem);
68
static void _bt_delete_or_dedup_one_page(Relation rel, Relation heapRel,
69
                     BTInsertState insertstate,
70
                     bool simpleonly, bool checkingunique,
71
                     bool uniquedup, bool indexUnchanged);
72
static void _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
73
                 OffsetNumber *deletable, int ndeletable,
74
                 IndexTuple newitem, OffsetNumber minoff,
75
                 OffsetNumber maxoff);
76
static BlockNumber *_bt_deadblocks(Page page, OffsetNumber *deletable,
77
                   int ndeletable, IndexTuple newitem,
78
                   int *nblocks);
79
static inline int _bt_blk_cmp(const void *arg1, const void *arg2);
80
81
/*
82
 *  _bt_doinsert() -- Handle insertion of a single index tuple in the tree.
83
 *
84
 *    This routine is called by the public interface routine, btinsert.
85
 *    By here, itup is filled in, including the TID.
86
 *
87
 *    If checkUnique is UNIQUE_CHECK_NO or UNIQUE_CHECK_PARTIAL, this
88
 *    will allow duplicates.  Otherwise (UNIQUE_CHECK_YES or
89
 *    UNIQUE_CHECK_EXISTING) it will throw error for a duplicate.
90
 *    For UNIQUE_CHECK_EXISTING we merely run the duplicate check, and
91
 *    don't actually insert.
92
 *
93
 *    indexUnchanged executor hint indicates if itup is from an
94
 *    UPDATE that didn't logically change the indexed value, but
95
 *    must nevertheless have a new entry to point to a successor
96
 *    version.
97
 *
98
 *    The result value is only significant for UNIQUE_CHECK_PARTIAL:
99
 *    it must be true if the entry is known unique, else false.
100
 *    (In the current implementation we'll also return true after a
101
 *    successful UNIQUE_CHECK_YES or UNIQUE_CHECK_EXISTING call, but
102
 *    that's just a coding artifact.)
103
 */
104
bool
105
_bt_doinsert(Relation rel, IndexTuple itup,
106
       IndexUniqueCheck checkUnique, bool indexUnchanged,
107
       Relation heapRel)
108
0
{
109
0
  bool    is_unique = false;
110
0
  BTInsertStateData insertstate;
111
0
  BTScanInsert itup_key;
112
0
  BTStack   stack;
113
0
  bool    checkingunique = (checkUnique != UNIQUE_CHECK_NO);
114
115
  /* we need an insertion scan key to do our search, so build one */
116
0
  itup_key = _bt_mkscankey(rel, itup);
117
118
0
  if (checkingunique)
119
0
  {
120
0
    if (!itup_key->anynullkeys)
121
0
    {
122
      /* No (heapkeyspace) scantid until uniqueness established */
123
0
      itup_key->scantid = NULL;
124
0
    }
125
0
    else
126
0
    {
127
      /*
128
       * Scan key for new tuple contains NULL key values.  Bypass
129
       * checkingunique steps.  They are unnecessary because core code
130
       * considers NULL unequal to every value, including NULL.
131
       *
132
       * This optimization avoids O(N^2) behavior within the
133
       * _bt_findinsertloc() heapkeyspace path when a unique index has a
134
       * large number of "duplicates" with NULL key values.
135
       */
136
0
      checkingunique = false;
137
      /* Tuple is unique in the sense that core code cares about */
138
0
      Assert(checkUnique != UNIQUE_CHECK_EXISTING);
139
0
      is_unique = true;
140
0
    }
141
0
  }
142
143
  /*
144
   * Fill in the BTInsertState working area, to track the current page and
145
   * position within the page to insert on.
146
   *
147
   * Note that itemsz is passed down to lower level code that deals with
148
   * inserting the item.  It must be MAXALIGN()'d.  This ensures that space
149
   * accounting code consistently considers the alignment overhead that we
150
   * expect PageAddItem() will add later.  (Actually, index_form_tuple() is
151
   * already conservative about alignment, but we don't rely on that from
152
   * this distance.  Besides, preserving the "true" tuple size in index
153
   * tuple headers for the benefit of nbtsplitloc.c might happen someday.
154
   * Note that heapam does not MAXALIGN() each heap tuple's lp_len field.)
155
   */
156
0
  insertstate.itup = itup;
157
0
  insertstate.itemsz = MAXALIGN(IndexTupleSize(itup));
158
0
  insertstate.itup_key = itup_key;
159
0
  insertstate.bounds_valid = false;
160
0
  insertstate.buf = InvalidBuffer;
161
0
  insertstate.postingoff = 0;
162
163
0
search:
164
165
  /*
166
   * Find and lock the leaf page that the tuple should be added to by
167
   * searching from the root page.  insertstate.buf will hold a buffer that
168
   * is locked in exclusive mode afterwards.
169
   */
170
0
  stack = _bt_search_insert(rel, heapRel, &insertstate);
171
172
  /*
173
   * checkingunique inserts are not allowed to go ahead when two tuples with
174
   * equal key attribute values would be visible to new MVCC snapshots once
175
   * the xact commits.  Check for conflicts in the locked page/buffer (if
176
   * needed) here.
177
   *
178
   * It might be necessary to check a page to the right in _bt_check_unique,
179
   * though that should be very rare.  In practice the first page the value
180
   * could be on (with scantid omitted) is almost always also the only page
181
   * that a matching tuple might be found on.  This is due to the behavior
182
   * of _bt_findsplitloc with duplicate tuples -- a group of duplicates can
183
   * only be allowed to cross a page boundary when there is no candidate
184
   * leaf page split point that avoids it.  Also, _bt_check_unique can use
185
   * the leaf page high key to determine that there will be no duplicates on
186
   * the right sibling without actually visiting it (it uses the high key in
187
   * cases where the new item happens to belong at the far right of the leaf
188
   * page).
189
   *
190
   * NOTE: obviously, _bt_check_unique can only detect keys that are already
191
   * in the index; so it cannot defend against concurrent insertions of the
192
   * same key.  We protect against that by means of holding a write lock on
193
   * the first page the value could be on, with omitted/-inf value for the
194
   * implicit heap TID tiebreaker attribute.  Any other would-be inserter of
195
   * the same key must acquire a write lock on the same page, so only one
196
   * would-be inserter can be making the check at one time.  Furthermore,
197
   * once we are past the check we hold write locks continuously until we
198
   * have performed our insertion, so no later inserter can fail to see our
199
   * insertion.  (This requires some care in _bt_findinsertloc.)
200
   *
201
   * If we must wait for another xact, we release the lock while waiting,
202
   * and then must perform a new search.
203
   *
204
   * For a partial uniqueness check, we don't wait for the other xact. Just
205
   * let the tuple in and return false for possibly non-unique, or true for
206
   * definitely unique.
207
   */
208
0
  if (checkingunique)
209
0
  {
210
0
    TransactionId xwait;
211
0
    uint32    speculativeToken;
212
213
0
    xwait = _bt_check_unique(rel, &insertstate, heapRel, checkUnique,
214
0
                 &is_unique, &speculativeToken);
215
216
0
    if (unlikely(TransactionIdIsValid(xwait)))
217
0
    {
218
      /* Have to wait for the other guy ... */
219
0
      _bt_relbuf(rel, insertstate.buf);
220
0
      insertstate.buf = InvalidBuffer;
221
222
      /*
223
       * If it's a speculative insertion, wait for it to finish (ie. to
224
       * go ahead with the insertion, or kill the tuple).  Otherwise
225
       * wait for the transaction to finish as usual.
226
       */
227
0
      if (speculativeToken)
228
0
        SpeculativeInsertionWait(xwait, speculativeToken);
229
0
      else
230
0
        XactLockTableWait(xwait, rel, &itup->t_tid, XLTW_InsertIndex);
231
232
      /* start over... */
233
0
      if (stack)
234
0
        _bt_freestack(stack);
235
0
      goto search;
236
0
    }
237
238
    /* Uniqueness is established -- restore heap tid as scantid */
239
0
    if (itup_key->heapkeyspace)
240
0
      itup_key->scantid = &itup->t_tid;
241
0
  }
242
243
0
  if (checkUnique != UNIQUE_CHECK_EXISTING)
244
0
  {
245
0
    OffsetNumber newitemoff;
246
247
    /*
248
     * The only conflict predicate locking cares about for indexes is when
249
     * an index tuple insert conflicts with an existing lock.  We don't
250
     * know the actual page we're going to insert on for sure just yet in
251
     * checkingunique and !heapkeyspace cases, but it's okay to use the
252
     * first page the value could be on (with scantid omitted) instead.
253
     */
254
0
    CheckForSerializableConflictIn(rel, NULL, BufferGetBlockNumber(insertstate.buf));
255
256
    /*
257
     * Do the insertion.  Note that insertstate contains cached binary
258
     * search bounds established within _bt_check_unique when insertion is
259
     * checkingunique.
260
     */
261
0
    newitemoff = _bt_findinsertloc(rel, &insertstate, checkingunique,
262
0
                     indexUnchanged, stack, heapRel);
263
0
    _bt_insertonpg(rel, heapRel, itup_key, insertstate.buf, InvalidBuffer,
264
0
             stack, itup, insertstate.itemsz, newitemoff,
265
0
             insertstate.postingoff, false);
266
0
  }
267
0
  else
268
0
  {
269
    /* just release the buffer */
270
0
    _bt_relbuf(rel, insertstate.buf);
271
0
  }
272
273
  /* be tidy */
274
0
  if (stack)
275
0
    _bt_freestack(stack);
276
0
  pfree(itup_key);
277
278
0
  return is_unique;
279
0
}
280
281
/*
282
 *  _bt_search_insert() -- _bt_search() wrapper for inserts
283
 *
284
 * Search the tree for a particular scankey, or more precisely for the first
285
 * leaf page it could be on.  Try to make use of the fastpath optimization's
286
 * rightmost leaf page cache before actually searching the tree from the root
287
 * page, though.
288
 *
289
 * Return value is a stack of parent-page pointers (though see notes about
290
 * fastpath optimization and page splits below).  insertstate->buf is set to
291
 * the address of the leaf-page buffer, which is write-locked and pinned in
292
 * all cases (if necessary by creating a new empty root page for caller).
293
 *
294
 * The fastpath optimization avoids most of the work of searching the tree
295
 * repeatedly when a single backend inserts successive new tuples on the
296
 * rightmost leaf page of an index.  A backend cache of the rightmost leaf
297
 * page is maintained within _bt_insertonpg(), and used here.  The cache is
298
 * invalidated here when an insert of a non-pivot tuple must take place on a
299
 * non-rightmost leaf page.
300
 *
301
 * The optimization helps with indexes on an auto-incremented field.  It also
302
 * helps with indexes on datetime columns, as well as indexes with lots of
303
 * NULL values.  (NULLs usually get inserted in the rightmost page for single
304
 * column indexes, since they usually get treated as coming after everything
305
 * else in the key space.  Individual NULL tuples will generally be placed on
306
 * the rightmost leaf page due to the influence of the heap TID column.)
307
 *
308
 * Note that we avoid applying the optimization when there is insufficient
309
 * space on the rightmost page to fit caller's new item.  This is necessary
310
 * because we'll need to return a real descent stack when a page split is
311
 * expected (actually, caller can cope with a leaf page split that uses a NULL
312
 * stack, but that's very slow and so must be avoided).  Note also that the
313
 * fastpath optimization acquires the lock on the page conditionally as a way
314
 * of reducing extra contention when there are concurrent insertions into the
315
 * rightmost page (we give up if we'd have to wait for the lock).  We assume
316
 * that it isn't useful to apply the optimization when there is contention,
317
 * since each per-backend cache won't stay valid for long.
318
 */
319
static BTStack
320
_bt_search_insert(Relation rel, Relation heaprel, BTInsertState insertstate)
321
0
{
322
0
  Assert(insertstate->buf == InvalidBuffer);
323
0
  Assert(!insertstate->bounds_valid);
324
0
  Assert(insertstate->postingoff == 0);
325
326
0
  if (RelationGetTargetBlock(rel) != InvalidBlockNumber)
327
0
  {
328
    /* Simulate a _bt_getbuf() call with conditional locking */
329
0
    insertstate->buf = ReadBuffer(rel, RelationGetTargetBlock(rel));
330
0
    if (_bt_conditionallockbuf(rel, insertstate->buf))
331
0
    {
332
0
      Page    page;
333
0
      BTPageOpaque opaque;
334
335
0
      _bt_checkpage(rel, insertstate->buf);
336
0
      page = BufferGetPage(insertstate->buf);
337
0
      opaque = BTPageGetOpaque(page);
338
339
      /*
340
       * Check if the page is still the rightmost leaf page and has
341
       * enough free space to accommodate the new tuple.  Also check
342
       * that the insertion scan key is strictly greater than the first
343
       * non-pivot tuple on the page.  (Note that we expect itup_key's
344
       * scantid to be unset when our caller is a checkingunique
345
       * inserter.)
346
       */
347
0
      if (P_RIGHTMOST(opaque) &&
348
0
        P_ISLEAF(opaque) &&
349
0
        !P_IGNORE(opaque) &&
350
0
        PageGetFreeSpace(page) > insertstate->itemsz &&
351
0
        PageGetMaxOffsetNumber(page) >= P_HIKEY &&
352
0
        _bt_compare(rel, insertstate->itup_key, page, P_HIKEY) > 0)
353
0
      {
354
        /*
355
         * Caller can use the fastpath optimization because cached
356
         * block is still rightmost leaf page, which can fit caller's
357
         * new tuple without splitting.  Keep block in local cache for
358
         * next insert, and have caller use NULL stack.
359
         *
360
         * Note that _bt_insert_parent() has an assertion that catches
361
         * leaf page splits that somehow follow from a fastpath insert
362
         * (it should only be passed a NULL stack when it must deal
363
         * with a concurrent root page split, and never because a NULL
364
         * stack was returned here).
365
         */
366
0
        return NULL;
367
0
      }
368
369
      /* Page unsuitable for caller, drop lock and pin */
370
0
      _bt_relbuf(rel, insertstate->buf);
371
0
    }
372
0
    else
373
0
    {
374
      /* Lock unavailable, drop pin */
375
0
      ReleaseBuffer(insertstate->buf);
376
0
    }
377
378
    /* Forget block, since cache doesn't appear to be useful */
379
0
    RelationSetTargetBlock(rel, InvalidBlockNumber);
380
0
  }
381
382
  /* Cannot use optimization -- descend tree, return proper descent stack */
383
0
  return _bt_search(rel, heaprel, insertstate->itup_key, &insertstate->buf,
384
0
            BT_WRITE, true);
385
0
}
386
387
/*
388
 *  _bt_check_unique() -- Check for violation of unique index constraint
389
 *
390
 * Returns InvalidTransactionId if there is no conflict, else an xact ID
391
 * we must wait for to see if it commits a conflicting tuple.   If an actual
392
 * conflict is detected, no return --- just ereport().  If an xact ID is
393
 * returned, and the conflicting tuple still has a speculative insertion in
394
 * progress, *speculativeToken is set to non-zero, and the caller can wait for
395
 * the verdict on the insertion using SpeculativeInsertionWait().
396
 *
397
 * However, if checkUnique == UNIQUE_CHECK_PARTIAL, we always return
398
 * InvalidTransactionId because we don't want to wait.  In this case we
399
 * set *is_unique to false if there is a potential conflict, and the
400
 * core code must redo the uniqueness check later.
401
 *
402
 * As a side-effect, sets state in insertstate that can later be used by
403
 * _bt_findinsertloc() to reuse most of the binary search work we do
404
 * here.
405
 *
406
 * This code treats NULLs as equal, unlike the default semantics for unique
407
 * indexes.  So do not call here when there are NULL values in scan key and
408
 * the index uses the default NULLS DISTINCT mode.
409
 */
410
static TransactionId
411
_bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
412
         IndexUniqueCheck checkUnique, bool *is_unique,
413
         uint32 *speculativeToken)
414
0
{
415
0
  IndexTuple  itup = insertstate->itup;
416
0
  IndexTuple  curitup = NULL;
417
0
  ItemId    curitemid = NULL;
418
0
  BTScanInsert itup_key = insertstate->itup_key;
419
0
  SnapshotData SnapshotDirty;
420
0
  OffsetNumber offset;
421
0
  OffsetNumber maxoff;
422
0
  Page    page;
423
0
  BTPageOpaque opaque;
424
0
  Buffer    nbuf = InvalidBuffer;
425
0
  bool    found = false;
426
0
  bool    inposting = false;
427
0
  bool    prevalldead = true;
428
0
  int     curposti = 0;
429
430
  /* Assume unique until we find a duplicate */
431
0
  *is_unique = true;
432
433
0
  InitDirtySnapshot(SnapshotDirty);
434
435
0
  page = BufferGetPage(insertstate->buf);
436
0
  opaque = BTPageGetOpaque(page);
437
0
  maxoff = PageGetMaxOffsetNumber(page);
438
439
  /*
440
   * Find the first tuple with the same key.
441
   *
442
   * This also saves the binary search bounds in insertstate.  We use them
443
   * in the fastpath below, but also in the _bt_findinsertloc() call later.
444
   */
445
0
  Assert(!insertstate->bounds_valid);
446
0
  offset = _bt_binsrch_insert(rel, insertstate);
447
448
  /*
449
   * Scan over all equal tuples, looking for live conflicts.
450
   */
451
0
  Assert(!insertstate->bounds_valid || insertstate->low == offset);
452
0
  Assert(!itup_key->anynullkeys);
453
0
  Assert(itup_key->scantid == NULL);
454
0
  for (;;)
455
0
  {
456
    /*
457
     * Each iteration of the loop processes one heap TID, not one index
458
     * tuple.  Current offset number for page isn't usually advanced on
459
     * iterations that process heap TIDs from posting list tuples.
460
     *
461
     * "inposting" state is set when _inside_ a posting list --- not when
462
     * we're at the start (or end) of a posting list.  We advance curposti
463
     * at the end of the iteration when inside a posting list tuple.  In
464
     * general, every loop iteration either advances the page offset or
465
     * advances curposti --- an iteration that handles the rightmost/max
466
     * heap TID in a posting list finally advances the page offset (and
467
     * unsets "inposting").
468
     *
469
     * Make sure the offset points to an actual index tuple before trying
470
     * to examine it...
471
     */
472
0
    if (offset <= maxoff)
473
0
    {
474
      /*
475
       * Fastpath: In most cases, we can use cached search bounds to
476
       * limit our consideration to items that are definitely
477
       * duplicates.  This fastpath doesn't apply when the original page
478
       * is empty, or when initial offset is past the end of the
479
       * original page, which may indicate that we need to examine a
480
       * second or subsequent page.
481
       *
482
       * Note that this optimization allows us to avoid calling
483
       * _bt_compare() directly when there are no duplicates, as long as
484
       * the offset where the key will go is not at the end of the page.
485
       */
486
0
      if (nbuf == InvalidBuffer && offset == insertstate->stricthigh)
487
0
      {
488
0
        Assert(insertstate->bounds_valid);
489
0
        Assert(insertstate->low >= P_FIRSTDATAKEY(opaque));
490
0
        Assert(insertstate->low <= insertstate->stricthigh);
491
0
        Assert(_bt_compare(rel, itup_key, page, offset) < 0);
492
0
        break;
493
0
      }
494
495
      /*
496
       * We can skip items that are already marked killed.
497
       *
498
       * In the presence of heavy update activity an index may contain
499
       * many killed items with the same key; running _bt_compare() on
500
       * each killed item gets expensive.  Just advance over killed
501
       * items as quickly as we can.  We only apply _bt_compare() when
502
       * we get to a non-killed item.  We could reuse the bounds to
503
       * avoid _bt_compare() calls for known equal tuples, but it
504
       * doesn't seem worth it.
505
       */
506
0
      if (!inposting)
507
0
        curitemid = PageGetItemId(page, offset);
508
0
      if (inposting || !ItemIdIsDead(curitemid))
509
0
      {
510
0
        ItemPointerData htid;
511
0
        bool    all_dead = false;
512
513
0
        if (!inposting)
514
0
        {
515
          /* Plain tuple, or first TID in posting list tuple */
516
0
          if (_bt_compare(rel, itup_key, page, offset) != 0)
517
0
            break; /* we're past all the equal tuples */
518
519
          /* Advanced curitup */
520
0
          curitup = (IndexTuple) PageGetItem(page, curitemid);
521
0
          Assert(!BTreeTupleIsPivot(curitup));
522
0
        }
523
524
        /* okay, we gotta fetch the heap tuple using htid ... */
525
0
        if (!BTreeTupleIsPosting(curitup))
526
0
        {
527
          /* ... htid is from simple non-pivot tuple */
528
0
          Assert(!inposting);
529
0
          htid = curitup->t_tid;
530
0
        }
531
0
        else if (!inposting)
532
0
        {
533
          /* ... htid is first TID in new posting list */
534
0
          inposting = true;
535
0
          prevalldead = true;
536
0
          curposti = 0;
537
0
          htid = *BTreeTupleGetPostingN(curitup, 0);
538
0
        }
539
0
        else
540
0
        {
541
          /* ... htid is second or subsequent TID in posting list */
542
0
          Assert(curposti > 0);
543
0
          htid = *BTreeTupleGetPostingN(curitup, curposti);
544
0
        }
545
546
        /*
547
         * If we are doing a recheck, we expect to find the tuple we
548
         * are rechecking.  It's not a duplicate, but we have to keep
549
         * scanning.
550
         */
551
0
        if (checkUnique == UNIQUE_CHECK_EXISTING &&
552
0
          ItemPointerCompare(&htid, &itup->t_tid) == 0)
553
0
        {
554
0
          found = true;
555
0
        }
556
557
        /*
558
         * Check if there's any table tuples for this index entry
559
         * satisfying SnapshotDirty. This is necessary because for AMs
560
         * with optimizations like heap's HOT, we have just a single
561
         * index entry for the entire chain.
562
         */
563
0
        else if (table_fetch_tid(heapRel, &htid, &SnapshotDirty,
564
0
                     &all_dead))
565
0
        {
566
0
          TransactionId xwait;
567
568
          /*
569
           * It is a duplicate. If we are only doing a partial
570
           * check, then don't bother checking if the tuple is being
571
           * updated in another transaction. Just return the fact
572
           * that it is a potential conflict and leave the full
573
           * check till later. Don't invalidate binary search
574
           * bounds.
575
           */
576
0
          if (checkUnique == UNIQUE_CHECK_PARTIAL)
577
0
          {
578
0
            if (nbuf != InvalidBuffer)
579
0
              _bt_relbuf(rel, nbuf);
580
0
            *is_unique = false;
581
0
            return InvalidTransactionId;
582
0
          }
583
584
          /*
585
           * If this tuple is being updated by other transaction
586
           * then we have to wait for its commit/abort.
587
           */
588
0
          xwait = (TransactionIdIsValid(SnapshotDirty.xmin)) ?
589
0
            SnapshotDirty.xmin : SnapshotDirty.xmax;
590
591
0
          if (TransactionIdIsValid(xwait))
592
0
          {
593
0
            if (nbuf != InvalidBuffer)
594
0
              _bt_relbuf(rel, nbuf);
595
            /* Tell _bt_doinsert to wait... */
596
0
            *speculativeToken = SnapshotDirty.speculativeToken;
597
            /* Caller releases lock on buf immediately */
598
0
            insertstate->bounds_valid = false;
599
0
            return xwait;
600
0
          }
601
602
          /*
603
           * Otherwise we have a definite conflict.  But before
604
           * complaining, look to see if the tuple we want to insert
605
           * is itself now committed dead --- if so, don't complain.
606
           * This is a waste of time in normal scenarios but we must
607
           * do it to support CREATE INDEX CONCURRENTLY.
608
           *
609
           * We must follow HOT-chains here because during
610
           * concurrent index build, we insert the root TID though
611
           * the actual tuple may be somewhere in the HOT-chain.
612
           * While following the chain we might not stop at the
613
           * exact tuple which triggered the insert, but that's OK
614
           * because if we find a live tuple anywhere in this chain,
615
           * we have a unique key conflict.  The other live tuple is
616
           * not part of this chain because it had a different index
617
           * entry.
618
           */
619
0
          htid = itup->t_tid;
620
0
          if (table_fetch_tid(heapRel, &htid, SnapshotSelf, NULL))
621
0
          {
622
            /* Normal case --- it's still live */
623
0
          }
624
0
          else
625
0
          {
626
            /*
627
             * It's been deleted, so no error, and no need to
628
             * continue searching
629
             */
630
0
            break;
631
0
          }
632
633
          /*
634
           * Check for a conflict-in as we would if we were going to
635
           * write to this page.  We aren't actually going to write,
636
           * but we want a chance to report SSI conflicts that would
637
           * otherwise be masked by this unique constraint
638
           * violation.
639
           */
640
0
          CheckForSerializableConflictIn(rel, NULL, BufferGetBlockNumber(insertstate->buf));
641
642
          /*
643
           * This is a definite conflict.  Break the tuple down into
644
           * datums and report the error.  But first, make sure we
645
           * release the buffer locks we're holding ---
646
           * BuildIndexValueDescription could make catalog accesses,
647
           * which in the worst case might touch this same index and
648
           * cause deadlocks.
649
           */
650
0
          if (nbuf != InvalidBuffer)
651
0
            _bt_relbuf(rel, nbuf);
652
0
          _bt_relbuf(rel, insertstate->buf);
653
0
          insertstate->buf = InvalidBuffer;
654
0
          insertstate->bounds_valid = false;
655
656
0
          {
657
0
            Datum   values[INDEX_MAX_KEYS];
658
0
            bool    isnull[INDEX_MAX_KEYS];
659
0
            char     *key_desc;
660
661
0
            index_deform_tuple(itup, RelationGetDescr(rel),
662
0
                       values, isnull);
663
664
0
            key_desc = BuildIndexValueDescription(rel, values,
665
0
                                isnull);
666
667
0
            ereport(ERROR,
668
0
                (errcode(ERRCODE_UNIQUE_VIOLATION),
669
0
                 errmsg("duplicate key value violates unique constraint \"%s\"",
670
0
                    RelationGetRelationName(rel)),
671
0
                 key_desc ? errdetail("Key %s already exists.",
672
0
                            key_desc) : 0,
673
0
                 errtableconstraint(heapRel,
674
0
                          RelationGetRelationName(rel))));
675
0
          }
676
0
        }
677
0
        else if (all_dead && (!inposting ||
678
0
                    (prevalldead &&
679
0
                     curposti == BTreeTupleGetNPosting(curitup) - 1)))
680
0
        {
681
          /*
682
           * The conflicting tuple (or all HOT chains pointed to by
683
           * all posting list TIDs) is dead to everyone, so try to
684
           * mark the index entry killed. It's ok if we're not
685
           * allowed to, this isn't required for correctness.
686
           */
687
0
          Buffer    buf;
688
689
          /* Be sure to operate on the proper buffer */
690
0
          if (nbuf != InvalidBuffer)
691
0
            buf = nbuf;
692
0
          else
693
0
            buf = insertstate->buf;
694
695
          /*
696
           * Use the hint bit infrastructure to check if we can
697
           * update the page while just holding a share lock.
698
           *
699
           * Can't use BufferSetHintBits16() here as we update two
700
           * different locations.
701
           */
702
0
          if (BufferBeginSetHintBits(buf))
703
0
          {
704
0
            ItemIdMarkDead(curitemid);
705
0
            opaque->btpo_flags |= BTP_HAS_GARBAGE;
706
0
            BufferFinishSetHintBits(buf, true, true);
707
0
          }
708
0
        }
709
710
        /*
711
         * Remember if posting list tuple has even a single HOT chain
712
         * whose members are not all dead
713
         */
714
0
        if (!all_dead && inposting)
715
0
          prevalldead = false;
716
0
      }
717
0
    }
718
719
0
    if (inposting && curposti < BTreeTupleGetNPosting(curitup) - 1)
720
0
    {
721
      /* Advance to next TID in same posting list */
722
0
      curposti++;
723
0
      continue;
724
0
    }
725
0
    else if (offset < maxoff)
726
0
    {
727
      /* Advance to next tuple */
728
0
      curposti = 0;
729
0
      inposting = false;
730
0
      offset = OffsetNumberNext(offset);
731
0
    }
732
0
    else
733
0
    {
734
0
      int     highkeycmp;
735
736
      /* If scankey == hikey we gotta check the next page too */
737
0
      if (P_RIGHTMOST(opaque))
738
0
        break;
739
0
      highkeycmp = _bt_compare(rel, itup_key, page, P_HIKEY);
740
0
      Assert(highkeycmp <= 0);
741
0
      if (highkeycmp != 0)
742
0
        break;
743
      /* Advance to next non-dead page --- there must be one */
744
0
      for (;;)
745
0
      {
746
0
        BlockNumber nblkno = opaque->btpo_next;
747
748
0
        nbuf = _bt_relandgetbuf(rel, nbuf, nblkno, BT_READ);
749
0
        page = BufferGetPage(nbuf);
750
0
        opaque = BTPageGetOpaque(page);
751
0
        if (!P_IGNORE(opaque))
752
0
          break;
753
0
        if (P_RIGHTMOST(opaque))
754
0
          elog(ERROR, "fell off the end of index \"%s\"",
755
0
             RelationGetRelationName(rel));
756
0
      }
757
      /* Will also advance to next tuple */
758
0
      curposti = 0;
759
0
      inposting = false;
760
0
      maxoff = PageGetMaxOffsetNumber(page);
761
0
      offset = P_FIRSTDATAKEY(opaque);
762
      /* Don't invalidate binary search bounds */
763
0
    }
764
0
  }
765
766
  /*
767
   * If we are doing a recheck then we should have found the tuple we are
768
   * checking.  Otherwise there's something very wrong --- probably, the
769
   * index is on a non-immutable expression.
770
   */
771
0
  if (checkUnique == UNIQUE_CHECK_EXISTING && !found)
772
0
    ereport(ERROR,
773
0
        (errcode(ERRCODE_INTERNAL_ERROR),
774
0
         errmsg("failed to re-find tuple within index \"%s\"",
775
0
            RelationGetRelationName(rel)),
776
0
         errhint("This may be because of a non-immutable index expression."),
777
0
         errtableconstraint(heapRel,
778
0
                  RelationGetRelationName(rel))));
779
780
0
  if (nbuf != InvalidBuffer)
781
0
    _bt_relbuf(rel, nbuf);
782
783
0
  return InvalidTransactionId;
784
0
}
785
786
787
/*
788
 *  _bt_findinsertloc() -- Finds an insert location for a tuple
789
 *
790
 *    On entry, insertstate buffer contains the page the new tuple belongs
791
 *    on.  It is exclusive-locked and pinned by the caller.
792
 *
793
 *    If 'checkingunique' is true, the buffer on entry is the first page
794
 *    that contains duplicates of the new key.  If there are duplicates on
795
 *    multiple pages, the correct insertion position might be some page to
796
 *    the right, rather than the first page.  In that case, this function
797
 *    moves right to the correct target page.
798
 *
799
 *    (In a !heapkeyspace index, there can be multiple pages with the same
800
 *    high key, where the new tuple could legitimately be placed on.  In
801
 *    that case, the caller passes the first page containing duplicates,
802
 *    just like when checkingunique=true.  If that page doesn't have enough
803
 *    room for the new tuple, this function moves right, trying to find a
804
 *    legal page that does.)
805
 *
806
 *    If 'indexUnchanged' is true, this is for an UPDATE that didn't
807
 *    logically change the indexed value, but must nevertheless have a new
808
 *    entry to point to a successor version.  This hint from the executor
809
 *    will influence our behavior when the page might have to be split and
810
 *    we must consider our options.  Bottom-up index deletion can avoid
811
 *    pathological version-driven page splits, but we only want to go to the
812
 *    trouble of trying it when we already have moderate confidence that
813
 *    it's appropriate.  The hint should not significantly affect our
814
 *    behavior over time unless practically all inserts on to the leaf page
815
 *    get the hint.
816
 *
817
 *    On exit, insertstate buffer contains the chosen insertion page, and
818
 *    the offset within that page is returned.  If _bt_findinsertloc needed
819
 *    to move right, the lock and pin on the original page are released, and
820
 *    the new buffer is exclusively locked and pinned instead.
821
 *
822
 *    If insertstate contains cached binary search bounds, we will take
823
 *    advantage of them.  This avoids repeating comparisons that we made in
824
 *    _bt_check_unique() already.
825
 */
826
static OffsetNumber
827
_bt_findinsertloc(Relation rel,
828
          BTInsertState insertstate,
829
          bool checkingunique,
830
          bool indexUnchanged,
831
          BTStack stack,
832
          Relation heapRel)
833
0
{
834
0
  BTScanInsert itup_key = insertstate->itup_key;
835
0
  Page    page = BufferGetPage(insertstate->buf);
836
0
  BTPageOpaque opaque;
837
0
  OffsetNumber newitemoff;
838
839
0
  opaque = BTPageGetOpaque(page);
840
841
  /* Check 1/3 of a page restriction */
842
0
  if (unlikely(insertstate->itemsz > BTMaxItemSize))
843
0
    _bt_check_third_page(rel, heapRel, itup_key->heapkeyspace, page,
844
0
               insertstate->itup);
845
846
0
  Assert(P_ISLEAF(opaque) && !P_INCOMPLETE_SPLIT(opaque));
847
0
  Assert(!insertstate->bounds_valid || checkingunique);
848
0
  Assert(!itup_key->heapkeyspace || itup_key->scantid != NULL);
849
0
  Assert(itup_key->heapkeyspace || itup_key->scantid == NULL);
850
0
  Assert(!itup_key->allequalimage || itup_key->heapkeyspace);
851
852
0
  if (itup_key->heapkeyspace)
853
0
  {
854
    /* Keep track of whether checkingunique duplicate seen */
855
0
    bool    uniquedup = indexUnchanged;
856
857
    /*
858
     * If we're inserting into a unique index, we may have to walk right
859
     * through leaf pages to find the one leaf page that we must insert on
860
     * to.
861
     *
862
     * This is needed for checkingunique callers because a scantid was not
863
     * used when we called _bt_search().  scantid can only be set after
864
     * _bt_check_unique() has checked for duplicates.  The buffer
865
     * initially stored in insertstate->buf has the page where the first
866
     * duplicate key might be found, which isn't always the page that new
867
     * tuple belongs on.  The heap TID attribute for new tuple (scantid)
868
     * could force us to insert on a sibling page, though that should be
869
     * very rare in practice.
870
     */
871
0
    if (checkingunique)
872
0
    {
873
0
      if (insertstate->low < insertstate->stricthigh)
874
0
      {
875
        /* Encountered a duplicate in _bt_check_unique() */
876
0
        Assert(insertstate->bounds_valid);
877
0
        uniquedup = true;
878
0
      }
879
880
0
      for (;;)
881
0
      {
882
        /*
883
         * Does the new tuple belong on this page?
884
         *
885
         * The earlier _bt_check_unique() call may well have
886
         * established a strict upper bound on the offset for the new
887
         * item.  If it's not the last item of the page (i.e. if there
888
         * is at least one tuple on the page that goes after the tuple
889
         * we're inserting) then we know that the tuple belongs on
890
         * this page.  We can skip the high key check.
891
         */
892
0
        if (insertstate->bounds_valid &&
893
0
          insertstate->low <= insertstate->stricthigh &&
894
0
          insertstate->stricthigh <= PageGetMaxOffsetNumber(page))
895
0
          break;
896
897
        /* Test '<=', not '!=', since scantid is set now */
898
0
        if (P_RIGHTMOST(opaque) ||
899
0
          _bt_compare(rel, itup_key, page, P_HIKEY) <= 0)
900
0
          break;
901
902
0
        _bt_stepright(rel, heapRel, insertstate, stack);
903
        /* Update local state after stepping right */
904
0
        page = BufferGetPage(insertstate->buf);
905
0
        opaque = BTPageGetOpaque(page);
906
        /* Assume duplicates (if checkingunique) */
907
0
        uniquedup = true;
908
0
      }
909
0
    }
910
911
    /*
912
     * If the target page cannot fit newitem, try to avoid splitting the
913
     * page on insert by performing deletion or deduplication now
914
     */
915
0
    if (PageGetFreeSpace(page) < insertstate->itemsz)
916
0
      _bt_delete_or_dedup_one_page(rel, heapRel, insertstate, false,
917
0
                     checkingunique, uniquedup,
918
0
                     indexUnchanged);
919
0
  }
920
0
  else
921
0
  {
922
    /*----------
923
     * This is a !heapkeyspace (version 2 or 3) index.  The current page
924
     * is the first page that we could insert the new tuple to, but there
925
     * may be other pages to the right that we could opt to use instead.
926
     *
927
     * If the new key is equal to one or more existing keys, we can
928
     * legitimately place it anywhere in the series of equal keys.  In
929
     * fact, if the new key is equal to the page's "high key" we can place
930
     * it on the next page.  If it is equal to the high key, and there's
931
     * not room to insert the new tuple on the current page without
932
     * splitting, then we move right hoping to find more free space and
933
     * avoid a split.
934
     *
935
     * Keep scanning right until we
936
     *    (a) find a page with enough free space,
937
     *    (b) reach the last page where the tuple can legally go, or
938
     *    (c) get tired of searching.
939
     * (c) is not flippant; it is important because if there are many
940
     * pages' worth of equal keys, it's better to split one of the early
941
     * pages than to scan all the way to the end of the run of equal keys
942
     * on every insert.  We implement "get tired" as a random choice,
943
     * since stopping after scanning a fixed number of pages wouldn't work
944
     * well (we'd never reach the right-hand side of previously split
945
     * pages).  The probability of moving right is set at 0.99, which may
946
     * seem too high to change the behavior much, but it does an excellent
947
     * job of preventing O(N^2) behavior with many equal keys.
948
     *----------
949
     */
950
0
    while (PageGetFreeSpace(page) < insertstate->itemsz)
951
0
    {
952
      /*
953
       * Before considering moving right, see if we can obtain enough
954
       * space by erasing LP_DEAD items
955
       */
956
0
      if (P_HAS_GARBAGE(opaque))
957
0
      {
958
        /* Perform simple deletion */
959
0
        _bt_delete_or_dedup_one_page(rel, heapRel, insertstate, true,
960
0
                       false, false, false);
961
962
0
        if (PageGetFreeSpace(page) >= insertstate->itemsz)
963
0
          break;   /* OK, now we have enough space */
964
0
      }
965
966
      /*
967
       * Nope, so check conditions (b) and (c) enumerated above
968
       *
969
       * The earlier _bt_check_unique() call may well have established a
970
       * strict upper bound on the offset for the new item.  If it's not
971
       * the last item of the page (i.e. if there is at least one tuple
972
       * on the page that's greater than the tuple we're inserting to)
973
       * then we know that the tuple belongs on this page.  We can skip
974
       * the high key check.
975
       */
976
0
      if (insertstate->bounds_valid &&
977
0
        insertstate->low <= insertstate->stricthigh &&
978
0
        insertstate->stricthigh <= PageGetMaxOffsetNumber(page))
979
0
        break;
980
981
0
      if (P_RIGHTMOST(opaque) ||
982
0
        _bt_compare(rel, itup_key, page, P_HIKEY) != 0 ||
983
0
        pg_prng_uint32(&pg_global_prng_state) <= (PG_UINT32_MAX / 100))
984
0
        break;
985
986
0
      _bt_stepright(rel, heapRel, insertstate, stack);
987
      /* Update local state after stepping right */
988
0
      page = BufferGetPage(insertstate->buf);
989
0
      opaque = BTPageGetOpaque(page);
990
0
    }
991
0
  }
992
993
  /*
994
   * We should now be on the correct page.  Find the offset within the page
995
   * for the new tuple. (Possibly reusing earlier search bounds.)
996
   */
997
0
  Assert(P_RIGHTMOST(opaque) ||
998
0
       _bt_compare(rel, itup_key, page, P_HIKEY) <= 0);
999
1000
0
  newitemoff = _bt_binsrch_insert(rel, insertstate);
1001
1002
0
  if (insertstate->postingoff == -1)
1003
0
  {
1004
    /*
1005
     * There is an overlapping posting list tuple with its LP_DEAD bit
1006
     * set.  We don't want to unnecessarily unset its LP_DEAD bit while
1007
     * performing a posting list split, so perform simple index tuple
1008
     * deletion early.
1009
     */
1010
0
    _bt_delete_or_dedup_one_page(rel, heapRel, insertstate, true,
1011
0
                   false, false, false);
1012
1013
    /*
1014
     * Do new binary search.  New insert location cannot overlap with any
1015
     * posting list now.
1016
     */
1017
0
    Assert(!insertstate->bounds_valid);
1018
0
    insertstate->postingoff = 0;
1019
0
    newitemoff = _bt_binsrch_insert(rel, insertstate);
1020
0
    Assert(insertstate->postingoff == 0);
1021
0
  }
1022
1023
0
  return newitemoff;
1024
0
}
1025
1026
/*
1027
 * Step right to next non-dead page, during insertion.
1028
 *
1029
 * This is a bit more complicated than moving right in a search.  We must
1030
 * write-lock the target page before releasing write lock on current page;
1031
 * else someone else's _bt_check_unique scan could fail to see our insertion.
1032
 * Write locks on intermediate dead pages won't do because we don't know when
1033
 * they will get de-linked from the tree.
1034
 *
1035
 * This is more aggressive than it needs to be for non-unique !heapkeyspace
1036
 * indexes.
1037
 */
1038
static void
1039
_bt_stepright(Relation rel, Relation heaprel, BTInsertState insertstate,
1040
        BTStack stack)
1041
0
{
1042
0
  Page    page;
1043
0
  BTPageOpaque opaque;
1044
0
  Buffer    rbuf;
1045
0
  BlockNumber rblkno;
1046
1047
0
  Assert(heaprel != NULL);
1048
0
  page = BufferGetPage(insertstate->buf);
1049
0
  opaque = BTPageGetOpaque(page);
1050
1051
0
  rbuf = InvalidBuffer;
1052
0
  rblkno = opaque->btpo_next;
1053
0
  for (;;)
1054
0
  {
1055
0
    rbuf = _bt_relandgetbuf(rel, rbuf, rblkno, BT_WRITE);
1056
0
    page = BufferGetPage(rbuf);
1057
0
    opaque = BTPageGetOpaque(page);
1058
1059
    /*
1060
     * If this page was incompletely split, finish the split now.  We do
1061
     * this while holding a lock on the left sibling, which is not good
1062
     * because finishing the split could be a fairly lengthy operation.
1063
     * But this should happen very seldom.
1064
     */
1065
0
    if (P_INCOMPLETE_SPLIT(opaque))
1066
0
    {
1067
0
      _bt_finish_split(rel, heaprel, rbuf, stack);
1068
0
      rbuf = InvalidBuffer;
1069
0
      continue;
1070
0
    }
1071
1072
0
    if (!P_IGNORE(opaque))
1073
0
      break;
1074
0
    if (P_RIGHTMOST(opaque))
1075
0
      elog(ERROR, "fell off the end of index \"%s\"",
1076
0
         RelationGetRelationName(rel));
1077
1078
0
    rblkno = opaque->btpo_next;
1079
0
  }
1080
  /* rbuf locked; unlock buf, update state for caller */
1081
0
  _bt_relbuf(rel, insertstate->buf);
1082
0
  insertstate->buf = rbuf;
1083
0
  insertstate->bounds_valid = false;
1084
0
}
1085
1086
/*----------
1087
 *  _bt_insertonpg() -- Insert a tuple on a particular page in the index.
1088
 *
1089
 *    This recursive procedure does the following things:
1090
 *
1091
 *      +  if postingoff != 0, splits existing posting list tuple
1092
 *         (since it overlaps with new 'itup' tuple).
1093
 *      +  if necessary, splits the target page, using 'itup_key' for
1094
 *         suffix truncation on leaf pages (caller passes NULL for
1095
 *         non-leaf pages).
1096
 *      +  inserts the new tuple (might be split from posting list).
1097
 *      +  if the page was split, pops the parent stack, and finds the
1098
 *         right place to insert the new child pointer (by walking
1099
 *         right using information stored in the parent stack).
1100
 *      +  invokes itself with the appropriate tuple for the right
1101
 *         child page on the parent.
1102
 *      +  updates the metapage if a true root or fast root is split.
1103
 *
1104
 *    On entry, we must have the correct buffer in which to do the
1105
 *    insertion, and the buffer must be pinned and write-locked.  On return,
1106
 *    we will have dropped both the pin and the lock on the buffer.
1107
 *
1108
 *    This routine only performs retail tuple insertions.  'itup' should
1109
 *    always be either a non-highkey leaf item, or a downlink (new high
1110
 *    key items are created indirectly, when a page is split).  When
1111
 *    inserting to a non-leaf page, 'cbuf' is the left-sibling of the page
1112
 *    we're inserting the downlink for.  This function will clear the
1113
 *    INCOMPLETE_SPLIT flag on it, and release the buffer.
1114
 *----------
1115
 */
1116
static void
1117
_bt_insertonpg(Relation rel,
1118
         Relation heaprel,
1119
         BTScanInsert itup_key,
1120
         Buffer buf,
1121
         Buffer cbuf,
1122
         BTStack stack,
1123
         IndexTuple itup,
1124
         Size itemsz,
1125
         OffsetNumber newitemoff,
1126
         int postingoff,
1127
         bool split_only_page)
1128
0
{
1129
0
  Page    page;
1130
0
  BTPageOpaque opaque;
1131
0
  bool    isleaf,
1132
0
        isroot,
1133
0
        isrightmost,
1134
0
        isonly;
1135
0
  IndexTuple  oposting = NULL;
1136
0
  IndexTuple  origitup = NULL;
1137
0
  IndexTuple  nposting = NULL;
1138
0
  XLogRecPtr  recptr;
1139
1140
0
  page = BufferGetPage(buf);
1141
0
  opaque = BTPageGetOpaque(page);
1142
0
  isleaf = P_ISLEAF(opaque);
1143
0
  isroot = P_ISROOT(opaque);
1144
0
  isrightmost = P_RIGHTMOST(opaque);
1145
0
  isonly = P_LEFTMOST(opaque) && P_RIGHTMOST(opaque);
1146
1147
  /* child buffer must be given iff inserting on an internal page */
1148
0
  Assert(isleaf == !BufferIsValid(cbuf));
1149
  /* tuple must have appropriate number of attributes */
1150
0
  Assert(!isleaf ||
1151
0
       BTreeTupleGetNAtts(itup, rel) ==
1152
0
       IndexRelationGetNumberOfAttributes(rel));
1153
0
  Assert(isleaf ||
1154
0
       BTreeTupleGetNAtts(itup, rel) <=
1155
0
       IndexRelationGetNumberOfKeyAttributes(rel));
1156
0
  Assert(!BTreeTupleIsPosting(itup));
1157
0
  Assert(MAXALIGN(IndexTupleSize(itup)) == itemsz);
1158
  /* Caller must always finish incomplete split for us */
1159
0
  Assert(!P_INCOMPLETE_SPLIT(opaque));
1160
1161
  /*
1162
   * Every internal page should have exactly one negative infinity item at
1163
   * all times.  Only _bt_split() and _bt_newlevel() should add items that
1164
   * become negative infinity items through truncation, since they're the
1165
   * only routines that allocate new internal pages.
1166
   */
1167
0
  Assert(isleaf || newitemoff > P_FIRSTDATAKEY(opaque));
1168
1169
  /*
1170
   * Do we need to split an existing posting list item?
1171
   */
1172
0
  if (postingoff != 0)
1173
0
  {
1174
0
    ItemId    itemid = PageGetItemId(page, newitemoff);
1175
1176
    /*
1177
     * The new tuple is a duplicate with a heap TID that falls inside the
1178
     * range of an existing posting list tuple on a leaf page.  Prepare to
1179
     * split an existing posting list.  Overwriting the posting list with
1180
     * its post-split version is treated as an extra step in either the
1181
     * insert or page split critical section.
1182
     */
1183
0
    Assert(isleaf && itup_key->heapkeyspace && itup_key->allequalimage);
1184
0
    oposting = (IndexTuple) PageGetItem(page, itemid);
1185
1186
    /*
1187
     * postingoff value comes from earlier call to _bt_binsrch_posting().
1188
     * Its binary search might think that a plain tuple must be a posting
1189
     * list tuple that needs to be split.  This can happen with corruption
1190
     * involving an existing plain tuple that is a duplicate of the new
1191
     * item, up to and including its table TID.  Check for that here in
1192
     * passing.
1193
     *
1194
     * Also verify that our caller has made sure that the existing posting
1195
     * list tuple does not have its LP_DEAD bit set.
1196
     */
1197
0
    if (!BTreeTupleIsPosting(oposting) || ItemIdIsDead(itemid))
1198
0
      ereport(ERROR,
1199
0
          (errcode(ERRCODE_INDEX_CORRUPTED),
1200
0
           errmsg_internal("table tid from new index tuple (%u,%u) overlaps with invalid duplicate tuple at offset %u of block %u in index \"%s\"",
1201
0
                   ItemPointerGetBlockNumber(&itup->t_tid),
1202
0
                   ItemPointerGetOffsetNumber(&itup->t_tid),
1203
0
                   newitemoff, BufferGetBlockNumber(buf),
1204
0
                   RelationGetRelationName(rel))));
1205
1206
    /* use a mutable copy of itup as our itup from here on */
1207
0
    origitup = itup;
1208
0
    itup = CopyIndexTuple(origitup);
1209
0
    nposting = _bt_swap_posting(itup, oposting, postingoff);
1210
    /* itup now contains rightmost/max TID from oposting */
1211
1212
    /* Alter offset so that newitem goes after posting list */
1213
0
    newitemoff = OffsetNumberNext(newitemoff);
1214
0
  }
1215
1216
  /*
1217
   * Do we need to split the page to fit the item on it?
1218
   *
1219
   * Note: PageGetFreeSpace() subtracts sizeof(ItemIdData) from its result,
1220
   * so this comparison is correct even though we appear to be accounting
1221
   * only for the item and not for its line pointer.
1222
   */
1223
0
  if (PageGetFreeSpace(page) < itemsz)
1224
0
  {
1225
0
    Buffer    rbuf;
1226
1227
0
    Assert(!split_only_page);
1228
1229
    /* split the buffer into left and right halves */
1230
0
    rbuf = _bt_split(rel, heaprel, itup_key, buf, cbuf, newitemoff, itemsz,
1231
0
             itup, origitup, nposting, postingoff);
1232
0
    PredicateLockPageSplit(rel,
1233
0
                 BufferGetBlockNumber(buf),
1234
0
                 BufferGetBlockNumber(rbuf));
1235
1236
    /*----------
1237
     * By here,
1238
     *
1239
     *    +  our target page has been split;
1240
     *    +  the original tuple has been inserted;
1241
     *    +  we have write locks on both the old (left half)
1242
     *       and new (right half) buffers, after the split; and
1243
     *    +  we know the key we want to insert into the parent
1244
     *       (it's the "high key" on the left child page).
1245
     *
1246
     * We're ready to do the parent insertion.  We need to hold onto the
1247
     * locks for the child pages until we locate the parent, but we can
1248
     * at least release the lock on the right child before doing the
1249
     * actual insertion.  The lock on the left child will be released
1250
     * last of all by parent insertion, where it is the 'cbuf' of parent
1251
     * page.
1252
     *----------
1253
     */
1254
#ifdef USE_INJECTION_POINTS
1255
    if (P_ISLEAF(opaque))
1256
      INJECTION_POINT("nbtree-leave-leaf-split-incomplete", NULL);
1257
    else
1258
      INJECTION_POINT("nbtree-leave-internal-split-incomplete", NULL);
1259
#endif
1260
1261
0
    _bt_insert_parent(rel, heaprel, buf, rbuf, stack, isroot, isonly);
1262
0
  }
1263
0
  else
1264
0
  {
1265
0
    Buffer    metabuf = InvalidBuffer;
1266
0
    Page    metapg = NULL;
1267
0
    BTMetaPageData *metad = NULL;
1268
0
    BlockNumber blockcache;
1269
1270
    /*
1271
     * If we are doing this insert because we split a page that was the
1272
     * only one on its tree level, but was not the root, it may have been
1273
     * the "fast root".  We need to ensure that the fast root link points
1274
     * at or above the current page.  We can safely acquire a lock on the
1275
     * metapage here --- see comments for _bt_newlevel().
1276
     */
1277
0
    if (unlikely(split_only_page))
1278
0
    {
1279
0
      Assert(!isleaf);
1280
0
      Assert(BufferIsValid(cbuf));
1281
1282
0
      metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
1283
0
      metapg = BufferGetPage(metabuf);
1284
0
      metad = BTPageGetMeta(metapg);
1285
1286
0
      if (metad->btm_fastlevel >= opaque->btpo_level)
1287
0
      {
1288
        /* no update wanted */
1289
0
        _bt_relbuf(rel, metabuf);
1290
0
        metabuf = InvalidBuffer;
1291
0
      }
1292
0
    }
1293
1294
    /* Do the update.  No ereport(ERROR) until changes are logged */
1295
0
    START_CRIT_SECTION();
1296
1297
0
    if (postingoff != 0)
1298
0
      memcpy(oposting, nposting, MAXALIGN(IndexTupleSize(nposting)));
1299
1300
0
    if (PageAddItem(page, itup, itemsz, newitemoff, false, false) == InvalidOffsetNumber)
1301
0
      elog(PANIC, "failed to add new item to block %u in index \"%s\"",
1302
0
         BufferGetBlockNumber(buf), RelationGetRelationName(rel));
1303
1304
0
    MarkBufferDirty(buf);
1305
1306
0
    if (BufferIsValid(metabuf))
1307
0
    {
1308
      /* upgrade meta-page if needed */
1309
0
      if (metad->btm_version < BTREE_NOVAC_VERSION)
1310
0
        _bt_upgrademetapage(metapg);
1311
0
      metad->btm_fastroot = BufferGetBlockNumber(buf);
1312
0
      metad->btm_fastlevel = opaque->btpo_level;
1313
0
      MarkBufferDirty(metabuf);
1314
0
    }
1315
1316
    /*
1317
     * Clear INCOMPLETE_SPLIT flag on child if inserting the new item
1318
     * finishes a split
1319
     */
1320
0
    if (!isleaf)
1321
0
    {
1322
0
      Page    cpage = BufferGetPage(cbuf);
1323
0
      BTPageOpaque cpageop = BTPageGetOpaque(cpage);
1324
1325
0
      Assert(P_INCOMPLETE_SPLIT(cpageop));
1326
0
      cpageop->btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
1327
0
      MarkBufferDirty(cbuf);
1328
0
    }
1329
1330
    /* XLOG stuff */
1331
0
    if (RelationNeedsWAL(rel))
1332
0
    {
1333
0
      xl_btree_insert xlrec;
1334
0
      xl_btree_metadata xlmeta;
1335
0
      uint8   xlinfo;
1336
0
      uint16    upostingoff;
1337
1338
0
      xlrec.offnum = newitemoff;
1339
1340
0
      XLogBeginInsert();
1341
0
      XLogRegisterData(&xlrec, SizeOfBtreeInsert);
1342
1343
0
      if (isleaf && postingoff == 0)
1344
0
      {
1345
        /* Simple leaf insert */
1346
0
        xlinfo = XLOG_BTREE_INSERT_LEAF;
1347
0
      }
1348
0
      else if (postingoff != 0)
1349
0
      {
1350
        /*
1351
         * Leaf insert with posting list split.  Must include
1352
         * postingoff field before newitem/orignewitem.
1353
         */
1354
0
        Assert(isleaf);
1355
0
        xlinfo = XLOG_BTREE_INSERT_POST;
1356
0
      }
1357
0
      else
1358
0
      {
1359
        /* Internal page insert, which finishes a split on cbuf */
1360
0
        xlinfo = XLOG_BTREE_INSERT_UPPER;
1361
0
        XLogRegisterBuffer(1, cbuf, REGBUF_STANDARD);
1362
1363
0
        if (BufferIsValid(metabuf))
1364
0
        {
1365
          /* Actually, it's an internal page insert + meta update */
1366
0
          xlinfo = XLOG_BTREE_INSERT_META;
1367
1368
0
          Assert(metad->btm_version >= BTREE_NOVAC_VERSION);
1369
0
          xlmeta.version = metad->btm_version;
1370
0
          xlmeta.root = metad->btm_root;
1371
0
          xlmeta.level = metad->btm_level;
1372
0
          xlmeta.fastroot = metad->btm_fastroot;
1373
0
          xlmeta.fastlevel = metad->btm_fastlevel;
1374
0
          xlmeta.last_cleanup_num_delpages = metad->btm_last_cleanup_num_delpages;
1375
0
          xlmeta.allequalimage = metad->btm_allequalimage;
1376
1377
0
          XLogRegisterBuffer(2, metabuf,
1378
0
                     REGBUF_WILL_INIT | REGBUF_STANDARD);
1379
0
          XLogRegisterBufData(2, &xlmeta,
1380
0
                    sizeof(xl_btree_metadata));
1381
0
        }
1382
0
      }
1383
1384
0
      XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
1385
0
      if (postingoff == 0)
1386
0
      {
1387
        /* Just log itup from caller */
1388
0
        XLogRegisterBufData(0, itup, IndexTupleSize(itup));
1389
0
      }
1390
0
      else
1391
0
      {
1392
        /*
1393
         * Insert with posting list split (XLOG_BTREE_INSERT_POST
1394
         * record) case.
1395
         *
1396
         * Log postingoff.  Also log origitup, not itup.  REDO routine
1397
         * must reconstruct final itup (as well as nposting) using
1398
         * _bt_swap_posting().
1399
         */
1400
0
        upostingoff = postingoff;
1401
1402
0
        XLogRegisterBufData(0, &upostingoff, sizeof(uint16));
1403
0
        XLogRegisterBufData(0, origitup,
1404
0
                  IndexTupleSize(origitup));
1405
0
      }
1406
1407
0
      recptr = XLogInsert(RM_BTREE_ID, xlinfo);
1408
0
    }
1409
0
    else
1410
0
      recptr = XLogGetFakeLSN(rel);
1411
1412
0
    if (BufferIsValid(metabuf))
1413
0
      PageSetLSN(metapg, recptr);
1414
0
    if (!isleaf)
1415
0
      PageSetLSN(BufferGetPage(cbuf), recptr);
1416
1417
0
    PageSetLSN(page, recptr);
1418
1419
0
    END_CRIT_SECTION();
1420
1421
    /* Release subsidiary buffers */
1422
0
    if (BufferIsValid(metabuf))
1423
0
      _bt_relbuf(rel, metabuf);
1424
0
    if (!isleaf)
1425
0
      _bt_relbuf(rel, cbuf);
1426
1427
    /*
1428
     * Cache the block number if this is the rightmost leaf page.  Cache
1429
     * may be used by a future inserter within _bt_search_insert().
1430
     */
1431
0
    blockcache = InvalidBlockNumber;
1432
0
    if (isrightmost && isleaf && !isroot)
1433
0
      blockcache = BufferGetBlockNumber(buf);
1434
1435
    /* Release buffer for insertion target block */
1436
0
    _bt_relbuf(rel, buf);
1437
1438
    /*
1439
     * If we decided to cache the insertion target block before releasing
1440
     * its buffer lock, then cache it now.  Check the height of the tree
1441
     * first, though.  We don't go for the optimization with small
1442
     * indexes.  Defer final check to this point to ensure that we don't
1443
     * call _bt_getrootheight while holding a buffer lock.
1444
     */
1445
0
    if (BlockNumberIsValid(blockcache) &&
1446
0
      _bt_getrootheight(rel) >= BTREE_FASTPATH_MIN_LEVEL)
1447
0
      RelationSetTargetBlock(rel, blockcache);
1448
0
  }
1449
1450
  /* be tidy */
1451
0
  if (postingoff != 0)
1452
0
  {
1453
    /* itup is actually a modified copy of caller's original */
1454
0
    pfree(nposting);
1455
0
    pfree(itup);
1456
0
  }
1457
0
}
1458
1459
/*
1460
 *  _bt_split() -- split a page in the btree.
1461
 *
1462
 *    On entry, buf is the page to split, and is pinned and write-locked.
1463
 *    newitemoff etc. tell us about the new item that must be inserted
1464
 *    along with the data from the original page.
1465
 *
1466
 *    itup_key is used for suffix truncation on leaf pages (internal
1467
 *    page callers pass NULL).  When splitting a non-leaf page, 'cbuf'
1468
 *    is the left-sibling of the page we're inserting the downlink for.
1469
 *    This function will clear the INCOMPLETE_SPLIT flag on it, and
1470
 *    release the buffer.
1471
 *
1472
 *    orignewitem, nposting, and postingoff are needed when an insert of
1473
 *    orignewitem results in both a posting list split and a page split.
1474
 *    These extra posting list split details are used here in the same
1475
 *    way as they are used in the more common case where a posting list
1476
 *    split does not coincide with a page split.  We need to deal with
1477
 *    posting list splits directly in order to ensure that everything
1478
 *    that follows from the insert of orignewitem is handled as a single
1479
 *    atomic operation (though caller's insert of a new pivot/downlink
1480
 *    into parent page will still be a separate operation).  See
1481
 *    nbtree/README for details on the design of posting list splits.
1482
 *
1483
 *    Returns the new right sibling of buf, pinned and write-locked.
1484
 *    The pin and lock on buf are maintained.
1485
 */
1486
static Buffer
1487
_bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf,
1488
      Buffer cbuf, OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem,
1489
      IndexTuple orignewitem, IndexTuple nposting, uint16 postingoff)
1490
0
{
1491
0
  Buffer    rbuf;
1492
0
  Page    origpage;
1493
0
  Page    leftpage,
1494
0
        rightpage;
1495
0
  PGAlignedBlock leftpage_buf,
1496
0
        rightpage_buf;
1497
0
  BlockNumber origpagenumber,
1498
0
        rightpagenumber;
1499
0
  BTPageOpaque ropaque,
1500
0
        lopaque,
1501
0
        oopaque;
1502
0
  Buffer    sbuf = InvalidBuffer;
1503
0
  Page    spage = NULL;
1504
0
  BTPageOpaque sopaque = NULL;
1505
0
  Size    itemsz;
1506
0
  ItemId    itemid;
1507
0
  IndexTuple  firstright,
1508
0
        lefthighkey;
1509
0
  OffsetNumber firstrightoff;
1510
0
  OffsetNumber afterleftoff,
1511
0
        afterrightoff,
1512
0
        minusinfoff;
1513
0
  OffsetNumber origpagepostingoff;
1514
0
  OffsetNumber maxoff;
1515
0
  OffsetNumber i;
1516
0
  bool    newitemonleft,
1517
0
        isleaf,
1518
0
        isrightmost;
1519
0
  XLogRecPtr  recptr;
1520
1521
  /*
1522
   * origpage is the original page to be split.  leftpage is a temporary
1523
   * buffer that receives the left-sibling data, which will be copied back
1524
   * into origpage on success.  rightpage is the new page that will receive
1525
   * the right-sibling data.
1526
   *
1527
   * leftpage is allocated after choosing a split point.  rightpage's new
1528
   * buffer isn't acquired until after leftpage is initialized and has new
1529
   * high key, the last point where splitting the page may fail (barring
1530
   * corruption).  Failing before acquiring new buffer won't have lasting
1531
   * consequences, since origpage won't have been modified and leftpage is
1532
   * only workspace.
1533
   */
1534
0
  origpage = BufferGetPage(buf);
1535
0
  oopaque = BTPageGetOpaque(origpage);
1536
0
  isleaf = P_ISLEAF(oopaque);
1537
0
  isrightmost = P_RIGHTMOST(oopaque);
1538
0
  maxoff = PageGetMaxOffsetNumber(origpage);
1539
0
  origpagenumber = BufferGetBlockNumber(buf);
1540
1541
  /*
1542
   * Choose a point to split origpage at.
1543
   *
1544
   * A split point can be thought of as a point _between_ two existing data
1545
   * items on origpage (the lastleft and firstright tuples), provided you
1546
   * pretend that the new item that didn't fit is already on origpage.
1547
   *
1548
   * Since origpage does not actually contain newitem, the representation of
1549
   * split points needs to work with two boundary cases: splits where
1550
   * newitem is lastleft, and splits where newitem is firstright.
1551
   * newitemonleft resolves the ambiguity that would otherwise exist when
1552
   * newitemoff == firstrightoff.  In all other cases it's clear which side
1553
   * of the split every tuple goes on from context.  newitemonleft is
1554
   * usually (but not always) redundant information.
1555
   *
1556
   * firstrightoff is supposed to be an origpage offset number, but it's
1557
   * possible that its value will be maxoff+1, which is "past the end" of
1558
   * origpage.  This happens in the rare case where newitem goes after all
1559
   * existing items (i.e. newitemoff is maxoff+1) and we end up splitting
1560
   * origpage at the point that leaves newitem alone on new right page.  Any
1561
   * "!newitemonleft && newitemoff == firstrightoff" split point makes
1562
   * newitem the firstright tuple, though, so this case isn't a special
1563
   * case.
1564
   */
1565
0
  firstrightoff = _bt_findsplitloc(rel, origpage, newitemoff, newitemsz,
1566
0
                   newitem, &newitemonleft);
1567
1568
  /* Use temporary buffer for leftpage */
1569
0
  leftpage = leftpage_buf.data;
1570
0
  _bt_pageinit(leftpage, BufferGetPageSize(buf));
1571
0
  lopaque = BTPageGetOpaque(leftpage);
1572
1573
  /*
1574
   * leftpage won't be the root when we're done.  Also, clear the SPLIT_END
1575
   * and HAS_GARBAGE flags.
1576
   */
1577
0
  lopaque->btpo_flags = oopaque->btpo_flags;
1578
0
  lopaque->btpo_flags &= ~(BTP_ROOT | BTP_SPLIT_END | BTP_HAS_GARBAGE);
1579
  /* set flag in leftpage indicating that rightpage has no downlink yet */
1580
0
  lopaque->btpo_flags |= BTP_INCOMPLETE_SPLIT;
1581
0
  lopaque->btpo_prev = oopaque->btpo_prev;
1582
  /* handle btpo_next after rightpage buffer acquired */
1583
0
  lopaque->btpo_level = oopaque->btpo_level;
1584
  /* handle btpo_cycleid after rightpage buffer acquired */
1585
1586
  /*
1587
   * Copy the original page's LSN into leftpage, which will become the
1588
   * updated version of the page.  We need this because XLogInsert will
1589
   * examine the LSN and possibly dump it in a page image.
1590
   */
1591
0
  PageSetLSN(leftpage, PageGetLSN(origpage));
1592
1593
  /*
1594
   * Determine page offset number of existing overlapped-with-orignewitem
1595
   * posting list when it is necessary to perform a posting list split in
1596
   * passing.  Note that newitem was already changed by caller (newitem no
1597
   * longer has the orignewitem TID).
1598
   *
1599
   * This page offset number (origpagepostingoff) will be used to pretend
1600
   * that the posting split has already taken place, even though the
1601
   * required modifications to origpage won't occur until we reach the
1602
   * critical section.  The lastleft and firstright tuples of our page split
1603
   * point should, in effect, come from an imaginary version of origpage
1604
   * that has the nposting tuple instead of the original posting list tuple.
1605
   *
1606
   * Note: _bt_findsplitloc() should have compensated for coinciding posting
1607
   * list splits in just the same way, at least in theory.  It doesn't
1608
   * bother with that, though.  In practice it won't affect its choice of
1609
   * split point.
1610
   */
1611
0
  origpagepostingoff = InvalidOffsetNumber;
1612
0
  if (postingoff != 0)
1613
0
  {
1614
0
    Assert(isleaf);
1615
0
    Assert(ItemPointerCompare(&orignewitem->t_tid,
1616
0
                  &newitem->t_tid) < 0);
1617
0
    Assert(BTreeTupleIsPosting(nposting));
1618
0
    origpagepostingoff = OffsetNumberPrev(newitemoff);
1619
0
  }
1620
1621
  /*
1622
   * The high key for the new left page is a possibly-truncated copy of
1623
   * firstright on the leaf level (it's "firstright itself" on internal
1624
   * pages; see !isleaf comments below).  This may seem to be contrary to
1625
   * Lehman & Yao's approach of using a copy of lastleft as the new high key
1626
   * when splitting on the leaf level.  It isn't, though.
1627
   *
1628
   * Suffix truncation will leave the left page's high key fully equal to
1629
   * lastleft when lastleft and firstright are equal prior to heap TID (that
1630
   * is, the tiebreaker TID value comes from lastleft).  It isn't actually
1631
   * necessary for a new leaf high key to be a copy of lastleft for the L&Y
1632
   * "subtree" invariant to hold.  It's sufficient to make sure that the new
1633
   * leaf high key is strictly less than firstright, and greater than or
1634
   * equal to (not necessarily equal to) lastleft.  In other words, when
1635
   * suffix truncation isn't possible during a leaf page split, we take
1636
   * L&Y's exact approach to generating a new high key for the left page.
1637
   * (Actually, that is slightly inaccurate.  We don't just use a copy of
1638
   * lastleft.  A tuple with all the keys from firstright but the max heap
1639
   * TID from lastleft is used, to avoid introducing a special case.)
1640
   */
1641
0
  if (!newitemonleft && newitemoff == firstrightoff)
1642
0
  {
1643
    /* incoming tuple becomes firstright */
1644
0
    itemsz = newitemsz;
1645
0
    firstright = newitem;
1646
0
  }
1647
0
  else
1648
0
  {
1649
    /* existing item at firstrightoff becomes firstright */
1650
0
    itemid = PageGetItemId(origpage, firstrightoff);
1651
0
    itemsz = ItemIdGetLength(itemid);
1652
0
    firstright = (IndexTuple) PageGetItem(origpage, itemid);
1653
0
    if (firstrightoff == origpagepostingoff)
1654
0
      firstright = nposting;
1655
0
  }
1656
1657
0
  if (isleaf)
1658
0
  {
1659
0
    IndexTuple  lastleft;
1660
1661
    /* Attempt suffix truncation for leaf page splits */
1662
0
    if (newitemonleft && newitemoff == firstrightoff)
1663
0
    {
1664
      /* incoming tuple becomes lastleft */
1665
0
      lastleft = newitem;
1666
0
    }
1667
0
    else
1668
0
    {
1669
0
      OffsetNumber lastleftoff;
1670
1671
      /* existing item before firstrightoff becomes lastleft */
1672
0
      lastleftoff = OffsetNumberPrev(firstrightoff);
1673
0
      Assert(lastleftoff >= P_FIRSTDATAKEY(oopaque));
1674
0
      itemid = PageGetItemId(origpage, lastleftoff);
1675
0
      lastleft = (IndexTuple) PageGetItem(origpage, itemid);
1676
0
      if (lastleftoff == origpagepostingoff)
1677
0
        lastleft = nposting;
1678
0
    }
1679
1680
0
    lefthighkey = _bt_truncate(rel, lastleft, firstright, itup_key);
1681
0
    itemsz = IndexTupleSize(lefthighkey);
1682
0
  }
1683
0
  else
1684
0
  {
1685
    /*
1686
     * Don't perform suffix truncation on a copy of firstright to make
1687
     * left page high key for internal page splits.  Must use firstright
1688
     * as new high key directly.
1689
     *
1690
     * Each distinct separator key value originates as a leaf level high
1691
     * key; all other separator keys/pivot tuples are copied from one
1692
     * level down.  A separator key in a grandparent page must be
1693
     * identical to high key in rightmost parent page of the subtree to
1694
     * its left, which must itself be identical to high key in rightmost
1695
     * child page of that same subtree (this even applies to separator
1696
     * from grandparent's high key).  There must always be an unbroken
1697
     * "seam" of identical separator keys that guide index scans at every
1698
     * level, starting from the grandparent.  That's why suffix truncation
1699
     * is unsafe here.
1700
     *
1701
     * Internal page splits will truncate firstright into a "negative
1702
     * infinity" data item when it gets inserted on the new right page
1703
     * below, though.  This happens during the call to _bt_pgaddtup() for
1704
     * the new first data item for right page.  Do not confuse this
1705
     * mechanism with suffix truncation.  It is just a convenient way of
1706
     * implementing page splits that split the internal page "inside"
1707
     * firstright.  The lefthighkey separator key cannot appear a second
1708
     * time in the right page (only firstright's downlink goes in right
1709
     * page).
1710
     */
1711
0
    lefthighkey = firstright;
1712
0
  }
1713
1714
  /*
1715
   * Add new high key to leftpage
1716
   */
1717
0
  afterleftoff = P_HIKEY;
1718
1719
0
  Assert(BTreeTupleGetNAtts(lefthighkey, rel) > 0);
1720
0
  Assert(BTreeTupleGetNAtts(lefthighkey, rel) <=
1721
0
       IndexRelationGetNumberOfKeyAttributes(rel));
1722
0
  Assert(itemsz == MAXALIGN(IndexTupleSize(lefthighkey)));
1723
0
  if (PageAddItem(leftpage, lefthighkey, itemsz, afterleftoff, false, false) == InvalidOffsetNumber)
1724
0
    elog(ERROR, "failed to add high key to the left sibling"
1725
0
       " while splitting block %u of index \"%s\"",
1726
0
       origpagenumber, RelationGetRelationName(rel));
1727
0
  afterleftoff = OffsetNumberNext(afterleftoff);
1728
1729
  /*
1730
   * Acquire a new right page to split into, now that left page has a new
1731
   * high key.
1732
   *
1733
   * To not confuse future VACUUM operations, we zero the right page and
1734
   * work on an in-memory copy of it before writing WAL, then copy its
1735
   * contents back to the actual page once we start the critical section
1736
   * work.  This simplifies the split work, so as there is no need to zero
1737
   * the right page before throwing an error.
1738
   */
1739
0
  rbuf = _bt_allocbuf(rel, heaprel);
1740
0
  rightpage = rightpage_buf.data;
1741
1742
  /*
1743
   * Copy the contents of the right page into its temporary location, and
1744
   * zero the original space.
1745
   */
1746
0
  memcpy(rightpage, BufferGetPage(rbuf), BLCKSZ);
1747
0
  memset(BufferGetPage(rbuf), 0, BLCKSZ);
1748
0
  rightpagenumber = BufferGetBlockNumber(rbuf);
1749
  /* rightpage was initialized by _bt_allocbuf */
1750
0
  ropaque = BTPageGetOpaque(rightpage);
1751
1752
  /*
1753
   * Finish off remaining leftpage special area fields.  They cannot be set
1754
   * before both origpage (leftpage) and rightpage buffers are acquired and
1755
   * locked.
1756
   *
1757
   * btpo_cycleid is only used with leaf pages, though we set it here in all
1758
   * cases just to be consistent.
1759
   */
1760
0
  lopaque->btpo_next = rightpagenumber;
1761
0
  lopaque->btpo_cycleid = _bt_vacuum_cycleid(rel);
1762
1763
  /*
1764
   * rightpage won't be the root when we're done.  Also, clear the SPLIT_END
1765
   * and HAS_GARBAGE flags.
1766
   */
1767
0
  ropaque->btpo_flags = oopaque->btpo_flags;
1768
0
  ropaque->btpo_flags &= ~(BTP_ROOT | BTP_SPLIT_END | BTP_HAS_GARBAGE);
1769
0
  ropaque->btpo_prev = origpagenumber;
1770
0
  ropaque->btpo_next = oopaque->btpo_next;
1771
0
  ropaque->btpo_level = oopaque->btpo_level;
1772
0
  ropaque->btpo_cycleid = lopaque->btpo_cycleid;
1773
1774
  /*
1775
   * Add new high key to rightpage where necessary.
1776
   *
1777
   * If the page we're splitting is not the rightmost page at its level in
1778
   * the tree, then the first entry on the page is the high key from
1779
   * origpage.
1780
   */
1781
0
  afterrightoff = P_HIKEY;
1782
1783
0
  if (!isrightmost)
1784
0
  {
1785
0
    IndexTuple  righthighkey;
1786
1787
0
    itemid = PageGetItemId(origpage, P_HIKEY);
1788
0
    itemsz = ItemIdGetLength(itemid);
1789
0
    righthighkey = (IndexTuple) PageGetItem(origpage, itemid);
1790
0
    Assert(BTreeTupleGetNAtts(righthighkey, rel) > 0);
1791
0
    Assert(BTreeTupleGetNAtts(righthighkey, rel) <=
1792
0
         IndexRelationGetNumberOfKeyAttributes(rel));
1793
0
    if (PageAddItem(rightpage, righthighkey, itemsz, afterrightoff, false, false) == InvalidOffsetNumber)
1794
0
    {
1795
0
      elog(ERROR, "failed to add high key to the right sibling"
1796
0
         " while splitting block %u of index \"%s\"",
1797
0
         origpagenumber, RelationGetRelationName(rel));
1798
0
    }
1799
0
    afterrightoff = OffsetNumberNext(afterrightoff);
1800
0
  }
1801
1802
  /*
1803
   * Internal page splits truncate first data item on right page -- it
1804
   * becomes "minus infinity" item for the page.  Set this up here.
1805
   */
1806
0
  minusinfoff = InvalidOffsetNumber;
1807
0
  if (!isleaf)
1808
0
    minusinfoff = afterrightoff;
1809
1810
  /*
1811
   * Now transfer all the data items (non-pivot tuples in isleaf case, or
1812
   * additional pivot tuples in !isleaf case) to the appropriate page.
1813
   *
1814
   * Note: we *must* insert at least the right page's items in item-number
1815
   * order, for the benefit of _bt_restore_page().
1816
   */
1817
0
  for (i = P_FIRSTDATAKEY(oopaque); i <= maxoff; i = OffsetNumberNext(i))
1818
0
  {
1819
0
    IndexTuple  dataitem;
1820
1821
0
    itemid = PageGetItemId(origpage, i);
1822
0
    itemsz = ItemIdGetLength(itemid);
1823
0
    dataitem = (IndexTuple) PageGetItem(origpage, itemid);
1824
1825
    /* replace original item with nposting due to posting split? */
1826
0
    if (i == origpagepostingoff)
1827
0
    {
1828
0
      Assert(BTreeTupleIsPosting(dataitem));
1829
0
      Assert(itemsz == MAXALIGN(IndexTupleSize(nposting)));
1830
0
      dataitem = nposting;
1831
0
    }
1832
1833
    /* does new item belong before this one? */
1834
0
    else if (i == newitemoff)
1835
0
    {
1836
0
      if (newitemonleft)
1837
0
      {
1838
0
        Assert(newitemoff <= firstrightoff);
1839
0
        if (!_bt_pgaddtup(leftpage, newitemsz, newitem, afterleftoff,
1840
0
                  false))
1841
0
        {
1842
0
          elog(ERROR, "failed to add new item to the left sibling"
1843
0
             " while splitting block %u of index \"%s\"",
1844
0
             origpagenumber, RelationGetRelationName(rel));
1845
0
        }
1846
0
        afterleftoff = OffsetNumberNext(afterleftoff);
1847
0
      }
1848
0
      else
1849
0
      {
1850
0
        Assert(newitemoff >= firstrightoff);
1851
0
        if (!_bt_pgaddtup(rightpage, newitemsz, newitem, afterrightoff,
1852
0
                  afterrightoff == minusinfoff))
1853
0
        {
1854
0
          elog(ERROR, "failed to add new item to the right sibling"
1855
0
             " while splitting block %u of index \"%s\"",
1856
0
             origpagenumber, RelationGetRelationName(rel));
1857
0
        }
1858
0
        afterrightoff = OffsetNumberNext(afterrightoff);
1859
0
      }
1860
0
    }
1861
1862
    /* decide which page to put it on */
1863
0
    if (i < firstrightoff)
1864
0
    {
1865
0
      if (!_bt_pgaddtup(leftpage, itemsz, dataitem, afterleftoff, false))
1866
0
      {
1867
0
        elog(ERROR, "failed to add old item to the left sibling"
1868
0
           " while splitting block %u of index \"%s\"",
1869
0
           origpagenumber, RelationGetRelationName(rel));
1870
0
      }
1871
0
      afterleftoff = OffsetNumberNext(afterleftoff);
1872
0
    }
1873
0
    else
1874
0
    {
1875
0
      if (!_bt_pgaddtup(rightpage, itemsz, dataitem, afterrightoff,
1876
0
                afterrightoff == minusinfoff))
1877
0
      {
1878
0
        elog(ERROR, "failed to add old item to the right sibling"
1879
0
           " while splitting block %u of index \"%s\"",
1880
0
           origpagenumber, RelationGetRelationName(rel));
1881
0
      }
1882
0
      afterrightoff = OffsetNumberNext(afterrightoff);
1883
0
    }
1884
0
  }
1885
1886
  /* Handle case where newitem goes at the end of rightpage */
1887
0
  if (i <= newitemoff)
1888
0
  {
1889
    /*
1890
     * Can't have newitemonleft here; that would imply we were told to put
1891
     * *everything* on the left page, which cannot fit (if it could, we'd
1892
     * not be splitting the page).
1893
     */
1894
0
    Assert(!newitemonleft && newitemoff == maxoff + 1);
1895
0
    if (!_bt_pgaddtup(rightpage, newitemsz, newitem, afterrightoff,
1896
0
              afterrightoff == minusinfoff))
1897
0
    {
1898
0
      elog(ERROR, "failed to add new item to the right sibling"
1899
0
         " while splitting block %u of index \"%s\"",
1900
0
         origpagenumber, RelationGetRelationName(rel));
1901
0
    }
1902
0
    afterrightoff = OffsetNumberNext(afterrightoff);
1903
0
  }
1904
1905
  /*
1906
   * We have to grab the original right sibling (if any) and update its prev
1907
   * link.  We are guaranteed that this is deadlock-free, since we couple
1908
   * the locks in the standard order: left to right.
1909
   */
1910
0
  if (!isrightmost)
1911
0
  {
1912
0
    sbuf = _bt_getbuf(rel, oopaque->btpo_next, BT_WRITE);
1913
0
    spage = BufferGetPage(sbuf);
1914
0
    sopaque = BTPageGetOpaque(spage);
1915
0
    if (sopaque->btpo_prev != origpagenumber)
1916
0
    {
1917
0
      ereport(ERROR,
1918
0
          (errcode(ERRCODE_INDEX_CORRUPTED),
1919
0
           errmsg_internal("right sibling's left-link doesn't match: "
1920
0
                   "block %u links to %u instead of expected %u in index \"%s\"",
1921
0
                   oopaque->btpo_next, sopaque->btpo_prev, origpagenumber,
1922
0
                   RelationGetRelationName(rel))));
1923
0
    }
1924
1925
    /*
1926
     * Check to see if we can set the SPLIT_END flag in the right-hand
1927
     * split page; this can save some I/O for vacuum since it need not
1928
     * proceed to the right sibling.  We can set the flag if the right
1929
     * sibling has a different cycleid: that means it could not be part of
1930
     * a group of pages that were all split off from the same ancestor
1931
     * page.  If you're confused, imagine that page A splits to A B and
1932
     * then again, yielding A C B, while vacuum is in progress.  Tuples
1933
     * originally in A could now be in either B or C, hence vacuum must
1934
     * examine both pages.  But if D, our right sibling, has a different
1935
     * cycleid then it could not contain any tuples that were in A when
1936
     * the vacuum started.
1937
     */
1938
0
    if (sopaque->btpo_cycleid != ropaque->btpo_cycleid)
1939
0
      ropaque->btpo_flags |= BTP_SPLIT_END;
1940
0
  }
1941
1942
  /*
1943
   * Right sibling is locked, new siblings are prepared, but original page
1944
   * is not updated yet.
1945
   *
1946
   * NO EREPORT(ERROR) till right sibling is updated.  We can get away with
1947
   * not starting the critical section till here because we haven't been
1948
   * scribbling on the original page yet; see comments above.
1949
   */
1950
0
  START_CRIT_SECTION();
1951
1952
  /*
1953
   * By here, the original data page has been split into two new halves, and
1954
   * these are correct.  The algorithm requires that the left page never
1955
   * move during a split, so we copy the new left page back on top of the
1956
   * original.  We need to do this before writing the WAL record, so that
1957
   * XLogInsert can WAL log an image of the page if necessary.
1958
   */
1959
0
  memcpy(origpage, leftpage, BLCKSZ);
1960
  /* leftpage, lopaque must not be used below here */
1961
1962
  /*
1963
   * Move the contents of the right page from its temporary location to the
1964
   * destination buffer, before writing the WAL record.  Unlike the left
1965
   * page, the right page and its opaque area are still needed to complete
1966
   * the update of the page, so reinitialize them.
1967
   */
1968
0
  rightpage = BufferGetPage(rbuf);
1969
0
  memcpy(rightpage, rightpage_buf.data, BLCKSZ);
1970
0
  ropaque = BTPageGetOpaque(rightpage);
1971
1972
0
  MarkBufferDirty(buf);
1973
0
  MarkBufferDirty(rbuf);
1974
1975
0
  if (!isrightmost)
1976
0
  {
1977
0
    sopaque->btpo_prev = rightpagenumber;
1978
0
    MarkBufferDirty(sbuf);
1979
0
  }
1980
1981
  /*
1982
   * Clear INCOMPLETE_SPLIT flag on child if inserting the new item finishes
1983
   * a split
1984
   */
1985
0
  if (!isleaf)
1986
0
  {
1987
0
    Page    cpage = BufferGetPage(cbuf);
1988
0
    BTPageOpaque cpageop = BTPageGetOpaque(cpage);
1989
1990
0
    cpageop->btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
1991
0
    MarkBufferDirty(cbuf);
1992
0
  }
1993
1994
  /* XLOG stuff */
1995
0
  if (RelationNeedsWAL(rel))
1996
0
  {
1997
0
    xl_btree_split xlrec;
1998
0
    uint8   xlinfo;
1999
2000
0
    xlrec.level = ropaque->btpo_level;
2001
    /* See comments below on newitem, orignewitem, and posting lists */
2002
0
    xlrec.firstrightoff = firstrightoff;
2003
0
    xlrec.newitemoff = newitemoff;
2004
0
    xlrec.postingoff = 0;
2005
0
    if (postingoff != 0 && origpagepostingoff < firstrightoff)
2006
0
      xlrec.postingoff = postingoff;
2007
2008
0
    XLogBeginInsert();
2009
0
    XLogRegisterData(&xlrec, SizeOfBtreeSplit);
2010
2011
0
    XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
2012
0
    XLogRegisterBuffer(1, rbuf, REGBUF_WILL_INIT);
2013
    /* Log original right sibling, since we've changed its prev-pointer */
2014
0
    if (!isrightmost)
2015
0
      XLogRegisterBuffer(2, sbuf, REGBUF_STANDARD);
2016
0
    if (!isleaf)
2017
0
      XLogRegisterBuffer(3, cbuf, REGBUF_STANDARD);
2018
2019
    /*
2020
     * Log the new item, if it was inserted on the left page. (If it was
2021
     * put on the right page, we don't need to explicitly WAL log it
2022
     * because it's included with all the other items on the right page.)
2023
     * Show the new item as belonging to the left page buffer, so that it
2024
     * is not stored if XLogInsert decides it needs a full-page image of
2025
     * the left page.  We always store newitemoff in the record, though.
2026
     *
2027
     * The details are sometimes slightly different for page splits that
2028
     * coincide with a posting list split.  If both the replacement
2029
     * posting list and newitem go on the right page, then we don't need
2030
     * to log anything extra, just like the simple !newitemonleft
2031
     * no-posting-split case (postingoff is set to zero in the WAL record,
2032
     * so recovery doesn't need to process a posting list split at all).
2033
     * Otherwise, we set postingoff and log orignewitem instead of
2034
     * newitem, despite having actually inserted newitem.  REDO routine
2035
     * must reconstruct nposting and newitem using _bt_swap_posting().
2036
     *
2037
     * Note: It's possible that our page split point is the point that
2038
     * makes the posting list lastleft and newitem firstright.  This is
2039
     * the only case where we log orignewitem/newitem despite newitem
2040
     * going on the right page.  If XLogInsert decides that it can omit
2041
     * orignewitem due to logging a full-page image of the left page,
2042
     * everything still works out, since recovery only needs to log
2043
     * orignewitem for items on the left page (just like the regular
2044
     * newitem-logged case).
2045
     */
2046
0
    if (newitemonleft && xlrec.postingoff == 0)
2047
0
      XLogRegisterBufData(0, newitem, newitemsz);
2048
0
    else if (xlrec.postingoff != 0)
2049
0
    {
2050
0
      Assert(isleaf);
2051
0
      Assert(newitemonleft || firstrightoff == newitemoff);
2052
0
      Assert(newitemsz == IndexTupleSize(orignewitem));
2053
0
      XLogRegisterBufData(0, orignewitem, newitemsz);
2054
0
    }
2055
2056
    /* Log the left page's new high key */
2057
0
    if (!isleaf)
2058
0
    {
2059
      /* lefthighkey isn't local copy, get current pointer */
2060
0
      itemid = PageGetItemId(origpage, P_HIKEY);
2061
0
      lefthighkey = (IndexTuple) PageGetItem(origpage, itemid);
2062
0
    }
2063
0
    XLogRegisterBufData(0, lefthighkey,
2064
0
              MAXALIGN(IndexTupleSize(lefthighkey)));
2065
2066
    /*
2067
     * Log the contents of the right page in the format understood by
2068
     * _bt_restore_page().  The whole right page will be recreated.
2069
     *
2070
     * Direct access to page is not good but faster - we should implement
2071
     * some new func in page API.  Note we only store the tuples
2072
     * themselves, knowing that they were inserted in item-number order
2073
     * and so the line pointers can be reconstructed.  See comments for
2074
     * _bt_restore_page().
2075
     */
2076
0
    XLogRegisterBufData(1,
2077
0
              (char *) rightpage + ((PageHeader) rightpage)->pd_upper,
2078
0
              ((PageHeader) rightpage)->pd_special - ((PageHeader) rightpage)->pd_upper);
2079
2080
0
    xlinfo = newitemonleft ? XLOG_BTREE_SPLIT_L : XLOG_BTREE_SPLIT_R;
2081
0
    recptr = XLogInsert(RM_BTREE_ID, xlinfo);
2082
0
  }
2083
0
  else
2084
0
    recptr = XLogGetFakeLSN(rel);
2085
2086
0
  PageSetLSN(origpage, recptr);
2087
0
  PageSetLSN(rightpage, recptr);
2088
0
  if (!isrightmost)
2089
0
    PageSetLSN(spage, recptr);
2090
0
  if (!isleaf)
2091
0
    PageSetLSN(BufferGetPage(cbuf), recptr);
2092
2093
0
  END_CRIT_SECTION();
2094
2095
  /* release the old right sibling */
2096
0
  if (!isrightmost)
2097
0
    _bt_relbuf(rel, sbuf);
2098
2099
  /* release the child */
2100
0
  if (!isleaf)
2101
0
    _bt_relbuf(rel, cbuf);
2102
2103
  /* be tidy */
2104
0
  if (isleaf)
2105
0
    pfree(lefthighkey);
2106
2107
  /* split's done */
2108
0
  return rbuf;
2109
0
}
2110
2111
/*
2112
 * _bt_insert_parent() -- Insert downlink into parent, completing split.
2113
 *
2114
 * On entry, buf and rbuf are the left and right split pages, which we
2115
 * still hold write locks on.  Both locks will be released here.  We
2116
 * release the rbuf lock once we have a write lock on the page that we
2117
 * intend to insert a downlink to rbuf on (i.e. buf's current parent page).
2118
 * The lock on buf is released at the same point as the lock on the parent
2119
 * page, since buf's INCOMPLETE_SPLIT flag must be cleared by the same
2120
 * atomic operation that completes the split by inserting a new downlink.
2121
 *
2122
 * stack - stack showing how we got here.  Will be NULL when splitting true
2123
 *      root, or during concurrent root split, where we can be inefficient
2124
 * isroot - we split the true root
2125
 * isonly - we split a page alone on its level (might have been fast root)
2126
 */
2127
static void
2128
_bt_insert_parent(Relation rel,
2129
          Relation heaprel,
2130
          Buffer buf,
2131
          Buffer rbuf,
2132
          BTStack stack,
2133
          bool isroot,
2134
          bool isonly)
2135
0
{
2136
0
  Assert(heaprel != NULL);
2137
2138
  /*
2139
   * Here we have to do something Lehman and Yao don't talk about: deal with
2140
   * a root split and construction of a new root.  If our stack is empty
2141
   * then we have just split a node on what had been the root level when we
2142
   * descended the tree.  If it was still the root then we perform a
2143
   * new-root construction.  If it *wasn't* the root anymore, search to find
2144
   * the next higher level that someone constructed meanwhile, and find the
2145
   * right place to insert as for the normal case.
2146
   *
2147
   * If we have to search for the parent level, we do so by re-descending
2148
   * from the root.  This is not super-efficient, but it's rare enough not
2149
   * to matter.
2150
   */
2151
0
  if (isroot)
2152
0
  {
2153
0
    Buffer    rootbuf;
2154
2155
0
    Assert(stack == NULL);
2156
0
    Assert(isonly);
2157
    /* create a new root node one level up and update the metapage */
2158
0
    rootbuf = _bt_newlevel(rel, heaprel, buf, rbuf);
2159
    /* release the split buffers */
2160
0
    _bt_relbuf(rel, rootbuf);
2161
0
    _bt_relbuf(rel, rbuf);
2162
0
    _bt_relbuf(rel, buf);
2163
0
  }
2164
0
  else
2165
0
  {
2166
0
    BlockNumber bknum = BufferGetBlockNumber(buf);
2167
0
    BlockNumber rbknum = BufferGetBlockNumber(rbuf);
2168
0
    Page    page = BufferGetPage(buf);
2169
0
    IndexTuple  new_item;
2170
0
    BTStackData fakestack;
2171
0
    IndexTuple  ritem;
2172
0
    Buffer    pbuf;
2173
2174
0
    if (stack == NULL)
2175
0
    {
2176
0
      BTPageOpaque opaque;
2177
2178
0
      elog(DEBUG2, "concurrent ROOT page split");
2179
0
      opaque = BTPageGetOpaque(page);
2180
2181
      /*
2182
       * We should never reach here when a leaf page split takes place
2183
       * despite the insert of newitem being able to apply the fastpath
2184
       * optimization.  Make sure of that with an assertion.
2185
       *
2186
       * This is more of a performance issue than a correctness issue.
2187
       * The fastpath won't have a descent stack.  Using a phony stack
2188
       * here works, but never rely on that.  The fastpath should be
2189
       * rejected within _bt_search_insert() when the rightmost leaf
2190
       * page will split, since it's faster to go through _bt_search()
2191
       * and get a stack in the usual way.
2192
       */
2193
0
      Assert(!(P_ISLEAF(opaque) &&
2194
0
           BlockNumberIsValid(RelationGetTargetBlock(rel))));
2195
2196
      /* Find the leftmost page at the next level up */
2197
0
      pbuf = _bt_get_endpoint(rel, opaque->btpo_level + 1, false);
2198
      /* Set up a phony stack entry pointing there */
2199
0
      stack = &fakestack;
2200
0
      stack->bts_blkno = BufferGetBlockNumber(pbuf);
2201
0
      stack->bts_offset = InvalidOffsetNumber;
2202
0
      stack->bts_parent = NULL;
2203
0
      _bt_relbuf(rel, pbuf);
2204
0
    }
2205
2206
    /* get high key from left, a strict lower bound for new right page */
2207
0
    ritem = (IndexTuple) PageGetItem(page,
2208
0
                     PageGetItemId(page, P_HIKEY));
2209
2210
    /* form an index tuple that points at the new right page */
2211
0
    new_item = CopyIndexTuple(ritem);
2212
0
    BTreeTupleSetDownLink(new_item, rbknum);
2213
2214
    /*
2215
     * Re-find and write lock the parent of buf.
2216
     *
2217
     * It's possible that the location of buf's downlink has changed since
2218
     * our initial _bt_search() descent.  _bt_getstackbuf() will detect
2219
     * and recover from this, updating the stack, which ensures that the
2220
     * new downlink will be inserted at the correct offset. Even buf's
2221
     * parent may have changed.
2222
     */
2223
0
    pbuf = _bt_getstackbuf(rel, heaprel, stack, bknum);
2224
2225
    /*
2226
     * Unlock the right child.  The left child will be unlocked in
2227
     * _bt_insertonpg().
2228
     *
2229
     * Unlocking the right child must be delayed until here to ensure that
2230
     * no concurrent VACUUM operation can become confused.  Page deletion
2231
     * cannot be allowed to fail to re-find a downlink for the rbuf page.
2232
     * (Actually, this is just a vestige of how things used to work.  The
2233
     * page deletion code is expected to check for the INCOMPLETE_SPLIT
2234
     * flag on the left child.  It won't attempt deletion of the right
2235
     * child until the split is complete.  Despite all this, we opt to
2236
     * conservatively delay unlocking the right child until here.)
2237
     */
2238
0
    _bt_relbuf(rel, rbuf);
2239
2240
0
    if (pbuf == InvalidBuffer)
2241
0
      ereport(ERROR,
2242
0
          (errcode(ERRCODE_INDEX_CORRUPTED),
2243
0
           errmsg_internal("failed to re-find parent key in index \"%s\" for split pages %u/%u",
2244
0
                   RelationGetRelationName(rel), bknum, rbknum)));
2245
2246
    /* Recursively insert into the parent */
2247
0
    _bt_insertonpg(rel, heaprel, NULL, pbuf, buf, stack->bts_parent,
2248
0
             new_item, MAXALIGN(IndexTupleSize(new_item)),
2249
0
             stack->bts_offset + 1, 0, isonly);
2250
2251
    /* be tidy */
2252
0
    pfree(new_item);
2253
0
  }
2254
0
}
2255
2256
/*
2257
 * _bt_finish_split() -- Finish an incomplete split
2258
 *
2259
 * A crash or other failure can leave a split incomplete.  The insertion
2260
 * routines won't allow to insert on a page that is incompletely split.
2261
 * Before inserting on such a page, call _bt_finish_split().
2262
 *
2263
 * On entry, 'lbuf' must be locked in write-mode.  On exit, it is unlocked
2264
 * and unpinned.
2265
 *
2266
 * Caller must provide a valid heaprel, since finishing a page split requires
2267
 * allocating a new page if and when the parent page splits in turn.
2268
 */
2269
void
2270
_bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf, BTStack stack)
2271
{
2272
  Page    lpage = BufferGetPage(lbuf);
2273
  BTPageOpaque lpageop = BTPageGetOpaque(lpage);
2274
  Buffer    rbuf;
2275
  Page    rpage;
2276
  BTPageOpaque rpageop;
2277
  bool    wasroot;
2278
  bool    wasonly;
2279
2280
  Assert(P_INCOMPLETE_SPLIT(lpageop));
2281
  Assert(heaprel != NULL);
2282
2283
  /* Lock right sibling, the one missing the downlink */
2284
  rbuf = _bt_getbuf(rel, lpageop->btpo_next, BT_WRITE);
2285
  rpage = BufferGetPage(rbuf);
2286
  rpageop = BTPageGetOpaque(rpage);
2287
2288
  /* Could this be a root split? */
2289
  if (!stack)
2290
  {
2291
    Buffer    metabuf;
2292
    Page    metapg;
2293
    BTMetaPageData *metad;
2294
2295
    /* acquire lock on the metapage */
2296
    metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
2297
    metapg = BufferGetPage(metabuf);
2298
    metad = BTPageGetMeta(metapg);
2299
2300
    wasroot = (metad->btm_root == BufferGetBlockNumber(lbuf));
2301
2302
    _bt_relbuf(rel, metabuf);
2303
  }
2304
  else
2305
    wasroot = false;
2306
2307
  /* Was this the only page on the level before split? */
2308
  wasonly = (P_LEFTMOST(lpageop) && P_RIGHTMOST(rpageop));
2309
2310
  INJECTION_POINT("nbtree-finish-incomplete-split", NULL);
2311
  elog(DEBUG1, "finishing incomplete split of %u/%u",
2312
     BufferGetBlockNumber(lbuf), BufferGetBlockNumber(rbuf));
2313
2314
  _bt_insert_parent(rel, heaprel, lbuf, rbuf, stack, wasroot, wasonly);
2315
}
2316
2317
/*
2318
 *  _bt_getstackbuf() -- Walk back up the tree one step, and find the pivot
2319
 *             tuple whose downlink points to child page.
2320
 *
2321
 *    Caller passes child's block number, which is used to identify
2322
 *    associated pivot tuple in parent page using a linear search that
2323
 *    matches on pivot's downlink/block number.  The expected location of
2324
 *    the pivot tuple is taken from the stack one level above the child
2325
 *    page.  This is used as a starting point.  Insertions into the
2326
 *    parent level could cause the pivot tuple to move right; deletions
2327
 *    could cause it to move left, but not left of the page we previously
2328
 *    found it on.
2329
 *
2330
 *    Caller can use its stack to relocate the pivot tuple/downlink for
2331
 *    any same-level page to the right of the page found by its initial
2332
 *    descent.  This is necessary because of the possibility that caller
2333
 *    moved right to recover from a concurrent page split.  It's also
2334
 *    convenient for certain callers to be able to step right when there
2335
 *    wasn't a concurrent page split, while still using their original
2336
 *    stack.  For example, the checkingunique _bt_doinsert() case may
2337
 *    have to step right when there are many physical duplicates, and its
2338
 *    scantid forces an insertion to the right of the "first page the
2339
 *    value could be on".  (This is also relied on by all of our callers
2340
 *    when dealing with !heapkeyspace indexes.)
2341
 *
2342
 *    Returns write-locked parent page buffer, or InvalidBuffer if pivot
2343
 *    tuple not found (should not happen).  Adjusts bts_blkno &
2344
 *    bts_offset if changed.  Page split caller should insert its new
2345
 *    pivot tuple for its new right sibling page on parent page, at the
2346
 *    offset number bts_offset + 1.
2347
 */
2348
Buffer
2349
_bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child)
2350
0
{
2351
0
  BlockNumber blkno;
2352
0
  OffsetNumber start;
2353
2354
0
  blkno = stack->bts_blkno;
2355
0
  start = stack->bts_offset;
2356
2357
0
  for (;;)
2358
0
  {
2359
0
    Buffer    buf;
2360
0
    Page    page;
2361
0
    BTPageOpaque opaque;
2362
2363
0
    buf = _bt_getbuf(rel, blkno, BT_WRITE);
2364
0
    page = BufferGetPage(buf);
2365
0
    opaque = BTPageGetOpaque(page);
2366
2367
0
    Assert(heaprel != NULL);
2368
0
    if (P_INCOMPLETE_SPLIT(opaque))
2369
0
    {
2370
0
      _bt_finish_split(rel, heaprel, buf, stack->bts_parent);
2371
0
      continue;
2372
0
    }
2373
2374
0
    if (!P_IGNORE(opaque))
2375
0
    {
2376
0
      OffsetNumber offnum,
2377
0
            minoff,
2378
0
            maxoff;
2379
0
      ItemId    itemid;
2380
0
      IndexTuple  item;
2381
2382
0
      minoff = P_FIRSTDATAKEY(opaque);
2383
0
      maxoff = PageGetMaxOffsetNumber(page);
2384
2385
      /*
2386
       * start = InvalidOffsetNumber means "search the whole page". We
2387
       * need this test anyway due to possibility that page has a high
2388
       * key now when it didn't before.
2389
       */
2390
0
      if (start < minoff)
2391
0
        start = minoff;
2392
2393
      /*
2394
       * Need this check too, to guard against possibility that page
2395
       * split since we visited it originally.
2396
       */
2397
0
      if (start > maxoff)
2398
0
        start = OffsetNumberNext(maxoff);
2399
2400
      /*
2401
       * These loops will check every item on the page --- but in an
2402
       * order that's attuned to the probability of where it actually
2403
       * is.  Scan to the right first, then to the left.
2404
       */
2405
0
      for (offnum = start;
2406
0
         offnum <= maxoff;
2407
0
         offnum = OffsetNumberNext(offnum))
2408
0
      {
2409
0
        itemid = PageGetItemId(page, offnum);
2410
0
        item = (IndexTuple) PageGetItem(page, itemid);
2411
2412
0
        if (BTreeTupleGetDownLink(item) == child)
2413
0
        {
2414
          /* Return accurate pointer to where link is now */
2415
0
          stack->bts_blkno = blkno;
2416
0
          stack->bts_offset = offnum;
2417
0
          return buf;
2418
0
        }
2419
0
      }
2420
2421
0
      for (offnum = OffsetNumberPrev(start);
2422
0
         offnum >= minoff;
2423
0
         offnum = OffsetNumberPrev(offnum))
2424
0
      {
2425
0
        itemid = PageGetItemId(page, offnum);
2426
0
        item = (IndexTuple) PageGetItem(page, itemid);
2427
2428
0
        if (BTreeTupleGetDownLink(item) == child)
2429
0
        {
2430
          /* Return accurate pointer to where link is now */
2431
0
          stack->bts_blkno = blkno;
2432
0
          stack->bts_offset = offnum;
2433
0
          return buf;
2434
0
        }
2435
0
      }
2436
0
    }
2437
2438
    /*
2439
     * The item we're looking for moved right at least one page.
2440
     *
2441
     * Lehman and Yao couple/chain locks when moving right here, which we
2442
     * can avoid.  See nbtree/README.
2443
     */
2444
0
    if (P_RIGHTMOST(opaque))
2445
0
    {
2446
0
      _bt_relbuf(rel, buf);
2447
0
      return InvalidBuffer;
2448
0
    }
2449
0
    blkno = opaque->btpo_next;
2450
0
    start = InvalidOffsetNumber;
2451
0
    _bt_relbuf(rel, buf);
2452
0
  }
2453
0
}
2454
2455
/*
2456
 * _bt_freestack() -- free a retracement stack made by _bt_search_insert.
2457
 */
2458
static void
2459
_bt_freestack(BTStack stack)
2460
0
{
2461
0
  BTStack   ostack;
2462
2463
0
  while (stack != NULL)
2464
0
  {
2465
0
    ostack = stack;
2466
0
    stack = stack->bts_parent;
2467
0
    pfree(ostack);
2468
0
  }
2469
0
}
2470
2471
/*
2472
 *  _bt_newlevel() -- Create a new level above root page.
2473
 *
2474
 *    We've just split the old root page and need to create a new one.
2475
 *    In order to do this, we add a new root page to the file, then lock
2476
 *    the metadata page and update it.  This is guaranteed to be deadlock-
2477
 *    free, because all readers release their locks on the metadata page
2478
 *    before trying to lock the root, and all writers lock the root before
2479
 *    trying to lock the metadata page.  We have a write lock on the old
2480
 *    root page, so we have not introduced any cycles into the waits-for
2481
 *    graph.
2482
 *
2483
 *    On entry, lbuf (the old root) and rbuf (its new peer) are write-
2484
 *    locked. On exit, a new root page exists with entries for the
2485
 *    two new children, metapage is updated and unlocked/unpinned.
2486
 *    The new root buffer is returned to caller which has to unlock/unpin
2487
 *    lbuf, rbuf & rootbuf.
2488
 */
2489
static Buffer
2490
_bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf)
2491
0
{
2492
0
  Buffer    rootbuf;
2493
0
  Page    lpage,
2494
0
        rootpage;
2495
0
  BlockNumber lbkno,
2496
0
        rbkno;
2497
0
  BlockNumber rootblknum;
2498
0
  BTPageOpaque rootopaque;
2499
0
  BTPageOpaque lopaque;
2500
0
  ItemId    itemid;
2501
0
  IndexTuple  item;
2502
0
  IndexTuple  left_item;
2503
0
  Size    left_item_sz;
2504
0
  IndexTuple  right_item;
2505
0
  Size    right_item_sz;
2506
0
  Buffer    metabuf;
2507
0
  Page    metapg;
2508
0
  BTMetaPageData *metad;
2509
0
  XLogRecPtr  recptr;
2510
2511
0
  lbkno = BufferGetBlockNumber(lbuf);
2512
0
  rbkno = BufferGetBlockNumber(rbuf);
2513
0
  lpage = BufferGetPage(lbuf);
2514
0
  lopaque = BTPageGetOpaque(lpage);
2515
2516
  /* get a new root page */
2517
0
  rootbuf = _bt_allocbuf(rel, heaprel);
2518
0
  rootpage = BufferGetPage(rootbuf);
2519
0
  rootblknum = BufferGetBlockNumber(rootbuf);
2520
2521
  /* acquire lock on the metapage */
2522
0
  metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
2523
0
  metapg = BufferGetPage(metabuf);
2524
0
  metad = BTPageGetMeta(metapg);
2525
2526
  /*
2527
   * Create downlink item for left page (old root).  The key value used is
2528
   * "minus infinity", a sentinel value that's reliably less than any real
2529
   * key value that could appear in the left page.
2530
   */
2531
0
  left_item_sz = sizeof(IndexTupleData);
2532
0
  left_item = (IndexTuple) palloc(left_item_sz);
2533
0
  left_item->t_info = left_item_sz;
2534
0
  BTreeTupleSetDownLink(left_item, lbkno);
2535
0
  BTreeTupleSetNAtts(left_item, 0, false);
2536
2537
  /*
2538
   * Create downlink item for right page.  The key for it is obtained from
2539
   * the "high key" position in the left page.
2540
   */
2541
0
  itemid = PageGetItemId(lpage, P_HIKEY);
2542
0
  right_item_sz = ItemIdGetLength(itemid);
2543
0
  item = (IndexTuple) PageGetItem(lpage, itemid);
2544
0
  right_item = CopyIndexTuple(item);
2545
0
  BTreeTupleSetDownLink(right_item, rbkno);
2546
2547
  /* NO EREPORT(ERROR) from here till newroot op is logged */
2548
0
  START_CRIT_SECTION();
2549
2550
  /* upgrade metapage if needed */
2551
0
  if (metad->btm_version < BTREE_NOVAC_VERSION)
2552
0
    _bt_upgrademetapage(metapg);
2553
2554
  /* set btree special data */
2555
0
  rootopaque = BTPageGetOpaque(rootpage);
2556
0
  rootopaque->btpo_prev = rootopaque->btpo_next = P_NONE;
2557
0
  rootopaque->btpo_flags = BTP_ROOT;
2558
0
  rootopaque->btpo_level =
2559
0
    (BTPageGetOpaque(lpage))->btpo_level + 1;
2560
0
  rootopaque->btpo_cycleid = 0;
2561
2562
  /* update metapage data */
2563
0
  metad->btm_root = rootblknum;
2564
0
  metad->btm_level = rootopaque->btpo_level;
2565
0
  metad->btm_fastroot = rootblknum;
2566
0
  metad->btm_fastlevel = rootopaque->btpo_level;
2567
2568
  /*
2569
   * Insert the left page pointer into the new root page.  The root page is
2570
   * the rightmost page on its level so there is no "high key" in it; the
2571
   * two items will go into positions P_HIKEY and P_FIRSTKEY.
2572
   *
2573
   * Note: we *must* insert the two items in item-number order, for the
2574
   * benefit of _bt_restore_page().
2575
   */
2576
0
  Assert(BTreeTupleGetNAtts(left_item, rel) == 0);
2577
0
  if (PageAddItem(rootpage, left_item, left_item_sz, P_HIKEY, false, false) == InvalidOffsetNumber)
2578
0
    elog(PANIC, "failed to add leftkey to new root page"
2579
0
       " while splitting block %u of index \"%s\"",
2580
0
       BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
2581
2582
  /*
2583
   * insert the right page pointer into the new root page.
2584
   */
2585
0
  Assert(BTreeTupleGetNAtts(right_item, rel) > 0);
2586
0
  Assert(BTreeTupleGetNAtts(right_item, rel) <=
2587
0
       IndexRelationGetNumberOfKeyAttributes(rel));
2588
0
  if (PageAddItem(rootpage, right_item, right_item_sz, P_FIRSTKEY, false, false) == InvalidOffsetNumber)
2589
0
    elog(PANIC, "failed to add rightkey to new root page"
2590
0
       " while splitting block %u of index \"%s\"",
2591
0
       BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
2592
2593
  /* Clear the incomplete-split flag in the left child */
2594
0
  Assert(P_INCOMPLETE_SPLIT(lopaque));
2595
0
  lopaque->btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
2596
0
  MarkBufferDirty(lbuf);
2597
2598
0
  MarkBufferDirty(rootbuf);
2599
0
  MarkBufferDirty(metabuf);
2600
2601
  /* XLOG stuff */
2602
0
  if (RelationNeedsWAL(rel))
2603
0
  {
2604
0
    xl_btree_newroot xlrec;
2605
0
    xl_btree_metadata md;
2606
2607
0
    xlrec.rootblk = rootblknum;
2608
0
    xlrec.level = metad->btm_level;
2609
2610
0
    XLogBeginInsert();
2611
0
    XLogRegisterData(&xlrec, SizeOfBtreeNewroot);
2612
2613
0
    XLogRegisterBuffer(0, rootbuf, REGBUF_WILL_INIT);
2614
0
    XLogRegisterBuffer(1, lbuf, REGBUF_STANDARD);
2615
0
    XLogRegisterBuffer(2, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD);
2616
2617
0
    Assert(metad->btm_version >= BTREE_NOVAC_VERSION);
2618
0
    md.version = metad->btm_version;
2619
0
    md.root = rootblknum;
2620
0
    md.level = metad->btm_level;
2621
0
    md.fastroot = rootblknum;
2622
0
    md.fastlevel = metad->btm_level;
2623
0
    md.last_cleanup_num_delpages = metad->btm_last_cleanup_num_delpages;
2624
0
    md.allequalimage = metad->btm_allequalimage;
2625
2626
0
    XLogRegisterBufData(2, &md, sizeof(xl_btree_metadata));
2627
2628
    /*
2629
     * Direct access to page is not good but faster - we should implement
2630
     * some new func in page API.
2631
     */
2632
0
    XLogRegisterBufData(0,
2633
0
              (char *) rootpage + ((PageHeader) rootpage)->pd_upper,
2634
0
              ((PageHeader) rootpage)->pd_special -
2635
0
              ((PageHeader) rootpage)->pd_upper);
2636
2637
0
    recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_NEWROOT);
2638
0
  }
2639
0
  else
2640
0
    recptr = XLogGetFakeLSN(rel);
2641
2642
0
  PageSetLSN(lpage, recptr);
2643
0
  PageSetLSN(rootpage, recptr);
2644
0
  PageSetLSN(metapg, recptr);
2645
2646
0
  END_CRIT_SECTION();
2647
2648
  /* done with metapage */
2649
0
  _bt_relbuf(rel, metabuf);
2650
2651
0
  pfree(left_item);
2652
0
  pfree(right_item);
2653
2654
0
  return rootbuf;
2655
0
}
2656
2657
/*
2658
 *  _bt_pgaddtup() -- add a data item to a particular page during split.
2659
 *
2660
 *    The difference between this routine and a bare PageAddItem call is
2661
 *    that this code can deal with the first data item on an internal btree
2662
 *    page in passing.  This data item (which is called "firstright" within
2663
 *    _bt_split()) has a key that must be treated as minus infinity after
2664
 *    the split.  Therefore, we truncate away all attributes when caller
2665
 *    specifies it's the first data item on page (downlink is not changed,
2666
 *    though).  This extra step is only needed for the right page of an
2667
 *    internal page split.  There is no need to do this for the first data
2668
 *    item on the existing/left page, since that will already have been
2669
 *    truncated during an earlier page split.
2670
 *
2671
 *    See _bt_split() for a high level explanation of why we truncate here.
2672
 *    Note that this routine has nothing to do with suffix truncation,
2673
 *    despite using some of the same infrastructure.
2674
 */
2675
static inline bool
2676
_bt_pgaddtup(Page page,
2677
       Size itemsize,
2678
       const IndexTupleData *itup,
2679
       OffsetNumber itup_off,
2680
       bool newfirstdataitem)
2681
0
{
2682
0
  IndexTupleData trunctuple;
2683
2684
0
  if (newfirstdataitem)
2685
0
  {
2686
0
    trunctuple = *itup;
2687
0
    trunctuple.t_info = sizeof(IndexTupleData);
2688
0
    BTreeTupleSetNAtts(&trunctuple, 0, false);
2689
0
    itup = &trunctuple;
2690
0
    itemsize = sizeof(IndexTupleData);
2691
0
  }
2692
2693
0
  if (unlikely(PageAddItem(page, itup, itemsize, itup_off, false, false) == InvalidOffsetNumber))
2694
0
    return false;
2695
2696
0
  return true;
2697
0
}
2698
2699
/*
2700
 * _bt_delete_or_dedup_one_page - Try to avoid a leaf page split.
2701
 *
2702
 * There are three operations performed here: simple index deletion, bottom-up
2703
 * index deletion, and deduplication.  If all three operations fail to free
2704
 * enough space for the incoming item then caller will go on to split the
2705
 * page.  We always consider simple deletion first.  If that doesn't work out
2706
 * we consider alternatives.  Callers that only want us to consider simple
2707
 * deletion (without any fallback) ask for that using the 'simpleonly'
2708
 * argument.
2709
 *
2710
 * We usually pick only one alternative "complex" operation when simple
2711
 * deletion alone won't prevent a page split.  The 'checkingunique',
2712
 * 'uniquedup', and 'indexUnchanged' arguments are used for that.
2713
 *
2714
 * Note: We used to only delete LP_DEAD items when the BTP_HAS_GARBAGE page
2715
 * level flag was found set.  The flag was useful back when there wasn't
2716
 * necessarily one single page for a duplicate tuple to go on (before heap TID
2717
 * became a part of the key space in version 4 indexes).  But we don't
2718
 * actually look at the flag anymore (it's not a gating condition for our
2719
 * caller).  That would cause us to miss tuples that are safe to delete,
2720
 * without getting any benefit in return.  We know that the alternative is to
2721
 * split the page; scanning the line pointer array in passing won't have
2722
 * noticeable overhead.  (We still maintain the BTP_HAS_GARBAGE flag despite
2723
 * all this because !heapkeyspace indexes must still do a "getting tired"
2724
 * linear search, and so are likely to get some benefit from using it as a
2725
 * gating condition.)
2726
 */
2727
static void
2728
_bt_delete_or_dedup_one_page(Relation rel, Relation heapRel,
2729
               BTInsertState insertstate,
2730
               bool simpleonly, bool checkingunique,
2731
               bool uniquedup, bool indexUnchanged)
2732
0
{
2733
0
  OffsetNumber deletable[MaxIndexTuplesPerPage];
2734
0
  int     ndeletable = 0;
2735
0
  OffsetNumber offnum,
2736
0
        minoff,
2737
0
        maxoff;
2738
0
  Buffer    buffer = insertstate->buf;
2739
0
  BTScanInsert itup_key = insertstate->itup_key;
2740
0
  Page    page = BufferGetPage(buffer);
2741
0
  BTPageOpaque opaque = BTPageGetOpaque(page);
2742
2743
0
  Assert(P_ISLEAF(opaque));
2744
0
  Assert(simpleonly || itup_key->heapkeyspace);
2745
0
  Assert(!simpleonly || (!checkingunique && !uniquedup && !indexUnchanged));
2746
2747
  /*
2748
   * Scan over all items to see which ones need to be deleted according to
2749
   * LP_DEAD flags.  We'll usually manage to delete a few extra items that
2750
   * are not marked LP_DEAD in passing.  Often the extra items that actually
2751
   * end up getting deleted are items that would have had their LP_DEAD bit
2752
   * set before long anyway (if we opted not to include them as extras).
2753
   */
2754
0
  minoff = P_FIRSTDATAKEY(opaque);
2755
0
  maxoff = PageGetMaxOffsetNumber(page);
2756
0
  for (offnum = minoff;
2757
0
     offnum <= maxoff;
2758
0
     offnum = OffsetNumberNext(offnum))
2759
0
  {
2760
0
    ItemId    itemId = PageGetItemId(page, offnum);
2761
2762
0
    if (ItemIdIsDead(itemId))
2763
0
      deletable[ndeletable++] = offnum;
2764
0
  }
2765
2766
0
  if (ndeletable > 0)
2767
0
  {
2768
0
    _bt_simpledel_pass(rel, buffer, heapRel, deletable, ndeletable,
2769
0
               insertstate->itup, minoff, maxoff);
2770
0
    insertstate->bounds_valid = false;
2771
2772
    /* Return when a page split has already been avoided */
2773
0
    if (PageGetFreeSpace(page) >= insertstate->itemsz)
2774
0
      return;
2775
2776
    /* Might as well assume duplicates (if checkingunique) */
2777
0
    uniquedup = true;
2778
0
  }
2779
2780
  /*
2781
   * We're done with simple deletion.  Return early with callers that only
2782
   * call here so that simple deletion can be considered.  This includes
2783
   * callers that explicitly ask for this and checkingunique callers that
2784
   * probably don't have any version churn duplicates on the page.
2785
   *
2786
   * Note: The page's BTP_HAS_GARBAGE hint flag may still be set when we
2787
   * return at this point (or when we go on the try either or both of our
2788
   * other strategies and they also fail).  We do not bother expending a
2789
   * separate write to clear it, however.  Caller will definitely clear it
2790
   * when it goes on to split the page (note also that the deduplication
2791
   * process will clear the flag in passing, just to keep things tidy).
2792
   */
2793
0
  if (simpleonly || (checkingunique && !uniquedup))
2794
0
  {
2795
0
    Assert(!indexUnchanged);
2796
0
    return;
2797
0
  }
2798
2799
  /* Assume bounds about to be invalidated (this is almost certain now) */
2800
0
  insertstate->bounds_valid = false;
2801
2802
  /*
2803
   * Perform bottom-up index deletion pass when executor hint indicated that
2804
   * incoming item is logically unchanged, or for a unique index that is
2805
   * known to have physical duplicates for some other reason.  (There is a
2806
   * large overlap between these two cases for a unique index.  It's worth
2807
   * having both triggering conditions in order to apply the optimization in
2808
   * the event of successive related INSERT and DELETE statements.)
2809
   *
2810
   * We'll go on to do a deduplication pass when a bottom-up pass fails to
2811
   * delete an acceptable amount of free space (a significant fraction of
2812
   * the page, or space for the new item, whichever is greater).
2813
   *
2814
   * Note: Bottom-up index deletion uses the same equality/equivalence
2815
   * routines as deduplication internally.  However, it does not merge
2816
   * together index tuples, so the same correctness considerations do not
2817
   * apply.  We deliberately omit an index-is-allequalimage test here.
2818
   */
2819
0
  if ((indexUnchanged || uniquedup) &&
2820
0
    _bt_bottomupdel_pass(rel, buffer, heapRel, insertstate->itemsz))
2821
0
    return;
2822
2823
  /* Perform deduplication pass (when enabled and index-is-allequalimage) */
2824
0
  if (BTGetDeduplicateItems(rel) && itup_key->allequalimage)
2825
0
    _bt_dedup_pass(rel, buffer, insertstate->itup, insertstate->itemsz,
2826
0
             (indexUnchanged || uniquedup));
2827
0
}
2828
2829
/*
2830
 * _bt_simpledel_pass - Simple index tuple deletion pass.
2831
 *
2832
 * We delete all LP_DEAD-set index tuples on a leaf page.  The offset numbers
2833
 * of all such tuples are determined by caller (caller passes these to us as
2834
 * its 'deletable' argument).
2835
 *
2836
 * We might also delete extra index tuples that turn out to be safe to delete
2837
 * in passing (though they must be cheap to check in passing to begin with).
2838
 * There is no certainty that any extra tuples will be deleted, though.  The
2839
 * high level goal of the approach we take is to get the most out of each call
2840
 * here (without noticeably increasing the per-call overhead compared to what
2841
 * we need to do just to be able to delete the page's LP_DEAD-marked index
2842
 * tuples).
2843
 *
2844
 * The number of extra index tuples that turn out to be deletable might
2845
 * greatly exceed the number of LP_DEAD-marked index tuples due to various
2846
 * locality related effects.  For example, it's possible that the total number
2847
 * of table blocks (pointed to by all TIDs on the leaf page) is naturally
2848
 * quite low, in which case we might end up checking if it's possible to
2849
 * delete _most_ index tuples on the page (without the tableam needing to
2850
 * access additional table blocks).  The tableam will sometimes stumble upon
2851
 * _many_ extra deletable index tuples in indexes where this pattern is
2852
 * common.
2853
 *
2854
 * See nbtree/README for further details on simple index tuple deletion.
2855
 */
2856
static void
2857
_bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
2858
           OffsetNumber *deletable, int ndeletable, IndexTuple newitem,
2859
           OffsetNumber minoff, OffsetNumber maxoff)
2860
0
{
2861
0
  Page    page = BufferGetPage(buffer);
2862
0
  BlockNumber *deadblocks;
2863
0
  int     ndeadblocks;
2864
0
  TM_IndexDeleteOp delstate;
2865
0
  OffsetNumber offnum;
2866
2867
  /* Get array of table blocks pointed to by LP_DEAD-set tuples */
2868
0
  deadblocks = _bt_deadblocks(page, deletable, ndeletable, newitem,
2869
0
                &ndeadblocks);
2870
2871
  /* Initialize tableam state that describes index deletion operation */
2872
0
  delstate.irel = rel;
2873
0
  delstate.iblknum = BufferGetBlockNumber(buffer);
2874
0
  delstate.bottomup = false;
2875
0
  delstate.bottomupfreespace = 0;
2876
0
  delstate.ndeltids = 0;
2877
0
  delstate.deltids = palloc_array(TM_IndexDelete, MaxTIDsPerBTreePage);
2878
0
  delstate.status = palloc_array(TM_IndexStatus, MaxTIDsPerBTreePage);
2879
2880
0
  for (offnum = minoff;
2881
0
     offnum <= maxoff;
2882
0
     offnum = OffsetNumberNext(offnum))
2883
0
  {
2884
0
    ItemId    itemid = PageGetItemId(page, offnum);
2885
0
    IndexTuple  itup = (IndexTuple) PageGetItem(page, itemid);
2886
0
    TM_IndexDelete *odeltid = &delstate.deltids[delstate.ndeltids];
2887
0
    TM_IndexStatus *ostatus = &delstate.status[delstate.ndeltids];
2888
0
    BlockNumber tidblock;
2889
0
    void     *match;
2890
2891
0
    if (!BTreeTupleIsPosting(itup))
2892
0
    {
2893
0
      tidblock = ItemPointerGetBlockNumber(&itup->t_tid);
2894
0
      match = bsearch(&tidblock, deadblocks, ndeadblocks,
2895
0
              sizeof(BlockNumber), _bt_blk_cmp);
2896
2897
0
      if (!match)
2898
0
      {
2899
0
        Assert(!ItemIdIsDead(itemid));
2900
0
        continue;
2901
0
      }
2902
2903
      /*
2904
       * TID's table block is among those pointed to by the TIDs from
2905
       * LP_DEAD-bit set tuples on page -- add TID to deltids
2906
       */
2907
0
      odeltid->tid = itup->t_tid;
2908
0
      odeltid->id = delstate.ndeltids;
2909
0
      ostatus->idxoffnum = offnum;
2910
0
      ostatus->knowndeletable = ItemIdIsDead(itemid);
2911
0
      ostatus->promising = false; /* unused */
2912
0
      ostatus->freespace = 0; /* unused */
2913
2914
0
      delstate.ndeltids++;
2915
0
    }
2916
0
    else
2917
0
    {
2918
0
      int     nitem = BTreeTupleGetNPosting(itup);
2919
2920
0
      for (int p = 0; p < nitem; p++)
2921
0
      {
2922
0
        ItemPointer tid = BTreeTupleGetPostingN(itup, p);
2923
2924
0
        tidblock = ItemPointerGetBlockNumber(tid);
2925
0
        match = bsearch(&tidblock, deadblocks, ndeadblocks,
2926
0
                sizeof(BlockNumber), _bt_blk_cmp);
2927
2928
0
        if (!match)
2929
0
        {
2930
0
          Assert(!ItemIdIsDead(itemid));
2931
0
          continue;
2932
0
        }
2933
2934
        /*
2935
         * TID's table block is among those pointed to by the TIDs
2936
         * from LP_DEAD-bit set tuples on page -- add TID to deltids
2937
         */
2938
0
        odeltid->tid = *tid;
2939
0
        odeltid->id = delstate.ndeltids;
2940
0
        ostatus->idxoffnum = offnum;
2941
0
        ostatus->knowndeletable = ItemIdIsDead(itemid);
2942
0
        ostatus->promising = false; /* unused */
2943
0
        ostatus->freespace = 0; /* unused */
2944
2945
0
        odeltid++;
2946
0
        ostatus++;
2947
0
        delstate.ndeltids++;
2948
0
      }
2949
0
    }
2950
0
  }
2951
2952
0
  pfree(deadblocks);
2953
2954
0
  Assert(delstate.ndeltids >= ndeletable);
2955
2956
  /* Physically delete LP_DEAD tuples (plus any delete-safe extra TIDs) */
2957
0
  _bt_delitems_delete_check(rel, buffer, heapRel, &delstate);
2958
2959
0
  pfree(delstate.deltids);
2960
0
  pfree(delstate.status);
2961
0
}
2962
2963
/*
2964
 * _bt_deadblocks() -- Get LP_DEAD related table blocks.
2965
 *
2966
 * Builds sorted and unique-ified array of table block numbers from index
2967
 * tuple TIDs whose line pointers are marked LP_DEAD.  Also adds the table
2968
 * block from incoming newitem just in case it isn't among the LP_DEAD-related
2969
 * table blocks.
2970
 *
2971
 * Always counting the newitem's table block as an LP_DEAD related block makes
2972
 * sense because the cost is consistently low; it is practically certain that
2973
 * the table block will not incur a buffer miss in tableam.  On the other hand
2974
 * the benefit is often quite high.  There is a decent chance that there will
2975
 * be some deletable items from this block, since in general most garbage
2976
 * tuples became garbage in the recent past (in many cases this won't be the
2977
 * first logical row that core code added to/modified in table block
2978
 * recently).
2979
 *
2980
 * Returns final array, and sets *nblocks to its final size for caller.
2981
 */
2982
static BlockNumber *
2983
_bt_deadblocks(Page page, OffsetNumber *deletable, int ndeletable,
2984
         IndexTuple newitem, int *nblocks)
2985
0
{
2986
0
  int     spacentids,
2987
0
        ntids;
2988
0
  BlockNumber *tidblocks;
2989
2990
  /*
2991
   * Accumulate each TID's block in array whose initial size has space for
2992
   * one table block per LP_DEAD-set tuple (plus space for the newitem table
2993
   * block).  Array will only need to grow when there are LP_DEAD-marked
2994
   * posting list tuples (which is not that common).
2995
   */
2996
0
  spacentids = ndeletable + 1;
2997
0
  ntids = 0;
2998
0
  tidblocks = palloc_array(BlockNumber, spacentids);
2999
3000
  /*
3001
   * First add the table block for the incoming newitem.  This is the one
3002
   * case where simple deletion can visit a table block that doesn't have
3003
   * any known deletable items.
3004
   */
3005
0
  Assert(!BTreeTupleIsPosting(newitem) && !BTreeTupleIsPivot(newitem));
3006
0
  tidblocks[ntids++] = ItemPointerGetBlockNumber(&newitem->t_tid);
3007
3008
0
  for (int i = 0; i < ndeletable; i++)
3009
0
  {
3010
0
    ItemId    itemid = PageGetItemId(page, deletable[i]);
3011
0
    IndexTuple  itup = (IndexTuple) PageGetItem(page, itemid);
3012
3013
0
    Assert(ItemIdIsDead(itemid));
3014
3015
0
    if (!BTreeTupleIsPosting(itup))
3016
0
    {
3017
0
      if (ntids + 1 > spacentids)
3018
0
      {
3019
0
        spacentids *= 2;
3020
0
        tidblocks = repalloc_array(tidblocks, BlockNumber, spacentids);
3021
0
      }
3022
3023
0
      tidblocks[ntids++] = ItemPointerGetBlockNumber(&itup->t_tid);
3024
0
    }
3025
0
    else
3026
0
    {
3027
0
      int     nposting = BTreeTupleGetNPosting(itup);
3028
3029
0
      if (ntids + nposting > spacentids)
3030
0
      {
3031
0
        spacentids = Max(spacentids * 2, ntids + nposting);
3032
0
        tidblocks = repalloc_array(tidblocks, BlockNumber, spacentids);
3033
0
      }
3034
3035
0
      for (int j = 0; j < nposting; j++)
3036
0
      {
3037
0
        ItemPointer tid = BTreeTupleGetPostingN(itup, j);
3038
3039
0
        tidblocks[ntids++] = ItemPointerGetBlockNumber(tid);
3040
0
      }
3041
0
    }
3042
0
  }
3043
3044
0
  qsort(tidblocks, ntids, sizeof(BlockNumber), _bt_blk_cmp);
3045
0
  *nblocks = qunique(tidblocks, ntids, sizeof(BlockNumber), _bt_blk_cmp);
3046
3047
0
  return tidblocks;
3048
0
}
3049
3050
/*
3051
 * _bt_blk_cmp() -- qsort comparison function for _bt_simpledel_pass
3052
 */
3053
static inline int
3054
_bt_blk_cmp(const void *arg1, const void *arg2)
3055
0
{
3056
0
  BlockNumber b1 = *((const BlockNumber *) arg1);
3057
0
  BlockNumber b2 = *((const BlockNumber *) arg2);
3058
3059
0
  return pg_cmp_u32(b1, b2);
3060
0
}