提交 dfd26da7 authored 作者: Thomas Mueller's avatar Thomas Mueller

Ensure the JDBC client doesn't reference the Database class. Add missing @Override

上级 3fcb3c2a
...@@ -42,6 +42,7 @@ import org.h2.store.FileLock; ...@@ -42,6 +42,7 @@ import org.h2.store.FileLock;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.InDoubtTransaction; import org.h2.store.InDoubtTransaction;
import org.h2.store.LobStorageBackend; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageFrontend;
import org.h2.store.PageStore; import org.h2.store.PageStore;
import org.h2.store.WriterThread; import org.h2.store.WriterThread;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
...@@ -1121,7 +1122,7 @@ public class Database implements DataHandler { ...@@ -1121,7 +1122,7 @@ public class Database implements DataHandler {
if (lobStorageIsUsed) { if (lobStorageIsUsed) {
try { try {
getLobStorage(); getLobStorage();
lobStorage.removeAllForTable(LobStorageBackend.TABLE_ID_SESSION_VARIABLE); lobStorage.removeAllForTable(LobStorageFrontend.TABLE_ID_SESSION_VARIABLE);
} catch (DbException e) { } catch (DbException e) {
trace.error(e, "close"); trace.error(e, "close");
} }
......
...@@ -33,6 +33,7 @@ import org.h2.schema.Schema; ...@@ -33,6 +33,7 @@ import org.h2.schema.Schema;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.InDoubtTransaction; import org.h2.store.InDoubtTransaction;
import org.h2.store.LobStorageBackend; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageFrontend;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -148,7 +149,7 @@ public class Session extends SessionWithState { ...@@ -148,7 +149,7 @@ public class Session extends SessionWithState {
old = variables.remove(name); old = variables.remove(name);
} else { } else {
// link LOB values, to make sure we have our own object // link LOB values, to make sure we have our own object
value = value.link(database, LobStorageBackend.TABLE_ID_SESSION_VARIABLE); value = value.link(database, LobStorageFrontend.TABLE_ID_SESSION_VARIABLE);
old = variables.put(name, value); old = variables.put(name, value);
} }
if (old != null) { if (old != null) {
...@@ -578,6 +579,7 @@ public class Session extends SessionWithState { ...@@ -578,6 +579,7 @@ public class Session extends SessionWithState {
} }
} }
@Override
public boolean hasPendingTransaction() { public boolean hasPendingTransaction() {
return undoLog.size() > 0; return undoLog.size() > 0;
} }
......
...@@ -123,6 +123,7 @@ public class SessionRemote extends SessionWithState implements DataHandler { ...@@ -123,6 +123,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
return trans; return trans;
} }
@Override
public boolean hasPendingTransaction() { public boolean hasPendingTransaction() {
if (clientVersion < Constants.TCP_PROTOCOL_VERSION_10) { if (clientVersion < Constants.TCP_PROTOCOL_VERSION_10) {
return true; return true;
......
...@@ -15,6 +15,7 @@ import java.sql.ResultSetMetaData; ...@@ -15,6 +15,7 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
...@@ -23,7 +24,7 @@ import org.h2.mvstore.type.DataType; ...@@ -23,7 +24,7 @@ import org.h2.mvstore.type.DataType;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.LobStorageBackend; import org.h2.store.LobStorageFrontend;
import org.h2.store.LobStorageInterface; import org.h2.store.LobStorageInterface;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
...@@ -597,7 +598,7 @@ public class ValueDataType implements DataType { ...@@ -597,7 +598,7 @@ public class ValueDataType implements DataType {
if (smallLen >= 0) { if (smallLen >= 0) {
byte[] small = DataUtils.newBytes(smallLen); byte[] small = DataUtils.newBytes(smallLen);
buff.get(small, 0, smallLen); buff.get(small, 0, smallLen);
return LobStorageBackend.createSmallLob(type, small); return LobStorageFrontend.createSmallLob(type, small);
} else if (smallLen == -3) { } else if (smallLen == -3) {
int tableId = readVarInt(buff); int tableId = readVarInt(buff);
long lobId = readVarLong(buff); long lobId = readVarLong(buff);
......
...@@ -787,7 +787,7 @@ public class Data { ...@@ -787,7 +787,7 @@ public class Data {
if (smallLen >= 0) { if (smallLen >= 0) {
byte[] small = DataUtils.newBytes(smallLen); byte[] small = DataUtils.newBytes(smallLen);
read(small, 0, smallLen); read(small, 0, smallLen);
return LobStorageBackend.createSmallLob(type, small); return LobStorageFrontend.createSmallLob(type, small);
} else if (smallLen == -3) { } else if (smallLen == -3) {
int tableId = readVarInt(); int tableId = readVarInt();
long lobId = readVarLong(); long lobId = readVarLong();
......
...@@ -17,6 +17,7 @@ import java.sql.Statement; ...@@ -17,6 +17,7 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -37,16 +38,6 @@ import org.h2.value.ValueLobDb; ...@@ -37,16 +38,6 @@ import org.h2.value.ValueLobDb;
*/ */
public class LobStorageBackend implements LobStorageInterface { public class LobStorageBackend implements LobStorageInterface {
/**
* The table id for session variables (LOBs not assigned to a table).
*/
public static final int TABLE_ID_SESSION_VARIABLE = -1;
/**
* The table id for temporary objects (not assigned to any object).
*/
public static final int TABLE_TEMP = -2;
/** /**
* The name of the lob data table. If this table exists, then lob storage is * The name of the lob data table. If this table exists, then lob storage is
* used. * used.
...@@ -183,8 +174,8 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -183,8 +174,8 @@ public class LobStorageBackend implements LobStorageInterface {
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} }
if (tableId == TABLE_ID_SESSION_VARIABLE) { if (tableId == LobStorageFrontend.TABLE_ID_SESSION_VARIABLE) {
removeAllForTable(TABLE_TEMP); removeAllForTable(LobStorageFrontend.TABLE_TEMP);
} }
// 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
// (compatibility) // (compatibility)
...@@ -192,26 +183,6 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -192,26 +183,6 @@ public class LobStorageBackend implements LobStorageInterface {
ValueLob.removeAllForTable(database, tableId); ValueLob.removeAllForTable(database, tableId);
} }
/**
* Create a LOB object that fits in memory.
*
* @param type the value type
* @param small the byte array
* @return the LOB
*/
public static Value createSmallLob(int type, byte[] small) {
if (SysProperties.LOB_IN_DATABASE) {
int precision;
if (type == Value.CLOB) {
precision = new String(small, Constants.UTF8).length();
} else {
precision = small.length;
}
return ValueLobDb.createSmallLob(type, small, precision);
}
return ValueLob.createSmallLob(type, small);
}
/** /**
* Read a block of data from the given LOB. * Read a block of data from the given LOB.
* *
...@@ -270,144 +241,6 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -270,144 +241,6 @@ public class LobStorageBackend implements LobStorageInterface {
} }
} }
/**
* An input stream that reads from a LOB.
*/
public class LobInputStream extends InputStream {
/**
* The size of the lob.
*/
private final long length;
/**
* The remaining bytes in the lob.
*/
private long remainingBytes;
/**
* The temporary buffer.
*/
private byte[] buffer;
/**
* The position within the buffer.
*/
private int pos;
/**
* The lob id.
*/
private final long lob;
/**
* The lob sequence id.
*/
private int seq;
public LobInputStream(long lob, long byteCount) {
this.lob = lob;
remainingBytes = byteCount;
this.length = byteCount;
}
@Override
public int read() throws IOException {
fillBuffer();
if (remainingBytes <= 0) {
return -1;
}
remainingBytes--;
return buffer[pos++] & 255;
}
@Override
public long skip(long n) throws IOException {
long remaining = n;
remaining -= skipSmall(remaining);
if (remaining > BLOCK_LENGTH) {
long toPos = length - remainingBytes + remaining;
try {
long[] seqPos = skipBuffer(lob, toPos);
if (seqPos == null) {
remaining -= super.skip(remaining);
return n - remaining;
}
seq = (int) seqPos[0];
long p = seqPos[1];
remainingBytes = length - p;
remaining = toPos - p;
} catch (SQLException e) {
throw DbException.convertToIOException(e);
}
pos = 0;
buffer = null;
}
fillBuffer();
remaining -= skipSmall(remaining);
remaining -= super.skip(remaining);
return n - remaining;
}
private int skipSmall(long n) {
if (n > 0 && buffer != null && pos < buffer.length) {
int x = MathUtils.convertLongToInt(Math.min(n, buffer.length - pos));
pos += x;
remainingBytes -= x;
return x;
}
return 0;
}
@Override
public int read(byte[] buff) throws IOException {
return readFully(buff, 0, buff.length);
}
@Override
public int read(byte[] buff, int off, int length) throws IOException {
return readFully(buff, off, length);
}
private int readFully(byte[] buff, int off, int length) throws IOException {
if (length == 0) {
return 0;
}
int read = 0;
while (length > 0) {
fillBuffer();
if (remainingBytes <= 0) {
break;
}
int len = (int) Math.min(length, remainingBytes);
len = Math.min(len, buffer.length - pos);
System.arraycopy(buffer, pos, buff, off, len);
pos += len;
read += len;
remainingBytes -= len;
off += len;
length -= len;
}
return read == 0 ? -1 : read;
}
private void fillBuffer() throws IOException {
if (buffer != null && pos < buffer.length) {
return;
}
if (remainingBytes <= 0) {
return;
}
try {
buffer = readBlock(lob, seq++);
pos = 0;
} catch (SQLException e) {
throw DbException.convertToIOException(e);
}
}
}
private PreparedStatement prepare(String sql) throws SQLException { private PreparedStatement prepare(String sql) throws SQLException {
if (SysProperties.CHECK2) { if (SysProperties.CHECK2) {
if (!Thread.holdsLock(database)) { if (!Thread.holdsLock(database)) {
...@@ -430,11 +263,6 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -430,11 +263,6 @@ public class LobStorageBackend implements LobStorageInterface {
prepared.put(sql, prep); prepared.put(sql, prep);
} }
/**
* Delete a LOB from the database.
*
* @param lob the lob id
*/
@Override @Override
public void removeLob(long lob) { public void removeLob(long lob) {
try { try {
...@@ -479,14 +307,6 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -479,14 +307,6 @@ public class LobStorageBackend implements LobStorageInterface {
} }
} }
/**
* Get the input stream for the given lob.
*
* @param lobId the lob id
* @param hmac the message authentication code (for remote input streams)
* @param byteCount the number of bytes to read, or -1 if not known
* @return the stream
*/
@Override @Override
public InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException { public InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException {
init(); init();
...@@ -557,7 +377,7 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -557,7 +377,7 @@ public class LobStorageBackend implements LobStorageInterface {
ValueLobDb v = ValueLobDb.createSmallLob(type, small, small.length); ValueLobDb v = ValueLobDb.createSmallLob(type, small, small.length);
return v; return v;
} }
return registerLob(type, lobId, TABLE_TEMP, length); return registerLob(type, lobId, LobStorageFrontend.TABLE_TEMP, length);
} catch (IOException e) { } catch (IOException e) {
if (lobId != -1) { if (lobId != -1) {
removeLob(lobId); removeLob(lobId);
...@@ -587,15 +407,6 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -587,15 +407,6 @@ public class LobStorageBackend implements LobStorageInterface {
} }
} }
/**
* Copy a lob.
*
* @param type the type
* @param oldLobId the old lob id
* @param tableId the new table id
* @param length the length
* @return the new lob
*/
@Override @Override
public ValueLobDb copyLob(int type, long oldLobId, int tableId, long length) { public ValueLobDb copyLob(int type, long oldLobId, int tableId, long length) {
synchronized (database) { synchronized (database) {
...@@ -710,6 +521,183 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -710,6 +521,183 @@ public class LobStorageBackend implements LobStorageInterface {
} }
} }
@Override
public Value createBlob(InputStream in, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) {
init();
return addLob(in, maxLength, Value.BLOB);
}
return ValueLob.createBlob(in, maxLength, database);
}
@Override
public Value createClob(Reader reader, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) {
init();
long max = maxLength == -1 ? Long.MAX_VALUE : maxLength;
CountingReaderInputStream in = new CountingReaderInputStream(reader, max);
ValueLobDb lob = addLob(in, Long.MAX_VALUE, Value.CLOB);
lob.setPrecision(in.getLength());
return lob;
}
return ValueLob.createClob(reader, maxLength, database);
}
@Override
public void setTable(long lobId, int table) {
synchronized (database) {
try {
init();
String sql = "UPDATE " + LOBS + " SET TABLE = ? WHERE ID = ?";
PreparedStatement prep = prepare(sql);
prep.setInt(1, table);
prep.setLong(2, lobId);
prep.executeUpdate();
reuse(sql, prep);
} catch (SQLException e) {
throw DbException.convert(e);
}
}
}
/**
* An input stream that reads from a LOB.
*/
public class LobInputStream extends InputStream {
/**
* The size of the lob.
*/
private final long length;
/**
* The remaining bytes in the lob.
*/
private long remainingBytes;
/**
* The temporary buffer.
*/
private byte[] buffer;
/**
* The position within the buffer.
*/
private int pos;
/**
* The lob id.
*/
private final long lob;
/**
* The lob sequence id.
*/
private int seq;
public LobInputStream(long lob, long byteCount) {
this.lob = lob;
remainingBytes = byteCount;
this.length = byteCount;
}
@Override
public int read() throws IOException {
fillBuffer();
if (remainingBytes <= 0) {
return -1;
}
remainingBytes--;
return buffer[pos++] & 255;
}
@Override
public long skip(long n) throws IOException {
long remaining = n;
remaining -= skipSmall(remaining);
if (remaining > BLOCK_LENGTH) {
long toPos = length - remainingBytes + remaining;
try {
long[] seqPos = skipBuffer(lob, toPos);
if (seqPos == null) {
remaining -= super.skip(remaining);
return n - remaining;
}
seq = (int) seqPos[0];
long p = seqPos[1];
remainingBytes = length - p;
remaining = toPos - p;
} catch (SQLException e) {
throw DbException.convertToIOException(e);
}
pos = 0;
buffer = null;
}
fillBuffer();
remaining -= skipSmall(remaining);
remaining -= super.skip(remaining);
return n - remaining;
}
private int skipSmall(long n) {
if (n > 0 && buffer != null && pos < buffer.length) {
int x = MathUtils.convertLongToInt(Math.min(n, buffer.length - pos));
pos += x;
remainingBytes -= x;
return x;
}
return 0;
}
@Override
public int read(byte[] buff) throws IOException {
return readFully(buff, 0, buff.length);
}
@Override
public int read(byte[] buff, int off, int length) throws IOException {
return readFully(buff, off, length);
}
private int readFully(byte[] buff, int off, int length) throws IOException {
if (length == 0) {
return 0;
}
int read = 0;
while (length > 0) {
fillBuffer();
if (remainingBytes <= 0) {
break;
}
int len = (int) Math.min(length, remainingBytes);
len = Math.min(len, buffer.length - pos);
System.arraycopy(buffer, pos, buff, off, len);
pos += len;
read += len;
remainingBytes -= len;
off += len;
length -= len;
}
return read == 0 ? -1 : read;
}
private void fillBuffer() throws IOException {
if (buffer != null && pos < buffer.length) {
return;
}
if (remainingBytes <= 0) {
return;
}
try {
buffer = readBlock(lob, seq++);
pos = 0;
} catch (SQLException e) {
throw DbException.convertToIOException(e);
}
}
}
/** /**
* An input stream that reads the data from a reader. * An input stream that reads the data from a reader.
*/ */
...@@ -787,62 +775,4 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -787,62 +775,4 @@ public class LobStorageBackend implements LobStorageInterface {
} }
/**
* Create a BLOB object.
*
* @param in the input stream
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
@Override
public Value createBlob(InputStream in, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) {
init();
return addLob(in, maxLength, Value.BLOB);
}
return ValueLob.createBlob(in, maxLength, database);
}
/**
* Create a CLOB object.
*
* @param reader the reader
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
@Override
public Value createClob(Reader reader, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) {
init();
long max = maxLength == -1 ? Long.MAX_VALUE : maxLength;
CountingReaderInputStream in = new CountingReaderInputStream(reader, max);
ValueLobDb lob = addLob(in, Long.MAX_VALUE, Value.CLOB);
lob.setPrecision(in.getLength());
return lob;
}
return ValueLob.createClob(reader, maxLength, database);
}
/**
* Set the table reference of this lob.
*
* @param lobId the lob
* @param table the table
*/
public void setTable(long lobId, int table) {
synchronized (database) {
try {
init();
String sql = "UPDATE " + LOBS + " SET TABLE = ? WHERE ID = ?";
PreparedStatement prep = prepare(sql);
prep.setInt(1, table);
prep.setLong(2, lobId);
prep.executeUpdate();
reuse(sql, prep);
} catch (SQLException e) {
throw DbException.convert(e);
}
}
}
} }
...@@ -11,6 +11,7 @@ import java.io.IOException; ...@@ -11,6 +11,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob; import org.h2.value.ValueLob;
import org.h2.value.ValueLobDb; import org.h2.value.ValueLobDb;
...@@ -20,6 +21,16 @@ import org.h2.value.ValueLobDb; ...@@ -20,6 +21,16 @@ import org.h2.value.ValueLobDb;
* This is the front-end i.e. the client side of the LOB storage. * This is the front-end i.e. the client side of the LOB storage.
*/ */
public class LobStorageFrontend implements LobStorageInterface { public class LobStorageFrontend implements LobStorageInterface {
/**
* The table id for session variables (LOBs not assigned to a table).
*/
public static final int TABLE_ID_SESSION_VARIABLE = -1;
/**
* The table id for temporary objects (not assigned to any object).
*/
public static final int TABLE_TEMP = -2;
private final DataHandler handler; private final DataHandler handler;
...@@ -53,29 +64,16 @@ public class LobStorageFrontend implements LobStorageInterface { ...@@ -53,29 +64,16 @@ public class LobStorageFrontend implements LobStorageInterface {
return new BufferedInputStream(new LobStorageRemoteInputStream(handler, lobId, hmac, byteCount)); return new BufferedInputStream(new LobStorageRemoteInputStream(handler, lobId, hmac, byteCount));
} }
/**
* Copy a lob.
*
* @param type the type
* @param oldLobId the old lob id
* @param tableId the new table id
* @param length the length
* @return the new lob
*/
@Override @Override
public ValueLobDb copyLob(int type, long oldLobId, int tableId, long length) { public ValueLobDb copyLob(int type, long oldLobId, int tableId, long length) {
// TODO this should not be called at all, but that's a refactoring for another day throw new UnsupportedOperationException();
// this should never be called }
@Override
public void setTable(long lobId, int tableIdSessionVariable) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/**
* Create a BLOB object.
*
* @param in the input stream
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
@Override @Override
public Value createBlob(InputStream in, long maxLength) { public Value createBlob(InputStream in, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) { if (SysProperties.LOB_IN_DATABASE) {
...@@ -104,5 +102,26 @@ public class LobStorageFrontend implements LobStorageInterface { ...@@ -104,5 +102,26 @@ public class LobStorageFrontend implements LobStorageInterface {
} }
return ValueLob.createClob(reader, maxLength, handler); return ValueLob.createClob(reader, maxLength, handler);
} }
/**
* Create a LOB object that fits in memory.
*
* @param type the value type
* @param small the byte array
* @return the LOB
*/
public static Value createSmallLob(int type, byte[] small) {
if (SysProperties.LOB_IN_DATABASE) {
int precision;
if (type == Value.CLOB) {
precision = new String(small, Constants.UTF8).length();
} else {
precision = small.length;
}
return ValueLobDb.createSmallLob(type, small, precision);
}
return ValueLob.createSmallLob(type, small);
}
} }
...@@ -56,6 +56,14 @@ public interface LobStorageInterface { ...@@ -56,6 +56,14 @@ public interface LobStorageInterface {
*/ */
InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException; InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException;
/**
* Set the table reference of this lob.
*
* @param lobId the lob
* @param table the table
*/
void setTable(long lobId, int tableIdSessionVariable);
/** /**
* Delete a LOB from the database. * Delete a LOB from the database.
* *
......
...@@ -39,6 +39,7 @@ import org.h2.store.FileLister; ...@@ -39,6 +39,7 @@ import org.h2.store.FileLister;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream; import org.h2.store.FileStoreInputStream;
import org.h2.store.LobStorageBackend; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageFrontend;
import org.h2.store.LobStorageInterface; import org.h2.store.LobStorageInterface;
import org.h2.store.Page; import org.h2.store.Page;
import org.h2.store.PageFreeList; import org.h2.store.PageFreeList;
...@@ -195,7 +196,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -195,7 +196,7 @@ public class Recover extends Tool implements DataHandler {
public static Value.ValueBlob readBlobDb(Connection conn, long lobId, long precision) { public static Value.ValueBlob readBlobDb(Connection conn, long lobId, long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
LobStorageInterface lobStorage = h.getLobStorage(); LobStorageInterface lobStorage = h.getLobStorage();
return ValueLobDb.create(Value.BLOB, lobStorage, LobStorageBackend.TABLE_TEMP, lobId, null, precision); return ValueLobDb.create(Value.BLOB, lobStorage, LobStorageFrontend.TABLE_TEMP, lobId, null, precision);
} }
/** /**
...@@ -204,7 +205,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -204,7 +205,7 @@ public class Recover extends Tool implements DataHandler {
public static Value.ValueClob readClobDb(Connection conn, long lobId, long precision) { public static Value.ValueClob readClobDb(Connection conn, long lobId, long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
LobStorageInterface lobStorage = h.getLobStorage(); LobStorageInterface lobStorage = h.getLobStorage();
return ValueLobDb.create(Value.CLOB, lobStorage, LobStorageBackend.TABLE_TEMP, lobId, null, precision); return ValueLobDb.create(Value.CLOB, lobStorage, LobStorageFrontend.TABLE_TEMP, lobId, null, precision);
} }
private void trace(String message) { private void trace(String message) {
...@@ -1235,7 +1236,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1235,7 +1236,7 @@ public class Recover extends Tool implements DataHandler {
writer.println("DELETE FROM " + name + ";"); writer.println("DELETE FROM " + name + ";");
writer.println("INSERT INTO " + name + " SELECT * FROM " + storageName + ";"); writer.println("INSERT INTO " + name + " SELECT * FROM " + storageName + ";");
if (name.startsWith("INFORMATION_SCHEMA.LOBS")) { if (name.startsWith("INFORMATION_SCHEMA.LOBS")) {
writer.println("UPDATE " + name + " SET TABLE = " + LobStorageBackend.TABLE_TEMP + ";"); writer.println("UPDATE " + name + " SET TABLE = " + LobStorageFrontend.TABLE_TEMP + ";");
deleteLobs = true; deleteLobs = true;
} }
} }
...@@ -1261,7 +1262,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1261,7 +1262,7 @@ public class Recover extends Tool implements DataHandler {
writer.println("DROP ALIAS READ_BLOB_DB;"); writer.println("DROP ALIAS READ_BLOB_DB;");
writer.println("DROP ALIAS READ_CLOB_DB;"); writer.println("DROP ALIAS READ_CLOB_DB;");
if (deleteLobs) { if (deleteLobs) {
writer.println("DELETE FROM INFORMATION_SCHEMA.LOBS WHERE TABLE = " + LobStorageBackend.TABLE_TEMP + ";"); writer.println("DELETE FROM INFORMATION_SCHEMA.LOBS WHERE TABLE = " + LobStorageFrontend.TABLE_TEMP + ";");
} }
for (MetaRecord m : schema) { for (MetaRecord m : schema) {
if (isSchemaObjectTypeDelayed(m)) { if (isSchemaObjectTypeDelayed(m)) {
......
...@@ -31,7 +31,7 @@ import org.h2.jdbc.JdbcBlob; ...@@ -31,7 +31,7 @@ import org.h2.jdbc.JdbcBlob;
import org.h2.jdbc.JdbcClob; import org.h2.jdbc.JdbcClob;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.LobStorageBackend; import org.h2.store.LobStorageFrontend;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -540,7 +540,7 @@ public class DataType { ...@@ -540,7 +540,7 @@ public class DataType {
} }
case Value.CLOB: { case Value.CLOB: {
if (session == null) { if (session == null) {
v = LobStorageBackend.createSmallLob(Value.CLOB, rs.getString(columnIndex).getBytes(Constants.UTF8)); v = LobStorageFrontend.createSmallLob(Value.CLOB, rs.getString(columnIndex).getBytes(Constants.UTF8));
} else { } else {
Reader in = rs.getCharacterStream(columnIndex); Reader in = rs.getCharacterStream(columnIndex);
if (in == null) { if (in == null) {
...@@ -553,7 +553,7 @@ public class DataType { ...@@ -553,7 +553,7 @@ public class DataType {
} }
case Value.BLOB: { case Value.BLOB: {
if (session == null) { if (session == null) {
v = LobStorageBackend.createSmallLob(Value.BLOB, rs.getBytes(columnIndex)); v = LobStorageFrontend.createSmallLob(Value.BLOB, rs.getBytes(columnIndex));
} else { } else {
InputStream in = rs.getBinaryStream(columnIndex); InputStream in = rs.getBinaryStream(columnIndex);
v = (in == null) ? (Value) ValueNull.INSTANCE : session.getDataHandler().getLobStorage().createBlob(in, -1); v = (in == null) ? (Value) ValueNull.INSTANCE : session.getDataHandler().getLobStorage().createBlob(in, -1);
......
...@@ -22,9 +22,9 @@ import java.sql.Types; ...@@ -22,9 +22,9 @@ import java.sql.Types;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.LobStorageBackend; import org.h2.store.DataHandler;
import org.h2.store.LobStorageFrontend;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -771,8 +771,7 @@ public abstract class Value { ...@@ -771,8 +771,7 @@ public abstract class Value {
case BLOB: { case BLOB: {
switch(getType()) { switch(getType()) {
case BYTES: case BYTES:
return LobStorageFrontend.createSmallLob(Value.BLOB, getBytesNoCopy());
return LobStorageBackend.createSmallLob(Value.BLOB, getBytesNoCopy());
} }
break; break;
} }
...@@ -835,9 +834,9 @@ public abstract class Value { ...@@ -835,9 +834,9 @@ public abstract class Value {
case FLOAT: case FLOAT:
return ValueFloat.get(Float.parseFloat(s.trim())); return ValueFloat.get(Float.parseFloat(s.trim()));
case CLOB: case CLOB:
return LobStorageBackend.createSmallLob(CLOB, s.getBytes(Constants.UTF8)); return LobStorageFrontend.createSmallLob(CLOB, s.getBytes(Constants.UTF8));
case BLOB: case BLOB:
return LobStorageBackend.createSmallLob(BLOB, StringUtils.convertHexToBytes(s.trim())); return LobStorageFrontend.createSmallLob(BLOB, StringUtils.convertHexToBytes(s.trim()));
case ARRAY: case ARRAY:
return ValueArray.get(new Value[]{ValueString.get(s)}); return ValueArray.get(new Value[]{ValueString.get(s)});
case RESULT_SET: { case RESULT_SET: {
...@@ -969,11 +968,11 @@ public abstract class Value { ...@@ -969,11 +968,11 @@ public abstract class Value {
* Link a large value to a given table. For values that are kept fully in * Link a large value to a given table. For values that are kept fully in
* memory this method has no effect. * memory this method has no effect.
* *
* @param database the database * @param handler the data handler
* @param tableId the table to link to * @param tableId the table to link to
* @return the new value or itself * @return the new value or itself
*/ */
public Value link(Database database, int tableId) { public Value link(DataHandler handler, int tableId) {
return this; return this;
} }
...@@ -990,8 +989,10 @@ public abstract class Value { ...@@ -990,8 +989,10 @@ public abstract class Value {
/** /**
* Mark any underlying resource as 'not linked to any table'. For values * Mark any underlying resource as 'not linked to any table'. For values
* that are kept fully in memory this method has no effect. * that are kept fully in memory this method has no effect.
*
* @param handler the data handler
*/ */
public void unlink(Database database) { public void unlink(DataHandler handler) {
// nothing to do // nothing to do
} }
......
...@@ -14,9 +14,9 @@ import java.io.InputStream; ...@@ -14,9 +14,9 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
...@@ -237,7 +237,7 @@ public class ValueLob extends Value { ...@@ -237,7 +237,7 @@ public class ValueLob extends Value {
} }
} }
private static String getFileNamePrefix(String path, int objectId) { public static String getFileNamePrefix(String path, int objectId) {
String name; String name;
int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY; int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY;
if (f > 0) { if (f > 0) {
...@@ -498,6 +498,7 @@ public class ValueLob extends Value { ...@@ -498,6 +498,7 @@ public class ValueLob extends Value {
} }
} }
@Override
public Value link(DataHandler h, int tabId) { public Value link(DataHandler h, int tabId) {
if (fileName == null) { if (fileName == null) {
this.tableId = tabId; this.tableId = tabId;
...@@ -741,29 +742,6 @@ public class ValueLob extends Value { ...@@ -741,29 +742,6 @@ public class ValueLob extends Value {
} }
} }
/**
* Remove all lobs for a given table id.
*
* @param database the database
* @param tableId the table id
*/
public static void removeAllForTable(Database database, int tableId) {
String dir = getFileNamePrefix(database.getDatabasePath(), 0);
removeAllForTable(database, dir, tableId);
}
private static void removeAllForTable(Database database, String dir, int tableId) {
for (String name : FileUtils.newDirectoryStream(dir)) {
if (FileUtils.isDirectory(name)) {
removeAllForTable(database, name, tableId);
} else {
if (name.endsWith(".t" + tableId + Constants.SUFFIX_LOB_FILE)) {
deleteFile(database, name);
}
}
}
}
/** /**
* Check if this lob value is compressed. * Check if this lob value is compressed.
* *
...@@ -773,7 +751,7 @@ public class ValueLob extends Value { ...@@ -773,7 +751,7 @@ public class ValueLob extends Value {
return compression; return compression;
} }
private static synchronized void deleteFile(DataHandler handler, String fileName) { public static synchronized void deleteFile(DataHandler handler, String fileName) {
// synchronize on the database, to avoid concurrent temp file creation / // synchronize on the database, to avoid concurrent temp file creation /
// deletion / backup // deletion / backup
synchronized (handler.getLobSyncObject()) { synchronized (handler.getLobSyncObject()) {
...@@ -805,6 +783,29 @@ public class ValueLob extends Value { ...@@ -805,6 +783,29 @@ public class ValueLob extends Value {
} }
return 140; return 140;
} }
/**
* Remove all lobs for a given table id.
*
* @param handler the data handler
* @param tableId the table id
*/
public static void removeAllForTable(DataHandler handler, int tableId) {
String dir = ValueLob.getFileNamePrefix(handler.getDatabasePath(), 0);
removeAllForTable(handler, dir, tableId);
}
private static void removeAllForTable(DataHandler handler, String dir, int tableId) {
for (String name : FileUtils.newDirectoryStream(dir)) {
if (FileUtils.isDirectory(name)) {
removeAllForTable(handler, name, tableId);
} else {
if (name.endsWith(".t" + tableId + Constants.SUFFIX_LOB_FILE)) {
ValueLob.deleteFile(handler, name);
}
}
}
}
/** /**
* Create an independent copy of this temporary value. * Create an independent copy of this temporary value.
......
...@@ -13,16 +13,16 @@ import java.io.InputStream; ...@@ -13,16 +13,16 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
import org.h2.store.DataHandler; 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.LobStorageBackend; import org.h2.store.LobStorageFrontend;
import org.h2.store.LobStorageInterface; import org.h2.store.LobStorageInterface;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -111,14 +111,14 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -111,14 +111,14 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
Value copy = lobStorage.createClob(getReader(), -1); Value copy = lobStorage.createClob(getReader(), -1);
return copy; return copy;
} else if (small != null) { } else if (small != null) {
return LobStorageBackend.createSmallLob(t, small); return LobStorageFrontend.createSmallLob(t, small);
} }
} else if (t == Value.BLOB) { } else if (t == Value.BLOB) {
if (lobStorage != null) { if (lobStorage != null) {
Value copy = lobStorage.createBlob(getInputStream(), -1); Value copy = lobStorage.createBlob(getInputStream(), -1);
return copy; return copy;
} else if (small != null) { } else if (small != null) {
return LobStorageBackend.createSmallLob(t, small); return LobStorageFrontend.createSmallLob(t, small);
} }
} }
return super.convertTo(t); return super.convertTo(t);
...@@ -126,7 +126,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -126,7 +126,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
@Override @Override
public boolean isLinked() { public boolean isLinked() {
return tableId != LobStorageBackend.TABLE_ID_SESSION_VARIABLE && small == null; return tableId != LobStorageFrontend.TABLE_ID_SESSION_VARIABLE && small == null;
} }
public boolean isStored() { public boolean isStored() {
...@@ -152,31 +152,31 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -152,31 +152,31 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
} }
@Override @Override
public void unlink(Database database) { public void unlink(DataHandler database) {
if (small == null && tableId != LobStorageBackend.TABLE_ID_SESSION_VARIABLE) { if (small == null && tableId != LobStorageFrontend.TABLE_ID_SESSION_VARIABLE) {
database.getLobStorage().setTable(lobId, LobStorageBackend.TABLE_ID_SESSION_VARIABLE); database.getLobStorage().setTable(lobId, LobStorageFrontend.TABLE_ID_SESSION_VARIABLE);
tableId = LobStorageBackend.TABLE_ID_SESSION_VARIABLE; tableId = LobStorageFrontend.TABLE_ID_SESSION_VARIABLE;
} }
} }
@Override @Override
public Value link(Database database, int tabId) { public Value link(DataHandler database, int tabId) {
if (small == null) { if (small == null) {
if (tableId == LobStorageBackend.TABLE_TEMP) { if (tableId == LobStorageFrontend.TABLE_TEMP) {
database.getLobStorage().setTable(lobId, tabId); database.getLobStorage().setTable(lobId, tabId);
this.tableId = tabId; this.tableId = tabId;
} else { } else {
return lobStorage.copyLob(type, lobId, tabId, getPrecision()); return lobStorage.copyLob(type, lobId, tabId, getPrecision());
} }
} else if (small.length > database.getMaxLengthInplaceLob()) { } else if (small.length > handler.getMaxLengthInplaceLob()) {
LobStorageInterface s = database.getLobStorage(); LobStorageInterface s = handler.getLobStorage();
Value v; Value v;
if (type == Value.BLOB) { if (type == Value.BLOB) {
v = s.createBlob(getInputStream(), getPrecision()); v = s.createBlob(getInputStream(), getPrecision());
} else { } else {
v = s.createClob(getReader(), getPrecision()); v = s.createClob(getReader(), getPrecision());
} }
return v.link(database, tabId); return v.link(handler, tabId);
} }
return this; return this;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论