Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 71bdc99

Browse files
committed
tableam: Add helper for indexes to check if a corresponding table tuples exist.
This is, likely exclusively, useful to verify that conflicts detected in a unique index are with live tuples, rather than dead ones. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
1 parent aa1419e commit 71bdc99

File tree

4 files changed

+64
-14
lines changed

4 files changed

+64
-14
lines changed

src/backend/access/nbtree/nbtinsert.c

+10-7
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
#include "postgres.h"
1717

18-
#include "access/heapam.h"
1918
#include "access/nbtree.h"
2019
#include "access/nbtxlog.h"
20+
#include "access/tableam.h"
2121
#include "access/transam.h"
2222
#include "access/xloginsert.h"
2323
#include "miscadmin.h"
@@ -431,12 +431,14 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
431431
}
432432

433433
/*
434-
* We check the whole HOT-chain to see if there is any tuple
435-
* that satisfies SnapshotDirty. This is necessary because we
436-
* have just a single index entry for the entire chain.
434+
* Check if there's any table tuples for this index entry
435+
* satisfying SnapshotDirty. This is necessary because for AMs
436+
* with optimizations like heap's HOT, we have just a single
437+
* index entry for the entire chain.
437438
*/
438-
else if (heap_hot_search(&htid, heapRel, &SnapshotDirty,
439-
&all_dead))
439+
else if (table_index_fetch_tuple_check(heapRel, &htid,
440+
&SnapshotDirty,
441+
&all_dead))
440442
{
441443
TransactionId xwait;
442444

@@ -489,7 +491,8 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel,
489491
* entry.
490492
*/
491493
htid = itup->t_tid;
492-
if (heap_hot_search(&htid, heapRel, SnapshotSelf, NULL))
494+
if (table_index_fetch_tuple_check(heapRel, &htid,
495+
SnapshotSelf, NULL))
493496
{
494497
/* Normal case --- it's still live */
495498
}

src/backend/access/nbtree/nbtsort.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@
5757

5858
#include "postgres.h"
5959

60-
#include "access/heapam.h"
6160
#include "access/nbtree.h"
6261
#include "access/parallel.h"
6362
#include "access/relscan.h"
63+
#include "access/table.h"
6464
#include "access/tableam.h"
6565
#include "access/xact.h"
6666
#include "access/xlog.h"

src/backend/access/table/tableam.c

+34
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,40 @@ table_beginscan_parallel(Relation relation, ParallelTableScanDesc parallel_scan)
176176
}
177177

178178

179+
/* ----------------------------------------------------------------------------
180+
* Index scan related functions.
181+
* ----------------------------------------------------------------------------
182+
*/
183+
184+
/*
185+
* To perform that check simply start an index scan, create the necessary
186+
* slot, do the heap lookup, and shut everything down again. This could be
187+
* optimized, but is unlikely to matter from a performance POV. If there
188+
* frequently are live index pointers also matching a unique index key, the
189+
* CPU overhead of this routine is unlikely to matter.
190+
*/
191+
bool
192+
table_index_fetch_tuple_check(Relation rel,
193+
ItemPointer tid,
194+
Snapshot snapshot,
195+
bool *all_dead)
196+
{
197+
IndexFetchTableData *scan;
198+
TupleTableSlot *slot;
199+
bool call_again = false;
200+
bool found;
201+
202+
slot = table_slot_create(rel, NULL);
203+
scan = table_index_fetch_begin(rel);
204+
found = table_index_fetch_tuple(scan, tid, snapshot, slot, &call_again,
205+
all_dead);
206+
table_index_fetch_end(scan);
207+
ExecDropSingleTupleTableSlot(slot);
208+
209+
return found;
210+
}
211+
212+
179213
/* ----------------------------------------------------------------------------
180214
* Functions to make modifications a bit simpler.
181215
* ----------------------------------------------------------------------------

src/include/access/tableam.h

+19-6
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,10 @@ typedef struct TableAmRoutine
256256
* needs be set to true by index_fetch_tuple, signalling to the caller
257257
* that index_fetch_tuple should be called again for the same tid.
258258
*
259-
* *all_dead should be set to true by index_fetch_tuple iff it is
260-
* guaranteed that no backend needs to see that tuple. Index AMs can use
261-
* that do avoid returning that tid in future searches.
259+
* *all_dead, if all_dead is not NULL, should be set to true if by
260+
* index_fetch_tuple iff it is guaranteed that no backend needs to see
261+
* that tuple. Index AMs can use that do avoid returning that tid in
262+
* future searches.
262263
*/
263264
bool (*index_fetch_tuple) (struct IndexFetchTableData *scan,
264265
ItemPointer tid,
@@ -594,9 +595,10 @@ table_index_fetch_end(struct IndexFetchTableData *scan)
594595
* will be set to true, signalling that table_index_fetch_tuple() should be called
595596
* again for the same tid.
596597
*
597-
* *all_dead will be set to true by table_index_fetch_tuple() iff it is guaranteed
598-
* that no backend needs to see that tuple. Index AMs can use that do avoid
599-
* returning that tid in future searches.
598+
* *all_dead, if all_dead is not NULL, will be set to true by
599+
* table_index_fetch_tuple() iff it is guaranteed that no backend needs to see
600+
* that tuple. Index AMs can use that do avoid returning that tid in future
601+
* searches.
600602
*
601603
* The difference between this function and table_fetch_row_version is that
602604
* this function returns the currently visible version of a row if the AM
@@ -618,6 +620,17 @@ table_index_fetch_tuple(struct IndexFetchTableData *scan,
618620
all_dead);
619621
}
620622

623+
/*
624+
* This is a convenience wrapper around table_index_fetch_tuple() which
625+
* returns whether there are table tuple items corresponding to an index
626+
* entry. This likely is only useful to verify if there's a conflict in a
627+
* unique index.
628+
*/
629+
extern bool table_index_fetch_tuple_check(Relation rel,
630+
ItemPointer tid,
631+
Snapshot snapshot,
632+
bool *all_dead);
633+
621634

622635
/* ------------------------------------------------------------------------
623636
* Functions for non-modifying operations on individual tuples

0 commit comments

Comments
 (0)