Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
11b7e7cd
Unverified
提交
11b7e7cd
authored
6 年前
作者:
Noel Grandin
提交者:
GitHub
6 年前
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1233 from grandinj/simplify_old_lob
Simplify old lob ValueLob class
上级
10ed1eb9
77e95155
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
79 行增加
和
372 行删除
+79
-372
Data.java
h2/src/main/org/h2/store/Data.java
+0
-2
Recover.java
h2/src/main/org/h2/tools/Recover.java
+2
-2
DataType.java
h2/src/main/org/h2/value/DataType.java
+4
-3
Value.java
h2/src/main/org/h2/value/Value.java
+0
-14
ValueLob.java
h2/src/main/org/h2/value/ValueLob.java
+42
-323
ValueLobDb.java
h2/src/main/org/h2/value/ValueLobDb.java
+28
-26
TestValue.java
h2/src/test/org/h2/test/unit/TestValue.java
+3
-2
没有找到文件。
h2/src/main/org/h2/store/Data.java
浏览文件 @
11b7e7cd
...
...
@@ -584,7 +584,6 @@ public class Data {
writeByte
((
byte
)
type
);
if
(
v
instanceof
ValueLob
)
{
ValueLob
lob
=
(
ValueLob
)
v
;
lob
.
convertToFileIfRequired
(
handler
);
byte
[]
small
=
lob
.
getSmall
();
if
(
small
==
null
)
{
int
t
=
-
1
;
...
...
@@ -1013,7 +1012,6 @@ public class Data {
int
len
=
1
;
if
(
v
instanceof
ValueLob
)
{
ValueLob
lob
=
(
ValueLob
)
v
;
lob
.
convertToFileIfRequired
(
handler
);
byte
[]
small
=
lob
.
getSmall
();
if
(
small
==
null
)
{
int
t
=
-
1
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/tools/Recover.java
浏览文件 @
11b7e7cd
...
...
@@ -214,7 +214,7 @@ public class Recover extends Tool implements DataHandler {
/**
* INTERNAL
*/
public
static
Value
.
ValueBlo
b
readBlobDb
(
Connection
conn
,
long
lobId
,
public
static
Value
LobD
b
readBlobDb
(
Connection
conn
,
long
lobId
,
long
precision
)
{
DataHandler
h
=
((
JdbcConnection
)
conn
).
getSession
().
getDataHandler
();
verifyPageStore
(
h
);
...
...
@@ -235,7 +235,7 @@ public class Recover extends Tool implements DataHandler {
/**
* INTERNAL
*/
public
static
Value
.
ValueClo
b
readClobDb
(
Connection
conn
,
long
lobId
,
public
static
Value
LobD
b
readClobDb
(
Connection
conn
,
long
lobId
,
long
precision
)
{
DataHandler
h
=
((
JdbcConnection
)
conn
).
getSession
().
getDataHandler
();
verifyPageStore
(
h
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/DataType.java
浏览文件 @
11b7e7cd
...
...
@@ -995,10 +995,11 @@ public class DataType {
return
Value
.
DECIMAL
;
}
else
if
(
ResultSet
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
RESULT_SET
;
}
else
if
(
Value
.
ValueBlo
b
.
class
.
isAssignableFrom
(
x
))
{
}
else
if
(
Value
LobD
b
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
BLOB
;
}
else
if
(
Value
.
ValueClob
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
CLOB
;
// FIXME no way to distinguish between these 2 types
// } else if (ValueLobDb.class.isAssignableFrom(x)) {
// return Value.CLOB;
}
else
if
(
Date
.
class
.
isAssignableFrom
(
x
))
{
return
Value
.
DATE
;
}
else
if
(
Time
.
class
.
isAssignableFrom
(
x
))
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/Value.java
浏览文件 @
11b7e7cd
...
...
@@ -1395,18 +1395,4 @@ public abstract class Value {
return
null
;
}
/**
* A "binary large object".
*/
public
interface
ValueClob
{
// this is a marker interface
}
/**
* A "character large object".
*/
public
interface
ValueBlob
{
// this is a marker interface
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/ValueLob.java
浏览文件 @
11b7e7cd
...
...
@@ -6,15 +6,12 @@
package
org
.
h2
.
value
;
import
java.io.BufferedInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.nio.charset.StandardCharsets
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
...
...
@@ -22,7 +19,6 @@ import org.h2.message.DbException;
import
org.h2.store.DataHandler
;
import
org.h2.store.FileStore
;
import
org.h2.store.FileStoreInputStream
;
import
org.h2.store.FileStoreOutputStream
;
import
org.h2.store.RangeInputStream
;
import
org.h2.store.RangeReader
;
import
org.h2.store.fs.FileUtils
;
...
...
@@ -34,19 +30,8 @@ import org.h2.util.StringUtils;
import
org.h2.util.Utils
;
/**
* Implementation of the BLOB and CLOB data types. Small objects are kept in
* memory and stored in the record.
*
* Large objects are stored in their own files. When large objects are set in a
* prepared statement, they are first stored as 'temporary' files. Later, when
* they are used in a record, and when the record is stored, the lob files are
* linked: the file is renamed using the file format (tableId).(objectId). There
* is one exception: large variables are stored in the file (-1).(objectId).
*
* When lobs are deleted, they are first renamed to a temp file, and if the
* delete operation is committed the file is deleted.
*
* Data compression is supported.
* This is the legacy implementation of LOBs for PageStore databases where the
* LOB was stored in an external file.
*/
public
class
ValueLob
extends
Value
{
...
...
@@ -109,22 +94,23 @@ public class ValueLob extends Value {
*/
private
static
int
dirCounter
;
private
final
int
type
;
private
long
precision
;
private
DataHandler
handler
;
/**
* either Value.BLOB or Value.CLOB
*/
private
final
int
valueType
;
private
final
long
precision
;
private
final
DataHandler
handler
;
private
int
tableId
;
private
int
objectId
;
private
final
int
objectId
;
private
String
fileName
;
private
boolean
linked
;
private
byte
[]
small
;
private
int
hash
;
private
boolean
compressed
;
private
FileStore
tempFile
;
private
final
boolean
compressed
;
private
ValueLob
(
int
type
,
DataHandler
handler
,
String
fileName
,
int
tableId
,
int
objectId
,
boolean
linked
,
long
precision
,
boolean
compressed
)
{
this
.
t
ype
=
type
;
this
.
valueT
ype
=
type
;
this
.
handler
=
handler
;
this
.
fileName
=
fileName
;
this
.
tableId
=
tableId
;
...
...
@@ -134,37 +120,6 @@ public class ValueLob extends Value {
this
.
compressed
=
compressed
;
}
private
ValueLob
(
int
type
,
byte
[]
small
)
{
this
.
type
=
type
;
this
.
small
=
small
;
if
(
small
!=
null
)
{
if
(
type
==
Value
.
BLOB
)
{
this
.
precision
=
small
.
length
;
}
else
{
this
.
precision
=
getString
().
length
();
}
}
}
private
static
ValueLob
copy
(
ValueLob
lob
)
{
ValueLob
copy
=
new
ValueLob
(
lob
.
type
,
lob
.
handler
,
lob
.
fileName
,
lob
.
tableId
,
lob
.
objectId
,
lob
.
linked
,
lob
.
precision
,
lob
.
compressed
);
copy
.
small
=
lob
.
small
;
copy
.
hash
=
lob
.
hash
;
return
copy
;
}
/**
* Create a small lob using the given byte array.
*
* @param type the type (Value.BLOB or CLOB)
* @param small the byte array
* @return the lob value
*/
private
static
ValueLob
createSmallLob
(
int
type
,
byte
[]
small
)
{
return
new
ValueLob
(
type
,
small
);
}
private
static
String
getFileName
(
DataHandler
handler
,
int
tableId
,
int
objectId
)
{
if
(
SysProperties
.
CHECK
&&
tableId
==
0
&&
objectId
==
0
)
{
...
...
@@ -178,7 +133,7 @@ public class ValueLob extends Value {
/**
* Create a LOB value with the given parameters.
*
* @param type the data type
* @param type the data type
, either Value.BLOB or Value.CLOB
* @param handler the file handler
* @param tableId the table object id
* @param objectId the object id
...
...
@@ -196,7 +151,7 @@ public class ValueLob extends Value {
/**
* Create a LOB value with the given parameters.
*
* @param type the data type
* @param type the data type
, either Value.BLOB or Value.CLOB
* @param handler the file handler
* @param tableId the table object id
* @param objectId the object id
...
...
@@ -212,92 +167,6 @@ public class ValueLob extends Value {
false
/* linked */
,
precision
,
compression
);
}
/**
* Create a CLOB value from a stream.
*
* @param in the reader
* @param length the number of characters to read, or -1 for no limit
* @param handler the data handler
* @return the lob value
*/
private
static
ValueLob
createClob
(
Reader
in
,
long
length
,
DataHandler
handler
)
{
try
{
if
(
handler
==
null
)
{
String
s
=
IOUtils
.
readStringAndClose
(
in
,
(
int
)
length
);
return
createSmallLob
(
Value
.
CLOB
,
s
.
getBytes
(
StandardCharsets
.
UTF_8
));
}
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
Value
.
CLOB
)
!=
null
;
long
remaining
=
Long
.
MAX_VALUE
;
if
(
length
>=
0
&&
length
<
remaining
)
{
remaining
=
length
;
}
int
len
=
getBufferSize
(
handler
,
compress
,
remaining
);
char
[]
buff
;
if
(
len
>=
Integer
.
MAX_VALUE
)
{
String
data
=
IOUtils
.
readStringAndClose
(
in
,
-
1
);
buff
=
data
.
toCharArray
();
len
=
buff
.
length
;
}
else
{
buff
=
new
char
[
len
];
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
}
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
new
String
(
buff
,
0
,
len
).
getBytes
(
StandardCharsets
.
UTF_8
);
return
ValueLob
.
createSmallLob
(
Value
.
CLOB
,
small
);
}
ValueLob
lob
=
new
ValueLob
(
Value
.
CLOB
,
null
);
lob
.
createFromReader
(
buff
,
len
,
in
,
remaining
,
handler
);
return
lob
;
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
private
static
int
getBufferSize
(
DataHandler
handler
,
boolean
compress
,
long
remaining
)
{
if
(
remaining
<
0
||
remaining
>
Integer
.
MAX_VALUE
)
{
remaining
=
Integer
.
MAX_VALUE
;
}
int
inplace
=
handler
.
getMaxLengthInplaceLob
();
long
m
=
compress
?
Constants
.
IO_BUFFER_SIZE_COMPRESS
:
Constants
.
IO_BUFFER_SIZE
;
if
(
m
<
remaining
&&
m
<=
inplace
)
{
// using "1L" to force long arithmetic
m
=
Math
.
min
(
remaining
,
inplace
+
1L
);
// the buffer size must be bigger than the inplace lob, otherwise we
// can't know if it must be stored in-place or not
m
=
MathUtils
.
roundUpLong
(
m
,
Constants
.
IO_BUFFER_SIZE
);
}
m
=
Math
.
min
(
remaining
,
m
);
m
=
MathUtils
.
convertLongToInt
(
m
);
if
(
m
<
0
)
{
m
=
Integer
.
MAX_VALUE
;
}
return
(
int
)
m
;
}
private
void
createFromReader
(
char
[]
buff
,
int
len
,
Reader
in
,
long
remaining
,
DataHandler
h
)
throws
IOException
{
try
(
FileStoreOutputStream
out
=
initLarge
(
h
))
{
boolean
compress
=
h
.
getLobCompressionAlgorithm
(
Value
.
CLOB
)
!=
null
;
while
(
true
)
{
precision
+=
len
;
byte
[]
b
=
new
String
(
buff
,
0
,
len
).
getBytes
(
StandardCharsets
.
UTF_8
);
out
.
write
(
b
,
0
,
b
.
length
);
remaining
-=
len
;
if
(
remaining
<=
0
)
{
break
;
}
len
=
getBufferSize
(
h
,
compress
,
remaining
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
if
(
len
==
0
)
{
break
;
}
}
}
}
private
static
String
getFileNamePrefix
(
String
path
,
int
objectId
)
{
String
name
;
int
f
=
objectId
%
SysProperties
.
LOB_FILES_PER_DIRECTORY
;
...
...
@@ -406,91 +275,6 @@ public class ValueLob extends Value {
return
list
;
}
/**
* Create a BLOB value from a stream.
*
* @param in the input stream
* @param length the number of characters to read, or -1 for no limit
* @param handler the data handler
* @return the lob value
*/
private
static
ValueLob
createBlob
(
InputStream
in
,
long
length
,
DataHandler
handler
)
{
try
{
if
(
handler
==
null
)
{
byte
[]
data
=
IOUtils
.
readBytesAndClose
(
in
,
(
int
)
length
);
return
createSmallLob
(
Value
.
BLOB
,
data
);
}
long
remaining
=
Long
.
MAX_VALUE
;
boolean
compress
=
handler
.
getLobCompressionAlgorithm
(
Value
.
BLOB
)
!=
null
;
if
(
length
>=
0
&&
length
<
remaining
)
{
remaining
=
length
;
}
int
len
=
getBufferSize
(
handler
,
compress
,
remaining
);
byte
[]
buff
;
if
(
len
>=
Integer
.
MAX_VALUE
)
{
buff
=
IOUtils
.
readBytesAndClose
(
in
,
-
1
);
len
=
buff
.
length
;
}
else
{
buff
=
Utils
.
newBytes
(
len
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
}
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
Utils
.
copyBytes
(
buff
,
len
);
return
ValueLob
.
createSmallLob
(
Value
.
BLOB
,
small
);
}
ValueLob
lob
=
new
ValueLob
(
Value
.
BLOB
,
null
);
lob
.
createFromStream
(
buff
,
len
,
in
,
remaining
,
handler
);
return
lob
;
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
private
FileStoreOutputStream
initLarge
(
DataHandler
h
)
{
this
.
handler
=
h
;
this
.
tableId
=
0
;
this
.
linked
=
false
;
this
.
precision
=
0
;
this
.
small
=
null
;
this
.
hash
=
0
;
String
compressionAlgorithm
=
h
.
getLobCompressionAlgorithm
(
type
);
this
.
compressed
=
compressionAlgorithm
!=
null
;
synchronized
(
h
)
{
String
path
=
h
.
getDatabasePath
();
if
((
path
!=
null
)
&&
(
path
.
length
()
==
0
))
{
path
=
new
File
(
Utils
.
getProperty
(
"java.io.tmpdir"
,
"."
),
SysProperties
.
PREFIX_TEMP_FILE
).
getAbsolutePath
();
}
objectId
=
getNewObjectId
(
h
);
fileName
=
getFileNamePrefix
(
path
,
objectId
)
+
Constants
.
SUFFIX_TEMP_FILE
;
tempFile
=
h
.
openFile
(
fileName
,
"rw"
,
false
);
tempFile
.
autoDelete
();
}
return
new
FileStoreOutputStream
(
tempFile
,
h
,
compressionAlgorithm
);
}
private
void
createFromStream
(
byte
[]
buff
,
int
len
,
InputStream
in
,
long
remaining
,
DataHandler
h
)
throws
IOException
{
try
(
FileStoreOutputStream
out
=
initLarge
(
h
))
{
boolean
compress
=
h
.
getLobCompressionAlgorithm
(
Value
.
BLOB
)
!=
null
;
while
(
true
)
{
precision
+=
len
;
out
.
write
(
buff
,
0
,
len
);
remaining
-=
len
;
if
(
remaining
<=
0
)
{
break
;
}
len
=
getBufferSize
(
h
,
compress
,
remaining
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
if
(
len
<=
0
)
{
break
;
}
}
}
}
/**
* Convert a lob to another data type. The data is fully read in memory
* except when converting to BLOB or CLOB.
...
...
@@ -507,12 +291,12 @@ public class ValueLob extends Value {
*/
@Override
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
if
(
t
==
t
ype
)
{
if
(
t
==
valueT
ype
)
{
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
return
ValueLob
.
create
Clob
(
getReader
(),
-
1
,
handler
);
return
ValueLob
Db
.
createTemp
Clob
(
getReader
(),
-
1
,
handler
);
}
else
if
(
t
==
Value
.
BLOB
)
{
return
ValueLob
.
create
Blob
(
getInputStream
(),
-
1
,
handler
);
return
ValueLob
Db
.
createTemp
Blob
(
getInputStream
(),
-
1
,
handler
);
}
return
super
.
convertTo
(
t
,
precision
,
mode
,
column
,
null
);
}
...
...
@@ -533,24 +317,15 @@ public class ValueLob extends Value {
@Override
public
void
remove
()
{
if
(
fileName
!=
null
)
{
if
(
tempFile
!=
null
)
{
tempFile
.
stopAutoDelete
();
tempFile
=
null
;
}
deleteFile
(
handler
,
fileName
);
}
deleteFile
(
handler
,
fileName
);
}
@Override
public
Value
copy
(
DataHandler
h
,
int
tabId
)
{
if
(
fileName
==
null
)
{
this
.
tableId
=
tabId
;
return
this
;
}
if
(
linked
)
{
ValueLob
copy
=
ValueLob
.
copy
(
this
);
copy
.
objectId
=
getNewObjectId
(
h
);
ValueLob
copy
=
new
ValueLob
(
this
.
valueType
,
this
.
handler
,
this
.
fileName
,
this
.
tableId
,
getNewObjectId
(
h
),
this
.
linked
,
this
.
precision
,
this
.
compressed
);
copy
.
hash
=
this
.
hash
;
copy
.
tableId
=
tabId
;
String
live
=
getFileName
(
h
,
copy
.
tableId
,
copy
.
objectId
);
copyFileTo
(
h
,
fileName
,
live
);
...
...
@@ -561,10 +336,6 @@ public class ValueLob extends Value {
if
(!
linked
)
{
this
.
tableId
=
tabId
;
String
live
=
getFileName
(
h
,
tableId
,
objectId
);
if
(
tempFile
!=
null
)
{
tempFile
.
stopAutoDelete
();
tempFile
=
null
;
}
renameFile
(
h
,
fileName
,
live
);
fileName
=
live
;
linked
=
true
;
...
...
@@ -593,7 +364,7 @@ public class ValueLob extends Value {
@Override
public
int
getType
()
{
return
t
ype
;
return
valueT
ype
;
}
@Override
...
...
@@ -606,18 +377,10 @@ public class ValueLob extends Value {
int
len
=
precision
>
Integer
.
MAX_VALUE
||
precision
==
0
?
Integer
.
MAX_VALUE
:
(
int
)
precision
;
try
{
if
(
type
==
Value
.
CLOB
)
{
if
(
small
!=
null
)
{
return
new
String
(
small
,
StandardCharsets
.
UTF_8
);
}
if
(
valueType
==
Value
.
CLOB
)
{
return
IOUtils
.
readStringAndClose
(
getReader
(),
len
);
}
byte
[]
buff
;
if
(
small
!=
null
)
{
buff
=
small
;
}
else
{
buff
=
IOUtils
.
readBytesAndClose
(
getInputStream
(),
len
);
}
byte
[]
buff
=
IOUtils
.
readBytesAndClose
(
getInputStream
(),
len
);
return
StringUtils
.
convertBytesToHex
(
buff
);
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
fileName
);
...
...
@@ -626,7 +389,7 @@ public class ValueLob extends Value {
@Override
public
byte
[]
getBytes
()
{
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
// convert hex to string
return
super
.
getBytes
();
}
...
...
@@ -636,13 +399,10 @@ public class ValueLob extends Value {
@Override
public
byte
[]
getBytesNoCopy
()
{
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
// convert hex to string
return
super
.
getBytesNoCopy
();
}
if
(
small
!=
null
)
{
return
small
;
}
try
{
return
IOUtils
.
readBytesAndClose
(
getInputStream
(),
Integer
.
MAX_VALUE
);
...
...
@@ -659,7 +419,7 @@ public class ValueLob extends Value {
// it in the database file
return
(
int
)
(
precision
^
(
precision
>>>
32
));
}
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
hash
=
getString
().
hashCode
();
}
else
{
hash
=
Utils
.
getByteArrayHash
(
getBytes
());
...
...
@@ -670,7 +430,7 @@ public class ValueLob extends Value {
@Override
protected
int
compareSecure
(
Value
v
,
CompareMode
mode
)
{
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
return
Integer
.
signum
(
getString
().
compareTo
(
v
.
getString
()));
}
byte
[]
v2
=
v
.
getBytesNoCopy
();
...
...
@@ -679,7 +439,7 @@ public class ValueLob extends Value {
@Override
public
Object
getObject
()
{
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
return
getReader
();
}
return
getInputStream
();
...
...
@@ -692,14 +452,11 @@ public class ValueLob extends Value {
@Override
public
Reader
getReader
(
long
oneBasedOffset
,
long
length
)
{
return
rangeReader
(
getReader
(),
oneBasedOffset
,
length
,
t
ype
==
Value
.
CLOB
?
precision
:
-
1
);
return
rangeReader
(
getReader
(),
oneBasedOffset
,
length
,
valueT
ype
==
Value
.
CLOB
?
precision
:
-
1
);
}
@Override
public
InputStream
getInputStream
()
{
if
(
fileName
==
null
)
{
return
new
ByteArrayInputStream
(
small
);
}
FileStore
store
=
handler
.
openFile
(
fileName
,
"r"
,
true
);
boolean
alwaysClose
=
SysProperties
.
lobCloseBetweenReads
;
return
new
BufferedInputStream
(
...
...
@@ -709,9 +466,6 @@ public class ValueLob extends Value {
@Override
public
InputStream
getInputStream
(
long
oneBasedOffset
,
long
length
)
{
if
(
fileName
==
null
)
{
return
super
.
getInputStream
(
oneBasedOffset
,
length
);
}
FileStore
store
=
handler
.
openFile
(
fileName
,
"r"
,
true
);
boolean
alwaysClose
=
SysProperties
.
lobCloseBetweenReads
;
InputStream
inputStream
=
new
BufferedInputStream
(
...
...
@@ -727,7 +481,7 @@ public class ValueLob extends Value {
if
(
p
>
Integer
.
MAX_VALUE
||
p
<=
0
)
{
p
=
-
1
;
}
if
(
t
ype
==
Value
.
BLOB
)
{
if
(
valueT
ype
==
Value
.
BLOB
)
{
prep
.
setBinaryStream
(
parameterIndex
,
getInputStream
(),
(
int
)
p
);
}
else
{
prep
.
setCharacterStream
(
parameterIndex
,
getReader
(),
(
int
)
p
);
...
...
@@ -737,7 +491,7 @@ public class ValueLob extends Value {
@Override
public
String
getSQL
()
{
String
s
;
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
s
=
getString
();
return
StringUtils
.
quoteStringSQL
(
s
);
}
...
...
@@ -748,11 +502,8 @@ public class ValueLob extends Value {
@Override
public
String
getTraceSQL
()
{
if
(
small
!=
null
&&
getPrecision
()
<=
SysProperties
.
MAX_TRACE_DATA_LENGTH
)
{
return
getSQL
();
}
StringBuilder
buff
=
new
StringBuilder
();
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
buff
.
append
(
"SPACE("
).
append
(
getPrecision
());
}
else
{
buff
.
append
(
"CAST(REPEAT('00', "
).
append
(
getPrecision
()).
append
(
") AS BINARY"
);
...
...
@@ -768,7 +519,7 @@ public class ValueLob extends Value {
*/
@Override
public
byte
[]
getSmall
()
{
return
sma
ll
;
return
nu
ll
;
}
@Override
...
...
@@ -781,35 +532,6 @@ public class ValueLob extends Value {
return
other
instanceof
ValueLob
&&
compareSecure
((
Value
)
other
,
null
)
==
0
;
}
/**
* Store the lob data to a file if the size of the buffer is larger than the
* maximum size for an in-place lob.
*
* @param h the data handler
*/
public
void
convertToFileIfRequired
(
DataHandler
h
)
{
try
{
if
(
small
!=
null
&&
small
.
length
>
h
.
getMaxLengthInplaceLob
())
{
boolean
compress
=
h
.
getLobCompressionAlgorithm
(
type
)
!=
null
;
int
len
=
getBufferSize
(
h
,
compress
,
Long
.
MAX_VALUE
);
int
tabId
=
tableId
;
if
(
type
==
Value
.
BLOB
)
{
createFromStream
(
Utils
.
newBytes
(
len
),
0
,
getInputStream
(),
Long
.
MAX_VALUE
,
h
);
}
else
{
createFromReader
(
new
char
[
len
],
0
,
getReader
(),
Long
.
MAX_VALUE
,
h
);
}
Value
v2
=
copy
(
h
,
tabId
);
if
(
SysProperties
.
CHECK
&&
v2
!=
this
)
{
DbException
.
throwInternalError
(
v2
.
toString
());
}
}
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
/**
* Check if this lob value is compressed.
*
...
...
@@ -848,9 +570,6 @@ public class ValueLob extends Value {
@Override
public
int
getMemory
()
{
if
(
small
!=
null
)
{
return
small
.
length
+
104
;
}
return
140
;
}
...
...
@@ -861,12 +580,12 @@ public class ValueLob extends Value {
* @return the value
*/
@Override
public
ValueLob
copyToTemp
()
{
ValueLob
lob
;
if
(
t
ype
==
CLOB
)
{
lob
=
ValueLob
.
create
Clob
(
getReader
(),
precision
,
handler
);
public
ValueLob
Db
copyToTemp
()
{
ValueLob
Db
lob
;
if
(
valueT
ype
==
CLOB
)
{
lob
=
ValueLob
Db
.
createTemp
Clob
(
getReader
(),
precision
,
handler
);
}
else
{
lob
=
ValueLob
.
create
Blob
(
getInputStream
(),
precision
,
handler
);
lob
=
ValueLob
Db
.
createTemp
Blob
(
getInputStream
(),
precision
,
handler
);
}
return
lob
;
}
...
...
@@ -876,11 +595,11 @@ public class ValueLob extends Value {
if
(
this
.
precision
<=
precision
)
{
return
this
;
}
ValueLob
lob
;
if
(
t
ype
==
CLOB
)
{
lob
=
ValueLob
.
create
Clob
(
getReader
(),
precision
,
handler
);
ValueLob
Db
lob
;
if
(
valueT
ype
==
CLOB
)
{
lob
=
ValueLob
Db
.
createTemp
Clob
(
getReader
(),
precision
,
handler
);
}
else
{
lob
=
ValueLob
.
create
Blob
(
getInputStream
(),
precision
,
handler
);
lob
=
ValueLob
Db
.
createTemp
Blob
(
getInputStream
(),
precision
,
handler
);
}
return
lob
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/ValueLobDb.java
浏览文件 @
11b7e7cd
...
...
@@ -39,10 +39,12 @@ import org.h2.util.Utils;
* Small objects are kept in memory and stored in the record.
* Large objects are either stored in the database, or in temporary files.
*/
public
class
ValueLobDb
extends
Value
implements
Value
.
ValueClob
,
Value
.
ValueBlob
{
public
class
ValueLobDb
extends
Value
{
private
final
int
type
;
/**
* the value type (Value.BLOB or CLOB)
*/
private
final
int
valueType
;
private
final
long
lobId
;
private
final
byte
[]
hmac
;
private
final
byte
[]
small
;
...
...
@@ -66,7 +68,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
private
ValueLobDb
(
int
type
,
DataHandler
handler
,
int
tableId
,
long
lobId
,
byte
[]
hmac
,
long
precision
)
{
this
.
t
ype
=
type
;
this
.
valueT
ype
=
type
;
this
.
handler
=
handler
;
this
.
tableId
=
tableId
;
this
.
lobId
=
lobId
;
...
...
@@ -78,7 +80,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
}
private
ValueLobDb
(
int
type
,
byte
[]
small
,
long
precision
)
{
this
.
t
ype
=
type
;
this
.
valueT
ype
=
type
;
this
.
small
=
small
;
this
.
precision
=
precision
;
this
.
lobId
=
0
;
...
...
@@ -94,7 +96,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
*/
private
ValueLobDb
(
DataHandler
handler
,
Reader
in
,
long
remaining
)
throws
IOException
{
this
.
t
ype
=
Value
.
CLOB
;
this
.
valueT
ype
=
Value
.
CLOB
;
this
.
handler
=
handler
;
this
.
small
=
null
;
this
.
lobId
=
0
;
...
...
@@ -126,7 +128,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
*/
private
ValueLobDb
(
DataHandler
handler
,
byte
[]
buff
,
int
len
,
InputStream
in
,
long
remaining
)
throws
IOException
{
this
.
t
ype
=
Value
.
BLOB
;
this
.
valueT
ype
=
Value
.
BLOB
;
this
.
handler
=
handler
;
this
.
small
=
null
;
this
.
lobId
=
0
;
...
...
@@ -167,7 +169,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
/**
* Create a LOB value.
*
* @param type the type
* @param type the type
(Value.BLOB or CLOB)
* @param handler the data handler
* @param tableId the table id
* @param id the lob id
...
...
@@ -194,7 +196,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
*/
@Override
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
if
(
t
==
t
ype
)
{
if
(
t
==
valueT
ype
)
{
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
if
(
handler
!=
null
)
{
...
...
@@ -248,7 +250,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
}
else
if
(
small
.
length
>
database
.
getMaxLengthInplaceLob
())
{
LobStorageInterface
s
=
database
.
getLobStorage
();
Value
v
;
if
(
t
ype
==
Value
.
BLOB
)
{
if
(
valueT
ype
==
Value
.
BLOB
)
{
v
=
s
.
createBlob
(
getInputStream
(),
getPrecision
());
}
else
{
v
=
s
.
createClob
(
getReader
(),
getPrecision
());
...
...
@@ -272,7 +274,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
@Override
public
int
getType
()
{
return
t
ype
;
return
valueT
ype
;
}
@Override
...
...
@@ -285,7 +287,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
int
len
=
precision
>
Integer
.
MAX_VALUE
||
precision
==
0
?
Integer
.
MAX_VALUE
:
(
int
)
precision
;
try
{
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
if
(
small
!=
null
)
{
return
new
String
(
small
,
StandardCharsets
.
UTF_8
);
}
...
...
@@ -305,7 +307,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
@Override
public
byte
[]
getBytes
()
{
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
// convert hex to string
return
super
.
getBytes
();
}
...
...
@@ -315,7 +317,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
@Override
public
byte
[]
getBytesNoCopy
()
{
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
// convert hex to string
return
super
.
getBytesNoCopy
();
}
...
...
@@ -337,7 +339,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
// it in the database file
return
(
int
)
(
precision
^
(
precision
>>>
32
));
}
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
hash
=
getString
().
hashCode
();
}
else
{
hash
=
Utils
.
getByteArrayHash
(
getBytes
());
...
...
@@ -357,7 +359,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return
0
;
}
}
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
return
Integer
.
signum
(
getString
().
compareTo
(
v
.
getString
()));
}
byte
[]
v2
=
v
.
getBytesNoCopy
();
...
...
@@ -366,7 +368,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
@Override
public
Object
getObject
()
{
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
return
getReader
();
}
return
getInputStream
();
...
...
@@ -379,7 +381,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
@Override
public
Reader
getReader
(
long
oneBasedOffset
,
long
length
)
{
return
ValueLob
.
rangeReader
(
getReader
(),
oneBasedOffset
,
length
,
t
ype
==
Value
.
CLOB
?
precision
:
-
1
);
return
ValueLob
.
rangeReader
(
getReader
(),
oneBasedOffset
,
length
,
valueT
ype
==
Value
.
CLOB
?
precision
:
-
1
);
}
@Override
...
...
@@ -392,7 +394,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return
new
BufferedInputStream
(
new
FileStoreInputStream
(
store
,
handler
,
false
,
alwaysClose
),
Constants
.
IO_BUFFER_SIZE
);
}
long
byteCount
=
(
t
ype
==
Value
.
BLOB
)
?
precision
:
-
1
;
long
byteCount
=
(
valueT
ype
==
Value
.
BLOB
)
?
precision
:
-
1
;
try
{
return
handler
.
getLobStorage
().
getInputStream
(
this
,
hmac
,
byteCount
);
}
catch
(
IOException
e
)
{
...
...
@@ -413,7 +415,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
inputStream
=
new
BufferedInputStream
(
new
FileStoreInputStream
(
store
,
handler
,
false
,
alwaysClose
),
Constants
.
IO_BUFFER_SIZE
);
}
else
{
byteCount
=
(
t
ype
==
Value
.
BLOB
)
?
precision
:
-
1
;
byteCount
=
(
valueT
ype
==
Value
.
BLOB
)
?
precision
:
-
1
;
try
{
inputStream
=
handler
.
getLobStorage
().
getInputStream
(
this
,
hmac
,
byteCount
);
}
catch
(
IOException
e
)
{
...
...
@@ -430,7 +432,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
if
(
p
>
Integer
.
MAX_VALUE
||
p
<=
0
)
{
p
=
-
1
;
}
if
(
t
ype
==
Value
.
BLOB
)
{
if
(
valueT
ype
==
Value
.
BLOB
)
{
prep
.
setBinaryStream
(
parameterIndex
,
getInputStream
(),
(
int
)
p
);
}
else
{
prep
.
setCharacterStream
(
parameterIndex
,
getReader
(),
(
int
)
p
);
...
...
@@ -440,7 +442,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
@Override
public
String
getSQL
()
{
String
s
;
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
s
=
getString
();
return
StringUtils
.
quoteStringSQL
(
s
);
}
...
...
@@ -455,7 +457,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return
getSQL
();
}
StringBuilder
buff
=
new
StringBuilder
();
if
(
t
ype
==
Value
.
CLOB
)
{
if
(
valueT
ype
==
Value
.
CLOB
)
{
buff
.
append
(
"SPACE("
).
append
(
getPrecision
());
}
else
{
buff
.
append
(
"CAST(REPEAT('00', "
).
append
(
getPrecision
()).
append
(
") AS BINARY"
);
...
...
@@ -650,13 +652,13 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return
this
;
}
ValueLobDb
lob
;
if
(
t
ype
==
CLOB
)
{
if
(
valueT
ype
==
CLOB
)
{
if
(
handler
==
null
)
{
try
{
int
p
=
MathUtils
.
convertLongToInt
(
precision
);
String
s
=
IOUtils
.
readStringAndClose
(
getReader
(),
p
);
byte
[]
data
=
s
.
getBytes
(
StandardCharsets
.
UTF_8
);
lob
=
ValueLobDb
.
createSmallLob
(
t
ype
,
data
,
s
.
length
());
lob
=
ValueLobDb
.
createSmallLob
(
valueT
ype
,
data
,
s
.
length
());
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
...
...
@@ -668,7 +670,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
try
{
int
p
=
MathUtils
.
convertLongToInt
(
precision
);
byte
[]
data
=
IOUtils
.
readBytesAndClose
(
getInputStream
(),
p
);
lob
=
ValueLobDb
.
createSmallLob
(
t
ype
,
data
,
data
.
length
);
lob
=
ValueLobDb
.
createSmallLob
(
valueT
ype
,
data
,
data
.
length
);
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/unit/TestValue.java
浏览文件 @
11b7e7cd
...
...
@@ -265,8 +265,9 @@ public class TestValue extends TestDb {
testDataType
(
Value
.
NULL
,
Void
.
class
);
testDataType
(
Value
.
DECIMAL
,
BigDecimal
.
class
);
testDataType
(
Value
.
RESULT_SET
,
ResultSet
.
class
);
testDataType
(
Value
.
BLOB
,
Value
.
ValueBlob
.
class
);
testDataType
(
Value
.
CLOB
,
Value
.
ValueClob
.
class
);
testDataType
(
Value
.
BLOB
,
ValueLobDb
.
class
);
// see FIXME in DataType.getTypeFromClass
//testDataType(Value.CLOB, Value.ValueClob.class);
testDataType
(
Value
.
DATE
,
Date
.
class
);
testDataType
(
Value
.
TIME
,
Time
.
class
);
testDataType
(
Value
.
TIMESTAMP
,
Timestamp
.
class
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论