Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
27293b7c
提交
27293b7c
authored
7 年前
作者:
Noel Grandin
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
https://github.com/h2database/h2database
上级
e26337e9
6888e92a
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
212 行增加
和
143 行删除
+212
-143
AlterTableAddConstraint.java
h2/src/main/org/h2/command/ddl/AlterTableAddConstraint.java
+16
-15
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+8
-0
MVPrimaryIndex.java
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
+7
-12
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+4
-1
CreateCluster.java
h2/src/main/org/h2/tools/CreateCluster.java
+86
-103
TestCases.java
h2/src/test/org/h2/test/db/TestCases.java
+0
-12
TestConnection.java
h2/src/test/org/h2/test/jdbc/TestConnection.java
+26
-0
TestScript.java
h2/src/test/org/h2/test/scripts/TestScript.java
+2
-0
altertable-index-reuse.sql
h2/src/test/org/h2/test/scripts/altertable-index-reuse.sql
+33
-0
TestMVTableEngine.java
h2/src/test/org/h2/test/store/TestMVTableEngine.java
+30
-0
没有找到文件。
h2/src/main/org/h2/command/ddl/AlterTableAddConstraint.java
浏览文件 @
27293b7c
...
@@ -212,7 +212,7 @@ public class AlterTableAddConstraint extends SchemaCommand {
...
@@ -212,7 +212,7 @@ public class AlterTableAddConstraint extends SchemaCommand {
isOwner
=
true
;
isOwner
=
true
;
index
.
getIndexType
().
setBelongsToConstraint
(
true
);
index
.
getIndexType
().
setBelongsToConstraint
(
true
);
}
else
{
}
else
{
index
=
getIndex
(
table
,
indexColumns
,
tru
e
);
index
=
getIndex
(
table
,
indexColumns
,
fals
e
);
if
(
index
==
null
)
{
if
(
index
==
null
)
{
index
=
createIndex
(
table
,
indexColumns
,
false
);
index
=
createIndex
(
table
,
indexColumns
,
false
);
isOwner
=
true
;
isOwner
=
true
;
...
@@ -329,29 +329,30 @@ public class AlterTableAddConstraint extends SchemaCommand {
...
@@ -329,29 +329,30 @@ public class AlterTableAddConstraint extends SchemaCommand {
}
}
return
null
;
return
null
;
}
}
// all cols must be in the index key, the order doesn't matter and there must be no other fields in the index key
private
static
boolean
canUseUniqueIndex
(
Index
idx
,
Table
table
,
private
static
boolean
canUseUniqueIndex
(
Index
idx
,
Table
table
,
IndexColumn
[]
cols
)
{
IndexColumn
[]
cols
)
{
if
(
idx
.
getTable
()
!=
table
||
!
idx
.
getIndexType
().
isUnique
())
{
if
(
idx
.
getTable
()
!=
table
||
!
idx
.
getIndexType
().
isUnique
())
{
return
false
;
return
false
;
}
}
Column
[]
indexCols
=
idx
.
getColumns
();
Column
[]
indexCols
=
idx
.
getColumns
();
if
(
indexCols
.
length
>
cols
.
length
)
{
return
false
;
HashSet
<
Column
>
indexColsSet
=
New
.
hashSet
();
for
(
Column
c
:
indexCols
)
{
indexColsSet
.
add
(
c
);
}
}
HashSet
<
Column
>
set
=
New
.
hashSet
();
HashSet
<
Column
>
colsSet
=
New
.
hashSet
();
for
(
IndexColumn
c
:
cols
)
{
for
(
IndexColumn
c
:
cols
)
{
s
et
.
add
(
c
.
column
);
colsS
et
.
add
(
c
.
column
);
}
}
for
(
Column
c
:
indexCols
)
{
// all columns of the index must be part of the list,
return
colsSet
.
equals
(
indexColsSet
);
// but not all columns of the list need to be part of the index
}
if
(!
set
.
contains
(
c
))
{
return
false
;
}
}
return
true
;
}
private
static
boolean
canUseIndex
(
Index
existingIndex
,
Table
table
,
private
static
boolean
canUseIndex
(
Index
existingIndex
,
Table
table
,
IndexColumn
[]
cols
,
boolean
moreColumnsOk
)
{
IndexColumn
[]
cols
,
boolean
moreColumnsOk
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
27293b7c
...
@@ -30,9 +30,11 @@ import java.util.ArrayList;
...
@@ -30,9 +30,11 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Properties
;
import
java.util.Properties
;
import
java.util.concurrent.Executor
;
import
java.util.concurrent.Executor
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.CommandInterface
;
import
org.h2.engine.ConnectionInfo
;
import
org.h2.engine.ConnectionInfo
;
...
@@ -1737,6 +1739,12 @@ public class JdbcConnection extends TraceObject
...
@@ -1737,6 +1739,12 @@ public class JdbcConnection extends TraceObject
+
");"
);
+
");"
);
}
}
checkClosed
();
checkClosed
();
// no change to property: Ignore call. This early exit fixes a problem with websphere liberty
// resetting the client info of a pooled connection to its initial values.
if
(
Objects
.
equals
(
value
,
getClientInfo
(
name
)))
{
return
;
}
if
(
isInternalProperty
(
name
))
{
if
(
isInternalProperty
(
name
))
{
throw
new
SQLClientInfoException
(
throw
new
SQLClientInfoException
(
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
浏览文件 @
27293b7c
...
@@ -197,7 +197,7 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -197,7 +197,7 @@ public class MVPrimaryIndex extends BaseIndex {
}
}
}
}
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
return
new
MVStoreCursor
(
session
,
map
.
entryIterator
(
min
),
max
);
return
new
MVStoreCursor
(
session
,
map
.
entryIterator
(
min
,
max
)
);
}
}
@Override
@Override
...
@@ -270,13 +270,13 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -270,13 +270,13 @@ public class MVPrimaryIndex extends BaseIndex {
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
ValueLong
v
=
(
ValueLong
)
(
first
?
map
.
firstKey
()
:
map
.
lastKey
());
ValueLong
v
=
(
ValueLong
)
(
first
?
map
.
firstKey
()
:
map
.
lastKey
());
if
(
v
==
null
)
{
if
(
v
==
null
)
{
return
new
MVStoreCursor
(
session
,
Collections
return
new
MVStoreCursor
(
session
,
.<
Entry
<
Value
,
Value
>>
emptyList
().
iterator
(),
null
);
Collections
.<
Entry
<
Value
,
Value
>>
emptyList
().
iterator
()
);
}
}
Value
value
=
map
.
get
(
v
);
Value
value
=
map
.
get
(
v
);
Entry
<
Value
,
Value
>
e
=
new
DataUtils
.
MapEntry
<
Value
,
Value
>(
v
,
value
);
Entry
<
Value
,
Value
>
e
=
new
DataUtils
.
MapEntry
<
Value
,
Value
>(
v
,
value
);
List
<
Entry
<
Value
,
Value
>>
list
=
Arrays
.
as
List
(
e
);
List
<
Entry
<
Value
,
Value
>>
list
=
Collections
.
singleton
List
(
e
);
MVStoreCursor
c
=
new
MVStoreCursor
(
session
,
list
.
iterator
()
,
v
);
MVStoreCursor
c
=
new
MVStoreCursor
(
session
,
list
.
iterator
());
c
.
next
();
c
.
next
();
return
c
;
return
c
;
}
}
...
@@ -356,7 +356,7 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -356,7 +356,7 @@ public class MVPrimaryIndex extends BaseIndex {
*/
*/
Cursor
find
(
Session
session
,
ValueLong
first
,
ValueLong
last
)
{
Cursor
find
(
Session
session
,
ValueLong
first
,
ValueLong
last
)
{
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
return
new
MVStoreCursor
(
session
,
map
.
entryIterator
(
first
),
last
);
return
new
MVStoreCursor
(
session
,
map
.
entryIterator
(
first
,
last
)
);
}
}
@Override
@Override
...
@@ -385,14 +385,12 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -385,14 +385,12 @@ public class MVPrimaryIndex extends BaseIndex {
private
final
Session
session
;
private
final
Session
session
;
private
final
Iterator
<
Entry
<
Value
,
Value
>>
it
;
private
final
Iterator
<
Entry
<
Value
,
Value
>>
it
;
private
final
ValueLong
last
;
private
Entry
<
Value
,
Value
>
current
;
private
Entry
<
Value
,
Value
>
current
;
private
Row
row
;
private
Row
row
;
public
MVStoreCursor
(
Session
session
,
Iterator
<
Entry
<
Value
,
Value
>>
it
,
ValueLong
last
)
{
public
MVStoreCursor
(
Session
session
,
Iterator
<
Entry
<
Value
,
Value
>>
it
)
{
this
.
session
=
session
;
this
.
session
=
session
;
this
.
it
=
it
;
this
.
it
=
it
;
this
.
last
=
last
;
}
}
@Override
@Override
...
@@ -415,9 +413,6 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -415,9 +413,6 @@ public class MVPrimaryIndex extends BaseIndex {
@Override
@Override
public
boolean
next
()
{
public
boolean
next
()
{
current
=
it
.
hasNext
()
?
it
.
next
()
:
null
;
current
=
it
.
hasNext
()
?
it
.
next
()
:
null
;
if
(
current
!=
null
&&
current
.
getKey
().
getLong
()
>
last
.
getLong
())
{
current
=
null
;
}
row
=
null
;
row
=
null
;
return
current
!=
null
;
return
current
!=
null
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
27293b7c
...
@@ -1470,7 +1470,7 @@ public class TransactionStore {
...
@@ -1470,7 +1470,7 @@ public class TransactionStore {
* @param from the first key to return
* @param from the first key to return
* @return the iterator
* @return the iterator
*/
*/
public
Iterator
<
Entry
<
K
,
V
>>
entryIterator
(
final
K
from
)
{
public
Iterator
<
Entry
<
K
,
V
>>
entryIterator
(
final
K
from
,
final
K
to
)
{
return
new
Iterator
<
Entry
<
K
,
V
>>()
{
return
new
Iterator
<
Entry
<
K
,
V
>>()
{
private
Entry
<
K
,
V
>
current
;
private
Entry
<
K
,
V
>
current
;
private
K
currentKey
=
from
;
private
K
currentKey
=
from
;
...
@@ -1507,6 +1507,9 @@ public class TransactionStore {
...
@@ -1507,6 +1507,9 @@ public class TransactionStore {
}
}
}
}
final
K
key
=
k
;
final
K
key
=
k
;
if
(
to
!=
null
&&
map
.
getKeyType
().
compare
(
k
,
to
)
>
0
)
{
break
;
}
VersionedValue
data
=
cursor
.
getValue
();
VersionedValue
data
=
cursor
.
getValue
();
data
=
getValue
(
key
,
readLogId
,
data
);
data
=
getValue
(
key
,
readLogId
,
data
);
if
(
data
!=
null
&&
data
.
value
!=
null
)
{
if
(
data
!=
null
&&
data
.
value
!=
null
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/tools/CreateCluster.java
浏览文件 @
27293b7c
...
@@ -13,14 +13,15 @@ import java.sql.DriverManager;
...
@@ -13,14 +13,15 @@ import java.sql.DriverManager;
import
java.sql.ResultSet
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
org.h2.api.ErrorCode
;
import
java.util.concurrent.ExecutionException
;
import
org.h2.engine.Constants
;
import
java.util.concurrent.ExecutorService
;
import
org.h2.util.IOUtils
;
import
java.util.concurrent.Executors
;
import
org.h2.util.JdbcUtils
;
import
java.util.concurrent.Future
;
import
org.h2.util.Tool
;
import
org.h2.util.Tool
;
/**
/**
* Creates a cluster from a standalone database.
* Creates a cluster from a stand
-
alone database.
* <br />
* <br />
* Copies a database to another location if required.
* Copies a database to another location if required.
* @h2.resource
* @h2.resource
...
@@ -100,116 +101,98 @@ public class CreateCluster extends Tool {
...
@@ -100,116 +101,98 @@ public class CreateCluster extends Tool {
private
static
void
process
(
String
urlSource
,
String
urlTarget
,
private
static
void
process
(
String
urlSource
,
String
urlTarget
,
String
user
,
String
password
,
String
serverList
)
throws
SQLException
{
String
user
,
String
password
,
String
serverList
)
throws
SQLException
{
Connection
connSource
=
null
,
connTarget
=
null
;
org
.
h2
.
Driver
.
load
();
Statement
statSource
=
null
,
statTarget
=
null
;
PipedReader
pipeReader
=
null
;
try
(
Connection
connSource
=
DriverManager
.
getConnection
(
// use cluster='' so connecting is possible
try
{
// even if the cluster is enabled
org
.
h2
.
Driver
.
load
();
urlSource
+
";CLUSTER=''"
,
user
,
password
);
Statement
statSource
=
connSource
.
createStatement
())
// verify that the database doesn't exist,
{
// or if it exists (an old cluster instance), it is deleted
boolean
exists
=
true
;
try
{
connTarget
=
DriverManager
.
getConnection
(
urlTarget
+
";IFEXISTS=TRUE;CLUSTER="
+
Constants
.
CLUSTERING_ENABLED
,
user
,
password
);
Statement
stat
=
connTarget
.
createStatement
();
stat
.
execute
(
"DROP ALL OBJECTS DELETE FILES"
);
stat
.
close
();
exists
=
false
;
connTarget
.
close
();
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
DATABASE_NOT_FOUND_1
)
{
// database does not exists yet - ok
exists
=
false
;
}
else
{
throw
e
;
}
}
if
(
exists
)
{
throw
new
SQLException
(
"Target database must not yet exist. Please delete it first: "
+
urlTarget
);
}
// use cluster='' so connecting is possible
// even if the cluster is enabled
connSource
=
DriverManager
.
getConnection
(
urlSource
+
";CLUSTER=''"
,
user
,
password
);
statSource
=
connSource
.
createStatement
();
// enable the exclusive mode and close other connections,
// enable the exclusive mode and close other connections,
// so that data can't change while restoring the second database
// so that data can't change while restoring the second database
statSource
.
execute
(
"SET EXCLUSIVE 2"
);
statSource
.
execute
(
"SET EXCLUSIVE 2"
);
pipeReader
=
new
PipedReader
();
try
{
try
{
/*
performTransfer
(
statSource
,
urlTarget
,
user
,
password
,
serverList
);
* Pipe writer is used + closed in the inner class, in a
}
finally
{
* separate thread (needs to be final). It should be initialized
// switch back to the regular mode
* within try{} so an exception could be caught if creation
statSource
.
execute
(
"SET EXCLUSIVE FALSE"
);
* fails. In that scenario, the the writer should be null and
}
* needs no closing, and the main goal is that finally{} should
}
* bring the source DB out of exclusive mode, and close the
}
* reader.
*/
final
PipedWriter
pipeWriter
=
new
PipedWriter
(
pipeReader
);
// Backup data from source database in script form.
// Start writing to pipe writer in separate thread.
final
ResultSet
rs
=
statSource
.
executeQuery
(
"SCRIPT"
);
// Delete the target database first.
connTarget
=
DriverManager
.
getConnection
(
urlTarget
+
";CLUSTER=''"
,
user
,
password
);
statTarget
=
connTarget
.
createStatement
();
statTarget
.
execute
(
"DROP ALL OBJECTS DELETE FILES"
);
connTarget
.
close
();
new
Thread
(
new
Runnable
(){
@Override
public
void
run
()
{
try
{
while
(
rs
.
next
())
{
pipeWriter
.
write
(
rs
.
getString
(
1
)
+
"\n"
);
}
}
catch
(
SQLException
ex
)
{
throw
new
IllegalStateException
(
"Producing script from the source DB is failing."
,
ex
);
}
catch
(
IOException
ex
)
{
throw
new
IllegalStateException
(
"Producing script from the source DB is failing."
,
ex
);
}
finally
{
IOUtils
.
closeSilently
(
pipeWriter
);
}
}
}
).
start
();
// Read data from pipe reader, restore on target.
private
static
void
performTransfer
(
Statement
statSource
,
String
urlTarget
,
connTarget
=
DriverManager
.
getConnection
(
urlTarget
,
user
,
password
);
String
user
,
String
password
,
String
serverList
)
throws
SQLException
{
RunScript
.
execute
(
connTarget
,
pipeReader
);
statTarget
=
connTarget
.
createStatement
();
// Delete the target database first.
try
(
Connection
connTarget
=
DriverManager
.
getConnection
(
urlTarget
+
";CLUSTER=''"
,
user
,
password
);
Statement
statTarget
=
connTarget
.
createStatement
())
{
statTarget
.
execute
(
"DROP ALL OBJECTS DELETE FILES"
);
}
try
(
PipedReader
pipeReader
=
new
PipedReader
())
{
Future
<?>
threadFuture
=
startWriter
(
pipeReader
,
statSource
);
// Read data from pipe reader, restore on target.
try
(
Connection
connTarget
=
DriverManager
.
getConnection
(
urlTarget
,
user
,
password
);
Statement
statTarget
=
connTarget
.
createStatement
())
{
RunScript
.
execute
(
connTarget
,
pipeReader
);
// Check if the writer encountered any exception
try
{
threadFuture
.
get
();
}
catch
(
ExecutionException
ex
)
{
throw
new
SQLException
(
ex
.
getCause
());
}
catch
(
InterruptedException
ex
)
{
throw
new
SQLException
(
ex
);
}
// set the cluster to the serverList on both databases
// set the cluster to the serverList on both databases
statSource
.
executeUpdate
(
"SET CLUSTER '"
+
serverList
+
"'"
);
statSource
.
executeUpdate
(
"SET CLUSTER '"
+
serverList
+
"'"
);
statTarget
.
executeUpdate
(
"SET CLUSTER '"
+
serverList
+
"'"
);
statTarget
.
executeUpdate
(
"SET CLUSTER '"
+
serverList
+
"'"
);
}
catch
(
IOException
ex
)
{
throw
new
SQLException
(
ex
);
}
finally
{
// switch back to the regular mode
statSource
.
execute
(
"SET EXCLUSIVE FALSE"
);
}
}
}
finally
{
}
catch
(
IOException
ex
)
{
IOUtils
.
closeSilently
(
pipeReader
);
throw
new
SQLException
(
ex
);
JdbcUtils
.
closeSilently
(
statSource
);
JdbcUtils
.
closeSilently
(
statTarget
);
JdbcUtils
.
closeSilently
(
connSource
);
JdbcUtils
.
closeSilently
(
connTarget
);
}
}
}
}
private
static
Future
<?>
startWriter
(
final
PipedReader
pipeReader
,
final
Statement
statSource
)
throws
SQLException
,
IOException
{
final
ExecutorService
thread
=
Executors
.
newFixedThreadPool
(
1
);
// Since exceptions cannot be thrown across thread boundaries, return
// the task's future so we can check manually
Future
<?>
threadFuture
=
thread
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
/*
* If the creation of the piped writer fails, the reader will
* throw an IOException as soon as read() is called:
* IOException - if the pipe is broken, unconnected, closed,
* or an I/O error occurs.
* The reader's IOException will then trigger the finally{} that
* releases exclusive mode on the source DB.
*/
try
(
final
PipedWriter
pipeWriter
=
new
PipedWriter
(
pipeReader
);
final
ResultSet
rs
=
statSource
.
executeQuery
(
"SCRIPT"
))
{
while
(
rs
.
next
())
{
pipeWriter
.
write
(
rs
.
getString
(
1
)
+
"\n"
);
}
}
catch
(
SQLException
|
IOException
ex
)
{
throw
new
IllegalStateException
(
"Producing script from the source DB is failing."
,
ex
);
}
}
});
thread
.
shutdown
();
return
threadFuture
;
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestCases.java
浏览文件 @
27293b7c
...
@@ -150,18 +150,6 @@ public class TestCases extends TestBase {
...
@@ -150,18 +150,6 @@ public class TestCases extends TestBase {
"foreign key(a_id) references a(id)"
);
"foreign key(a_id) references a(id)"
);
stat
.
execute
(
"update a set x=200"
);
stat
.
execute
(
"update a set x=200"
);
stat
.
execute
(
"drop table if exists a, b"
);
stat
.
execute
(
"drop table if exists a, b"
);
stat
.
execute
(
"drop all objects"
);
stat
.
execute
(
"create table parent(id int primary key)"
);
stat
.
execute
(
"create table child(id int, parent_id int, x int)"
);
stat
.
execute
(
"create index y on child(parent_id, x)"
);
stat
.
execute
(
"alter table child add constraint z "
+
"foreign key(parent_id) references parent(id)"
);
ResultSet
rs
=
stat
.
executeQuery
(
"select * from information_schema.indexes where table_name = 'CHILD'"
);
while
(
rs
.
next
())
{
assertEquals
(
"Y"
,
rs
.
getString
(
"index_name"
));
}
conn
.
close
();
conn
.
close
();
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/jdbc/TestConnection.java
浏览文件 @
27293b7c
...
@@ -13,6 +13,8 @@ import java.sql.SQLException;
...
@@ -13,6 +13,8 @@ import java.sql.SQLException;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
java.util.Properties
;
import
java.util.Properties
;
/**
/**
* Tests the client info
* Tests the client info
*/
*/
...
@@ -35,6 +37,7 @@ public class TestConnection extends TestBase {
...
@@ -35,6 +37,7 @@ public class TestConnection extends TestBase {
testSetSupportedClientInfoProperties
();
testSetSupportedClientInfoProperties
();
testSetUnsupportedClientInfoProperties
();
testSetUnsupportedClientInfoProperties
();
testSetInternalProperty
();
testSetInternalProperty
();
testSetInternalPropertyToInitialValue
();
testSetGetSchema
();
testSetGetSchema
();
}
}
...
@@ -47,6 +50,29 @@ public class TestConnection extends TestBase {
...
@@ -47,6 +50,29 @@ public class TestConnection extends TestBase {
assertThrows
(
SQLClientInfoException
.
class
,
conn
).
setClientInfo
(
"server23"
,
"SomeValue"
);
assertThrows
(
SQLClientInfoException
.
class
,
conn
).
setClientInfo
(
"server23"
,
"SomeValue"
);
conn
.
close
();
conn
.
close
();
}
}
/**
* Test that no exception is thrown if the client info of a connection managed in a connection pool is reset
* to its initial values.
*
* This is needed when using h2 in websphere liberty.
*/
private
void
testSetInternalPropertyToInitialValue
()
throws
SQLException
{
// Use MySQL-mode since this allows all property names
// (apart from h2 internal names).
Connection
conn
=
getConnection
(
"clientInfoMySQL;MODE=MySQL"
);
String
numServersPropertyName
=
"numServers"
;
String
numServers
=
conn
.
getClientInfo
(
numServersPropertyName
);
conn
.
setClientInfo
(
numServersPropertyName
,
numServers
);
assertEquals
(
conn
.
getClientInfo
(
numServersPropertyName
),
numServers
);
conn
.
close
();
}
private
void
testSetUnsupportedClientInfoProperties
()
throws
SQLException
{
private
void
testSetUnsupportedClientInfoProperties
()
throws
SQLException
{
Connection
conn
=
getConnection
(
"clientInfo"
);
Connection
conn
=
getConnection
(
"clientInfo"
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
27293b7c
...
@@ -77,7 +77,9 @@ public class TestScript extends TestBase {
...
@@ -77,7 +77,9 @@ public class TestScript extends TestBase {
return
;
return
;
}
}
reconnectOften
=
!
config
.
memory
&&
config
.
big
;
reconnectOften
=
!
config
.
memory
&&
config
.
big
;
testScript
(
"testScript.sql"
);
testScript
(
"testScript.sql"
);
testScript
(
"altertable-index-reuse.sql"
);
testScript
(
"query-optimisations.sql"
);
testScript
(
"query-optimisations.sql"
);
testScript
(
"commands-dml-script.sql"
);
testScript
(
"commands-dml-script.sql"
);
testScript
(
"commands-dml-create-view.sql"
);
testScript
(
"commands-dml-create-view.sql"
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/altertable-index-reuse.sql
0 → 100644
浏览文件 @
27293b7c
-- Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE
TABLE
"domains"
(
"id"
bigint
NOT
NULL
auto_increment
PRIMARY
KEY
);
>
ok
CREATE
TABLE
"users"
(
"id"
bigint
NOT
NULL
auto_increment
PRIMARY
KEY
,
"username"
varchar_ignorecase
(
255
),
"domain"
bigint
,
"desc"
varchar_ignorecase
(
255
));
>
ok
-- adds constraint on (domain,username) and generates unique index domainusername_key_INDEX_xxx
ALTER
TABLE
"users"
ADD
CONSTRAINT
"domainusername_key"
UNIQUE
(
"domain"
,
"username"
);
>
ok
-- adds foreign key on domain - if domainusername_key didn't exist it would create unique index on domain, but it reuses the existing index
ALTER
TABLE
"users"
ADD
CONSTRAINT
"udomain_fkey"
FOREIGN
KEY
(
"domain"
)
REFERENCES
"domains"
(
"id"
)
ON
DELETE
RESTRICT
;
>
ok
-- now we drop the domainusername_key, but domainusername_key_INDEX_xxx is used by udomain_fkey and was not being dropped
-- this was an issue, because it's a unique index and still enforcing constraint on (domain,username)
ALTER
TABLE
"users"
DROP
CONSTRAINT
"domainusername_key"
;
>
ok
insert
into
"domains"
(
"id"
)
VALUES
(
1
);
>
update
count
:
1
insert
into
"users"
(
"username"
,
"domain"
,
"desc"
)
VALUES
(
'test'
,
1
,
'first user'
);
>
update
count
:
1
-- should work,because we dropped domainusername_key, but failed: Unique index or primary key violation
INSERT
INTO
"users"
(
"username"
,
"domain"
,
"desc"
)
VALUES
(
'test'
,
1
,
'second user'
);
>
update
count
:
1
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVTableEngine.java
浏览文件 @
27293b7c
...
@@ -18,6 +18,7 @@ import java.sql.ResultSet;
...
@@ -18,6 +18,7 @@ import java.sql.ResultSet;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Savepoint
;
import
java.sql.Savepoint
;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
...
@@ -85,6 +86,7 @@ public class TestMVTableEngine extends TestBase {
...
@@ -85,6 +86,7 @@ public class TestMVTableEngine extends TestBase {
testDataTypes
();
testDataTypes
();
testLocking
();
testLocking
();
testSimple
();
testSimple
();
testReverseDeletePerformance
();
}
}
private
void
testLobCopy
()
throws
Exception
{
private
void
testLobCopy
()
throws
Exception
{
...
@@ -1478,4 +1480,32 @@ public class TestMVTableEngine extends TestBase {
...
@@ -1478,4 +1480,32 @@ public class TestMVTableEngine extends TestBase {
conn
.
close
();
conn
.
close
();
}
}
private
void
testReverseDeletePerformance
()
throws
Exception
{
long
direct
=
0
;
long
reverse
=
0
;
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
reverse
+=
testReverseDeletePerformance
(
true
);
direct
+=
testReverseDeletePerformance
(
false
);
}
assertTrue
(
"direct: "
+
direct
+
", reverse: "
+
reverse
,
2
*
Math
.
abs
(
reverse
-
direct
)
<
reverse
+
direct
);
}
private
long
testReverseDeletePerformance
(
boolean
reverse
)
throws
Exception
{
deleteDb
(
getTestName
());
String
dbName
=
getTestName
()
+
";MV_STORE=TRUE"
;
try
(
Connection
conn
=
getConnection
(
dbName
))
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR) AS SELECT x, x || space(1024) || x FROM system_range(1, 1000)"
);
conn
.
setAutoCommit
(
false
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
"DELETE FROM test WHERE id = ?"
);
long
start
=
System
.
nanoTime
();
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
prep
.
setInt
(
1
,
reverse
?
1000
-
i
:
i
);
prep
.
execute
();
}
long
end
=
System
.
nanoTime
();
conn
.
commit
();
return
TimeUnit
.
NANOSECONDS
.
toMillis
(
end
-
start
);
}
}
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论