Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
postgres-lambda-diff
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jakob Huber
postgres-lambda-diff
Commits
bc292937
Commit
bc292937
authored
18 years ago
by
Bruce Momjian
Browse files
Options
Downloads
Patches
Plain Diff
Split _bt_insertonpg to two functions.
Heikki Linnakangas
parent
63c678d1
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/backend/access/nbtree/nbtinsert.c
+190
-142
190 additions, 142 deletions
src/backend/access/nbtree/nbtinsert.c
with
190 additions
and
142 deletions
src/backend/access/nbtree/nbtinsert.c
+
190
−
142
View file @
bc292937
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.15
2
2007/0
2/21 20:02:17
momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.15
3
2007/0
3/03 20:13:06
momjian Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -46,13 +46,18 @@ typedef struct
static
Buffer
_bt_newroot
(
Relation
rel
,
Buffer
lbuf
,
Buffer
rbuf
);
static
TransactionId
_bt_check_unique
(
Relation
rel
,
IndexTuple
itup
,
Relation
heapRel
,
Buffer
buf
,
Relation
heapRel
,
Buffer
buf
,
OffsetNumber
ioffset
,
ScanKey
itup_scankey
);
static
void
_bt_findinsertloc
(
Relation
rel
,
Buffer
*
bufptr
,
OffsetNumber
*
offsetptr
,
int
keysz
,
ScanKey
scankey
,
IndexTuple
newtup
);
static
void
_bt_insertonpg
(
Relation
rel
,
Buffer
buf
,
BTStack
stack
,
int
keysz
,
ScanKey
scankey
,
IndexTuple
itup
,
OffsetNumber
after
item
,
OffsetNumber
new
item
off
,
bool
split_only_page
);
static
Buffer
_bt_split
(
Relation
rel
,
Buffer
buf
,
OffsetNumber
firstright
,
OffsetNumber
newitemoff
,
Size
newitemsz
,
...
...
@@ -86,6 +91,7 @@ _bt_doinsert(Relation rel, IndexTuple itup,
ScanKey
itup_scankey
;
BTStack
stack
;
Buffer
buf
;
OffsetNumber
offset
;
/* we need an insertion scan key to do our search, so build one */
itup_scankey
=
_bt_mkscankey
(
rel
,
itup
);
...
...
@@ -94,6 +100,8 @@ top:
/* find the first page containing this key */
stack
=
_bt_search
(
rel
,
natts
,
itup_scankey
,
false
,
&
buf
,
BT_WRITE
);
offset
=
InvalidOffsetNumber
;
/* trade in our read lock for a write lock */
LockBuffer
(
buf
,
BUFFER_LOCK_UNLOCK
);
LockBuffer
(
buf
,
BT_WRITE
);
...
...
@@ -128,7 +136,8 @@ top:
{
TransactionId
xwait
;
xwait
=
_bt_check_unique
(
rel
,
itup
,
heapRel
,
buf
,
itup_scankey
);
offset
=
_bt_binsrch
(
rel
,
buf
,
natts
,
itup_scankey
,
false
);
xwait
=
_bt_check_unique
(
rel
,
itup
,
heapRel
,
buf
,
offset
,
itup_scankey
);
if
(
TransactionIdIsValid
(
xwait
))
{
...
...
@@ -142,7 +151,8 @@ top:
}
/* do the insertion */
_bt_insertonpg
(
rel
,
buf
,
stack
,
natts
,
itup_scankey
,
itup
,
0
,
false
);
_bt_findinsertloc
(
rel
,
&
buf
,
&
offset
,
natts
,
itup_scankey
,
itup
);
_bt_insertonpg
(
rel
,
buf
,
stack
,
itup
,
offset
,
false
);
/* be tidy */
_bt_freestack
(
stack
);
...
...
@@ -152,18 +162,21 @@ top:
/*
* _bt_check_unique() -- Check for violation of unique index constraint
*
* offset points to the first possible item that could conflict. It can
* also point to end-of-page, which means that the first tuple to check
* is the first tuple on the next page.
*
* Returns InvalidTransactionId if there is no conflict, else an xact ID
* we must wait for to see if it commits a conflicting tuple. If an actual
* conflict is detected, no return --- just ereport().
*/
static
TransactionId
_bt_check_unique
(
Relation
rel
,
IndexTuple
itup
,
Relation
heapRel
,
Buffer
buf
,
ScanKey
itup_scankey
)
Buffer
buf
,
OffsetNumber
offset
,
ScanKey
itup_scankey
)
{
TupleDesc
itupdesc
=
RelationGetDescr
(
rel
);
int
natts
=
rel
->
rd_rel
->
relnatts
;
OffsetNumber
offset
,
maxoff
;
OffsetNumber
maxoff
;
Page
page
;
BTPageOpaque
opaque
;
Buffer
nbuf
=
InvalidBuffer
;
...
...
@@ -172,12 +185,6 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
opaque
=
(
BTPageOpaque
)
PageGetSpecialPointer
(
page
);
maxoff
=
PageGetMaxOffsetNumber
(
page
);
/*
* Find first item >= proposed new item. Note we could also get a pointer
* to end-of-page here.
*/
offset
=
_bt_binsrch
(
rel
,
buf
,
natts
,
itup_scankey
,
false
);
/*
* Scan over all equal tuples, looking for live conflicts.
*/
...
...
@@ -342,33 +349,11 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
return
InvalidTransactionId
;
}
/*----------
* _bt_insertonpg() -- Insert a tuple on a particular page in the index.
*
* This recursive procedure does the following things:
*
* + finds the right place to insert the tuple.
* + if necessary, splits the target page (making sure that the
* split is equitable as far as post-insert free space goes).
* + inserts the tuple.
* + if the page was split, pops the parent stack, and finds the
* right place to insert the new child pointer (by walking
* right using information stored in the parent stack).
* + invokes itself with the appropriate tuple for the right
* child page on the parent.
* + updates the metapage if a true root or fast root is split.
*
* On entry, we must have the right buffer in which to do the
* insertion, and the buffer must be pinned and write-locked. On return,
* we will have dropped both the pin and the lock on the buffer.
*
* If 'afteritem' is >0 then the new tuple must be inserted after the
* existing item of that number, noplace else. If 'afteritem' is 0
* then the procedure finds the exact spot to insert it by searching.
* (keysz and scankey parameters are used ONLY if afteritem == 0.
* The scankey must be an insertion-type scankey.)
/*
* _bt_findinsertloc() -- Finds an insert location for a tuple
*
*
NOTE: i
f the new key is equal to one or more existing keys, we can
*
I
f the new key is equal to one or more existing keys, we can
* legitimately place it anywhere in the series of equal keys --- in fact,
* if the new key is equal to the page's "high key" we can place it on
* the next page. If it is equal to the high key, and there's not room
...
...
@@ -379,36 +364,40 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
* Once we have chosen the page to put the key on, we'll insert it before
* any existing equal keys because of the way _bt_binsrch() works.
*
* The locking interactions in this code are critical. You should
* grok Lehman and Yao's paper before making any changes. In addition,
* you need to understand how we disambiguate duplicate keys in this
* implementation, in order to be able to find our location using
* L&Y "move right" operations. Since we may insert duplicate user
* keys, and since these dups may propagate up the tree, we use the
* 'afteritem' parameter to position ourselves correctly for the
* insertion on internal pages.
*----------
* If there's not enough room in the space, we try to make room by
* removing any LP_DELETEd tuples.
*
* On entry, *buf and *offsetptr point to the first legal position
* where the new tuple could be inserted. The caller should hold an
* exclusive lock on *buf. *offsetptr can also be set to
* InvalidOffsetNumber, in which case the function will search the right
* location within the page if needed. On exit, they point to the chosen
* insert location. If findinsertloc decided to move right, the lock and
* pin on the original page will be released and the new page returned to
* the caller is exclusively locked instead.
*
* newtup is the new tuple we're inserting, and scankey is an insertion
* type scan key for it.
*/
static
void
_bt_insert
onpg
(
Relation
rel
,
Buffer
buf
,
BTStack
stack
,
_bt_
find
insert
loc
(
Relation
rel
,
Buffer
*
buf
ptr
,
OffsetNumber
*
offsetptr
,
int
keysz
,
ScanKey
scankey
,
IndexTuple
itup
,
OffsetNumber
afteritem
,
bool
split_only_page
)
IndexTuple
newtup
)
{
Page
page
;
Buffer
buf
=
*
bufptr
;
Page
page
=
BufferGetPage
(
buf
);
Size
itemsz
;
BTPageOpaque
lpageop
;
bool
movedright
,
vacuumed
;
OffsetNumber
newitemoff
;
OffsetNumber
firstright
=
InvalidOffsetNumber
;
Size
itemsz
;
OffsetNumber
firstlegaloff
=
*
offsetptr
;
page
=
BufferGetPage
(
buf
);
lpageop
=
(
BTPageOpaque
)
PageGetSpecialPointer
(
page
);
itemsz
=
IndexTupleDSize
(
*
i
tup
);
itemsz
=
IndexTupleDSize
(
*
new
tup
);
itemsz
=
MAXALIGN
(
itemsz
);
/* be safe, PageAddItem will do this but we
* need to be consistent */
...
...
@@ -429,15 +418,10 @@ _bt_insertonpg(Relation rel,
"Consider a function index of an MD5 hash of the value, "
"or use full text indexing."
)));
/*
* Determine exactly where new item will go.
*/
if
(
afteritem
>
0
)
newitemoff
=
afteritem
+
1
;
else
{
/*----------
* If we will need to split the page to put the item
her
e,
* If we will need to split the page to put the item
on this pag
e,
* check whether we can put the tuple somewhere to the right,
* instead. Keep scanning right until we
* (a) find a page with enough free space,
...
...
@@ -454,8 +438,8 @@ _bt_insertonpg(Relation rel,
* excellent job of preventing O(N^2) behavior with many equal keys.
*----------
*/
bool
movedright
=
false
;
movedright
=
false
;
vacuumed
=
false
;
while
(
PageGetFreeSpace
(
page
)
<
itemsz
)
{
Buffer
rbuf
;
...
...
@@ -467,6 +451,11 @@ _bt_insertonpg(Relation rel,
if
(
P_ISLEAF
(
lpageop
)
&&
P_HAS_GARBAGE
(
lpageop
))
{
_bt_vacuum_one_page
(
rel
,
buf
);
/* remember that we vacuumed this page, because that makes
* the hint supplied by the caller invalid */
vacuumed
=
true
;
if
(
PageGetFreeSpace
(
page
)
>=
itemsz
)
break
;
/* OK, now we have enough space */
}
...
...
@@ -506,19 +495,78 @@ _bt_insertonpg(Relation rel,
_bt_relbuf
(
rel
,
buf
);
buf
=
rbuf
;
movedright
=
true
;
vacuumed
=
false
;
}
/*
* Now we are on the right page, so find the insert position. If we
* moved right at all, we know we should insert at the start of the
* page, else must find the position by searching.
* page. If we didn't move right, we can use the firstlegaloff hint
* if the caller supplied one, unless we vacuumed the page which
* might have moved tuples around making the hint invalid. If we
* didn't move right or can't use the hint, find the position
* by searching.
*/
if
(
movedright
)
newitemoff
=
P_FIRSTDATAKEY
(
lpageop
);
else
if
(
firstlegaloff
!=
InvalidOffsetNumber
&&
!
vacuumed
)
newitemoff
=
firstlegaloff
;
else
newitemoff
=
_bt_binsrch
(
rel
,
buf
,
keysz
,
scankey
,
false
);
*
bufptr
=
buf
;
*
offsetptr
=
newitemoff
;
}
/*----------
* _bt_insertonpg() -- Insert a tuple on a particular page in the index.
*
* This recursive procedure does the following things:
*
* + if necessary, splits the target page (making sure that the
* split is equitable as far as post-insert free space goes).
* + inserts the tuple.
* + if the page was split, pops the parent stack, and finds the
* right place to insert the new child pointer (by walking
* right using information stored in the parent stack).
* + invokes itself with the appropriate tuple for the right
* child page on the parent.
* + updates the metapage if a true root or fast root is split.
*
* On entry, we must have the right buffer in which to do the
* insertion, and the buffer must be pinned and write-locked. On return,
* we will have dropped both the pin and the lock on the buffer.
*
* The locking interactions in this code are critical. You should
* grok Lehman and Yao's paper before making any changes. In addition,
* you need to understand how we disambiguate duplicate keys in this
* implementation, in order to be able to find our location using
* L&Y "move right" operations. Since we may insert duplicate user
* keys, and since these dups may propagate up the tree, we use the
* 'afteritem' parameter to position ourselves correctly for the
* insertion on internal pages.
*----------
*/
static
void
_bt_insertonpg
(
Relation
rel
,
Buffer
buf
,
BTStack
stack
,
IndexTuple
itup
,
OffsetNumber
newitemoff
,
bool
split_only_page
)
{
Page
page
;
BTPageOpaque
lpageop
;
OffsetNumber
firstright
=
InvalidOffsetNumber
;
Size
itemsz
;
page
=
BufferGetPage
(
buf
);
lpageop
=
(
BTPageOpaque
)
PageGetSpecialPointer
(
page
);
itemsz
=
IndexTupleDSize
(
*
itup
);
itemsz
=
MAXALIGN
(
itemsz
);
/* be safe, PageAddItem will do this but we
* need to be consistent */
/*
* Do we need to split the page to fit the item on it?
*
...
...
@@ -1427,7 +1475,7 @@ _bt_insert_parent(Relation rel,
/* Recursively update the parent */
_bt_insertonpg
(
rel
,
pbuf
,
stack
->
bts_parent
,
0
,
NULL
,
new_item
,
stack
->
bts_offset
,
new_item
,
stack
->
bts_offset
+
1
,
is_only
);
/* be tidy */
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment