Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
6bdaf52a
提交
6bdaf52a
authored
8月 09, 2009
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
New experimental page store.
上级
37acb1ff
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
216 行增加
和
165 行删除
+216
-165
PageBtree.java
h2/src/main/org/h2/index/PageBtree.java
+19
-10
PageBtreeIndex.java
h2/src/main/org/h2/index/PageBtreeIndex.java
+1
-1
PageBtreeLeaf.java
h2/src/main/org/h2/index/PageBtreeLeaf.java
+16
-16
PageBtreeNode.java
h2/src/main/org/h2/index/PageBtreeNode.java
+66
-36
PageData.java
h2/src/main/org/h2/index/PageData.java
+7
-7
PageDataLeaf.java
h2/src/main/org/h2/index/PageDataLeaf.java
+10
-9
PageDataNode.java
h2/src/main/org/h2/index/PageDataNode.java
+5
-3
PageScanIndex.java
h2/src/main/org/h2/index/PageScanIndex.java
+2
-2
PageLog.java
h2/src/main/org/h2/store/PageLog.java
+7
-3
PageStore.java
h2/src/main/org/h2/store/PageStore.java
+1
-0
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+0
-2
TestBtreeIndex.java
h2/src/test/org/h2/test/synth/TestBtreeIndex.java
+82
-76
没有找到文件。
h2/src/main/org/h2/index/PageBtree.java
浏览文件 @
6bdaf52a
...
@@ -94,9 +94,10 @@ abstract class PageBtree extends Record {
...
@@ -94,9 +94,10 @@ abstract class PageBtree extends Record {
* @param compare the row
* @param compare the row
* @param bigger if looking for a larger row
* @param bigger if looking for a larger row
* @param add if the row should be added (check for duplicate keys)
* @param add if the row should be added (check for duplicate keys)
* @param compareKeys compare the row keys as well
* @return the index of the found row
* @return the index of the found row
*/
*/
int
find
(
SearchRow
compare
,
boolean
bigger
,
boolean
add
)
throws
SQLException
{
int
find
(
SearchRow
compare
,
boolean
bigger
,
boolean
add
,
boolean
compareKeys
)
throws
SQLException
{
if
(
compare
==
null
)
{
if
(
compare
==
null
)
{
return
0
;
return
0
;
}
}
...
@@ -106,13 +107,18 @@ abstract class PageBtree extends Record {
...
@@ -106,13 +107,18 @@ abstract class PageBtree extends Record {
int
i
=
(
l
+
r
)
>>>
1
;
int
i
=
(
l
+
r
)
>>>
1
;
SearchRow
row
=
getRow
(
i
);
SearchRow
row
=
getRow
(
i
);
comp
=
index
.
compareRows
(
row
,
compare
);
comp
=
index
.
compareRows
(
row
,
compare
);
if
(
comp
==
0
&&
add
)
{
if
(
comp
==
0
)
{
if
(
index
.
indexType
.
isUnique
())
{
if
(
add
&&
index
.
indexType
.
isUnique
())
{
if
(!
index
.
containsNullAndAllowMultipleNull
(
compare
))
{
if
(!
index
.
containsNullAndAllowMultipleNull
(
compare
))
{
throw
index
.
getDuplicateKeyException
();
throw
index
.
getDuplicateKeyException
();
}
}
}
}
comp
=
index
.
compareKeys
(
row
,
compare
);
if
(
compareKeys
)
{
comp
=
index
.
compareKeys
(
row
,
compare
);
if
(
comp
==
0
)
{
return
i
;
}
}
}
}
if
(
comp
>
0
||
(!
bigger
&&
comp
==
0
))
{
if
(
comp
>
0
||
(!
bigger
&&
comp
==
0
))
{
r
=
i
;
r
=
i
;
...
@@ -129,12 +135,13 @@ abstract class PageBtree extends Record {
...
@@ -129,12 +135,13 @@ abstract class PageBtree extends Record {
abstract
void
read
()
throws
SQLException
;
abstract
void
read
()
throws
SQLException
;
/**
/**
* Try to add a row.
* Add a row if possible. If it is possible this method returns -1, otherwise
* the split point. It is always possible to add one row.
*
*
* @param row the row
* @param row the row to add
* @return 0 if successful, or the split position if the page needs to be
* @return the split point of this page, or -1 if no split is required
* split
*/
*/
abstract
int
addRowTry
(
SearchRow
row
)
throws
SQLException
;
abstract
int
addRowTry
(
SearchRow
row
)
throws
SQLException
;
/**
/**
...
@@ -221,9 +228,11 @@ abstract class PageBtree extends Record {
...
@@ -221,9 +228,11 @@ abstract class PageBtree extends Record {
* Remove a row.
* Remove a row.
*
*
* @param row the row to remove
* @param row the row to remove
* @return true if this page is now empty
* @return null if the last row didn't change,
* the deleted row if the page is now empty,
* otherwise the new last row of this page
*/
*/
abstract
boolean
remove
(
SearchRow
row
)
throws
SQLException
;
abstract
SearchRow
remove
(
SearchRow
row
)
throws
SQLException
;
/**
/**
* Free up all child pages.
* Free up all child pages.
...
...
h2/src/main/org/h2/index/PageBtreeIndex.java
浏览文件 @
6bdaf52a
...
@@ -87,7 +87,7 @@ public class PageBtreeIndex extends BaseIndex {
...
@@ -87,7 +87,7 @@ public class PageBtreeIndex extends BaseIndex {
while
(
true
)
{
while
(
true
)
{
PageBtree
root
=
getPage
(
headPos
);
PageBtree
root
=
getPage
(
headPos
);
int
splitPoint
=
root
.
addRowTry
(
newRow
);
int
splitPoint
=
root
.
addRowTry
(
newRow
);
if
(
splitPoint
==
0
)
{
if
(
splitPoint
==
-
1
)
{
break
;
break
;
}
}
if
(
trace
.
isDebugEnabled
())
{
if
(
trace
.
isDebugEnabled
())
{
...
...
h2/src/main/org/h2/index/PageBtreeLeaf.java
浏览文件 @
6bdaf52a
...
@@ -54,20 +54,13 @@ class PageBtreeLeaf extends PageBtree {
...
@@ -54,20 +54,13 @@ class PageBtreeLeaf extends PageBtree {
start
=
data
.
length
();
start
=
data
.
length
();
}
}
/**
* Add a row if possible. If it is possible this method returns 0, otherwise
* the split point. It is always possible to add one row.
*
* @param row the now to add
* @return the split point of this page, or 0 if no split is required
*/
int
addRowTry
(
SearchRow
row
)
throws
SQLException
{
int
addRowTry
(
SearchRow
row
)
throws
SQLException
{
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
int
pageSize
=
index
.
getPageStore
().
getPageSize
();
int
pageSize
=
index
.
getPageStore
().
getPageSize
();
int
last
=
entryCount
==
0
?
pageSize
:
offsets
[
entryCount
-
1
];
int
last
=
entryCount
==
0
?
pageSize
:
offsets
[
entryCount
-
1
];
if
(
last
-
rowLength
<
start
+
OFFSET_LENGTH
)
{
if
(
last
-
rowLength
<
start
+
OFFSET_LENGTH
)
{
if
(
entryCount
>
1
)
{
if
(
entryCount
>
1
)
{
return
(
entryCount
/
2
)
+
1
;
return
entryCount
/
2
;
}
}
onlyPosition
=
true
;
onlyPosition
=
true
;
// change the offsets (now storing only positions)
// change the offsets (now storing only positions)
...
@@ -91,7 +84,7 @@ class PageBtreeLeaf extends PageBtree {
...
@@ -91,7 +84,7 @@ class PageBtreeLeaf extends PageBtree {
x
=
0
;
x
=
0
;
}
else
{
}
else
{
readAllRows
();
readAllRows
();
x
=
find
(
row
,
false
,
true
);
x
=
find
(
row
,
false
,
true
,
true
);
System
.
arraycopy
(
offsets
,
0
,
newOffsets
,
0
,
x
);
System
.
arraycopy
(
offsets
,
0
,
newOffsets
,
0
,
x
);
System
.
arraycopy
(
rows
,
0
,
newRows
,
0
,
x
);
System
.
arraycopy
(
rows
,
0
,
newRows
,
0
,
x
);
if
(
x
<
entryCount
)
{
if
(
x
<
entryCount
)
{
...
@@ -109,7 +102,7 @@ class PageBtreeLeaf extends PageBtree {
...
@@ -109,7 +102,7 @@ class PageBtreeLeaf extends PageBtree {
offsets
=
newOffsets
;
offsets
=
newOffsets
;
rows
=
newRows
;
rows
=
newRows
;
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
return
0
;
return
-
1
;
}
}
private
void
removeRow
(
int
i
)
throws
SQLException
{
private
void
removeRow
(
int
i
)
throws
SQLException
{
...
@@ -156,17 +149,24 @@ class PageBtreeLeaf extends PageBtree {
...
@@ -156,17 +149,24 @@ class PageBtreeLeaf extends PageBtree {
return
this
;
return
this
;
}
}
boolean
remove
(
SearchRow
row
)
throws
SQLException
{
SearchRow
remove
(
SearchRow
row
)
throws
SQLException
{
int
at
=
find
(
row
,
false
,
false
);
int
at
=
find
(
row
,
false
,
false
,
true
);
if
(
index
.
compareRows
(
row
,
getRow
(
at
))
!=
0
)
{
SearchRow
delete
=
getRow
(
at
);
if
(
index
.
compareRows
(
row
,
delete
)
!=
0
||
delete
.
getPos
()
!=
row
.
getPos
())
{
throw
Message
.
getSQLException
(
ErrorCode
.
ROW_NOT_FOUND_WHEN_DELETING_1
,
index
.
getSQL
()
+
": "
+
row
);
throw
Message
.
getSQLException
(
ErrorCode
.
ROW_NOT_FOUND_WHEN_DELETING_1
,
index
.
getSQL
()
+
": "
+
row
);
}
}
if
(
entryCount
==
1
)
{
if
(
entryCount
==
1
)
{
return
true
;
// the page is now empty
return
row
;
}
}
removeRow
(
at
);
removeRow
(
at
);
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
return
false
;
if
(
at
==
entryCount
)
{
// the last row changed
return
getRow
(
at
-
1
);
}
// the last row didn't change
return
null
;
}
}
void
freeChildren
()
{
void
freeChildren
()
{
...
@@ -210,7 +210,7 @@ class PageBtreeLeaf extends PageBtree {
...
@@ -210,7 +210,7 @@ class PageBtreeLeaf extends PageBtree {
}
}
void
find
(
PageBtreeCursor
cursor
,
SearchRow
first
,
boolean
bigger
)
throws
SQLException
{
void
find
(
PageBtreeCursor
cursor
,
SearchRow
first
,
boolean
bigger
)
throws
SQLException
{
int
i
=
find
(
first
,
bigger
,
false
);
int
i
=
find
(
first
,
bigger
,
false
,
false
);
if
(
i
>
entryCount
)
{
if
(
i
>
entryCount
)
{
if
(
parentPageId
==
Page
.
ROOT
)
{
if
(
parentPageId
==
Page
.
ROOT
)
{
return
;
return
;
...
...
h2/src/main/org/h2/index/PageBtreeNode.java
浏览文件 @
6bdaf52a
...
@@ -16,16 +16,18 @@ import org.h2.store.PageStore;
...
@@ -16,16 +16,18 @@ import org.h2.store.PageStore;
import
org.h2.util.MemoryUtils
;
import
org.h2.util.MemoryUtils
;
/**
/**
* A b-tree node page that contains index data.
* A b-tree node page that contains index data. Data is organized as follows:
* Data is organized as follows: [leaf 0] (largest value of leaf 0) [leaf 1]
* [leaf 0] (largest value of leaf 0) [leaf 1] Format:
* Format:
* <ul>
* <ul><li>0-3: parent page id
* <li>0-3: parent page id</li>
* </li><li>4-4: page type
* <li>4-4: page type</li>
* </li><li>5-6: entry count
* <li>5-6: entry count</li>
* </li><li>7-10: row count of all children (-1 if not known)
* <li>7-10: row count of all children (-1 if not known)</li>
* </li><li>11-14: rightmost child page id
* <li>11-14: rightmost child page id</li>
* </li><li>15- entries: 4 bytes leaf page id, 4 bytes offset to data
* <li>15- entries: 4 bytes leaf page id, 4 bytes offset to data</li>
* </li></ul>
* </ul>
* The row is the largest row of the respective child, meaning
* row[0] is the largest row of child[0].
*/
*/
class
PageBtreeNode
extends
PageBtree
{
class
PageBtreeNode
extends
PageBtree
{
...
@@ -37,7 +39,7 @@ class PageBtreeNode extends PageBtree {
...
@@ -37,7 +39,7 @@ class PageBtreeNode extends PageBtree {
*/
*/
private
int
[]
childPageIds
;
private
int
[]
childPageIds
;
//
private int rowCountStored = UNKNOWN_ROWCOUNT;
//
private int rowCountStored = UNKNOWN_ROWCOUNT;
private
int
rowCount
=
UNKNOWN_ROWCOUNT
;
private
int
rowCount
=
UNKNOWN_ROWCOUNT
;
...
@@ -67,25 +69,32 @@ class PageBtreeNode extends PageBtree {
...
@@ -67,25 +69,32 @@ class PageBtreeNode extends PageBtree {
start
=
data
.
length
();
start
=
data
.
length
();
}
}
/**
* Add a row. If it is possible this method returns -1, otherwise
* the split point. It is always possible to two rows.
*
* @param row the now to add
* @return the split point of this page, or -1 if no split is required
*/
private
int
addChildTry
(
SearchRow
row
)
throws
SQLException
{
private
int
addChildTry
(
SearchRow
row
)
throws
SQLException
{
if
(
entryCount
<
2
)
{
if
(
entryCount
<
2
)
{
return
0
;
return
-
1
;
}
}
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
int
pageSize
=
index
.
getPageStore
().
getPageSize
();
int
pageSize
=
index
.
getPageStore
().
getPageSize
();
int
last
=
entryCount
==
0
?
pageSize
:
offsets
[
entryCount
-
1
];
int
last
=
entryCount
==
0
?
pageSize
:
offsets
[
entryCount
-
1
];
if
(
last
-
rowLength
<
start
+
CHILD_OFFSET_PAIR_LENGTH
)
{
if
(
last
-
rowLength
<
start
+
CHILD_OFFSET_PAIR_LENGTH
)
{
return
(
entryCount
/
2
)
+
1
;
return
entryCount
/
2
;
}
}
return
0
;
return
-
1
;
}
}
/**
/**
* Add a row. If it is possible this method returns 0, otherwise
* Add a child at the given position.
* the split point. It is always possible to add one row.
*
*
* @param row the now to add
* @param x the position
* @return the split point of this page, or 0 if no split is required
* @param childPageId the child
* @param row the row smaller than the first row of the child and its children
*/
*/
private
void
addChild
(
int
x
,
int
childPageId
,
SearchRow
row
)
throws
SQLException
{
private
void
addChild
(
int
x
,
int
childPageId
,
SearchRow
row
)
throws
SQLException
{
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
...
@@ -136,15 +145,15 @@ class PageBtreeNode extends PageBtree {
...
@@ -136,15 +145,15 @@ class PageBtreeNode extends PageBtree {
int
addRowTry
(
SearchRow
row
)
throws
SQLException
{
int
addRowTry
(
SearchRow
row
)
throws
SQLException
{
while
(
true
)
{
while
(
true
)
{
int
x
=
find
(
row
,
false
,
fals
e
);
int
x
=
find
(
row
,
false
,
true
,
tru
e
);
PageBtree
page
=
index
.
getPage
(
childPageIds
[
x
]);
PageBtree
page
=
index
.
getPage
(
childPageIds
[
x
]);
int
splitPoint
=
page
.
addRowTry
(
row
);
int
splitPoint
=
page
.
addRowTry
(
row
);
if
(
splitPoint
==
0
)
{
if
(
splitPoint
==
-
1
)
{
break
;
break
;
}
}
SearchRow
pivot
=
page
.
getRow
(
splitPoint
-
1
);
SearchRow
pivot
=
page
.
getRow
(
splitPoint
-
1
);
int
splitPoint2
=
addChildTry
(
pivot
);
int
splitPoint2
=
addChildTry
(
pivot
);
if
(
splitPoint2
!=
0
)
{
if
(
splitPoint2
!=
-
1
)
{
return
splitPoint2
;
return
splitPoint2
;
}
}
PageBtree
page2
=
page
.
split
(
splitPoint
);
PageBtree
page2
=
page
.
split
(
splitPoint
);
...
@@ -156,7 +165,7 @@ class PageBtreeNode extends PageBtree {
...
@@ -156,7 +165,7 @@ class PageBtreeNode extends PageBtree {
}
}
updateRowCount
(
1
);
updateRowCount
(
1
);
written
=
false
;
written
=
false
;
return
0
;
return
-
1
;
}
}
private
void
updateRowCount
(
int
offset
)
{
private
void
updateRowCount
(
int
offset
)
{
...
@@ -215,7 +224,7 @@ class PageBtreeNode extends PageBtree {
...
@@ -215,7 +224,7 @@ class PageBtreeNode extends PageBtree {
}
}
void
find
(
PageBtreeCursor
cursor
,
SearchRow
first
,
boolean
bigger
)
throws
SQLException
{
void
find
(
PageBtreeCursor
cursor
,
SearchRow
first
,
boolean
bigger
)
throws
SQLException
{
int
i
=
find
(
first
,
bigger
,
false
);
int
i
=
find
(
first
,
bigger
,
false
,
false
);
if
(
i
>
entryCount
)
{
if
(
i
>
entryCount
)
{
if
(
parentPageId
==
Page
.
ROOT
)
{
if
(
parentPageId
==
Page
.
ROOT
)
{
return
;
return
;
...
@@ -243,26 +252,48 @@ class PageBtreeNode extends PageBtree {
...
@@ -243,26 +252,48 @@ class PageBtreeNode extends PageBtree {
return
index
.
getPage
(
child
).
getLastLeaf
();
return
index
.
getPage
(
child
).
getLastLeaf
();
}
}
boolean
remove
(
SearchRow
row
)
throws
SQLException
{
SearchRow
remove
(
SearchRow
row
)
throws
SQLException
{
int
at
=
find
(
row
,
false
,
false
);
int
at
=
find
(
row
,
false
,
false
,
true
);
// merge is not implemented to allow concurrent usage
// merge is not implemented to allow concurrent usage
// TODO maybe implement merge
// TODO maybe implement merge
PageBtree
page
=
index
.
getPage
(
childPageIds
[
at
]);
PageBtree
page
=
index
.
getPage
(
childPageIds
[
at
]);
boolean
empty
=
page
.
remove
(
row
);
SearchRow
last
=
page
.
remove
(
row
);
updateRowCount
(-
1
);
updateRowCount
(-
1
);
if
(!
empty
)
{
if
(
last
==
null
)
{
// the first row didn't change - nothing to do
// the last row didn't change - nothing to do
return
false
;
return
null
;
}
else
if
(
last
==
row
)
{
// this child is now empty
index
.
getPageStore
().
freePage
(
page
.
getPos
(),
true
,
page
.
data
);
if
(
entryCount
<
1
)
{
// no more children - this page is empty as well
return
row
;
}
if
(
at
==
entryCount
)
{
// removing the last child
last
=
getRow
(
at
-
1
);
}
else
{
last
=
null
;
}
removeChild
(
at
);
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
return
last
;
}
}
// this child is now empty
// the last row is in the last child
index
.
getPageStore
().
freePage
(
page
.
getPos
(),
true
,
page
.
data
);
if
(
at
==
entryCount
)
{
if
(
entryCount
<
1
)
{
return
last
;
// no more children - this page is empty as well
return
true
;
}
}
int
child
=
childPageIds
[
at
];
removeChild
(
at
);
removeChild
(
at
);
// TODO this can mean only the position is now stored
// should split at the next possible moment
addChild
(
at
,
child
,
last
);
// remove and add swapped two children, fix that
int
temp
=
childPageIds
[
at
];
childPageIds
[
at
]
=
childPageIds
[
at
+
1
];
childPageIds
[
at
+
1
]
=
temp
;
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
return
false
;
return
null
;
}
}
int
getRowCount
()
throws
SQLException
{
int
getRowCount
()
throws
SQLException
{
...
@@ -420,5 +451,4 @@ class PageBtreeNode extends PageBtree {
...
@@ -420,5 +451,4 @@ class PageBtreeNode extends PageBtree {
return
"page["
+
getPos
()
+
"] b-tree node table:"
+
index
.
getId
()
+
" entries:"
+
entryCount
;
return
"page["
+
getPos
()
+
"] b-tree node table:"
+
index
.
getId
()
+
" entries:"
+
entryCount
;
}
}
}
}
\ No newline at end of file
h2/src/main/org/h2/index/PageData.java
浏览文件 @
6bdaf52a
...
@@ -84,10 +84,10 @@ abstract class PageData extends Record {
...
@@ -84,10 +84,10 @@ abstract class PageData extends Record {
while
(
l
<
r
)
{
while
(
l
<
r
)
{
int
i
=
(
l
+
r
)
>>>
1
;
int
i
=
(
l
+
r
)
>>>
1
;
int
k
=
keys
[
i
];
int
k
=
keys
[
i
];
if
(
k
>
key
)
{
if
(
k
==
key
)
{
r
=
i
;
}
else
if
(
k
==
key
)
{
return
i
;
return
i
;
}
else
if
(
k
>
key
)
{
r
=
i
;
}
else
{
}
else
{
l
=
i
+
1
;
l
=
i
+
1
;
}
}
...
@@ -101,11 +101,11 @@ abstract class PageData extends Record {
...
@@ -101,11 +101,11 @@ abstract class PageData extends Record {
abstract
void
read
()
throws
SQLException
;
abstract
void
read
()
throws
SQLException
;
/**
/**
* Try to add a row.
* Add a row if possible. If it is possible this method returns -1, otherwise
* the split point. It is always possible to add one row.
*
*
* @param row the row
* @param row the now to add
* @return 0 if successful, or the split position if the page needs to be
* @return the split point of this page, or -1 if no split is required
* split
*/
*/
abstract
int
addRowTry
(
Row
row
)
throws
SQLException
;
abstract
int
addRowTry
(
Row
row
)
throws
SQLException
;
...
...
h2/src/main/org/h2/index/PageDataLeaf.java
浏览文件 @
6bdaf52a
...
@@ -92,19 +92,20 @@ class PageDataLeaf extends PageData {
...
@@ -92,19 +92,20 @@ class PageDataLeaf extends PageData {
start
=
data
.
length
();
start
=
data
.
length
();
}
}
/**
* Add a row if possible. If it is possible this method returns 0, otherwise
* the split point. It is always possible to add one row.
*
* @param row the now to add
* @return the split point of this page, or 0 if no split is required
*/
int
addRowTry
(
Row
row
)
throws
SQLException
{
int
addRowTry
(
Row
row
)
throws
SQLException
{
int
rowLength
=
row
.
getByteCount
(
data
);
int
rowLength
=
row
.
getByteCount
(
data
);
int
pageSize
=
index
.
getPageStore
().
getPageSize
();
int
pageSize
=
index
.
getPageStore
().
getPageSize
();
int
last
=
entryCount
==
0
?
pageSize
:
offsets
[
entryCount
-
1
];
int
last
=
entryCount
==
0
?
pageSize
:
offsets
[
entryCount
-
1
];
if
(
entryCount
>
0
&&
last
-
rowLength
<
start
+
KEY_OFFSET_PAIR_LENGTH
)
{
if
(
entryCount
>
0
&&
last
-
rowLength
<
start
+
KEY_OFFSET_PAIR_LENGTH
)
{
return
(
entryCount
/
2
)
+
1
;
if
(
entryCount
>
1
)
{
return
entryCount
/
2
;
}
int
todoIncorrect
;
if
(
find
(
row
.
getPos
())
!=
1
)
{
System
.
out
.
println
(
"todo "
+
find
(
row
.
getPos
()));
}
return
1
;
// find(row.getPos()) + 1;
}
}
int
offset
=
last
-
rowLength
;
int
offset
=
last
-
rowLength
;
int
[]
newOffsets
=
new
int
[
entryCount
+
1
];
int
[]
newOffsets
=
new
int
[
entryCount
+
1
];
...
@@ -181,7 +182,7 @@ class PageDataLeaf extends PageData {
...
@@ -181,7 +182,7 @@ class PageDataLeaf extends PageData {
}
while
(
remaining
>
0
);
}
while
(
remaining
>
0
);
data
.
truncate
(
index
.
getPageStore
().
getPageSize
());
data
.
truncate
(
index
.
getPageStore
().
getPageSize
());
}
}
return
0
;
return
-
1
;
}
}
private
void
removeRow
(
int
i
)
throws
SQLException
{
private
void
removeRow
(
int
i
)
throws
SQLException
{
...
...
h2/src/main/org/h2/index/PageDataNode.java
浏览文件 @
6bdaf52a
...
@@ -25,6 +25,8 @@ import org.h2.util.MemoryUtils;
...
@@ -25,6 +25,8 @@ import org.h2.util.MemoryUtils;
* </li><li>11-14: rightmost child page id
* </li><li>11-14: rightmost child page id
* </li><li>15- entries: 4 bytes leaf page id, 4 bytes key
* </li><li>15- entries: 4 bytes leaf page id, 4 bytes key
* </li></ul>
* </li></ul>
* The key is the largest key of the respective child, meaning
* key[0] is the largest key of child[0].
*/
*/
class
PageDataNode
extends
PageData
{
class
PageDataNode
extends
PageData
{
...
@@ -85,14 +87,14 @@ class PageDataNode extends PageData {
...
@@ -85,14 +87,14 @@ class PageDataNode extends PageData {
int
x
=
find
(
row
.
getPos
());
int
x
=
find
(
row
.
getPos
());
PageData
page
=
index
.
getPage
(
childPageIds
[
x
],
getPos
());
PageData
page
=
index
.
getPage
(
childPageIds
[
x
],
getPos
());
int
splitPoint
=
page
.
addRowTry
(
row
);
int
splitPoint
=
page
.
addRowTry
(
row
);
if
(
splitPoint
==
0
)
{
if
(
splitPoint
==
-
1
)
{
break
;
break
;
}
}
int
maxEntries
=
(
index
.
getPageStore
().
getPageSize
()
-
ENTRY_START
)
/
ENTRY_LENGTH
;
int
maxEntries
=
(
index
.
getPageStore
().
getPageSize
()
-
ENTRY_START
)
/
ENTRY_LENGTH
;
if
(
entryCount
>=
maxEntries
)
{
if
(
entryCount
>=
maxEntries
)
{
return
entryCount
/
2
;
return
entryCount
/
2
;
}
}
int
pivot
=
page
.
getKey
(
splitPoint
-
1
);
int
pivot
=
splitPoint
==
0
?
row
.
getPos
()
:
page
.
getKey
(
splitPoint
-
1
);
PageData
page2
=
page
.
split
(
splitPoint
);
PageData
page2
=
page
.
split
(
splitPoint
);
index
.
getPageStore
().
updateRecord
(
page
,
true
,
page
.
data
);
index
.
getPageStore
().
updateRecord
(
page
,
true
,
page
.
data
);
index
.
getPageStore
().
updateRecord
(
page2
,
true
,
page2
.
data
);
index
.
getPageStore
().
updateRecord
(
page2
,
true
,
page2
.
data
);
...
@@ -100,7 +102,7 @@ class PageDataNode extends PageData {
...
@@ -100,7 +102,7 @@ class PageDataNode extends PageData {
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
index
.
getPageStore
().
updateRecord
(
this
,
true
,
data
);
}
}
updateRowCount
(
1
);
updateRowCount
(
1
);
return
0
;
return
-
1
;
}
}
private
void
updateRowCount
(
int
offset
)
throws
SQLException
{
private
void
updateRowCount
(
int
offset
)
throws
SQLException
{
...
...
h2/src/main/org/h2/index/PageScanIndex.java
浏览文件 @
6bdaf52a
...
@@ -115,13 +115,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
...
@@ -115,13 +115,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
while
(
true
)
{
while
(
true
)
{
PageData
root
=
getPage
(
headPos
,
0
);
PageData
root
=
getPage
(
headPos
,
0
);
int
splitPoint
=
root
.
addRowTry
(
row
);
int
splitPoint
=
root
.
addRowTry
(
row
);
if
(
splitPoint
==
0
)
{
if
(
splitPoint
==
-
1
)
{
break
;
break
;
}
}
if
(
trace
.
isDebugEnabled
())
{
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"split "
+
splitPoint
);
trace
.
debug
(
"split "
+
splitPoint
);
}
}
int
pivot
=
root
.
getKey
(
splitPoint
-
1
);
int
pivot
=
splitPoint
==
0
?
row
.
getPos
()
:
root
.
getKey
(
splitPoint
-
1
);
PageData
page1
=
root
;
PageData
page1
=
root
;
PageData
page2
=
root
.
split
(
splitPoint
);
PageData
page2
=
root
.
split
(
splitPoint
);
int
rootPageId
=
root
.
getPos
();
int
rootPageId
=
root
.
getPos
();
...
...
h2/src/main/org/h2/store/PageLog.java
浏览文件 @
6bdaf52a
...
@@ -216,10 +216,13 @@ public class PageLog {
...
@@ -216,10 +216,13 @@ public class PageLog {
int
pageId
=
in
.
readInt
();
int
pageId
=
in
.
readInt
();
in
.
readFully
(
data
.
getBytes
(),
0
,
store
.
getPageSize
());
in
.
readFully
(
data
.
getBytes
(),
0
,
store
.
getPageSize
());
if
(
stage
==
RECOVERY_STAGE_UNDO
)
{
if
(
stage
==
RECOVERY_STAGE_UNDO
)
{
if
(
trace
.
isDebugEnabled
())
{
if
(!
undo
.
get
(
pageId
))
{
trace
.
debug
(
"log undo "
+
pageId
);
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"log undo "
+
pageId
);
}
store
.
writePage
(
pageId
,
data
);
undo
.
set
(
pageId
);
}
}
store
.
writePage
(
pageId
,
data
);
}
}
}
else
if
(
x
==
ADD
||
x
==
REMOVE
)
{
}
else
if
(
x
==
ADD
||
x
==
REMOVE
)
{
int
sessionId
=
in
.
readInt
();
int
sessionId
=
in
.
readInt
();
...
@@ -288,6 +291,7 @@ public class PageLog {
...
@@ -288,6 +291,7 @@ public class PageLog {
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
throw
Message
.
convertIOException
(
e
,
"recover"
);
throw
Message
.
convertIOException
(
e
,
"recover"
);
}
}
undo
=
new
BitField
();
}
}
/**
/**
...
...
h2/src/main/org/h2/store/PageStore.java
浏览文件 @
6bdaf52a
...
@@ -103,6 +103,7 @@ public class PageStore implements CacheWriter {
...
@@ -103,6 +103,7 @@ public class PageStore implements CacheWriter {
// TODO update: only log the key and changed values
// TODO update: only log the key and changed values
// TODO store dates differently in Data; test moving db to another timezone
// TODO store dates differently in Data; test moving db to another timezone
// TODO online backup using bsdiff
// TODO online backup using bsdiff
// TODO trying to insert duplicate key can split a page: not in recovery
// TODO when removing DiskFile:
// TODO when removing DiskFile:
// remove CacheObject.blockCount
// remove CacheObject.blockCount
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
6bdaf52a
...
@@ -295,8 +295,6 @@ java org.h2.test.TestAll timer
...
@@ -295,8 +295,6 @@ java org.h2.test.TestAll timer
/*
/*
page store: TestBtreeIndex
-------------
-------------
create a short documentation
create a short documentation
...
...
h2/src/test/org/h2/test/synth/TestBtreeIndex.java
浏览文件 @
6bdaf52a
...
@@ -41,24 +41,27 @@ public class TestBtreeIndex extends TestBase {
...
@@ -41,24 +41,27 @@ public class TestBtreeIndex extends TestBase {
private
void
testAddDelete
()
throws
SQLException
{
private
void
testAddDelete
()
throws
SQLException
{
deleteDb
(
"index"
);
deleteDb
(
"index"
);
Connection
conn
=
getConnection
(
"index"
);
Connection
conn
=
getConnection
(
"index"
);
Statement
stat
=
conn
.
createStatement
();
try
{
stat
.
execute
(
"CREATE TABLE TEST(ID bigint primary key)"
);
Statement
stat
=
conn
.
createStatement
();
int
count
=
1000
;
stat
.
execute
(
"CREATE TABLE TEST(ID bigint primary key)"
);
stat
.
execute
(
"insert into test select x from system_range(1, "
+
count
+
")"
);
int
count
=
1000
;
if
(!
config
.
memory
)
{
stat
.
execute
(
"insert into test select x from system_range(1, "
+
count
+
")"
);
conn
.
close
();
if
(!
config
.
memory
)
{
conn
=
getConnection
(
"index"
);
conn
.
close
();
stat
=
conn
.
createStatement
();
conn
=
getConnection
(
"index"
);
}
stat
=
conn
.
createStatement
();
for
(
int
i
=
1
;
i
<
count
;
i
++)
{
ResultSet
rs
=
stat
.
executeQuery
(
"select * from test order by id"
);
for
(
int
j
=
i
;
rs
.
next
();
j
++)
{
assertEquals
(
j
,
rs
.
getInt
(
1
));
}
}
stat
.
execute
(
"delete from test where id ="
+
i
);
for
(
int
i
=
1
;
i
<
count
;
i
++)
{
ResultSet
rs
=
stat
.
executeQuery
(
"select * from test order by id"
);
for
(
int
j
=
i
;
rs
.
next
();
j
++)
{
assertEquals
(
j
,
rs
.
getInt
(
1
));
}
stat
.
execute
(
"delete from test where id ="
+
i
);
}
stat
.
execute
(
"drop all objects delete files"
);
}
finally
{
conn
.
close
();
}
}
stat
.
execute
(
"drop all objects delete files"
);
conn
.
close
();
}
}
public
void
testCase
(
int
seed
)
throws
SQLException
{
public
void
testCase
(
int
seed
)
throws
SQLException
{
...
@@ -92,75 +95,78 @@ public class TestBtreeIndex extends TestBase {
...
@@ -92,75 +95,78 @@ public class TestBtreeIndex extends TestBase {
String
prefix
=
buff
.
toString
();
String
prefix
=
buff
.
toString
();
DeleteDbFiles
.
execute
(
baseDir
,
null
,
true
);
DeleteDbFiles
.
execute
(
baseDir
,
null
,
true
);
Connection
conn
=
getConnection
(
"index"
);
Connection
conn
=
getConnection
(
"index"
);
Statement
stat
=
conn
.
createStatement
();
try
{
stat
.
execute
(
"CREATE TABLE a(text VARCHAR PRIMARY KEY)"
);
Statement
stat
=
conn
.
createStatement
();
PreparedStatement
prepInsert
=
conn
.
prepareStatement
(
"INSERT INTO a VALUES(?)"
);
stat
.
execute
(
"CREATE TABLE a(text VARCHAR PRIMARY KEY)"
);
PreparedStatement
prepDelete
=
conn
.
prepareStatement
(
"DELETE FROM a WHERE text=?"
);
PreparedStatement
prepInsert
=
conn
.
prepareStatement
(
"INSERT INTO a VALUES(?)"
);
PreparedStatement
prepDeleteAllButOne
=
conn
.
prepareStatement
(
"DELETE FROM a WHERE text <> ?"
);
PreparedStatement
prepDelete
=
conn
.
prepareStatement
(
"DELETE FROM a WHERE text=?"
);
int
count
=
0
;
PreparedStatement
prepDeleteAllButOne
=
conn
.
prepareStatement
(
"DELETE FROM a WHERE text <> ?"
);
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
int
count
=
0
;
int
y
=
random
.
nextInt
(
distinct
);
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
try
{
int
y
=
random
.
nextInt
(
distinct
);
prepInsert
.
setString
(
1
,
prefix
+
y
);
try
{
prepInsert
.
executeUpdate
();
prepInsert
.
setString
(
1
,
prefix
+
y
);
count
++;
prepInsert
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
count
++;
if
(
e
.
getSQLState
().
equals
(
"23001"
))
{
}
catch
(
SQLException
e
)
{
// ignore
if
(
e
.
getSQLState
().
equals
(
"23001"
))
{
}
else
{
// ignore
TestBase
.
logError
(
"error"
,
e
);
}
else
{
break
;
}
}
if
(
delete
&&
random
.
nextInt
(
10
)
==
1
)
{
if
(
random
.
nextInt
(
4
)
==
1
)
{
try
{
prepDeleteAllButOne
.
setString
(
1
,
prefix
+
y
);
int
deleted
=
prepDeleteAllButOne
.
executeUpdate
();
if
(
deleted
<
count
-
1
)
{
printError
(
seed
,
"deleted:"
+
deleted
);
}
count
-=
deleted
;
}
catch
(
SQLException
e
)
{
TestBase
.
logError
(
"error"
,
e
);
TestBase
.
logError
(
"error"
,
e
);
break
;
break
;
}
}
}
else
{
}
try
{
if
(
delete
&&
random
.
nextInt
(
10
)
==
1
)
{
prepDelete
.
setString
(
1
,
prefix
+
y
);
if
(
random
.
nextInt
(
4
)
==
1
)
{
int
deleted
=
prepDelete
.
executeUpdate
();
try
{
if
(
deleted
>
1
)
{
prepDeleteAllButOne
.
setString
(
1
,
prefix
+
y
);
printError
(
seed
,
"deleted:"
+
deleted
);
int
deleted
=
prepDeleteAllButOne
.
executeUpdate
();
if
(
deleted
<
count
-
1
)
{
printError
(
seed
,
"deleted:"
+
deleted
+
" i:"
+
i
);
}
count
-=
deleted
;
}
catch
(
SQLException
e
)
{
TestBase
.
logError
(
"error"
,
e
);
break
;
}
}
else
{
try
{
prepDelete
.
setString
(
1
,
prefix
+
y
);
int
deleted
=
prepDelete
.
executeUpdate
();
if
(
deleted
>
1
)
{
printError
(
seed
,
"deleted:"
+
deleted
+
" i:"
+
i
);
}
count
-=
deleted
;
}
catch
(
SQLException
e
)
{
TestBase
.
logError
(
"error"
,
e
);
break
;
}
}
count
-=
deleted
;
}
catch
(
SQLException
e
)
{
TestBase
.
logError
(
"error"
,
e
);
break
;
}
}
}
}
}
}
}
int
testCount
;
int
testCount
;
testCount
=
0
;
testCount
=
0
;
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT text FROM a ORDER BY text"
);
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT text FROM a ORDER BY text"
);
ResultSet
rs2
=
conn
.
createStatement
().
executeQuery
(
"SELECT text FROM a ORDER BY 'x' || text"
);
ResultSet
rs2
=
conn
.
createStatement
().
executeQuery
(
"SELECT text FROM a ORDER BY 'x' || text"
);
testCount
=
0
;
testCount
=
0
;
while
(
rs
.
next
()
&&
rs2
.
next
())
{
while
(
rs
.
next
()
&&
rs2
.
next
())
{
if
(!
rs
.
getString
(
1
).
equals
(
rs2
.
getString
(
1
)))
{
if
(!
rs
.
getString
(
1
).
equals
(
rs2
.
getString
(
1
)))
{
fail
(
""
+
testCount
);
fail
(
""
+
testCount
);
}
testCount
++;
}
}
testCount
++;
assertFalse
(
rs
.
next
());
}
assertFalse
(
rs2
.
next
());
assertFalse
(
rs
.
next
());
if
(
testCount
!=
count
)
{
assertFalse
(
rs2
.
next
());
printError
(
seed
,
"count:"
+
count
+
" testCount:"
+
testCount
);
if
(
testCount
!=
count
)
{
}
printError
(
seed
,
"count:"
+
count
+
" testCount:"
+
testCount
);
rs
=
stat
.
executeQuery
(
"SELECT text, count(*) FROM a GROUP BY text HAVING COUNT(*)>1"
);
}
if
(
rs
.
next
())
{
rs
=
stat
.
executeQuery
(
"SELECT text, count(*) FROM a GROUP BY text HAVING COUNT(*)>1"
);
printError
(
seed
,
"testCount:"
+
testCount
+
" "
+
rs
.
getString
(
1
));
if
(
rs
.
next
())
{
}
printError
(
seed
,
"testCount:"
+
testCount
);
}
finally
{
conn
.
close
();
}
}
conn
.
close
();
}
}
private
void
printError
(
int
seed
,
String
message
)
{
private
void
printError
(
int
seed
,
String
message
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论