Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
181401fb
提交
181401fb
authored
15 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
New LOB storage.
上级
dd4594d2
master
noel-pr1
plus33-master
pr/267
stumc-Issue#576
version-1.4.198
version-1.4.197
version-1.4.196
version-1.4.195
version-1.4.194
version-1.4.193
version-1.4.192
version-1.4.191
version-1.4.190
version-1.4.188
version-1.4.187
version-1.4.186
version-1.4.185
version-1.4.184
version-1.4.183
version-1.4.182
version-1.4.181
version-1.4.178
version-1.4.177
version-1.3
version-1.2
version-1.1
version-1.0
无相关合并请求
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
157 行增加
和
91 行删除
+157
-91
LobStorage.java
h2/src/main/org/h2/store/LobStorage.java
+146
-87
Recover.java
h2/src/main/org/h2/tools/Recover.java
+2
-0
Build.java
h2/src/tools/org/h2/build/Build.java
+9
-4
没有找到文件。
h2/src/main/org/h2/store/LobStorage.java
浏览文件 @
181401fb
...
...
@@ -18,11 +18,15 @@ import java.util.Arrays;
import
java.util.HashMap
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.SysProperties
;
import
org.h2.engine.Constants
;
import
org.h2.message.DbException
;
import
org.h2.util.IOUtils
;
import
org.h2.util.New
;
import
org.h2.value.ValueLob
;
/**
* This class stores LOB objects in the database.
*/
public
class
LobStorage
{
/**
...
...
@@ -30,8 +34,6 @@ public class LobStorage {
*/
public
static
final
int
TABLE_ID_SESSION_VARIABLE
=
-
1
;
// TODO test recovery
private
static
final
String
LOBS
=
"INFORMATION_SCHEMA.LOBS"
;
private
static
final
String
LOB_MAP
=
"INFORMATION_SCHEMA.LOB_MAP"
;
private
static
final
String
LOB_DATA
=
"INFORMATION_SCHEMA.LOB_DATA"
;
...
...
@@ -44,6 +46,37 @@ public class LobStorage {
private
long
nextLob
;
private
long
nextBlock
;
public
LobStorage
(
Connection
newConn
)
{
try
{
this
.
conn
=
newConn
;
Statement
stat
=
conn
.
createStatement
();
// stat.execute("SET UNDO_LOG 0");
// stat.execute("SET REDO_LOG_BINARY 0");
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOBS
+
"(ID BIGINT PRIMARY KEY, LENGTH BIGINT, TABLE INT)"
);
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOB_MAP
+
"(LOB BIGINT, SEQ INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ))"
);
stat
.
execute
(
"CREATE INDEX INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON "
+
LOB_MAP
+
"(BLOCK, LOB)"
);
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOB_DATA
+
"(BLOCK BIGINT PRIMARY KEY, DATA BINARY)"
);
ResultSet
rs
;
rs
=
stat
.
executeQuery
(
"SELECT MAX(BLOCK) FROM "
+
LOB_DATA
);
rs
.
next
();
nextBlock
=
rs
.
getLong
(
1
)
+
1
;
if
(
HASH
)
{
nextBlock
=
Math
.
max
(
UNIQUE
+
1
,
nextLob
);
}
rs
=
stat
.
executeQuery
(
"SELECT MAX(ID) FROM "
+
LOBS
);
rs
.
next
();
nextLob
=
rs
.
getLong
(
1
)
+
1
;
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
}
}
/**
* Remove all LOBs for this table.
*
* @param handler the data handler
* @param tableId the table id
*/
public
static
void
removeAllForTable
(
DataHandler
handler
,
int
tableId
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
// remove both lobs in the database as well as in the file system
...
...
@@ -51,6 +84,13 @@ public class LobStorage {
ValueLob
.
removeAllForTable
(
handler
,
tableId
);
}
/**
* Create a LOB object that fits in memory.
*
* @param type the value type
* @param small the byte array
* @return the LOB
*/
public
static
ValueLob
createSmallLob
(
int
type
,
byte
[]
small
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
return
null
;
...
...
@@ -58,18 +98,35 @@ public class LobStorage {
return
ValueLob
.
createSmallLob
(
type
,
small
);
}
public
static
ValueLob
createBlob
(
InputStream
in
,
long
length
,
DataHandler
handler
)
{
/**
* Create a BLOB object.
*
* @param in the input stream
* @param maxLength the maximum length (-1 if not known)
* @param handler the data handler
* @return the LOB
*/
public
static
ValueLob
createBlob
(
InputStream
in
,
long
maxLength
,
DataHandler
handler
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
return
null
;
handler
.
getLobStorage
().
addLob
(
in
,
maxLength
,
LobStorage
.
TABLE_ID_SESSION_VARIABLE
)
;
}
return
ValueLob
.
createBlob
(
in
,
l
ength
,
handler
);
return
ValueLob
.
createBlob
(
in
,
maxL
ength
,
handler
);
}
public
static
ValueLob
createClob
(
Reader
in
,
long
length
,
DataHandler
handler
)
{
/**
* Create a CLOB object.
*
* @param reader the reader
* @param maxLength the maximum length (-1 if not known)
* @param handler the data handler
* @return the LOB
*/
public
static
ValueLob
createClob
(
Reader
reader
,
long
maxLength
,
DataHandler
handler
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
return
null
;
CountingReaderInputStream
in
=
new
CountingReaderInputStream
(
reader
);
handler
.
getLobStorage
().
addLob
(
in
,
maxLength
,
LobStorage
.
TABLE_ID_SESSION_VARIABLE
);
}
return
ValueLob
.
createClob
(
in
,
l
ength
,
handler
);
return
ValueLob
.
createClob
(
reader
,
maxL
ength
,
handler
);
}
/**
...
...
@@ -169,32 +226,7 @@ public class LobStorage {
}
public
LobStorage
(
Connection
newConn
)
{
try
{
this
.
conn
=
newConn
;
Statement
stat
=
conn
.
createStatement
();
// stat.execute("SET UNDO_LOG 0");
// stat.execute("SET REDO_LOG_BINARY 0");
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOBS
+
"(ID BIGINT PRIMARY KEY, LENGTH BIGINT, TABLE INT)"
);
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOB_MAP
+
"(LOB BIGINT, SEQ INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ))"
);
stat
.
execute
(
"CREATE INDEX INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON "
+
LOB_MAP
+
"(BLOCK, LOB)"
);
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOB_DATA
+
"(BLOCK BIGINT PRIMARY KEY, DATA BINARY)"
);
ResultSet
rs
;
rs
=
stat
.
executeQuery
(
"SELECT MAX(BLOCK) FROM "
+
LOB_DATA
);
rs
.
next
();
nextBlock
=
rs
.
getLong
(
1
)
+
1
;
if
(
HASH
)
{
nextBlock
=
Math
.
max
(
UNIQUE
+
1
,
nextLob
);
}
rs
=
stat
.
executeQuery
(
"SELECT MAX(ID) FROM "
+
LOBS
);
rs
.
next
();
nextLob
=
rs
.
getLong
(
1
)
+
1
;
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
}
}
protected
synchronized
PreparedStatement
prepare
(
String
sql
)
throws
SQLException
{
private
synchronized
PreparedStatement
prepare
(
String
sql
)
throws
SQLException
{
PreparedStatement
prep
=
prepared
.
get
(
sql
);
if
(
prep
==
null
)
{
prep
=
conn
.
prepareStatement
(
sql
);
...
...
@@ -225,7 +257,15 @@ public class LobStorage {
prep
.
execute
();
}
public
long
addLob
(
InputStream
in
,
long
maxLength
,
int
table
)
throws
SQLException
{
/**
* Store the LOB in the database.
*
* @param in the input stream
* @param maxLength the maximum length (-1 for unknown)
* @param table the table
* @return the LOB id
*/
public
long
addLob
(
InputStream
in
,
long
maxLength
,
int
table
)
{
byte
[]
buff
=
new
byte
[
BLOCK_LENGTH
];
if
(
maxLength
<
0
)
{
maxLength
=
Long
.
MAX_VALUE
;
...
...
@@ -233,71 +273,90 @@ public class LobStorage {
long
length
=
0
;
long
lob
=
nextLob
++;
try
{
for
(
int
seq
=
0
;
maxLength
>
0
;
seq
++)
{
int
len
=
IOUtils
.
readFully
(
in
,
buff
,
0
,
BLOCK_LENGTH
);
if
(
len
<=
0
)
{
break
;
}
length
+=
len
;
maxLength
-=
len
;
try
{
for
(
int
seq
=
0
;
maxLength
>
0
;
seq
++)
{
int
len
=
IOUtils
.
readFully
(
in
,
buff
,
0
,
BLOCK_LENGTH
);
if
(
len
<=
0
)
{
break
;
}
length
+=
len
;
maxLength
-=
len
;
byte
[]
b
;
if
(
len
!=
buff
.
length
)
{
b
=
new
byte
[
len
];
System
.
arraycopy
(
buff
,
0
,
b
,
0
,
len
);
}
else
{
b
=
buff
;
}
long
block
;
boolean
blockExists
=
false
;
if
(
HASH
)
{
block
=
Arrays
.
hashCode
(
b
)
&
UNIQUE
;
int
todoSynchronize
;
PreparedStatement
prep
=
prepare
(
"SELECT DATA FROM "
+
LOB_DATA
+
" WHERE BLOCK = ?"
);
prep
.
setLong
(
1
,
block
);
ResultSet
rs
=
prep
.
executeQuery
();
if
(
rs
.
next
())
{
byte
[]
compare
=
rs
.
getBytes
(
1
);
if
(
Arrays
.
equals
(
b
,
compare
))
{
blockExists
=
true
;
}
else
{
block
=
nextBlock
++;
byte
[]
b
;
if
(
len
!=
buff
.
length
)
{
b
=
new
byte
[
len
];
System
.
arraycopy
(
buff
,
0
,
b
,
0
,
len
);
}
else
{
b
=
buff
;
}
long
block
;
boolean
blockExists
=
false
;
if
(
HASH
)
{
block
=
Arrays
.
hashCode
(
b
)
&
UNIQUE
;
int
todoSynchronize
;
PreparedStatement
prep
=
prepare
(
"SELECT DATA FROM "
+
LOB_DATA
+
" WHERE BLOCK = ?"
);
prep
.
setLong
(
1
,
block
);
ResultSet
rs
=
prep
.
executeQuery
();
if
(
rs
.
next
())
{
byte
[]
compare
=
rs
.
getBytes
(
1
);
if
(
Arrays
.
equals
(
b
,
compare
))
{
blockExists
=
true
;
}
else
{
block
=
nextBlock
++;
}
}
}
else
{
block
=
nextBlock
++;
}
if
(!
blockExists
)
{
PreparedStatement
prep
=
prepare
(
"INSERT INTO "
+
LOB_DATA
+
"(BLOCK, DATA) VALUES(?, ?)"
);
prep
.
setLong
(
1
,
block
);
prep
.
setBytes
(
2
,
b
);
prep
.
execute
();
}
}
else
{
block
=
nextBlock
++;
}
if
(!
blockExists
)
{
PreparedStatement
prep
=
prepare
(
"INSERT INTO "
+
LOB_DATA
+
"(BLOCK, DATA) VALUES(?, ?)"
);
prep
.
setLong
(
1
,
block
);
prep
.
setBytes
(
2
,
b
);
"INSERT INTO "
+
LOB_MAP
+
"(LOB, SEQ, BLOCK) VALUES(?, ?, ?)"
);
prep
.
setLong
(
1
,
lob
);
prep
.
setInt
(
2
,
seq
);
prep
.
setLong
(
3
,
block
);
prep
.
execute
();
}
PreparedStatement
prep
=
prepare
(
"INSERT INTO "
+
LOB
_MAP
+
"(LOB, SEQ, BLOCK
) VALUES(?, ?, ?)"
);
"INSERT INTO "
+
LOB
S
+
"(ID, LENGTH, TABLE
) VALUES(?, ?, ?)"
);
prep
.
setLong
(
1
,
lob
);
prep
.
set
Int
(
2
,
seq
);
prep
.
set
Long
(
3
,
block
);
prep
.
set
Long
(
2
,
length
);
prep
.
set
Int
(
3
,
table
);
prep
.
execute
();
return
lob
;
}
catch
(
IOException
e
)
{
deleteLob
(
lob
);
throw
DbException
.
convertIOException
(
e
,
"adding blob"
);
}
PreparedStatement
prep
=
prepare
(
"INSERT INTO "
+
LOBS
+
"(ID, LENGTH, TABLE) VALUES(?, ?, ?)"
);
prep
.
setLong
(
1
,
lob
);
prep
.
setLong
(
2
,
length
);
prep
.
setInt
(
3
,
table
);
prep
.
execute
();
return
lob
;
}
catch
(
IOException
e
)
{
deleteLob
(
lob
);
throw
DbException
.
convertIOException
(
e
,
"adding blob"
);
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
}
}
public
InputStream
getInputStream
(
long
id
)
throws
IOException
{
return
new
LobInputStream
(
conn
,
id
);
/**
* An input stream that reads the data from a reader.
*/
static
class
CountingReaderInputStream
extends
InputStream
{
private
final
Reader
reader
;
private
long
length
;
private
char
[]
buffer
=
new
char
[
Constants
.
IO_BUFFER_SIZE
];
CountingReaderInputStream
(
Reader
reader
)
{
this
.
reader
=
reader
;
}
public
int
read
()
throws
IOException
{
return
0
;
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/tools/Recover.java
浏览文件 @
181401fb
...
...
@@ -1077,6 +1077,8 @@ public class Recover extends Tool implements DataHandler {
}
writer
.
println
(
"DROP ALIAS READ_CLOB;"
);
writer
.
println
(
"DROP ALIAS READ_BLOB;"
);
writer
.
println
(
"DROP ALIAS READ_CLOB_DB;"
);
writer
.
println
(
"DROP ALIAS READ_BLOB_DB;"
);
for
(
MetaRecord
m
:
schema
)
{
String
sql
=
m
.
getSQL
();
// everything except create
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/build/Build.java
浏览文件 @
181401fb
...
...
@@ -94,6 +94,7 @@ public class Build extends BuildBase {
* Run the Emma code coverage.
*/
public
void
coverage
()
{
downloadTest
();
download
(
"ext/emma-2.0.5312.jar"
,
"http://repo2.maven.org/maven2/emma/emma/2.0.5312/emma-2.0.5312.jar"
,
"30a40933caf67d88d9e75957950ccf353b181ab7"
);
...
...
@@ -225,6 +226,13 @@ public class Build extends BuildBase {
"3006beb1ca6a83449def6127dad3c060148a0209"
);
}
private
void
downloadTest
()
{
// for TestOldVersion
download
(
"ext/h2-1.2.127.jar"
,
"http://repo1.maven.org/maven2/com/h2database/h2/1.2.127/h2-1.2.127.jar"
,
"056e784c7cf009483366ab9cd8d21d02fe47031a"
);
}
private
String
getVersion
()
{
return
getStaticValue
(
"org.h2.engine.Constants"
,
"getVersion"
);
}
...
...
@@ -532,10 +540,7 @@ public class Build extends BuildBase {
* Compile and run all tests.
*/
public
void
test
()
{
// for TestOldVersion
download
(
"ext/h2-1.2.127.jar"
,
"http://repo1.maven.org/maven2/com/h2database/h2/1.2.127/h2-1.2.127.jar"
,
"056e784c7cf009483366ab9cd8d21d02fe47031a"
);
downloadTest
();
compile
();
java
(
"org.h2.test.TestAll"
,
null
);
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论