7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.8 1996/12/06 09:45:30 vadim Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.9 1997/01/10 10:06:20 vadim Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
17
17
#include <utils/memutils.h>
18
18
#include <storage/bufpage.h>
19
19
#include <access/nbtree.h>
20
+ #include <access/heapam.h>
20
21
#include <storage/bufmgr.h>
21
22
22
23
#ifndef HAVE_MEMMOVE
@@ -41,7 +42,7 @@ static void _bt_updateitem(Relation rel, Size keysz, Buffer buf, Oid bti_oid, BT
41
42
* (xid, seqno) pair.
42
43
*/
43
44
InsertIndexResult
44
- _bt_doinsert (Relation rel , BTItem btitem , bool index_is_unique , bool is_update )
45
+ _bt_doinsert (Relation rel , BTItem btitem , bool index_is_unique , Relation heapRel )
45
46
{
46
47
ScanKey itup_scankey ;
47
48
IndexTuple itup ;
@@ -60,30 +61,6 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, bool is_update)
60
61
/* find the page containing this key */
61
62
stack = _bt_search (rel , natts , itup_scankey , & buf );
62
63
63
- /* if we're not allowing duplicates, make sure the key isn't */
64
- /* already in the node */
65
- if (index_is_unique && !is_update ) {
66
- OffsetNumber offset ;
67
- TupleDesc itupdesc ;
68
- Page page ;
69
-
70
- itupdesc = RelationGetTupleDescriptor (rel );
71
- page = BufferGetPage (buf );
72
-
73
- offset = _bt_binsrch (rel , buf , natts , itup_scankey , BT_DESCENT );
74
-
75
- /* make sure the offset we're given points to an actual */
76
- /* key on the page before trying to compare it */
77
- if (!PageIsEmpty (page ) &&
78
- offset <= PageGetMaxOffsetNumber (page )) {
79
- if (!_bt_compare (rel , itupdesc , page ,
80
- natts , itup_scankey , offset )) {
81
- /* it is a duplicate */
82
- elog (WARN , "Cannot insert a duplicate key into a unique index." );
83
- }
84
- }
85
- }
86
-
87
64
blkno = BufferGetBlockNumber (buf );
88
65
89
66
/* trade in our read lock for a write lock */
@@ -99,6 +76,91 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, bool is_update)
99
76
*/
100
77
101
78
buf = _bt_moveright (rel , buf , natts , itup_scankey , BT_WRITE );
79
+
80
+ /* if we're not allowing duplicates, make sure the key isn't */
81
+ /* already in the node */
82
+ if ( index_is_unique )
83
+ {
84
+ OffsetNumber offset , maxoff ;
85
+ Page page ;
86
+
87
+ page = BufferGetPage (buf );
88
+ maxoff = PageGetMaxOffsetNumber (page );
89
+
90
+ offset = _bt_binsrch (rel , buf , natts , itup_scankey , BT_DESCENT );
91
+
92
+ /* make sure the offset we're given points to an actual */
93
+ /* key on the page before trying to compare it */
94
+ if ( !PageIsEmpty (page ) && offset <= maxoff )
95
+ {
96
+ TupleDesc itupdesc ;
97
+ BTItem btitem ;
98
+ IndexTuple itup ;
99
+ HeapTuple htup ;
100
+ BTPageOpaque opaque ;
101
+ Buffer nbuf ;
102
+ BlockNumber blkno ;
103
+
104
+ itupdesc = RelationGetTupleDescriptor (rel );
105
+ nbuf = InvalidBuffer ;
106
+ opaque = (BTPageOpaque ) PageGetSpecialPointer (page );
107
+ while ( !_bt_compare (rel , itupdesc , page ,
108
+ natts , itup_scankey , offset ) )
109
+ { /* they're equal */
110
+ btitem = (BTItem ) PageGetItem (page , PageGetItemId (page , offset ));
111
+ itup = & (btitem -> bti_itup );
112
+ htup = heap_fetch (heapRel , SelfTimeQual , & (itup -> t_tid ), NULL );
113
+ if ( htup != (HeapTuple ) NULL )
114
+ { /* it is a duplicate */
115
+ elog (WARN , "Cannot insert a duplicate key into a unique index." );
116
+ }
117
+ /* get next offnum */
118
+ if ( offset < maxoff )
119
+ {
120
+ offset = OffsetNumberNext (offset );
121
+ }
122
+ else
123
+ { /* move right ? */
124
+ if ( P_RIGHTMOST (opaque ) )
125
+ break ;
126
+ if ( _bt_compare (rel , itupdesc , page ,
127
+ natts , itup_scankey , P_HIKEY ) )
128
+ break ;
129
+ /*
130
+ * min key of the right page is the same,
131
+ * ooh - so many dead duplicates...
132
+ */
133
+ blkno = opaque -> btpo_next ;
134
+ if ( nbuf != InvalidBuffer )
135
+ _bt_relbuf (rel , nbuf , BT_READ );
136
+ for (nbuf = InvalidBuffer ; ; )
137
+ {
138
+ nbuf = _bt_getbuf (rel , blkno , BT_READ );
139
+ page = BufferGetPage (nbuf );
140
+ maxoff = PageGetMaxOffsetNumber (page );
141
+ opaque = (BTPageOpaque ) PageGetSpecialPointer (page );
142
+ offset = P_RIGHTMOST (opaque ) ? P_HIKEY : P_FIRSTKEY ;
143
+ if ( ! PageIsEmpty (page ) && offset <= maxoff )
144
+ { /* Found some key */
145
+ break ;
146
+ }
147
+ else
148
+ { /* Empty or "pseudo"-empty page - get next */
149
+ blkno = opaque -> btpo_next ;
150
+ _bt_relbuf (rel , nbuf , BT_READ );
151
+ nbuf = InvalidBuffer ;
152
+ if ( blkno == P_NONE )
153
+ break ;
154
+ }
155
+ }
156
+ if ( nbuf == InvalidBuffer )
157
+ break ;
158
+ }
159
+ }
160
+ if ( nbuf != InvalidBuffer )
161
+ _bt_relbuf (rel , nbuf , BT_READ );
162
+ }
163
+ }
102
164
103
165
/* do the insertion */
104
166
res = _bt_insertonpg (rel , buf , stack , natts , itup_scankey ,
0 commit comments