@@ -1433,6 +1433,13 @@ bt_target_page_check(BtreeCheckState *state)
1433
1433
bool lowersizelimit ;
1434
1434
ItemPointer scantid ;
1435
1435
1436
+ /*
1437
+ * True if we already called bt_entry_unique_check() for the current
1438
+ * item. This helps to avoid visiting the heap for keys, which are
1439
+ * anyway presented only once and can't comprise a unique violation.
1440
+ */
1441
+ bool unique_checked = false;
1442
+
1436
1443
CHECK_FOR_INTERRUPTS ();
1437
1444
1438
1445
itemid = PageGetItemIdCareful (state , state -> targetblock ,
@@ -1775,12 +1782,18 @@ bt_target_page_check(BtreeCheckState *state)
1775
1782
1776
1783
/*
1777
1784
* If the index is unique verify entries uniqueness by checking the
1778
- * heap tuples visibility.
1785
+ * heap tuples visibility. Immediately check posting tuples and
1786
+ * tuples with repeated keys. Postpone check for keys, which have the
1787
+ * first appearance.
1779
1788
*/
1780
1789
if (state -> checkunique && state -> indexinfo -> ii_Unique &&
1781
- P_ISLEAF (topaque ) && !skey -> anynullkeys )
1790
+ P_ISLEAF (topaque ) && !skey -> anynullkeys &&
1791
+ (BTreeTupleIsPosting (itup ) || ItemPointerIsValid (lVis .tid )))
1792
+ {
1782
1793
bt_entry_unique_check (state , itup , state -> targetblock , offset ,
1783
1794
& lVis );
1795
+ unique_checked = true;
1796
+ }
1784
1797
1785
1798
if (state -> checkunique && state -> indexinfo -> ii_Unique &&
1786
1799
P_ISLEAF (topaque ) && OffsetNumberNext (offset ) <= max )
@@ -1799,6 +1812,9 @@ bt_target_page_check(BtreeCheckState *state)
1799
1812
* data (whole index tuple or last posting in index tuple). Key
1800
1813
* containing null value does not violate unique constraint and
1801
1814
* treated as different to any other key.
1815
+ *
1816
+ * If the next key is the same as the previous one, do the
1817
+ * bt_entry_unique_check() call if it was postponed.
1802
1818
*/
1803
1819
if (_bt_compare (state -> rel , skey , state -> target ,
1804
1820
OffsetNumberNext (offset )) != 0 || skey -> anynullkeys )
@@ -1808,6 +1824,11 @@ bt_target_page_check(BtreeCheckState *state)
1808
1824
lVis .postingIndex = -1 ;
1809
1825
lVis .tid = NULL ;
1810
1826
}
1827
+ else if (!unique_checked )
1828
+ {
1829
+ bt_entry_unique_check (state , itup , state -> targetblock , offset ,
1830
+ & lVis );
1831
+ }
1811
1832
skey -> scantid = scantid ; /* Restore saved scan key state */
1812
1833
}
1813
1834
@@ -1890,10 +1911,19 @@ bt_target_page_check(BtreeCheckState *state)
1890
1911
rightkey -> scantid = NULL ;
1891
1912
1892
1913
/* The first key on the next page is the same */
1893
- if (_bt_compare (state -> rel , rightkey , state -> target , max ) == 0 && !rightkey -> anynullkeys )
1914
+ if (_bt_compare (state -> rel , rightkey , state -> target , max ) == 0 &&
1915
+ !rightkey -> anynullkeys )
1894
1916
{
1895
1917
Page rightpage ;
1896
1918
1919
+ /*
1920
+ * Do the bt_entry_unique_check() call if it was
1921
+ * postponed.
1922
+ */
1923
+ if (!unique_checked )
1924
+ bt_entry_unique_check (state , itup , state -> targetblock ,
1925
+ offset , & lVis );
1926
+
1897
1927
elog (DEBUG2 , "cross page equal keys" );
1898
1928
rightpage = palloc_btree_page (state ,
1899
1929
rightblock_number );
0 commit comments