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

New lob storage.

上级 8ffac30c
...@@ -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();
......
...@@ -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;
}
} }
...@@ -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.
......
...@@ -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;
} }
......
...@@ -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 {
return new JdbcClob(this, v, id); 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) { } 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;
} }
......
...@@ -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,25 +515,38 @@ public class Data { ...@@ -514,25 +515,38 @@ public class Data {
case Value.BLOB: case Value.BLOB:
case Value.CLOB: { case Value.CLOB: {
writeByte((byte) type); writeByte((byte) type);
ValueLob lob = (ValueLob) v; if (v instanceof ValueLob) {
lob.convertToFileIfRequired(handler); ValueLob lob = (ValueLob) v;
byte[] small = lob.getSmall(); lob.convertToFileIfRequired(handler);
if (small == null) { byte[] small = lob.getSmall();
int t = -1; if (small == null) {
if (!lob.isLinked()) { int t = -1;
t = -2; if (!lob.isLinked()) {
} t = -2;
writeVarInt(t); }
writeVarInt(lob.getTableId()); writeVarInt(t);
writeVarInt(lob.getObjectId()); writeVarInt(lob.getTableId());
writeVarLong(lob.getPrecision()); writeVarInt(lob.getObjectId());
writeByte((byte) (lob.useCompression() ? 1 : 0)); writeVarLong(lob.getPrecision());
if (t == -2) { writeByte((byte) (lob.useCompression() ? 1 : 0));
writeString(lob.getFileName()); if (t == -2) {
writeString(lob.getFileName());
}
} else {
writeVarInt(small.length);
write(small, 0, small.length);
} }
} else { } else {
writeVarInt(small.length); ValueLob2 lob = (ValueLob2) v;
write(small, 0, small.length); 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;
} }
...@@ -654,23 +668,29 @@ public class Data { ...@@ -654,23 +668,29 @@ 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 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: { case Value.ARRAY: {
int len = readVarInt(); int len = readVarInt();
...@@ -809,25 +829,38 @@ public class Data { ...@@ -809,25 +829,38 @@ public class Data {
case Value.BLOB: case Value.BLOB:
case Value.CLOB: { case Value.CLOB: {
int len = 1; int len = 1;
ValueLob lob = (ValueLob) v; if (v instanceof ValueLob) {
lob.convertToFileIfRequired(handler); ValueLob lob = (ValueLob) v;
byte[] small = lob.getSmall(); lob.convertToFileIfRequired(handler);
if (small == null) { byte[] small = lob.getSmall();
int t = -1; if (small == null) {
if (!lob.isLinked()) { int t = -1;
t = -2; if (!lob.isLinked()) {
} t = -2;
len += getVarIntLen(t); }
len += getVarIntLen(lob.getTableId()); len += getVarIntLen(t);
len += getVarIntLen(lob.getObjectId()); len += getVarIntLen(lob.getTableId());
len += getVarLongLen(lob.getPrecision()); len += getVarIntLen(lob.getObjectId());
len += 1; len += getVarLongLen(lob.getPrecision());
if (t == -2) { len += 1;
len += getStringLen(lob.getFileName()); if (t == -2) {
len += getStringLen(lob.getFileName());
}
} else {
len += getVarIntLen(small.length);
len += small.length;
} }
} else { } else {
len += getVarIntLen(small.length); ValueLob2 lob = (ValueLob2) v;
len += small.length; 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;
} }
......
...@@ -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();
} }
...@@ -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;
}
} }
...@@ -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);
} }
......
...@@ -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);
......
...@@ -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;
......
...@@ -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
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论