Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
40de3268
提交
40de3268
authored
3月 26, 2010
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
New lob storage.
上级
8ffac30c
显示空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
479 行增加
和
498 行删除
+479
-498
DropTable.java
h2/src/main/org/h2/command/ddl/DropTable.java
+1
-2
ScriptBase.java
h2/src/main/org/h2/command/dml/ScriptBase.java
+5
-0
SysProperties.java
h2/src/main/org/h2/constant/SysProperties.java
+7
-1
SessionRemote.java
h2/src/main/org/h2/engine/SessionRemote.java
+9
-0
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+16
-7
Data.java
h2/src/main/org/h2/store/Data.java
+83
-50
DataHandler.java
h2/src/main/org/h2/store/DataHandler.java
+13
-0
LobStorage.java
h2/src/main/org/h2/store/LobStorage.java
+120
-60
Recover.java
h2/src/main/org/h2/tools/Recover.java
+7
-0
DataType.java
h2/src/main/org/h2/value/DataType.java
+6
-6
Transfer.java
h2/src/main/org/h2/value/Transfer.java
+3
-4
Value.java
h2/src/main/org/h2/value/Value.java
+1
-0
ValueLob.java
h2/src/main/org/h2/value/ValueLob.java
+0
-3
ValueLob2.java
h2/src/main/org/h2/value/ValueLob2.java
+208
-365
没有找到文件。
h2/src/main/org/h2/command/ddl/DropTable.java
浏览文件 @
40de3268
...
@@ -12,7 +12,6 @@ import org.h2.engine.Right;
...
@@ -12,7 +12,6 @@ import org.h2.engine.Right;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.schema.Schema
;
import
org.h2.schema.Schema
;
import
org.h2.store.LobStorage
;
import
org.h2.table.Table
;
import
org.h2.table.Table
;
/**
/**
...
@@ -83,7 +82,7 @@ public class DropTable extends SchemaCommand {
...
@@ -83,7 +82,7 @@ public class DropTable extends SchemaCommand {
table
.
setModified
();
table
.
setModified
();
Database
db
=
session
.
getDatabase
();
Database
db
=
session
.
getDatabase
();
db
.
removeSchemaObject
(
session
,
table
);
db
.
removeSchemaObject
(
session
,
table
);
LobStorage
.
removeAllForTable
(
db
,
dropTableId
);
db
.
getLobStorage
().
removeAllForTable
(
dropTableId
);
}
}
if
(
next
!=
null
)
{
if
(
next
!=
null
)
{
next
.
executeDrop
();
next
.
executeDrop
();
...
...
h2/src/main/org/h2/command/dml/ScriptBase.java
浏览文件 @
40de3268
...
@@ -11,6 +11,7 @@ import java.io.BufferedOutputStream;
...
@@ -11,6 +11,7 @@ import java.io.BufferedOutputStream;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
java.sql.Connection
;
import
org.h2.command.Prepared
;
import
org.h2.command.Prepared
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.SysProperties
;
import
org.h2.constant.SysProperties
;
...
@@ -228,4 +229,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
...
@@ -228,4 +229,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
return
null
;
return
null
;
}
}
public
Connection
getLobConnection
()
{
return
null
;
}
}
}
h2/src/main/org/h2/constant/SysProperties.java
浏览文件 @
40de3268
...
@@ -66,7 +66,7 @@ public class SysProperties {
...
@@ -66,7 +66,7 @@ public class SysProperties {
public
static
final
String
LINE_SEPARATOR
=
getStringSetting
(
"line.separator"
,
"\n"
);
public
static
final
String
LINE_SEPARATOR
=
getStringSetting
(
"line.separator"
,
"\n"
);
/**
/**
* System property <code>user.home</code> (
default: empty string
).<br />
* System property <code>user.home</code> (
empty string if not set
).<br />
* It is usually set by the system, and used as a replacement for ~ in file
* It is usually set by the system, and used as a replacement for ~ in file
* names.
* names.
*/
*/
...
@@ -437,6 +437,12 @@ public class SysProperties {
...
@@ -437,6 +437,12 @@ public class SysProperties {
*/
*/
public
static
final
String
PG_DEFAULT_CLIENT_ENCODING
=
getStringSetting
(
"h2.pgClientEncoding"
,
"UTF-8"
);
public
static
final
String
PG_DEFAULT_CLIENT_ENCODING
=
getStringSetting
(
"h2.pgClientEncoding"
,
"UTF-8"
);
/**
* System property <code>h2.prefixTempFile</code> (default: h2.temp).<br />
* The prefix for temporary files in the temp directory.
*/
public
static
final
String
PREFIX_TEMP_FILE
=
getStringSetting
(
"h2.prefixTempFile"
,
"h2.temp"
);
/**
/**
* System property <code>h2.recompileAlways</code> (default: false).<br />
* System property <code>h2.recompileAlways</code> (default: false).<br />
* Always recompile prepared statements.
* Always recompile prepared statements.
...
...
h2/src/main/org/h2/engine/SessionRemote.java
浏览文件 @
40de3268
...
@@ -8,6 +8,7 @@ package org.h2.engine;
...
@@ -8,6 +8,7 @@ package org.h2.engine;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.net.Socket
;
import
java.net.Socket
;
import
java.sql.Connection
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.h2.api.DatabaseEventListener
;
import
org.h2.api.DatabaseEventListener
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.CommandInterface
;
...
@@ -80,6 +81,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
...
@@ -80,6 +81,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
private
int
lastReconnect
;
private
int
lastReconnect
;
private
SessionInterface
embedded
;
private
SessionInterface
embedded
;
private
DatabaseEventListener
eventListener
;
private
DatabaseEventListener
eventListener
;
private
LobStorage
lobStorage
;
public
SessionRemote
()
{
public
SessionRemote
()
{
// nothing to do
// nothing to do
...
@@ -620,6 +622,13 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
...
@@ -620,6 +622,13 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
}
}
public
LobStorage
getLobStorage
()
{
public
LobStorage
getLobStorage
()
{
if
(
lobStorage
==
null
)
{
lobStorage
=
new
LobStorage
(
this
);
}
return
lobStorage
;
}
public
Connection
getLobConnection
()
{
return
null
;
return
null
;
}
}
...
...
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
40de3268
...
@@ -6,7 +6,9 @@
...
@@ -6,7 +6,9 @@
*/
*/
package
org
.
h2
.
jdbc
;
package
org
.
h2
.
jdbc
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.Reader
;
import
java.io.Reader
;
import
java.sql.Blob
;
import
java.sql.Blob
;
import
java.sql.CallableStatement
;
import
java.sql.CallableStatement
;
...
@@ -32,7 +34,6 @@ import org.h2.message.DbException;
...
@@ -32,7 +34,6 @@ import org.h2.message.DbException;
import
org.h2.message.Trace
;
import
org.h2.message.Trace
;
import
org.h2.message.TraceObject
;
import
org.h2.message.TraceObject
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.ResultInterface
;
import
org.h2.store.LobStorage
;
import
org.h2.util.Utils
;
import
org.h2.util.Utils
;
import
org.h2.value.CompareMode
;
import
org.h2.value.CompareMode
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
...
@@ -1438,7 +1439,9 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -1438,7 +1439,9 @@ public class JdbcConnection extends TraceObject implements Connection {
debugCodeAssign
(
"Clob"
,
TraceObject
.
CLOB
,
id
,
"createClob()"
);
debugCodeAssign
(
"Clob"
,
TraceObject
.
CLOB
,
id
,
"createClob()"
);
checkClosedForWrite
();
checkClosedForWrite
();
try
{
try
{
Value
v
=
LobStorage
.
createSmallLob
(
Value
.
CLOB
,
Utils
.
EMPTY_BYTES
);
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createClob
(
new
InputStreamReader
(
new
ByteArrayInputStream
(
Utils
.
EMPTY_BYTES
)),
0
);
return
new
JdbcClob
(
this
,
v
,
id
);
return
new
JdbcClob
(
this
,
v
,
id
);
}
finally
{
}
finally
{
afterWriting
();
afterWriting
();
...
@@ -1459,7 +1462,7 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -1459,7 +1462,7 @@ public class JdbcConnection extends TraceObject implements Connection {
debugCodeAssign
(
"Blob"
,
TraceObject
.
BLOB
,
id
,
"createClob()"
);
debugCodeAssign
(
"Blob"
,
TraceObject
.
BLOB
,
id
,
"createClob()"
);
checkClosedForWrite
();
checkClosedForWrite
();
try
{
try
{
Value
v
=
LobStorage
.
createSmallLob
(
Value
.
BLOB
,
Utils
.
EMPTY_BYTES
);
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createBlob
(
new
ByteArrayInputStream
(
Utils
.
EMPTY_BYTES
),
0
);
return
new
JdbcBlob
(
this
,
v
,
id
);
return
new
JdbcBlob
(
this
,
v
,
id
);
}
finally
{
}
finally
{
afterWriting
();
afterWriting
();
...
@@ -1480,8 +1483,14 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -1480,8 +1483,14 @@ public class JdbcConnection extends TraceObject implements Connection {
int id = getNextId(TraceObject.CLOB);
int id = getNextId(TraceObject.CLOB);
debugCodeAssign("NClob", TraceObject.CLOB, id, "createNClob()");
debugCodeAssign("NClob", TraceObject.CLOB, id, "createNClob()");
checkClosedForWrite();
checkClosedForWrite();
Value v = LobStorage.createSmallLob(Value.CLOB, Utils.EMPTY_BYTES);
try {
Value v = session.getDataHandler().getLobStorage().createClob(
new InputStreamReader(
new ByteArrayInputStream(Utils.EMPTY_BYTES)), 0);
return new JdbcClob(this, v, id);
return new JdbcClob(this, v, id);
} finally {
afterWriting();
}
} catch (Exception e) {
} catch (Exception e) {
throw logAndConvert(e);
throw logAndConvert(e);
}
}
...
@@ -1614,7 +1623,7 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -1614,7 +1623,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if
(
length
<=
0
)
{
if
(
length
<=
0
)
{
length
=
-
1
;
length
=
-
1
;
}
}
Value
v
=
LobStorage
.
createClob
(
x
,
length
,
session
.
getDataHandler
()
);
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createClob
(
x
,
length
);
return
v
;
return
v
;
}
}
...
@@ -1633,7 +1642,7 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -1633,7 +1642,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if
(
length
<=
0
)
{
if
(
length
<=
0
)
{
length
=
-
1
;
length
=
-
1
;
}
}
Value
v
=
LobStorage
.
createBlob
(
x
,
length
,
session
.
getDataHandler
()
);
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createBlob
(
x
,
length
);
return
v
;
return
v
;
}
}
...
...
h2/src/main/org/h2/store/Data.java
浏览文件 @
40de3268
...
@@ -32,6 +32,7 @@ import org.h2.value.ValueFloat;
...
@@ -32,6 +32,7 @@ import org.h2.value.ValueFloat;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueJavaObject
;
import
org.h2.value.ValueJavaObject
;
import
org.h2.value.ValueLob
;
import
org.h2.value.ValueLob
;
import
org.h2.value.ValueLob2
;
import
org.h2.value.ValueLong
;
import
org.h2.value.ValueLong
;
import
org.h2.value.ValueNull
;
import
org.h2.value.ValueNull
;
import
org.h2.value.ValueShort
;
import
org.h2.value.ValueShort
;
...
@@ -514,6 +515,7 @@ public class Data {
...
@@ -514,6 +515,7 @@ public class Data {
case
Value
.
BLOB
:
case
Value
.
BLOB
:
case
Value
.
CLOB
:
{
case
Value
.
CLOB
:
{
writeByte
((
byte
)
type
);
writeByte
((
byte
)
type
);
if
(
v
instanceof
ValueLob
)
{
ValueLob
lob
=
(
ValueLob
)
v
;
ValueLob
lob
=
(
ValueLob
)
v
;
lob
.
convertToFileIfRequired
(
handler
);
lob
.
convertToFileIfRequired
(
handler
);
byte
[]
small
=
lob
.
getSmall
();
byte
[]
small
=
lob
.
getSmall
();
...
@@ -534,6 +536,18 @@ public class Data {
...
@@ -534,6 +536,18 @@ public class Data {
writeVarInt
(
small
.
length
);
writeVarInt
(
small
.
length
);
write
(
small
,
0
,
small
.
length
);
write
(
small
,
0
,
small
.
length
);
}
}
}
else
{
ValueLob2
lob
=
(
ValueLob2
)
v
;
byte
[]
small
=
lob
.
getSmall
();
if
(
small
==
null
)
{
writeVarInt
(-
3
);
writeVarLong
(
lob
.
getLobId
());
writeVarLong
(
lob
.
getPrecision
());
}
else
{
writeVarInt
(
small
.
length
);
write
(
small
,
0
,
small
.
length
);
}
}
break
;
break
;
}
}
case
Value
.
ARRAY
:
{
case
Value
.
ARRAY
:
{
...
@@ -654,12 +668,17 @@ public class Data {
...
@@ -654,12 +668,17 @@ public class Data {
byte
[]
small
=
Utils
.
newBytes
(
smallLen
);
byte
[]
small
=
Utils
.
newBytes
(
smallLen
);
read
(
small
,
0
,
smallLen
);
read
(
small
,
0
,
smallLen
);
return
LobStorage
.
createSmallLob
(
type
,
small
);
return
LobStorage
.
createSmallLob
(
type
,
small
);
}
}
else
if
(
smallLen
==
-
3
)
{
long
lobId
=
readVarLong
();
long
precision
=
readVarLong
();
LobStorage
lobStorage
=
handler
.
getLobStorage
();
ValueLob2
lob
=
ValueLob2
.
create
(
type
,
lobStorage
,
null
,
lobId
,
precision
);
return
lob
;
}
else
{
int
tableId
=
readVarInt
();
int
tableId
=
readVarInt
();
int
objectId
=
readVarInt
();
int
objectId
=
readVarInt
();
long
precision
=
0
;
long
precision
=
0
;
boolean
compression
=
false
;
boolean
compression
=
false
;
// TODO simplify
// -1: regular
// -1: regular
// -2: regular, but not linked (in this case: including file name)
// -2: regular, but not linked (in this case: including file name)
if
(
smallLen
==
-
1
||
smallLen
==
-
2
)
{
if
(
smallLen
==
-
1
||
smallLen
==
-
2
)
{
...
@@ -672,6 +691,7 @@ public class Data {
...
@@ -672,6 +691,7 @@ public class Data {
}
}
return
lob
;
return
lob
;
}
}
}
case
Value
.
ARRAY
:
{
case
Value
.
ARRAY
:
{
int
len
=
readVarInt
();
int
len
=
readVarInt
();
Value
[]
list
=
new
Value
[
len
];
Value
[]
list
=
new
Value
[
len
];
...
@@ -809,6 +829,7 @@ public class Data {
...
@@ -809,6 +829,7 @@ public class Data {
case
Value
.
BLOB
:
case
Value
.
BLOB
:
case
Value
.
CLOB
:
{
case
Value
.
CLOB
:
{
int
len
=
1
;
int
len
=
1
;
if
(
v
instanceof
ValueLob
)
{
ValueLob
lob
=
(
ValueLob
)
v
;
ValueLob
lob
=
(
ValueLob
)
v
;
lob
.
convertToFileIfRequired
(
handler
);
lob
.
convertToFileIfRequired
(
handler
);
byte
[]
small
=
lob
.
getSmall
();
byte
[]
small
=
lob
.
getSmall
();
...
@@ -829,6 +850,18 @@ public class Data {
...
@@ -829,6 +850,18 @@ public class Data {
len
+=
getVarIntLen
(
small
.
length
);
len
+=
getVarIntLen
(
small
.
length
);
len
+=
small
.
length
;
len
+=
small
.
length
;
}
}
}
else
{
ValueLob2
lob
=
(
ValueLob2
)
v
;
byte
[]
small
=
lob
.
getSmall
();
if
(
small
==
null
)
{
len
+=
getVarIntLen
(-
3
);
len
+=
getVarLongLen
(
lob
.
getLobId
());
len
+=
getVarLongLen
(
lob
.
getPrecision
());
}
else
{
len
+=
getVarIntLen
(
small
.
length
);
len
+=
small
.
length
;
}
}
return
len
;
return
len
;
}
}
case
Value
.
ARRAY
:
{
case
Value
.
ARRAY
:
{
...
...
h2/src/main/org/h2/store/DataHandler.java
浏览文件 @
40de3268
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
*/
*/
package
org
.
h2
.
store
;
package
org
.
h2
.
store
;
import
java.sql.Connection
;
import
org.h2.util.SmallLRUCache
;
import
org.h2.util.SmallLRUCache
;
import
org.h2.util.TempFileDeleter
;
import
org.h2.util.TempFileDeleter
;
...
@@ -91,6 +92,18 @@ public interface DataHandler {
...
@@ -91,6 +92,18 @@ public interface DataHandler {
*/
*/
SmallLRUCache
<
String
,
String
[]>
getLobFileListCache
();
SmallLRUCache
<
String
,
String
[]>
getLobFileListCache
();
/**
* Get the lob storage mechanism to use.
*
* @return the lob storage mechanism
*/
LobStorage
getLobStorage
();
LobStorage
getLobStorage
();
/**
* Get a database connection to be used for LOB access.
*
* @return the connection or null
*/
Connection
getLobConnection
();
}
}
h2/src/main/org/h2/store/LobStorage.java
浏览文件 @
40de3268
...
@@ -22,16 +22,17 @@ import org.h2.engine.Constants;
...
@@ -22,16 +22,17 @@ import org.h2.engine.Constants;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.util.IOUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.New
;
import
org.h2.util.New
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Utils
;
import
org.h2.value.Value
;
import
org.h2.value.ValueLob
;
import
org.h2.value.ValueLob
;
import
org.h2.value.ValueLob2
;
/**
/**
* This class stores LOB objects in the database.
* This class stores LOB objects in the database.
*/
*/
public
class
LobStorage
{
public
class
LobStorage
{
/**
* The 'table id' to use for session variables.
*/
public
static
final
int
TABLE_ID_SESSION_VARIABLE
=
-
1
;
public
static
final
int
TABLE_ID_SESSION_VARIABLE
=
-
1
;
private
static
final
String
LOBS
=
"INFORMATION_SCHEMA.LOBS"
;
private
static
final
String
LOBS
=
"INFORMATION_SCHEMA.LOBS"
;
...
@@ -46,15 +47,33 @@ public class LobStorage {
...
@@ -46,15 +47,33 @@ public class LobStorage {
private
long
nextLob
;
private
long
nextLob
;
private
long
nextBlock
;
private
long
nextBlock
;
public
LobStorage
(
Connection
newConn
)
{
private
final
DataHandler
handler
;
private
boolean
init
;
public
LobStorage
(
DataHandler
handler
)
{
this
.
handler
=
handler
;
}
/**
* Initialize the lob storage.
*/
public
void
init
()
{
if
(
init
)
{
return
;
}
conn
=
handler
.
getLobConnection
();
init
=
true
;
if
(
conn
==
null
)
{
return
;
}
int
todoDatabaseGetFirstUserTable
;
try
{
try
{
this
.
conn
=
newConn
;
Statement
stat
=
conn
.
createStatement
();
Statement
stat
=
conn
.
createStatement
();
// stat.execute("SET UNDO_LOG 0");
// stat.execute("SET UNDO_LOG 0");
// stat.execute("SET REDO_LOG_BINARY 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 "
+
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 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 INDEX I
F NOT EXISTS I
NFORMATION_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)"
);
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS "
+
LOB_DATA
+
"(BLOCK BIGINT PRIMARY KEY, DATA BINARY)"
);
ResultSet
rs
;
ResultSet
rs
;
rs
=
stat
.
executeQuery
(
"SELECT MAX(BLOCK) FROM "
+
LOB_DATA
);
rs
=
stat
.
executeQuery
(
"SELECT MAX(BLOCK) FROM "
+
LOB_DATA
);
...
@@ -77,8 +96,10 @@ public class LobStorage {
...
@@ -77,8 +96,10 @@ public class LobStorage {
* @param handler the data handler
* @param handler the data handler
* @param tableId the table id
* @param tableId the table id
*/
*/
public
static
void
removeAllForTable
(
DataHandler
handler
,
int
tableId
)
{
public
void
removeAllForTable
(
int
tableId
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
init
();
int
todo
;
// remove both lobs in the database as well as in the file system
// remove both lobs in the database as well as in the file system
}
}
ValueLob
.
removeAllForTable
(
handler
,
tableId
);
ValueLob
.
removeAllForTable
(
handler
,
tableId
);
...
@@ -91,50 +112,19 @@ public class LobStorage {
...
@@ -91,50 +112,19 @@ public class LobStorage {
* @param small the byte array
* @param small the byte array
* @return the LOB
* @return the LOB
*/
*/
public
static
Value
Lob
createSmallLob
(
int
type
,
byte
[]
small
)
{
public
static
Value
createSmallLob
(
int
type
,
byte
[]
small
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
return
null
;
return
ValueLob2
.
createSmallLob
(
type
,
small
)
;
}
}
return
ValueLob
.
createSmallLob
(
type
,
small
);
return
ValueLob
.
createSmallLob
(
type
,
small
);
}
}
/**
* 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
)
{
handler
.
getLobStorage
().
addLob
(
in
,
maxLength
,
LobStorage
.
TABLE_ID_SESSION_VARIABLE
);
}
return
ValueLob
.
createBlob
(
in
,
maxLength
,
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
)
{
CountingReaderInputStream
in
=
new
CountingReaderInputStream
(
reader
);
handler
.
getLobStorage
().
addLob
(
in
,
maxLength
,
LobStorage
.
TABLE_ID_SESSION_VARIABLE
);
}
return
ValueLob
.
createClob
(
reader
,
maxLength
,
handler
);
}
/**
/**
* An input stream that reads from a LOB.
* An input stream that reads from a LOB.
*/
*/
public
static
class
LobInputStream
extends
InputStream
{
public
static
class
LobInputStream
extends
InputStream
{
private
Connection
conn
;
private
final
Connection
conn
;
private
PreparedStatement
prepSelect
;
private
PreparedStatement
prepSelect
;
private
byte
[]
buffer
;
private
byte
[]
buffer
;
private
int
pos
;
private
int
pos
;
...
@@ -143,6 +133,7 @@ public class LobStorage {
...
@@ -143,6 +133,7 @@ public class LobStorage {
private
int
seq
;
private
int
seq
;
public
LobInputStream
(
Connection
conn
,
long
lob
)
throws
IOException
{
public
LobInputStream
(
Connection
conn
,
long
lob
)
throws
IOException
{
this
.
conn
=
conn
;
try
{
try
{
this
.
lob
=
lob
;
this
.
lob
=
lob
;
PreparedStatement
prep
=
conn
.
prepareStatement
(
PreparedStatement
prep
=
conn
.
prepareStatement
(
...
@@ -151,8 +142,9 @@ public class LobStorage {
...
@@ -151,8 +142,9 @@ public class LobStorage {
ResultSet
rs
=
prep
.
executeQuery
();
ResultSet
rs
=
prep
.
executeQuery
();
if
(!
rs
.
next
())
{
if
(!
rs
.
next
())
{
throw
DbException
.
get
(
ErrorCode
.
IO_EXCEPTION_1
,
"lob: "
+
lob
+
" seq: "
+
seq
).
getSQLException
();
throw
DbException
.
get
(
ErrorCode
.
IO_EXCEPTION_1
,
"lob: "
+
lob
+
" seq: "
+
seq
).
getSQLException
();
}
}
remaining
=
rs
.
getLong
(
1
);
rs
.
close
();
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
DbException
.
convertToIOException
(
e
);
throw
DbException
.
convertToIOException
(
e
);
}
}
...
@@ -257,21 +249,18 @@ public class LobStorage {
...
@@ -257,21 +249,18 @@ public class LobStorage {
prep
.
execute
();
prep
.
execute
();
}
}
/**
public
InputStream
getInputStream
(
long
lobId
)
throws
IOException
{
* Store the LOB in the database.
init
();
*
return
new
LobInputStream
(
conn
,
lobId
);
* @param in the input stream
}
* @param maxLength the maximum length (-1 for unknown)
* @param table the table
private
ValueLob2
addLob
(
InputStream
in
,
long
maxLength
,
int
type
)
{
* @return the LOB id
*/
public
long
addLob
(
InputStream
in
,
long
maxLength
,
int
table
)
{
byte
[]
buff
=
new
byte
[
BLOCK_LENGTH
];
byte
[]
buff
=
new
byte
[
BLOCK_LENGTH
];
if
(
maxLength
<
0
)
{
if
(
maxLength
<
0
)
{
maxLength
=
Long
.
MAX_VALUE
;
maxLength
=
Long
.
MAX_VALUE
;
}
}
long
length
=
0
;
long
length
=
0
;
long
lob
=
nextLob
++;
long
lob
Id
=
nextLob
++;
try
{
try
{
try
{
try
{
for
(
int
seq
=
0
;
maxLength
>
0
;
seq
++)
{
for
(
int
seq
=
0
;
maxLength
>
0
;
seq
++)
{
...
@@ -281,7 +270,6 @@ public class LobStorage {
...
@@ -281,7 +270,6 @@ public class LobStorage {
}
}
length
+=
len
;
length
+=
len
;
maxLength
-=
len
;
maxLength
-=
len
;
byte
[]
b
;
byte
[]
b
;
if
(
len
!=
buff
.
length
)
{
if
(
len
!=
buff
.
length
)
{
b
=
new
byte
[
len
];
b
=
new
byte
[
len
];
...
@@ -319,20 +307,21 @@ public class LobStorage {
...
@@ -319,20 +307,21 @@ public class LobStorage {
}
}
PreparedStatement
prep
=
prepare
(
PreparedStatement
prep
=
prepare
(
"INSERT INTO "
+
LOB_MAP
+
"(LOB, SEQ, BLOCK) VALUES(?, ?, ?)"
);
"INSERT INTO "
+
LOB_MAP
+
"(LOB, SEQ, BLOCK) VALUES(?, ?, ?)"
);
prep
.
setLong
(
1
,
lob
);
prep
.
setLong
(
1
,
lob
Id
);
prep
.
setInt
(
2
,
seq
);
prep
.
setInt
(
2
,
seq
);
prep
.
setLong
(
3
,
block
);
prep
.
setLong
(
3
,
block
);
prep
.
execute
();
prep
.
execute
();
}
}
PreparedStatement
prep
=
prepare
(
PreparedStatement
prep
=
prepare
(
"INSERT INTO "
+
LOBS
+
"(ID, LENGTH, TABLE) VALUES(?, ?, ?)"
);
"INSERT INTO "
+
LOBS
+
"(ID, LENGTH, TABLE) VALUES(?, ?, ?)"
);
prep
.
setLong
(
1
,
lob
);
prep
.
setLong
(
1
,
lob
Id
);
prep
.
setLong
(
2
,
length
);
prep
.
setLong
(
2
,
length
);
prep
.
setInt
(
3
,
table
);
prep
.
setInt
(
3
,
TABLE_ID_SESSION_VARIABLE
);
prep
.
execute
();
prep
.
execute
();
return
lob
;
ValueLob2
v
=
ValueLob2
.
create
(
type
,
this
,
null
,
lobId
,
length
);
return
v
;
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
deleteLob
(
lob
);
deleteLob
(
lob
Id
);
throw
DbException
.
convertIOException
(
e
,
"adding blob"
);
throw
DbException
.
convertIOException
(
e
,
"adding blob"
);
}
}
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
...
@@ -347,16 +336,87 @@ public class LobStorage {
...
@@ -347,16 +336,87 @@ public class LobStorage {
private
final
Reader
reader
;
private
final
Reader
reader
;
private
long
length
;
private
long
length
;
private
char
[]
buffer
=
new
char
[
Constants
.
IO_BUFFER_SIZE
];
private
int
pos
;
private
char
[]
charBuffer
=
new
char
[
Constants
.
IO_BUFFER_SIZE
];
private
byte
[]
buffer
;
CountingReaderInputStream
(
Reader
reader
)
{
CountingReaderInputStream
(
Reader
reader
)
{
this
.
reader
=
reader
;
this
.
reader
=
reader
;
buffer
=
Utils
.
EMPTY_BYTES
;
}
public
int
read
(
byte
[]
buff
,
int
offset
,
int
len
)
throws
IOException
{
if
(
pos
>=
buffer
.
length
)
{
fillBuffer
();
if
(
buffer
==
null
)
{
return
-
1
;
}
}
len
=
Math
.
min
(
len
,
buffer
.
length
-
pos
);
System
.
arraycopy
(
buffer
,
pos
,
buff
,
offset
,
len
);
return
len
;
}
}
public
int
read
()
throws
IOException
{
public
int
read
()
throws
IOException
{
return
0
;
if
(
pos
>=
buffer
.
length
)
{
fillBuffer
();
if
(
buffer
==
null
)
{
return
-
1
;
}
}
return
buffer
[
pos
++];
}
private
void
fillBuffer
()
throws
IOException
{
int
len
=
reader
.
read
(
charBuffer
);
if
(
len
<
0
)
{
buffer
=
null
;
}
else
{
buffer
=
StringUtils
.
utf8Encode
(
new
String
(
charBuffer
,
0
,
len
));
length
+=
len
;
}
}
public
long
getLength
()
{
return
length
;
}
}
public
void
close
()
throws
IOException
{
reader
.
close
();
}
}
/**
* Create a BLOB object.
*
* @param in the input stream
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
public
Value
createBlob
(
InputStream
in
,
long
maxLength
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
init
();
if
(
conn
==
null
)
{
return
ValueLob2
.
createTempBlob
(
in
,
maxLength
,
handler
);
}
return
addLob
(
in
,
maxLength
,
Value
.
BLOB
);
}
return
ValueLob
.
createBlob
(
in
,
maxLength
,
handler
);
}
public
Value
createClob
(
Reader
reader
,
long
maxLength
)
{
if
(
SysProperties
.
LOB_IN_DATABASE
)
{
init
();
if
(
conn
==
null
)
{
return
ValueLob2
.
createTempClob
(
reader
,
maxLength
,
handler
);
}
CountingReaderInputStream
in
=
new
CountingReaderInputStream
(
reader
);
ValueLob2
lob
=
addLob
(
in
,
maxLength
,
Value
.
BLOB
);
lob
.
setPrecision
(
in
.
getLength
());
return
lob
;
}
return
ValueLob
.
createClob
(
reader
,
maxLength
,
handler
);
}
}
}
}
h2/src/main/org/h2/tools/Recover.java
浏览文件 @
40de3268
...
@@ -1223,4 +1223,11 @@ public class Recover extends Tool implements DataHandler {
...
@@ -1223,4 +1223,11 @@ public class Recover extends Tool implements DataHandler {
return
null
;
return
null
;
}
}
/**
* INTERNAL
*/
public
Connection
getLobConnection
()
{
return
null
;
}
}
}
h2/src/main/org/h2/value/DataType.java
浏览文件 @
40de3268
...
@@ -546,7 +546,7 @@ public class DataType {
...
@@ -546,7 +546,7 @@ public class DataType {
if
(
in
==
null
)
{
if
(
in
==
null
)
{
v
=
ValueNull
.
INSTANCE
;
v
=
ValueNull
.
INSTANCE
;
}
else
{
}
else
{
v
=
LobStorage
.
createClob
(
new
BufferedReader
(
in
),
-
1
,
session
.
getDataHandler
()
);
v
=
session
.
getDataHandler
().
getLobStorage
().
createClob
(
new
BufferedReader
(
in
),
-
1
);
}
}
}
}
break
;
break
;
...
@@ -556,7 +556,7 @@ public class DataType {
...
@@ -556,7 +556,7 @@ public class DataType {
v
=
LobStorage
.
createSmallLob
(
Value
.
BLOB
,
rs
.
getBytes
(
columnIndex
));
v
=
LobStorage
.
createSmallLob
(
Value
.
BLOB
,
rs
.
getBytes
(
columnIndex
));
}
else
{
}
else
{
InputStream
in
=
rs
.
getBinaryStream
(
columnIndex
);
InputStream
in
=
rs
.
getBinaryStream
(
columnIndex
);
v
=
(
in
==
null
)
?
(
Value
)
ValueNull
.
INSTANCE
:
LobStorage
.
createBlob
(
in
,
-
1
,
session
.
getDataHandler
()
);
v
=
(
in
==
null
)
?
(
Value
)
ValueNull
.
INSTANCE
:
session
.
getDataHandler
().
getLobStorage
().
createBlob
(
in
,
-
1
);
}
}
break
;
break
;
}
}
...
@@ -864,19 +864,19 @@ public class DataType {
...
@@ -864,19 +864,19 @@ public class DataType {
return
ValueTimestamp
.
get
(
new
Timestamp
(((
java
.
util
.
Date
)
x
).
getTime
()));
return
ValueTimestamp
.
get
(
new
Timestamp
(((
java
.
util
.
Date
)
x
).
getTime
()));
}
else
if
(
x
instanceof
java
.
io
.
Reader
)
{
}
else
if
(
x
instanceof
java
.
io
.
Reader
)
{
Reader
r
=
new
BufferedReader
((
java
.
io
.
Reader
)
x
);
Reader
r
=
new
BufferedReader
((
java
.
io
.
Reader
)
x
);
return
LobStorage
.
createClob
(
r
,
-
1
,
session
.
getDataHandler
()
);
return
session
.
getDataHandler
().
getLobStorage
().
createClob
(
r
,
-
1
);
}
else
if
(
x
instanceof
java
.
sql
.
Clob
)
{
}
else
if
(
x
instanceof
java
.
sql
.
Clob
)
{
try
{
try
{
Reader
r
=
new
BufferedReader
(((
java
.
sql
.
Clob
)
x
).
getCharacterStream
());
Reader
r
=
new
BufferedReader
(((
java
.
sql
.
Clob
)
x
).
getCharacterStream
());
return
LobStorage
.
createClob
(
r
,
-
1
,
session
.
getDataHandler
()
);
return
session
.
getDataHandler
().
getLobStorage
().
createClob
(
r
,
-
1
);
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
throw
DbException
.
convert
(
e
);
}
}
}
else
if
(
x
instanceof
java
.
io
.
InputStream
)
{
}
else
if
(
x
instanceof
java
.
io
.
InputStream
)
{
return
LobStorage
.
createBlob
((
java
.
io
.
InputStream
)
x
,
-
1
,
session
.
getDataHandler
()
);
return
session
.
getDataHandler
().
getLobStorage
().
createBlob
((
java
.
io
.
InputStream
)
x
,
-
1
);
}
else
if
(
x
instanceof
java
.
sql
.
Blob
)
{
}
else
if
(
x
instanceof
java
.
sql
.
Blob
)
{
try
{
try
{
return
LobStorage
.
createBlob
(((
java
.
sql
.
Blob
)
x
).
getBinaryStream
(),
-
1
,
session
.
getDataHandler
()
);
return
session
.
getDataHandler
().
getLobStorage
().
createBlob
(((
java
.
sql
.
Blob
)
x
).
getBinaryStream
(),
-
1
);
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
throw
DbException
.
convert
(
e
);
}
}
...
...
h2/src/main/org/h2/value/Transfer.java
浏览文件 @
40de3268
...
@@ -29,13 +29,12 @@ import org.h2.engine.Constants;
...
@@ -29,13 +29,12 @@ import org.h2.engine.Constants;
import
org.h2.engine.SessionInterface
;
import
org.h2.engine.SessionInterface
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.message.TraceSystem
;
import
org.h2.message.TraceSystem
;
import
org.h2.store.LobStorage
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.Utils
;
import
org.h2.util.ExactUTF8InputStreamReader
;
import
org.h2.util.ExactUTF8InputStreamReader
;
import
org.h2.util.IOUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.NetUtils
;
import
org.h2.util.NetUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Utils
;
/**
/**
* The transfer class is used to send and receive Value objects.
* The transfer class is used to send and receive Value objects.
...
@@ -484,7 +483,7 @@ public class Transfer {
...
@@ -484,7 +483,7 @@ public class Transfer {
return
ValueStringFixed
.
get
(
readString
());
return
ValueStringFixed
.
get
(
readString
());
case
Value
.
BLOB
:
{
case
Value
.
BLOB
:
{
long
length
=
readLong
();
long
length
=
readLong
();
Value
v
=
LobStorage
.
createBlob
(
in
,
length
,
session
.
getDataHandler
()
);
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createBlob
(
in
,
length
);
int
magic
=
readInt
();
int
magic
=
readInt
();
if
(
magic
!=
LOB_MAGIC
)
{
if
(
magic
!=
LOB_MAGIC
)
{
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"magic="
+
magic
);
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"magic="
+
magic
);
...
@@ -493,7 +492,7 @@ public class Transfer {
...
@@ -493,7 +492,7 @@ public class Transfer {
}
}
case
Value
.
CLOB
:
{
case
Value
.
CLOB
:
{
long
length
=
readLong
();
long
length
=
readLong
();
Value
v
=
LobStorage
.
createClob
(
new
ExactUTF8InputStreamReader
(
in
),
length
,
session
.
getDataHandler
()
);
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createClob
(
new
ExactUTF8InputStreamReader
(
in
),
length
);
int
magic
=
readInt
();
int
magic
=
readInt
();
if
(
magic
!=
LOB_MAGIC
)
{
if
(
magic
!=
LOB_MAGIC
)
{
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"magic="
+
magic
);
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"magic="
+
magic
);
...
...
h2/src/main/org/h2/value/Value.java
浏览文件 @
40de3268
...
@@ -706,6 +706,7 @@ public abstract class Value {
...
@@ -706,6 +706,7 @@ public abstract class Value {
case
BLOB:
{
case
BLOB:
{
switch
(
getType
())
{
switch
(
getType
())
{
case
BYTES:
case
BYTES:
return
LobStorage
.
createSmallLob
(
Value
.
BLOB
,
getBytesNoCopy
());
return
LobStorage
.
createSmallLob
(
Value
.
BLOB
,
getBytesNoCopy
());
}
}
break
;
break
;
...
...
h2/src/main/org/h2/value/ValueLob.java
浏览文件 @
40de3268
...
@@ -44,9 +44,6 @@ import org.h2.util.Utils;
...
@@ -44,9 +44,6 @@ import org.h2.util.Utils;
* Data compression is supported.
* Data compression is supported.
*/
*/
public
class
ValueLob
extends
Value
{
public
class
ValueLob
extends
Value
{
// TODO lob: concatenate function for blob and clob
// (to create a large blob from pieces)
// and a getpart function (to get it in pieces) and make sure a file is created!
/**
/**
* This counter is used to calculate the next directory to store lobs. It is
* This counter is used to calculate the next directory to store lobs. It is
...
...
h2/src/main/org/h2/value/ValueLob2.java
浏览文件 @
40de3268
...
@@ -20,7 +20,7 @@ import org.h2.store.DataHandler;
...
@@ -20,7 +20,7 @@ import org.h2.store.DataHandler;
import
org.h2.store.FileStore
;
import
org.h2.store.FileStore
;
import
org.h2.store.FileStoreInputStream
;
import
org.h2.store.FileStoreInputStream
;
import
org.h2.store.FileStoreOutputStream
;
import
org.h2.store.FileStoreOutputStream
;
import
org.h2.store.
fs.FileSystem
;
import
org.h2.store.
LobStorage
;
import
org.h2.util.IOUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
...
@@ -31,33 +31,27 @@ import org.h2.util.Utils;
...
@@ -31,33 +31,27 @@ import org.h2.util.Utils;
*/
*/
public
class
ValueLob2
extends
Value
{
public
class
ValueLob2
extends
Value
{
/**
* The 'table id' to use for session variables.
*/
public
static
final
int
TABLE_ID_SESSION_VARIABLE
=
-
1
;
private
final
int
type
;
private
final
int
type
;
private
long
precision
;
private
long
precision
;
private
DataHandler
handler
;
private
int
tableId
;
private
int
tableId
;
private
int
hash
;
private
LobStorage
lobStorage
;
private
long
lobId
;
private
long
lobId
;
private
String
fileName
;
private
boolean
linked
;
private
byte
[]
small
;
private
byte
[]
small
;
private
int
hash
;
private
boolean
compression
;
private
DataHandler
handler
;
private
FileStore
tempFile
;
private
FileStore
tempFile
;
private
String
fileName
;
private
ValueLob2
(
int
type
,
DataHandler
handler
,
String
fileName
,
int
tableId
,
long
lobId
,
boolean
linked
,
private
ValueLob2
(
int
type
,
LobStorage
lobStorage
,
String
fileName
,
int
tableId
,
long
lobId
,
long
precision
)
{
long
precision
,
boolean
compression
)
{
this
.
type
=
type
;
this
.
type
=
type
;
this
.
handler
=
handler
;
this
.
lobStorage
=
lobStorage
;
this
.
fileName
=
fileName
;
this
.
fileName
=
fileName
;
this
.
tableId
=
tableId
;
this
.
tableId
=
tableId
;
this
.
lobId
=
lobId
;
this
.
lobId
=
lobId
;
this
.
linked
=
linked
;
this
.
precision
=
precision
;
this
.
precision
=
precision
;
this
.
compression
=
compression
;
}
}
private
ValueLob2
(
int
type
,
byte
[]
small
)
{
private
ValueLob2
(
int
type
,
byte
[]
small
)
{
...
@@ -72,11 +66,8 @@ public class ValueLob2 extends Value {
...
@@ -72,11 +66,8 @@ public class ValueLob2 extends Value {
}
}
}
}
private
static
ValueLob2
copy
(
ValueLob2
lob
)
{
public
static
ValueLob2
create
(
int
type
,
LobStorage
lobStorage
,
String
fileName
,
long
id
,
long
precision
)
{
ValueLob2
copy
=
new
ValueLob2
(
lob
.
type
,
lob
.
handler
,
lob
.
fileName
,
lob
.
tableId
,
lob
.
lobId
,
lob
.
linked
,
lob
.
precision
,
lob
.
compression
);
return
new
ValueLob2
(
type
,
lobStorage
,
fileName
,
LobStorage
.
TABLE_ID_SESSION_VARIABLE
,
id
,
precision
);
copy
.
small
=
lob
.
small
;
copy
.
hash
=
lob
.
hash
;
return
copy
;
}
}
/**
/**
...
@@ -90,204 +81,6 @@ public class ValueLob2 extends Value {
...
@@ -90,204 +81,6 @@ public class ValueLob2 extends Value {
return
new
ValueLob2
(
type
,
small
);
return
new
ValueLob2
(
type
,
small
);
}
}
private
static
String
getFileName
(
DataHandler
handler
,
int
tableId
,
long
objectId
)
{
if
(
SysProperties
.
CHECK
&&
tableId
==
0
&&
objectId
==
0
)
{
DbException
.
throwInternalError
(
"0 LOB"
);
}
String
table
=
tableId
<
0
?
".temp"
:
".t"
+
tableId
;
return
getFileNamePrefix
(
handler
.
getDatabasePath
(),
objectId
)
+
table
+
Constants
.
SUFFIX_LOB_FILE
;
}
/**
* Create a LOB value with the given parameters.
*
* @param type the data type
* @param handler the file handler
* @param tableId the table object id
* @param objectId the object id
* @param precision the precision (length in elements)
* @param compression if compression is used
* @return the value object
*/
public
static
ValueLob2
open
(
int
type
,
DataHandler
handler
,
int
tableId
,
int
objectId
,
long
precision
,
boolean
compression
)
{
String
fileName
=
getFileName
(
handler
,
tableId
,
objectId
);
return
new
ValueLob2
(
type
,
handler
,
fileName
,
tableId
,
objectId
,
true
,
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
*/
public
static
ValueLob2
createClob
(
Reader
in
,
long
length
,
DataHandler
handler
)
{
try
{
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
);
len
=
len
<
0
?
0
:
len
;
}
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
StringUtils
.
utf8Encode
(
new
String
(
buff
,
0
,
len
));
return
ValueLob2
.
createSmallLob
(
Value
.
CLOB
,
small
);
}
ValueLob2
lob
=
new
ValueLob2
(
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
;
}
long
inplace
=
handler
.
getMaxLengthInplaceLob
();
if
(
inplace
>=
Integer
.
MAX_VALUE
)
{
inplace
=
remaining
;
}
long
m
=
compress
?
Constants
.
IO_BUFFER_SIZE_COMPRESS
:
Constants
.
IO_BUFFER_SIZE
;
if
(
m
<
remaining
&&
m
<=
inplace
)
{
m
=
Math
.
min
(
remaining
,
inplace
+
1
);
// 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
)
{
try
{
FileStoreOutputStream
out
=
initLarge
(
h
);
boolean
compress
=
h
.
getLobCompressionAlgorithm
(
Value
.
CLOB
)
!=
null
;
try
{
while
(
true
)
{
precision
+=
len
;
byte
[]
b
=
StringUtils
.
utf8Encode
(
new
String
(
buff
,
0
,
len
));
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
;
}
}
}
finally
{
out
.
close
();
}
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
private
static
String
getFileNamePrefix
(
String
path
,
long
lobId
)
{
return
IOUtils
.
normalize
(
path
+
lobId
);
}
/**
* 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
*/
public
static
ValueLob2
createBlob
(
InputStream
in
,
long
length
,
DataHandler
handler
)
{
try
{
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
,
0
,
len
);
}
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
Utils
.
newBytes
(
len
);
System
.
arraycopy
(
buff
,
0
,
small
,
0
,
len
);
return
ValueLob2
.
createSmallLob
(
Value
.
BLOB
,
small
);
}
ValueLob2
lob
=
new
ValueLob2
(
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
.
compression
=
compressionAlgorithm
!=
null
;
synchronized
(
h
)
{
lobId
=
getNewObjectId
(
h
);
fileName
=
getFileNamePrefix
(
h
.
getDatabasePath
(),
lobId
)
+
Constants
.
SUFFIX_TEMP_FILE
;
tempFile
=
h
.
openFile
(
fileName
,
"rw"
,
false
);
tempFile
.
autoDelete
();
}
FileStoreOutputStream
out
=
new
FileStoreOutputStream
(
tempFile
,
h
,
compressionAlgorithm
);
return
out
;
}
private
void
createFromStream
(
byte
[]
buff
,
int
len
,
InputStream
in
,
long
remaining
,
DataHandler
h
)
{
try
{
FileStoreOutputStream
out
=
initLarge
(
h
);
boolean
compress
=
h
.
getLobCompressionAlgorithm
(
Value
.
BLOB
)
!=
null
;
try
{
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
,
0
,
len
);
if
(
len
<=
0
)
{
break
;
}
}
}
finally
{
out
.
close
();
}
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
/**
/**
* Convert a lob to another data type. The data is fully read in memory
* Convert a lob to another data type. The data is fully read in memory
* except when converting to BLOB or CLOB.
* except when converting to BLOB or CLOB.
...
@@ -299,26 +92,17 @@ public class ValueLob2 extends Value {
...
@@ -299,26 +92,17 @@ public class ValueLob2 extends Value {
if
(
t
==
type
)
{
if
(
t
==
type
)
{
return
this
;
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
}
else
if
(
t
==
Value
.
CLOB
)
{
Value
Lob2
copy
=
ValueLob2
.
createClob
(
getReader
(),
-
1
,
handler
);
Value
copy
=
handler
.
getLobStorage
().
createClob
(
getReader
(),
-
1
);
return
copy
;
return
copy
;
}
else
if
(
t
==
Value
.
BLOB
)
{
}
else
if
(
t
==
Value
.
BLOB
)
{
Value
Lob2
copy
=
ValueLob2
.
createBlob
(
getInputStream
(),
-
1
,
handler
);
Value
copy
=
handler
.
getLobStorage
().
createBlob
(
getInputStream
(),
-
1
);
return
copy
;
return
copy
;
}
}
return
super
.
convertTo
(
t
);
return
super
.
convertTo
(
t
);
}
}
public
boolean
isLinked
()
{
public
boolean
isLinked
()
{
return
linked
;
return
tableId
!=
LobStorage
.
TABLE_ID_SESSION_VARIABLE
;
}
/**
* Get the current file name where the lob is saved.
*
* @return the file name or null
*/
public
String
getFileName
()
{
return
fileName
;
}
}
public
void
close
()
{
public
void
close
()
{
...
@@ -330,50 +114,19 @@ public class ValueLob2 extends Value {
...
@@ -330,50 +114,19 @@ public class ValueLob2 extends Value {
}
}
}
}
public
void
unlink
()
{
private
static
synchronized
void
deleteFile
(
DataHandler
handler
,
String
fileName
)
{
if
(
linked
&&
fileName
!=
null
)
{
// synchronize on the database, to avoid concurrent temp file creation /
String
temp
;
// deletion / backup
// synchronize on the database, to avoid concurrent temp file
synchronized
(
handler
.
getLobSyncObject
())
{
// creation / deletion / backup
IOUtils
.
delete
(
fileName
);
synchronized
(
handler
)
{
temp
=
getFileName
(
handler
,
-
1
,
lobId
);
deleteFile
(
handler
,
temp
);
renameFile
(
handler
,
fileName
,
temp
);
tempFile
=
FileStore
.
open
(
handler
,
temp
,
"rw"
);
tempFile
.
autoDelete
();
tempFile
.
closeSilently
();
fileName
=
temp
;
linked
=
false
;
}
}
}
}
public
void
unlink
()
{
}
}
public
Value
link
(
DataHandler
h
,
int
tabId
)
{
public
Value
link
(
DataHandler
h
,
int
tabId
)
{
if
(
fileName
==
null
)
{
int
todo
;
this
.
tableId
=
tabId
;
return
this
;
}
if
(
linked
)
{
ValueLob2
copy
=
ValueLob2
.
copy
(
this
);
copy
.
lobId
=
getNewObjectId
(
h
);
copy
.
tableId
=
tabId
;
String
live
=
getFileName
(
h
,
copy
.
tableId
,
copy
.
lobId
);
copyFileTo
(
h
,
fileName
,
live
);
copy
.
fileName
=
live
;
copy
.
linked
=
true
;
return
copy
;
}
if
(!
linked
)
{
this
.
tableId
=
tabId
;
String
live
=
getFileName
(
h
,
tableId
,
lobId
);
if
(
tempFile
!=
null
)
{
tempFile
.
stopAutoDelete
();
tempFile
=
null
;
}
renameFile
(
h
,
fileName
,
live
);
fileName
=
live
;
linked
=
true
;
}
return
this
;
return
this
;
}
}
...
@@ -415,7 +168,7 @@ public class ValueLob2 extends Value {
...
@@ -415,7 +168,7 @@ public class ValueLob2 extends Value {
}
}
return
Utils
.
convertBytesToString
(
buff
);
return
Utils
.
convertBytesToString
(
buff
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
fileName
);
throw
DbException
.
convertIOException
(
e
,
toString
()
);
}
}
}
}
...
@@ -439,7 +192,7 @@ public class ValueLob2 extends Value {
...
@@ -439,7 +192,7 @@ public class ValueLob2 extends Value {
try
{
try
{
return
IOUtils
.
readBytesAndClose
(
getInputStream
(),
Integer
.
MAX_VALUE
);
return
IOUtils
.
readBytesAndClose
(
getInputStream
(),
Integer
.
MAX_VALUE
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
fileName
);
throw
DbException
.
convertIOException
(
e
,
toString
()
);
}
}
}
}
...
@@ -479,14 +232,20 @@ public class ValueLob2 extends Value {
...
@@ -479,14 +232,20 @@ public class ValueLob2 extends Value {
}
}
public
InputStream
getInputStream
()
{
public
InputStream
getInputStream
()
{
if
(
fileName
=
=
null
)
{
if
(
small
!
=
null
)
{
return
new
ByteArrayInputStream
(
small
);
return
new
ByteArrayInputStream
(
small
);
}
}
else
if
(
fileName
!=
null
)
{
FileStore
store
=
handler
.
openFile
(
fileName
,
"r"
,
true
);
FileStore
store
=
handler
.
openFile
(
fileName
,
"r"
,
true
);
boolean
alwaysClose
=
SysProperties
.
lobCloseBetweenReads
;
boolean
alwaysClose
=
SysProperties
.
lobCloseBetweenReads
;
return
new
BufferedInputStream
(
new
FileStoreInputStream
(
store
,
handler
,
compression
,
alwaysClose
),
return
new
BufferedInputStream
(
new
FileStoreInputStream
(
store
,
handler
,
false
,
alwaysClose
),
Constants
.
IO_BUFFER_SIZE
);
Constants
.
IO_BUFFER_SIZE
);
}
}
try
{
return
lobStorage
.
getInputStream
(
lobId
);
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
toString
());
}
}
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
long
p
=
getPrecision
();
long
p
=
getPrecision
();
...
@@ -521,7 +280,7 @@ public class ValueLob2 extends Value {
...
@@ -521,7 +280,7 @@ public class ValueLob2 extends Value {
}
else
{
}
else
{
buff
.
append
(
"CAST(REPEAT('00', "
).
append
(
getPrecision
()).
append
(
") AS BINARY"
);
buff
.
append
(
"CAST(REPEAT('00', "
).
append
(
getPrecision
()).
append
(
") AS BINARY"
);
}
}
buff
.
append
(
" /*
"
).
append
(
fileName
).
append
(
" */)"
);
buff
.
append
(
" /*
table: "
).
append
(
tableId
).
append
(
" id: "
).
append
(
lobId
).
append
(
" */)"
);
return
buff
.
toString
();
return
buff
.
toString
();
}
}
...
@@ -542,122 +301,206 @@ public class ValueLob2 extends Value {
...
@@ -542,122 +301,206 @@ public class ValueLob2 extends Value {
return
other
instanceof
ValueLob
&&
compareSecure
((
Value
)
other
,
null
)
==
0
;
return
other
instanceof
ValueLob
&&
compareSecure
((
Value
)
other
,
null
)
==
0
;
}
}
public
boolean
isFileBased
()
{
return
small
==
null
;
}
public
int
getMemory
()
{
if
(
small
!=
null
)
{
return
small
.
length
+
32
;
}
return
128
;
}
/**
/**
*
Store the lob data to a file if the size of the buffer it larger than the
*
Create an independent copy of this temporary value.
*
maximum size for an in-place lob
.
*
The file will not be deleted automatically
.
*
*
* @
param h the data handler
* @
return the value
*/
*/
public
void
convertToFileIfRequired
(
DataHandler
h
)
{
public
ValueLob2
copyToTemp
()
{
if
(
small
!=
null
&&
small
.
length
>
h
.
getMaxLengthInplaceLob
())
{
return
this
;
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
=
link
(
h
,
tabId
);
if
(
SysProperties
.
CHECK
&&
v2
!=
this
)
{
public
long
getLobId
(
)
{
DbException
.
throwInternalError
()
;
return
lobId
;
}
}
public
void
setPrecision
(
long
precision
)
{
this
.
precision
=
precision
;
}
}
public
String
toString
()
{
return
"lob: "
+
fileName
+
" table: "
+
tableId
+
" id: "
+
lobId
;
}
}
/**
/**
*
Remove all lobs for a given table id
.
*
Create a temporary 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
* @param handler the data handler
* @
param tableId the table id
* @
return the lob value
*/
*/
public
static
void
removeAllForTable
(
DataHandler
handler
,
int
tableId
)
{
public
static
ValueLob2
createTempClob
(
Reader
in
,
long
length
,
DataHandler
handler
)
{
String
dir
=
getFileNamePrefix
(
handler
.
getDatabasePath
(),
0
);
try
{
removeAllForTable
(
handler
,
dir
,
tableId
);
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
);
private
static
void
removeAllForTable
(
DataHandler
handler
,
String
dir
,
int
tableId
)
{
char
[]
buff
;
for
(
String
name
:
IOUtils
.
listFiles
(
dir
))
{
if
(
len
>=
Integer
.
MAX_VALUE
)
{
if
(
IOUtils
.
isDirectory
(
name
))
{
String
data
=
IOUtils
.
readStringAndClose
(
in
,
-
1
);
removeAllForTable
(
handler
,
name
,
tableId
);
buff
=
data
.
toCharArray
();
len
=
buff
.
length
;
}
else
{
}
else
{
if
(
name
.
endsWith
(
".t"
+
tableId
+
Constants
.
SUFFIX_LOB_FILE
))
{
buff
=
new
char
[
len
];
deleteFile
(
handler
,
name
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
len
=
len
<
0
?
0
:
len
;
}
}
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
byte
[]
small
=
StringUtils
.
utf8Encode
(
new
String
(
buff
,
0
,
len
));
return
ValueLob2
.
createSmallLob
(
Value
.
CLOB
,
small
);
}
}
ValueLob2
lob
=
new
ValueLob2
(
Value
.
CLOB
,
null
);
lob
.
createTempFromReader
(
buff
,
len
,
in
,
remaining
,
handler
);
return
lob
;
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
}
}
/**
/**
* C
heck if this lob value is compressed
.
* C
reate a temporary BLOB value from a stream
.
*
*
* @return true if it is
* @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
*/
*/
public
boolean
useCompression
()
{
public
static
ValueLob2
createTempBlob
(
InputStream
in
,
long
length
,
DataHandler
handler
)
{
return
compression
;
try
{
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
);
public
boolean
isFileBased
()
{
byte
[]
buff
;
return
fileName
!=
null
;
if
(
len
>=
Integer
.
MAX_VALUE
)
{
buff
=
IOUtils
.
readBytesAndClose
(
in
,
-
1
);
len
=
buff
.
length
;
}
else
{
buff
=
Utils
.
newBytes
(
len
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
0
,
len
);
}
}
if
(
len
<=
handler
.
getMaxLengthInplaceLob
())
{
private
static
synchronized
void
deleteFile
(
DataHandler
handler
,
String
fileName
)
{
byte
[]
small
=
Utils
.
newBytes
(
len
);
// synchronize on the database, to avoid concurrent temp file creation /
System
.
arraycopy
(
buff
,
0
,
small
,
0
,
len
);
// deletion / backup
return
ValueLob2
.
createSmallLob
(
Value
.
BLOB
,
small
);
synchronized
(
handler
.
getLobSyncObject
())
{
}
IOUtils
.
delete
(
fileName
);
ValueLob2
lob
=
new
ValueLob2
(
Value
.
BLOB
,
null
);
lob
.
createTempFromStream
(
buff
,
len
,
in
,
remaining
,
handler
);
return
lob
;
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
}
}
private
static
synchronized
void
renameFile
(
DataHandler
handler
,
String
oldName
,
String
newName
)
private
void
createTempFromReader
(
char
[]
buff
,
int
len
,
Reader
in
,
long
remaining
,
DataHandler
h
)
{
{
try
{
synchronized
(
handler
.
getLobSyncObject
())
{
FileStoreOutputStream
out
=
initTemp
(
h
);
IOUtils
.
rename
(
oldName
,
newName
);
try
{
while
(
true
)
{
precision
+=
len
;
byte
[]
b
=
StringUtils
.
utf8Encode
(
new
String
(
buff
,
0
,
len
));
out
.
write
(
b
,
0
,
b
.
length
);
remaining
-=
len
;
if
(
remaining
<=
0
)
{
break
;
}
}
len
=
getBufferSize
(
h
,
false
,
remaining
);
len
=
IOUtils
.
readFully
(
in
,
buff
,
len
);
if
(
len
<=
0
)
{
break
;
}
}
private
void
copyFileTo
(
DataHandler
h
,
String
sourceFileName
,
String
targetFileName
)
{
synchronized
(
h
.
getLobSyncObject
())
{
FileSystem
.
getInstance
(
sourceFileName
).
copy
(
sourceFileName
,
targetFileName
);
}
}
}
finally
{
out
.
close
();
}
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
/**
* Set the file name of this lob value.
*
* @param fileName the file name
* @param linked if the lob is linked
*/
public
void
setFileName
(
String
fileName
,
boolean
linked
)
{
this
.
fileName
=
fileName
;
this
.
linked
=
linked
;
}
}
public
int
getMemory
()
{
private
void
createTempFromStream
(
byte
[]
buff
,
int
len
,
InputStream
in
,
long
remaining
,
DataHandler
h
)
{
if
(
small
!=
null
)
{
try
{
return
small
.
length
+
32
;
FileStoreOutputStream
out
=
initTemp
(
h
);
boolean
compress
=
h
.
getLobCompressionAlgorithm
(
Value
.
BLOB
)
!=
null
;
try
{
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
,
0
,
len
);
if
(
len
<=
0
)
{
break
;
}
}
}
finally
{
out
.
close
();
}
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
}
return
128
;
}
}
/**
private
FileStoreOutputStream
initTemp
(
DataHandler
h
)
{
* Create an independent copy of this temporary value.
this
.
precision
=
0
;
* The file will not be deleted automatically.
this
.
handler
=
h
;
*
this
.
small
=
null
;
* @return the value
try
{
*/
String
path
=
h
.
getDatabasePath
();
public
ValueLob2
copyToTemp
()
{
if
(
path
.
length
()
==
0
)
{
ValueLob2
lob
;
path
=
SysProperties
.
PREFIX_TEMP_FILE
;
if
(
type
==
CLOB
)
{
lob
=
ValueLob2
.
createClob
(
getReader
(),
precision
,
handler
);
}
else
{
lob
=
ValueLob2
.
createBlob
(
getInputStream
(),
precision
,
handler
);
}
}
return
lob
;
fileName
=
IOUtils
.
createTempFile
(
path
,
Constants
.
SUFFIX_TEMP_FILE
,
true
,
true
);
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
null
);
}
tempFile
=
h
.
openFile
(
fileName
,
"rw"
,
false
);
tempFile
.
autoDelete
();
FileStoreOutputStream
out
=
new
FileStoreOutputStream
(
tempFile
,
null
,
null
);
return
out
;
}
}
public
long
getLobId
()
{
private
static
int
getBufferSize
(
DataHandler
handler
,
boolean
compress
,
long
remaining
)
{
return
lobId
;
if
(
remaining
<
0
||
remaining
>
Integer
.
MAX_VALUE
)
{
remaining
=
Integer
.
MAX_VALUE
;
}
long
inplace
=
handler
.
getMaxLengthInplaceLob
();
if
(
inplace
>=
Integer
.
MAX_VALUE
)
{
inplace
=
remaining
;
}
long
m
=
compress
?
Constants
.
IO_BUFFER_SIZE_COMPRESS
:
Constants
.
IO_BUFFER_SIZE
;
if
(
m
<
remaining
&&
m
<=
inplace
)
{
m
=
Math
.
min
(
remaining
,
inplace
+
1
);
// 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
;
}
}
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论