提交 40de3268 authored 作者: Thomas Mueller's avatar Thomas Mueller

New lob storage.

上级 8ffac30c
......@@ -12,7 +12,6 @@ import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.schema.Schema;
import org.h2.store.LobStorage;
import org.h2.table.Table;
/**
......@@ -83,7 +82,7 @@ public class DropTable extends SchemaCommand {
table.setModified();
Database db = session.getDatabase();
db.removeSchemaObject(session, table);
LobStorage.removeAllForTable(db, dropTableId);
db.getLobStorage().removeAllForTable(dropTableId);
}
if (next != null) {
next.executeDrop();
......
......@@ -11,6 +11,7 @@ import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import org.h2.command.Prepared;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
......@@ -228,4 +229,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
return null;
}
public Connection getLobConnection() {
return null;
}
}
......@@ -66,7 +66,7 @@ public class SysProperties {
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
* names.
*/
......@@ -437,6 +437,12 @@ public class SysProperties {
*/
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 />
* Always recompile prepared statements.
......
......@@ -8,6 +8,7 @@ package org.h2.engine;
import java.io.IOException;
import java.net.Socket;
import java.sql.Connection;
import java.util.ArrayList;
import org.h2.api.DatabaseEventListener;
import org.h2.command.CommandInterface;
......@@ -80,6 +81,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
private int lastReconnect;
private SessionInterface embedded;
private DatabaseEventListener eventListener;
private LobStorage lobStorage;
public SessionRemote() {
// nothing to do
......@@ -620,6 +622,13 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
}
public LobStorage getLobStorage() {
if (lobStorage == null) {
lobStorage = new LobStorage(this);
}
return lobStorage;
}
public Connection getLobConnection() {
return null;
}
......
......@@ -6,7 +6,9 @@
*/
package org.h2.jdbc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Blob;
import java.sql.CallableStatement;
......@@ -32,7 +34,6 @@ import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.message.TraceObject;
import org.h2.result.ResultInterface;
import org.h2.store.LobStorage;
import org.h2.util.Utils;
import org.h2.value.CompareMode;
import org.h2.value.Value;
......@@ -1438,7 +1439,9 @@ public class JdbcConnection extends TraceObject implements Connection {
debugCodeAssign("Clob", TraceObject.CLOB, id, "createClob()");
checkClosedForWrite();
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);
} finally {
afterWriting();
......@@ -1459,7 +1462,7 @@ public class JdbcConnection extends TraceObject implements Connection {
debugCodeAssign("Blob", TraceObject.BLOB, id, "createClob()");
checkClosedForWrite();
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);
} finally {
afterWriting();
......@@ -1480,8 +1483,14 @@ public class JdbcConnection extends TraceObject implements Connection {
int id = getNextId(TraceObject.CLOB);
debugCodeAssign("NClob", TraceObject.CLOB, id, "createNClob()");
checkClosedForWrite();
Value v = LobStorage.createSmallLob(Value.CLOB, Utils.EMPTY_BYTES);
return new JdbcClob(this, v, id);
try {
Value v = session.getDataHandler().getLobStorage().createClob(
new InputStreamReader(
new ByteArrayInputStream(Utils.EMPTY_BYTES)), 0);
return new JdbcClob(this, v, id);
} finally {
afterWriting();
}
} catch (Exception e) {
throw logAndConvert(e);
}
......@@ -1614,7 +1623,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if (length <= 0) {
length = -1;
}
Value v = LobStorage.createClob(x, length, session.getDataHandler());
Value v = session.getDataHandler().getLobStorage().createClob(x, length);
return v;
}
......@@ -1633,7 +1642,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if (length <= 0) {
length = -1;
}
Value v = LobStorage.createBlob(x, length, session.getDataHandler());
Value v = session.getDataHandler().getLobStorage().createBlob(x, length);
return v;
}
......
......@@ -32,6 +32,7 @@ import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
import org.h2.value.ValueJavaObject;
import org.h2.value.ValueLob;
import org.h2.value.ValueLob2;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
......@@ -514,25 +515,38 @@ public class Data {
case Value.BLOB:
case Value.CLOB: {
writeByte((byte) type);
ValueLob lob = (ValueLob) v;
lob.convertToFileIfRequired(handler);
byte[] small = lob.getSmall();
if (small == null) {
int t = -1;
if (!lob.isLinked()) {
t = -2;
}
writeVarInt(t);
writeVarInt(lob.getTableId());
writeVarInt(lob.getObjectId());
writeVarLong(lob.getPrecision());
writeByte((byte) (lob.useCompression() ? 1 : 0));
if (t == -2) {
writeString(lob.getFileName());
if (v instanceof ValueLob) {
ValueLob lob = (ValueLob) v;
lob.convertToFileIfRequired(handler);
byte[] small = lob.getSmall();
if (small == null) {
int t = -1;
if (!lob.isLinked()) {
t = -2;
}
writeVarInt(t);
writeVarInt(lob.getTableId());
writeVarInt(lob.getObjectId());
writeVarLong(lob.getPrecision());
writeByte((byte) (lob.useCompression() ? 1 : 0));
if (t == -2) {
writeString(lob.getFileName());
}
} else {
writeVarInt(small.length);
write(small, 0, small.length);
}
} else {
writeVarInt(small.length);
write(small, 0, small.length);
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;
}
......@@ -654,23 +668,29 @@ public class Data {
byte[] small = Utils.newBytes(smallLen);
read(small, 0, smallLen);
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 objectId = readVarInt();
long precision = 0;
boolean compression = false;
// -1: regular
// -2: regular, but not linked (in this case: including file name)
if (smallLen == -1 || smallLen == -2) {
precision = readVarLong();
compression = readByte() == 1;
}
ValueLob lob = ValueLob.open(type, handler, tableId, objectId, precision, compression);
if (smallLen == -2) {
lob.setFileName(readString(), false);
}
return lob;
}
int tableId = readVarInt();
int objectId = readVarInt();
long precision = 0;
boolean compression = false;
// TODO simplify
// -1: regular
// -2: regular, but not linked (in this case: including file name)
if (smallLen == -1 || smallLen == -2) {
precision = readVarLong();
compression = readByte() == 1;
}
ValueLob lob = ValueLob.open(type, handler, tableId, objectId, precision, compression);
if (smallLen == -2) {
lob.setFileName(readString(), false);
}
return lob;
}
case Value.ARRAY: {
int len = readVarInt();
......@@ -809,25 +829,38 @@ public class Data {
case Value.BLOB:
case Value.CLOB: {
int len = 1;
ValueLob lob = (ValueLob) v;
lob.convertToFileIfRequired(handler);
byte[] small = lob.getSmall();
if (small == null) {
int t = -1;
if (!lob.isLinked()) {
t = -2;
}
len += getVarIntLen(t);
len += getVarIntLen(lob.getTableId());
len += getVarIntLen(lob.getObjectId());
len += getVarLongLen(lob.getPrecision());
len += 1;
if (t == -2) {
len += getStringLen(lob.getFileName());
if (v instanceof ValueLob) {
ValueLob lob = (ValueLob) v;
lob.convertToFileIfRequired(handler);
byte[] small = lob.getSmall();
if (small == null) {
int t = -1;
if (!lob.isLinked()) {
t = -2;
}
len += getVarIntLen(t);
len += getVarIntLen(lob.getTableId());
len += getVarIntLen(lob.getObjectId());
len += getVarLongLen(lob.getPrecision());
len += 1;
if (t == -2) {
len += getStringLen(lob.getFileName());
}
} else {
len += getVarIntLen(small.length);
len += small.length;
}
} else {
len += getVarIntLen(small.length);
len += small.length;
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;
}
......
......@@ -6,6 +6,7 @@
*/
package org.h2.store;
import java.sql.Connection;
import org.h2.util.SmallLRUCache;
import org.h2.util.TempFileDeleter;
......@@ -91,6 +92,18 @@ public interface DataHandler {
*/
SmallLRUCache<String, String[]> getLobFileListCache();
/**
* Get the lob storage mechanism to use.
*
* @return the lob storage mechanism
*/
LobStorage getLobStorage();
/**
* Get a database connection to be used for LOB access.
*
* @return the connection or null
*/
Connection getLobConnection();
}
......@@ -1223,4 +1223,11 @@ public class Recover extends Tool implements DataHandler {
return null;
}
/**
* INTERNAL
*/
public Connection getLobConnection() {
return null;
}
}
......@@ -546,7 +546,7 @@ public class DataType {
if (in == null) {
v = ValueNull.INSTANCE;
} else {
v = LobStorage.createClob(new BufferedReader(in), -1, session.getDataHandler());
v = session.getDataHandler().getLobStorage().createClob(new BufferedReader(in), -1);
}
}
break;
......@@ -556,7 +556,7 @@ public class DataType {
v = LobStorage.createSmallLob(Value.BLOB, rs.getBytes(columnIndex));
} else {
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;
}
......@@ -864,19 +864,19 @@ public class DataType {
return ValueTimestamp.get(new Timestamp(((java.util.Date) x).getTime()));
} else if (x instanceof java.io.Reader) {
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) {
try {
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) {
throw DbException.convert(e);
}
} 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) {
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) {
throw DbException.convert(e);
}
......
......@@ -29,13 +29,12 @@ import org.h2.engine.Constants;
import org.h2.engine.SessionInterface;
import org.h2.message.DbException;
import org.h2.message.TraceSystem;
import org.h2.store.LobStorage;
import org.h2.tools.SimpleResultSet;
import org.h2.util.Utils;
import org.h2.util.ExactUTF8InputStreamReader;
import org.h2.util.IOUtils;
import org.h2.util.NetUtils;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
/**
* The transfer class is used to send and receive Value objects.
......@@ -484,7 +483,7 @@ public class Transfer {
return ValueStringFixed.get(readString());
case Value.BLOB: {
long length = readLong();
Value v = LobStorage.createBlob(in, length, session.getDataHandler());
Value v = session.getDataHandler().getLobStorage().createBlob(in, length);
int magic = readInt();
if (magic != LOB_MAGIC) {
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "magic=" + magic);
......@@ -493,7 +492,7 @@ public class Transfer {
}
case Value.CLOB: {
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();
if (magic != LOB_MAGIC) {
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "magic=" + magic);
......
......@@ -706,6 +706,7 @@ public abstract class Value {
case BLOB: {
switch(getType()) {
case BYTES:
return LobStorage.createSmallLob(Value.BLOB, getBytesNoCopy());
}
break;
......
......@@ -44,9 +44,6 @@ import org.h2.util.Utils;
* Data compression is supported.
*/
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
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论