Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
344f2633
提交
344f2633
authored
6月 01, 2013
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVTableEngine
上级
27d8e115
显示空白字符变更
内嵌
并排
正在显示
16 个修改的文件
包含
339 行增加
和
143 行删除
+339
-143
changelog.html
h2/src/docsrc/html/changelog.html
+2
-1
Insert.java
h2/src/main/org/h2/command/dml/Insert.java
+1
-0
Database.java
h2/src/main/org/h2/engine/Database.java
+13
-3
BaseIndex.java
h2/src/main/org/h2/index/BaseIndex.java
+14
-0
PageBtreeIndex.java
h2/src/main/org/h2/index/PageBtreeIndex.java
+0
-9
TreeIndex.java
h2/src/main/org/h2/index/TreeIndex.java
+3
-0
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+15
-5
MVPrimaryIndex.java
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
+1
-2
MVSecondaryIndex.java
h2/src/main/org/h2/mvstore/db/MVSecondaryIndex.java
+2
-12
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+14
-12
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+106
-60
FilePathMem.java
h2/src/main/org/h2/store/fs/FilePathMem.java
+1
-1
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+54
-17
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+4
-0
TestLob.java
h2/src/test/org/h2/test/db/TestLob.java
+22
-13
TestMVTableEngine.java
h2/src/test/org/h2/test/store/TestMVTableEngine.java
+87
-8
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
344f2633
...
...
@@ -25,7 +25,8 @@ Change Log
is no longer supported. This is to simplify the MVTableEngine.
</li><li>
New column "information_schema.tables.row_count_estimate".
</li><li>
Issue 468: trunc(timestamp) could return the wrong value.
</li><li><li>
Fix deadlock when updating LOB's concurrently. See TestLob.testDeadlock2().
</li><li>
Fixed a deadlock when updating LOB's concurrently. See TestLob.testDeadlock2().
</li><li>
Fixed a deadlock related to very large temporary result sets.
</li></ul>
<h2>
Version 1.3.172 (2013-05-25)
</h2>
...
...
h2/src/main/org/h2/command/dml/Insert.java
浏览文件 @
344f2633
...
...
@@ -100,6 +100,7 @@ public class Insert extends Prepared implements ResultTarget {
if
(
listSize
>
0
)
{
int
columnLen
=
columns
.
length
;
for
(
int
x
=
0
;
x
<
listSize
;
x
++)
{
session
.
startStatementWithinTransaction
();
Row
newRow
=
table
.
getTemplateRow
();
Expression
[]
expr
=
list
.
get
(
x
);
setCurrentRowNumber
(
x
+
1
);
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
344f2633
...
...
@@ -7,7 +7,6 @@
package
org
.
h2
.
engine
;
import
java.io.IOException
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
...
...
@@ -646,6 +645,9 @@ public class Database implements DataHandler {
for
(
MetaRecord
rec
:
records
)
{
rec
.
execute
(
this
,
systemSession
,
eventListener
);
}
if
(
mvStore
!=
null
)
{
mvStore
.
rollback
();
}
recompileInvalidViews
(
systemSession
);
starting
=
false
;
if
(!
readOnly
)
{
...
...
@@ -1797,11 +1799,16 @@ public class Database implements DataHandler {
* Flush all pending changes to the transaction log.
*/
public
synchronized
void
flush
()
{
if
(
readOnly
||
pageStore
==
null
)
{
if
(
readOnly
)
{
return
;
}
if
(
pageStore
!=
null
)
{
pageStore
.
flushLog
();
}
if
(
mvStore
!=
null
)
{
mvStore
.
store
();
}
}
public
void
setEventListener
(
DatabaseEventListener
eventListener
)
{
this
.
eventListener
=
eventListener
;
...
...
@@ -2276,6 +2283,9 @@ public class Database implements DataHandler {
pageStore
.
checkpoint
();
}
}
if
(
mvStore
!=
null
)
{
mvStore
.
store
();
}
}
getTempFileDeleter
().
deleteUnused
();
}
...
...
h2/src/main/org/h2/index/BaseIndex.java
浏览文件 @
344f2633
...
...
@@ -67,6 +67,20 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
}
}
/**
* Check that the index columns are not CLOB or BLOB.
*
* @param columns the columns
*/
protected
static
void
checkIndexColumnTypes
(
IndexColumn
[]
columns
)
{
for
(
IndexColumn
c
:
columns
)
{
int
type
=
c
.
column
.
getType
();
if
(
type
==
Value
.
CLOB
||
type
==
Value
.
BLOB
)
{
throw
DbException
.
get
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
"Index on BLOB or CLOB column: "
+
c
.
column
.
getCreateSQL
());
}
}
}
@Override
public
String
getDropSQL
()
{
return
null
;
...
...
h2/src/main/org/h2/index/PageBtreeIndex.java
浏览文件 @
344f2633
...
...
@@ -75,15 +75,6 @@ public class PageBtreeIndex extends PageIndex {
memoryPerPage
=
(
Constants
.
MEMORY_PAGE_BTREE
+
store
.
getPageSize
())
>>
2
;
}
private
static
void
checkIndexColumnTypes
(
IndexColumn
[]
columns
)
{
for
(
IndexColumn
c
:
columns
)
{
int
type
=
c
.
column
.
getType
();
if
(
type
==
Value
.
CLOB
||
type
==
Value
.
BLOB
)
{
throw
DbException
.
get
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
"Index on BLOB or CLOB column: "
+
c
.
column
.
getCreateSQL
());
}
}
}
@Override
public
void
add
(
Session
session
,
Row
row
)
{
if
(
trace
.
isDebugEnabled
())
{
...
...
h2/src/main/org/h2/index/TreeIndex.java
浏览文件 @
344f2633
...
...
@@ -31,6 +31,9 @@ public class TreeIndex extends BaseIndex {
public
TreeIndex
(
RegularTable
table
,
int
id
,
String
indexName
,
IndexColumn
[]
columns
,
IndexType
indexType
)
{
initBaseIndex
(
table
,
id
,
indexName
,
columns
,
indexType
);
tableData
=
table
;
if
(!
database
.
isStarting
())
{
checkIndexColumnTypes
(
columns
);
}
}
@Override
...
...
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
344f2633
...
...
@@ -535,7 +535,7 @@ public class MVStore {
}
}
catch
(
Exception
e
)
{
try
{
close
(
false
);
close
File
(
false
);
}
catch
(
Exception
e2
)
{
// ignore
}
...
...
@@ -668,10 +668,6 @@ public class MVStore {
* written but not committed, this is rolled back. All open maps are closed.
*/
public
void
close
()
{
close
(
true
);
}
private
void
close
(
boolean
shrinkIfPossible
)
{
if
(
closed
)
{
return
;
}
...
...
@@ -681,6 +677,20 @@ public class MVStore {
store
(
false
);
}
}
closeFile
(
true
);
}
/**
* Close the file and the store, without writing anything.
*/
public
void
closeImmediately
()
{
closeFile
(
false
);
}
private
void
closeFile
(
boolean
shrinkIfPossible
)
{
if
(
closed
)
{
return
;
}
closed
=
true
;
if
(
file
==
null
)
{
return
;
...
...
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
浏览文件 @
344f2633
...
...
@@ -329,8 +329,7 @@ public class MVPrimaryIndex extends BaseIndex {
return
dataMap
;
}
Transaction
t
=
mvTable
.
getTransaction
(
session
);
long
savepoint
=
session
.
getStatementSavepoint
();
return
dataMap
.
getInstance
(
t
,
savepoint
);
return
dataMap
.
getInstance
(
t
,
Long
.
MAX_VALUE
);
}
/**
...
...
h2/src/main/org/h2/mvstore/db/MVSecondaryIndex.java
浏览文件 @
344f2633
...
...
@@ -69,15 +69,6 @@ public class MVSecondaryIndex extends BaseIndex {
dataMap
=
mvTable
.
getTransaction
(
null
).
openMap
(
mapName
,
mapBuilder
);
}
private
static
void
checkIndexColumnTypes
(
IndexColumn
[]
columns
)
{
for
(
IndexColumn
c
:
columns
)
{
int
type
=
c
.
column
.
getType
();
if
(
type
==
Value
.
CLOB
||
type
==
Value
.
BLOB
)
{
throw
DbException
.
get
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
"Index on BLOB or CLOB column: "
+
c
.
column
.
getCreateSQL
());
}
}
}
@Override
public
void
close
(
Session
session
)
{
// ok
...
...
@@ -98,7 +89,7 @@ public class MVSecondaryIndex extends BaseIndex {
ValueArray
array
=
getKey
(
row
);
if
(
indexType
.
isUnique
())
{
array
.
getList
()[
keyColumns
-
1
]
=
ValueLong
.
get
(
Long
.
MIN_VALUE
);
ValueArray
key
=
(
ValueArray
)
map
.
c
eilingKey
(
array
);
ValueArray
key
=
(
ValueArray
)
map
.
getLatestC
eilingKey
(
array
);
if
(
key
!=
null
)
{
SearchRow
r2
=
getRow
(
key
.
getList
());
if
(
compareRows
(
row
,
r2
)
==
0
)
{
...
...
@@ -253,8 +244,7 @@ public class MVSecondaryIndex extends BaseIndex {
return
dataMap
;
}
Transaction
t
=
mvTable
.
getTransaction
(
session
);
long
savepoint
=
session
.
getStatementSavepoint
();
return
dataMap
.
getInstance
(
t
,
savepoint
);
return
dataMap
.
getInstance
(
t
,
Long
.
MAX_VALUE
);
}
/**
...
...
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
344f2633
...
...
@@ -6,8 +6,6 @@
*/
package
org
.
h2
.
mvstore
.
db
;
import
java.io.IOException
;
import
java.nio.channels.FileChannel
;
import
java.util.ArrayList
;
import
java.util.List
;
...
...
@@ -15,8 +13,9 @@ import org.h2.api.TableEngine;
import
org.h2.command.ddl.CreateTableData
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Database
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.db.TransactionStore.Transaction
;
import
org.h2.table.RegularTable
;
import
org.h2.table.TableBase
;
import
org.h2.util.New
;
...
...
@@ -28,6 +27,9 @@ public class MVTableEngine implements TableEngine {
@Override
public
TableBase
createTable
(
CreateTableData
data
)
{
Database
db
=
data
.
session
.
getDatabase
();
if
(!
data
.
persistData
||
(
data
.
temporary
&&
!
data
.
persistIndexes
))
{
return
new
RegularTable
(
data
);
}
Store
store
=
db
.
getMvStore
();
if
(
store
==
null
)
{
byte
[]
key
=
db
.
getFilePasswordHash
();
...
...
@@ -86,7 +88,7 @@ public class MVTableEngine implements TableEngine {
this
.
db
=
db
;
this
.
store
=
store
;
this
.
transactionStore
=
new
TransactionStore
(
store
,
new
ValueDataType
(
null
,
null
,
null
));
new
ValueDataType
(
null
,
db
,
null
));
}
public
MVStore
getStore
()
{
...
...
@@ -128,14 +130,7 @@ public class MVTableEngine implements TableEngine {
if
(
store
.
isClosed
())
{
return
;
}
FileChannel
f
=
store
.
getFile
();
if
(
f
!=
null
)
{
try
{
f
.
close
();
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
"Closing file"
);
}
}
store
.
closeImmediately
();
}
/**
...
...
@@ -154,6 +149,13 @@ public class MVTableEngine implements TableEngine {
store
.
setWriteDelay
(
value
);
}
public
void
rollback
()
{
List
<
Transaction
>
list
=
transactionStore
.
getOpenTransactions
();
for
(
Transaction
t
:
list
)
{
t
.
rollback
();
}
}
}
}
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
344f2633
...
...
@@ -61,6 +61,8 @@ public class TransactionStore {
*/
private
final
MVMap
<
String
,
String
>
settings
;
private
final
DataType
dataType
;
private
long
lastTransactionIdStored
;
private
long
lastTransactionId
;
...
...
@@ -80,23 +82,24 @@ public class TransactionStore {
* Create a new transaction store.
*
* @param store the store
* @param
keyType the data type for map key
s
* @param
dataType the data type for map keys and value
s
*/
public
TransactionStore
(
MVStore
store
,
DataType
key
Type
)
{
public
TransactionStore
(
MVStore
store
,
DataType
data
Type
)
{
this
.
store
=
store
;
this
.
dataType
=
dataType
;
settings
=
store
.
openMap
(
"settings"
);
preparedTransactions
=
store
.
openMap
(
"openTransactions"
,
new
MVMap
.
Builder
<
Long
,
Object
[]>());
// TODO commit of larger transaction could be faster if we have one undo
// log per transaction, or a range delete operation for maps
VersionedValueType
oldValueType
=
new
VersionedValueType
(
key
Type
);
ArrayType
v
alueType
=
new
ArrayType
(
new
DataType
[]{
new
ObjectDataType
(),
new
ObjectDataType
(),
key
Type
,
VersionedValueType
oldValueType
=
new
VersionedValueType
(
data
Type
);
ArrayType
undoLogV
alueType
=
new
ArrayType
(
new
DataType
[]{
new
ObjectDataType
(),
new
ObjectDataType
(),
data
Type
,
oldValueType
});
MVMap
.
Builder
<
long
[],
Object
[]>
builder
=
new
MVMap
.
Builder
<
long
[],
Object
[]>().
valueType
(
v
alueType
);
valueType
(
undoLogV
alueType
);
// TODO escape other map names, to avoid conflicts
undoLog
=
store
.
openMap
(
"undoLog"
,
builder
);
init
();
...
...
@@ -229,10 +232,7 @@ public class TransactionStore {
int
opType
=
(
Integer
)
op
[
0
];
if
(
opType
==
Transaction
.
OP_REMOVE
)
{
int
mapId
=
(
Integer
)
op
[
1
];
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapName
);
MVMap
<
Object
,
VersionedValue
>
map
=
openMap
(
mapId
);
Object
key
=
op
[
2
];
VersionedValue
value
=
map
.
get
(
key
);
// possibly the entry was added later on
...
...
@@ -247,6 +247,23 @@ public class TransactionStore {
endTransaction
(
t
);
}
private
MVMap
<
Object
,
VersionedValue
>
openMap
(
int
mapId
)
{
// TODO open map by id if possible
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
if
(
m
==
null
)
{
// the map was removed later on
return
null
;
}
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
VersionedValueType
vt
=
new
VersionedValueType
(
dataType
);
MVMap
.
Builder
<
Object
,
VersionedValue
>
mapBuilder
=
new
MVMap
.
Builder
<
Object
,
VersionedValue
>().
keyType
(
dataType
).
valueType
(
vt
);
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapName
,
mapBuilder
);
return
map
;
}
/**
* Check whether the given transaction id is still open and contains log
* entries.
...
...
@@ -304,11 +321,8 @@ public class TransactionStore {
long
[]
undoKey
=
new
long
[]
{
t
.
getId
(),
logId
};
Object
[]
op
=
undoLog
.
get
(
undoKey
);
int
mapId
=
((
Integer
)
op
[
1
]).
intValue
();
// TODO open map by id if possible
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapName
);
MVMap
<
Object
,
VersionedValue
>
map
=
openMap
(
mapId
);
if
(
map
!=
null
)
{
Object
key
=
op
[
2
];
VersionedValue
oldValue
=
(
VersionedValue
)
op
[
3
];
if
(
oldValue
==
null
)
{
...
...
@@ -318,6 +332,7 @@ public class TransactionStore {
// this transaction updated the value
map
.
put
(
key
,
oldValue
);
}
}
undoLog
.
remove
(
undoKey
);
}
}
...
...
@@ -339,9 +354,13 @@ public class TransactionStore {
// TODO open map by id if possible
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
if
(
m
==
null
)
{
// map was removed later on
}
else
{
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
set
.
add
(
mapName
);
}
}
return
set
;
}
...
...
@@ -940,6 +959,68 @@ public class TransactionStore {
return
map
.
lastKey
();
}
/**
* Get the most recent smallest key that is larger or equal to this key.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
getLatestCeilingKey
(
K
key
)
{
Cursor
<
K
>
cursor
=
map
.
keyIterator
(
key
);
while
(
cursor
.
hasNext
())
{
key
=
cursor
.
next
();
if
(
get
(
key
,
Long
.
MAX_VALUE
)
!=
null
)
{
return
key
;
}
}
return
null
;
}
/**
* Get the smallest key that is larger or equal to this key.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
ceilingKey
(
K
key
)
{
int
test
;
// TODO this method is slow
Cursor
<
K
>
cursor
=
map
.
keyIterator
(
key
);
while
(
cursor
.
hasNext
())
{
key
=
cursor
.
next
();
if
(
get
(
key
)
!=
null
)
{
return
key
;
}
}
return
null
;
// TODO transactional ceilingKey
// return map.ceilingKey(key);
}
/**
* Get the smallest key that is larger than the given key, or null if no
* such key exists.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
higherKey
(
K
key
)
{
// TODO transactional higherKey
return
map
.
higherKey
(
key
);
}
/**
* Get the largest key that is smaller than the given key, or null if no
* such key exists.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
lowerKey
(
K
key
)
{
// TODO Auto-generated method stub
return
map
.
lowerKey
(
key
);
}
/**
* Iterate over all keys.
*
...
...
@@ -985,41 +1066,6 @@ public class TransactionStore {
};
}
/**
* Get the smallest key that is larger or equal to this key.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
ceilingKey
(
K
key
)
{
// TODO transactional ceilingKey
return
map
.
ceilingKey
(
key
);
}
/**
* Get the smallest key that is larger than the given key, or null if no
* such key exists.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
higherKey
(
K
key
)
{
// TODO transactional higherKey
return
map
.
higherKey
(
key
);
}
/**
* Get the largest key that is smaller than the given key, or null if no
* such key exists.
*
* @param key the key (may not be null)
* @return the result
*/
public
K
lowerKey
(
K
key
)
{
// TODO Auto-generated method stub
return
map
.
lowerKey
(
key
);
}
public
Transaction
getTransaction
()
{
return
transaction
;
}
...
...
h2/src/main/org/h2/store/fs/FilePathMem.java
浏览文件 @
344f2633
...
...
@@ -183,7 +183,7 @@ public class FilePathMem extends FilePath {
}
private
boolean
isRoot
()
{
return
name
.
equals
(
getScheme
());
return
name
.
equals
(
getScheme
()
+
":"
);
}
private
static
String
getCanonicalPath
(
String
fileName
)
{
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
344f2633
...
...
@@ -6,6 +6,11 @@
*/
package
org
.
h2
.
test
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.ObjectInputStream
;
import
java.io.ObjectOutputStream
;
import
java.sql.SQLException
;
import
java.util.Properties
;
import
org.h2.Driver
;
...
...
@@ -493,7 +498,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
private
void
runTests
()
throws
SQLException
{
int
test
;
mvStore
=
fals
e
;
// mvStore = tru
e;
smallLog
=
big
=
networked
=
memory
=
ssl
=
false
;
diskResult
=
traceSystemOut
=
diskUndo
=
false
;
...
...
@@ -583,7 +588,9 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestDeadlock
().
runTest
(
this
);
new
TestEncryptedDb
().
runTest
(
this
);
new
TestExclusive
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestFullText
().
runTest
(
this
);
}
new
TestFunctionOverload
().
runTest
(
this
);
new
TestFunctions
().
runTest
(
this
);
new
TestInit
().
runTest
(
this
);
...
...
@@ -599,13 +606,17 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestMultiThreadedKernel
().
runTest
(
this
);
new
TestOpenClose
().
runTest
(
this
);
new
TestOptimizations
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestOutOfMemory
().
runTest
(
this
);
}
new
TestPowerOff
().
runTest
(
this
);
new
TestQueryCache
().
runTest
(
this
);
new
TestReadOnly
().
runTest
(
this
);
new
TestRecursiveQueries
().
runTest
(
this
);
new
TestRights
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestRunscript
().
runTest
(
this
);
}
new
TestSQLInjection
().
runTest
(
this
);
new
TestSessionsLocks
().
runTest
(
this
);
new
TestSelectCountNonNullColumn
().
runTest
(
this
);
...
...
@@ -614,9 +625,11 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestSpeed
().
runTest
(
this
);
new
TestTableEngines
().
runTest
(
this
);
new
TestTempTables
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestTransaction
().
runTest
(
this
);
new
TestTriggersConstraints
().
runTest
(
this
);
new
TestTwoPhaseCommit
().
runTest
(
this
);
}
new
TestView
().
runTest
(
this
);
new
TestViewAlterTable
().
runTest
(
this
);
new
TestViewDropView
().
runTest
(
this
);
...
...
@@ -652,7 +665,9 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestConnectionPool
().
runTest
(
this
);
new
TestDataSource
().
runTest
(
this
);
new
TestXA
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestXASimple
().
runTest
(
this
);
}
// server
new
TestAutoServer
().
runTest
(
this
);
...
...
@@ -663,8 +678,10 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestMvcc1
().
runTest
(
this
);
new
TestMvcc2
().
runTest
(
this
);
new
TestMvcc3
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestMvccMultiThreaded
().
runTest
(
this
);
new
TestRowLocks
().
runTest
(
this
);
}
// synth
new
TestBtreeIndex
().
runTest
(
this
);
...
...
@@ -700,7 +717,9 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
// unit
new
TestAutoReconnect
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestCache
().
runTest
(
this
);
}
new
TestClearReferences
().
runTest
(
this
);
new
TestCollation
().
runTest
(
this
);
new
TestCompress
().
runTest
(
this
);
...
...
@@ -717,7 +736,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestFileSystem
().
runTest
(
this
);
new
TestIntArray
().
runTest
(
this
);
new
TestIntIntHashMap
().
runTest
(
this
);
// verify
new
TestJmx
().
runTest
(
this
);
new
TestMathUtils
().
runTest
(
this
);
new
TestModifyOnWrite
().
runTest
(
this
);
...
...
@@ -726,12 +744,16 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestObjectDeserialization
().
runTest
(
this
);
new
TestMultiThreadedKernel
().
runTest
(
this
);
new
TestOverflow
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestPageStore
().
runTest
(
this
);
}
new
TestPageStoreCoverage
().
runTest
(
this
);
new
TestPattern
().
runTest
(
this
);
new
TestPgServer
().
runTest
(
this
);
new
TestReader
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestRecovery
().
runTest
(
this
);
}
new
TestSampleApps
().
runTest
(
this
);
new
TestScriptReader
().
runTest
(
this
);
runTest
(
"org.h2.test.unit.TestServlet"
);
...
...
@@ -741,7 +763,9 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestStreams
().
runTest
(
this
);
new
TestStringCache
().
runTest
(
this
);
new
TestStringUtils
().
runTest
(
this
);
if
(!
mvStore
)
{
new
TestTools
().
runTest
(
this
);
}
new
TestTraceSystem
().
runTest
(
this
);
new
TestUpgrade
().
runTest
(
this
);
new
TestUtils
().
runTest
(
this
);
...
...
@@ -750,6 +774,19 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestValueMemory
().
runTest
(
this
);
}
public
static
byte
[]
serialize
(
Object
obj
)
throws
IOException
{
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
ObjectOutputStream
os
=
new
ObjectOutputStream
(
out
);
os
.
writeObject
(
obj
);
return
out
.
toByteArray
();
}
public
static
Object
deserialize
(
byte
[]
data
)
throws
IOException
,
ClassNotFoundException
{
ByteArrayInputStream
in
=
new
ByteArrayInputStream
(
data
);
ObjectInputStream
is
=
new
ObjectInputStream
(
in
);
return
is
.
readObject
();
}
private
void
runTest
(
String
className
)
{
try
{
Class
<?>
clazz
=
Class
.
forName
(
className
);
...
...
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
344f2633
...
...
@@ -247,6 +247,10 @@ public abstract class TestBase {
protected
String
getURL
(
String
name
,
boolean
admin
)
{
String
url
;
if
(
name
.
startsWith
(
"jdbc:"
))
{
if
(
config
.
mvStore
)
{
name
=
addOption
(
name
,
"DEFAULT_TABLE_ENGINE"
,
"org.h2.mvstore.db.MVTableEngine"
);
}
return
name
;
}
if
(
config
.
memory
)
{
...
...
h2/src/test/org/h2/test/db/TestLob.java
浏览文件 @
344f2633
...
...
@@ -277,10 +277,14 @@ public class TestLob extends TestBase {
conn2
.
close
();
}
/**
* A background task.
*/
private
final
class
Deadlock2Task1
extends
Task
{
public
final
Connection
conn
;
private
Deadlock2Task1
()
throws
SQLException
{
Deadlock2Task1
()
throws
SQLException
{
this
.
conn
=
getDeadlock2Connection
();
}
...
...
@@ -294,7 +298,9 @@ public class TestLob extends TestBase {
ResultSet
rs
=
stat
.
executeQuery
(
"select name from test where id = "
+
random
.
nextInt
(
999
));
if
(
rs
.
next
())
{
Reader
r
=
rs
.
getClob
(
"name"
).
getCharacterStream
();
while
(
r
.
read
(
tmp
)
>
0
)
{}
while
(
r
.
read
(
tmp
)
>
0
)
{
// ignore
}
r
.
close
();
}
rs
.
close
();
...
...
@@ -315,12 +321,17 @@ public class TestLob extends TestBase {
}
}
}
}
/**
* A background task.
*/
private
final
class
Deadlock2Task2
extends
Task
{
public
final
Connection
conn
;
private
Deadlock2Task2
()
throws
SQLException
{
Deadlock2Task2
()
throws
SQLException
{
this
.
conn
=
getDeadlock2Connection
();
}
...
...
@@ -332,6 +343,7 @@ public class TestLob extends TestBase {
stat
.
execute
(
"update test set counter = "
+
random
.
nextInt
(
10
)
+
" where id = "
+
random
.
nextInt
(
1000
));
}
}
}
private
void
testDeadlock2
()
throws
Exception
{
...
...
@@ -370,7 +382,7 @@ public class TestLob extends TestBase {
conn
.
close
();
}
private
Connection
getDeadlock2Connection
()
throws
SQLException
{
Connection
getDeadlock2Connection
()
throws
SQLException
{
return
getConnection
(
"lob;MULTI_THREADED=TRUE;LOCK_TIMEOUT=60000"
);
}
...
...
@@ -473,15 +485,12 @@ public class TestLob extends TestBase {
Statement
stat
;
conn
=
getConnection
(
"lob"
);
stat
=
conn
.
createStatement
();
try
{
stat
.
execute
(
"create memory table test(x clob unique)"
);
stat
.
execute
(
"insert into test values('hello')"
);
stat
.
execute
(
"insert into test values('world')"
);
assertThrows
(
ErrorCode
.
DUPLICATE_KEY_1
,
stat
).
execute
(
"insert into test values('world')"
);
stat
.
execute
(
"insert into test values(space(10000) || 'a')"
);
assertThrows
(
ErrorCode
.
DUPLICATE_KEY_1
,
stat
).
execute
(
"insert into test values(space(10000) || 'a')"
);
stat
.
execute
(
"insert into test values(space(10000) || 'b')"
);
fail
();
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
e
.
getErrorCode
());
}
conn
.
close
();
}
...
...
h2/src/test/org/h2/test/store/TestMVTableEngine.java
浏览文件 @
344f2633
...
...
@@ -23,6 +23,7 @@ import org.h2.engine.Database;
import
org.h2.jdbc.JdbcConnection
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.tools.Restore
;
import
org.h2.util.Task
;
/**
...
...
@@ -42,6 +43,7 @@ public class TestMVTableEngine extends TestBase {
@Override
public
void
test
()
throws
Exception
{
// testSpeed();
testRollbackAfterCrash
();
testReferentialIntegrity
();
testWriteDelay
();
testAutoCommit
();
...
...
@@ -110,12 +112,90 @@ int test;
System
.
out
.
println
((
System
.
currentTimeMillis
()
-
time
)
+
" "
+
dbName
+
" after"
);
}
private
void
testRollbackAfterCrash
()
throws
Exception
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
Connection
conn
;
Statement
stat
;
String
url
=
"mvstore;default_table_engine=org.h2.mvstore.db.MVTableEngine"
;
String
url2
=
"mvstore2;default_table_engine=org.h2.mvstore.db.MVTableEngine"
;
conn
=
getConnection
(
url
);
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id int)"
);
stat
.
execute
(
"insert into test values(0)"
);
stat
.
execute
(
"set write_delay 0"
);
conn
.
setAutoCommit
(
false
);
stat
.
execute
(
"insert into test values(1)"
);
stat
.
execute
(
"shutdown immediately"
);
conn
=
getConnection
(
url
);
stat
=
conn
.
createStatement
();
ResultSet
rs
=
stat
.
executeQuery
(
"select row_count_estimate "
+
"from information_schema.tables where table_name='TEST'"
);
rs
.
next
();
assertEquals
(
1
,
rs
.
getLong
(
1
));
stat
.
execute
(
"drop table test"
);
stat
.
execute
(
"create table test(id int primary key, data clob)"
);
stat
.
execute
(
"insert into test values(1, space(10000))"
);
conn
.
setAutoCommit
(
false
);
stat
.
execute
(
"delete from test"
);
stat
.
execute
(
"checkpoint"
);
stat
.
execute
(
"shutdown immediately"
);
conn
=
getConnection
(
url
);
stat
=
conn
.
createStatement
();
rs
=
stat
.
executeQuery
(
"select * from test"
);
assertTrue
(
rs
.
next
());
stat
.
execute
(
"drop all objects delete files"
);
conn
.
close
();
conn
=
getConnection
(
url
);
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id int primary key, name varchar)"
);
stat
.
execute
(
"create index idx_name on test(name, id)"
);
stat
.
execute
(
"insert into test select x, x || space(200 * x) from system_range(1, 10)"
);
conn
.
setAutoCommit
(
false
);
stat
.
execute
(
"delete from test where id > 5"
);
stat
.
execute
(
"backup to '"
+
getBaseDir
()
+
"/backup.zip'"
);
conn
.
rollback
();
Restore
.
execute
(
getBaseDir
()
+
"/backup.zip"
,
getBaseDir
(),
"mvstore2"
);
Connection
conn2
;
conn2
=
getConnection
(
url2
);
conn
.
close
();
conn2
.
close
();
}
private
void
testReferentialIntegrity
()
throws
Exception
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
Connection
conn
;
Statement
stat
;
conn
=
getConnection
(
"mvstore;default_table_engine=org.h2.mvstore.db.MVTableEngine"
);
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id int, parent int "
+
"references test(id) on delete cascade)"
);
stat
.
execute
(
"insert into test values(0, 0)"
);
stat
.
execute
(
"delete from test"
);
stat
.
execute
(
"drop table test"
);
stat
.
execute
(
"create table parent(id int, name varchar)"
);
stat
.
execute
(
"create table child(id int, parentid int, "
+
"foreign key(parentid) references parent(id))"
);
stat
.
execute
(
"insert into parent values(1, 'mary'), (2, 'john')"
);
stat
.
execute
(
"insert into child values(10, 1), (11, 1), (20, 2), (21, 2)"
);
stat
.
execute
(
"update parent set name = 'marc' where id = 1"
);
stat
.
execute
(
"merge into parent key(id) values(1, 'marcy')"
);
stat
.
execute
(
"drop table parent, child"
);
stat
.
execute
(
"create table test(id identity, parent bigint, "
+
"foreign key(parent) references(id))"
);
stat
.
execute
(
"insert into test values(0, 0), (1, NULL), "
+
"(2, 1), (3, 3), (4, 3)"
);
stat
.
execute
(
"drop table test"
);
stat
.
execute
(
"create table parent(id int)"
);
stat
.
execute
(
"create table child(pid int)"
);
...
...
@@ -126,7 +206,7 @@ int test;
"foreign key(pid) references parent(id)"
);
fail
();
}
catch
(
SQLException
e
)
{
// expected
assertEquals
(
ErrorCode
.
REFERENTIAL_INTEGRITY_VIOLATED_PARENT_MISSING_1
,
e
.
getErrorCode
());
}
stat
.
execute
(
"update child set pid=1"
);
stat
.
execute
(
"drop table child, parent"
);
...
...
@@ -140,16 +220,15 @@ int test;
"foreign key(pid) references parent(id)"
);
fail
();
}
catch
(
SQLException
e
)
{
// expected
assertEquals
(
ErrorCode
.
REFERENTIAL_INTEGRITY_VIOLATED_PARENT_MISSING_1
,
e
.
getErrorCode
());
}
stat
.
execute
(
"drop table child, parent"
);
// currently not supported, as previous rows are not visible
// stat.execute("create table test(id identity, parent bigint,
// foreign key(parent) references(id))");
// stat.execute("insert into test values(0, 0), (1, NULL),
// (2, 1), (3, 3), (4, 3)");
// stat.execute("drop table test");
stat
.
execute
(
"create table test(id identity, parent bigint, "
+
"foreign key(parent) references(id))"
);
stat
.
execute
(
"insert into test values(0, 0), (1, NULL), "
+
"(2, 1), (3, 3), (4, 3)"
);
stat
.
execute
(
"drop table test"
);
stat
.
execute
(
"create table parent(id int, x int)"
);
stat
.
execute
(
"insert into parent values(1, 2)"
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论