提交 5d3a10b2 authored 作者: Thomas Mueller's avatar Thomas Mueller

New LOB storage.

上级 19a80ed5
...@@ -12,8 +12,8 @@ import org.h2.engine.Right; ...@@ -12,8 +12,8 @@ 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;
import org.h2.value.ValueLob;
/** /**
* This class represents the statement * This class represents the statement
...@@ -83,7 +83,7 @@ public class DropTable extends SchemaCommand { ...@@ -83,7 +83,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);
ValueLob.removeAllForTable(db, dropTableId); LobStorage.removeAllForTable(db, dropTableId);
} }
if (next != null) { if (next != null) {
next.executeDrop(); next.executeDrop();
......
...@@ -24,6 +24,7 @@ import org.h2.store.DataHandler; ...@@ -24,6 +24,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.LobStorage;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -223,4 +224,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -223,4 +224,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
return null; return null;
} }
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -54,7 +54,6 @@ import org.h2.util.StatementBuilder; ...@@ -54,7 +54,6 @@ import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueString; import org.h2.value.ValueString;
/** /**
...@@ -254,10 +253,10 @@ public class ScriptCommand extends ScriptBase { ...@@ -254,10 +253,10 @@ public class ScriptCommand extends ScriptBase {
if (v.getPrecision() > lobBlockSize) { if (v.getPrecision() > lobBlockSize) {
int id; int id;
if (v.getType() == Value.CLOB) { if (v.getType() == Value.CLOB) {
id = writeLobStream((ValueLob) v); id = writeLobStream(v);
buff.append("SYSTEM_COMBINE_CLOB(" + id + ")"); buff.append("SYSTEM_COMBINE_CLOB(" + id + ")");
} else if (v.getType() == Value.BLOB) { } else if (v.getType() == Value.BLOB) {
id = writeLobStream((ValueLob) v); id = writeLobStream(v);
buff.append("SYSTEM_COMBINE_BLOB(" + id + ")"); buff.append("SYSTEM_COMBINE_BLOB(" + id + ")");
} else { } else {
buff.append(v.getSQL()); buff.append(v.getSQL());
...@@ -328,7 +327,7 @@ public class ScriptCommand extends ScriptBase { ...@@ -328,7 +327,7 @@ public class ScriptCommand extends ScriptBase {
return r; return r;
} }
private int writeLobStream(ValueLob v) throws IOException { private int writeLobStream(Value v) throws IOException {
if (!tempLobTableCreated) { if (!tempLobTableCreated) {
add("CREATE TABLE IF NOT EXISTS SYSTEM_LOB_STREAM(ID INT NOT NULL, PART INT NOT NULL, CDATA VARCHAR, BDATA BINARY)", true); add("CREATE TABLE IF NOT EXISTS SYSTEM_LOB_STREAM(ID INT NOT NULL, PART INT NOT NULL, CDATA VARCHAR, BDATA BINARY)", true);
add("CREATE PRIMARY KEY SYSTEM_LOB_STREAM_PRIMARY_KEY ON SYSTEM_LOB_STREAM(ID, PART)", true); add("CREATE PRIMARY KEY SYSTEM_LOB_STREAM_PRIMARY_KEY ON SYSTEM_LOB_STREAM(ID, PART)", true);
......
...@@ -255,6 +255,12 @@ public class SysProperties { ...@@ -255,6 +255,12 @@ public class SysProperties {
*/ */
public static final int LOB_FILES_PER_DIRECTORY = getIntSetting("h2.lobFilesPerDirectory", 256); public static final int LOB_FILES_PER_DIRECTORY = getIntSetting("h2.lobFilesPerDirectory", 256);
/**
* System property <code>h2.lobInDatabase</code> (default: false).<br />
* Store LOB files in the database.
*/
public static final boolean LOB_IN_DATABASE = getBooleanSetting("h2.lobInDatabase", false);
/** /**
* System property <code>h2.logAllErrors</code> (default: false).<br /> * System property <code>h2.logAllErrors</code> (default: false).<br />
* Write stack traces of any kind of error to a file. * Write stack traces of any kind of error to a file.
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.engine; package org.h2.engine;
import java.io.IOException; import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
...@@ -25,6 +26,7 @@ import org.h2.constraint.Constraint; ...@@ -25,6 +26,7 @@ import org.h2.constraint.Constraint;
import org.h2.index.Cursor; import org.h2.index.Cursor;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
...@@ -38,6 +40,7 @@ import org.h2.store.DataHandler; ...@@ -38,6 +40,7 @@ import org.h2.store.DataHandler;
import org.h2.store.FileLock; 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.LobStorage;
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.FileSystemMemory; import org.h2.store.fs.FileSystemMemory;
...@@ -50,7 +53,6 @@ import org.h2.table.TableLinkConnection; ...@@ -50,7 +53,6 @@ import org.h2.table.TableLinkConnection;
import org.h2.table.TableView; import org.h2.table.TableView;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server; import org.h2.tools.Server;
import org.h2.util.Utils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
import org.h2.util.New; import org.h2.util.New;
...@@ -58,10 +60,10 @@ import org.h2.util.SmallLRUCache; ...@@ -58,10 +60,10 @@ import org.h2.util.SmallLRUCache;
import org.h2.util.SourceCompiler; import org.h2.util.SourceCompiler;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
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;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueLob;
/** /**
* There is one database object per open database. * There is one database object per open database.
...@@ -164,6 +166,7 @@ public class Database implements DataHandler { ...@@ -164,6 +166,7 @@ public class Database implements DataHandler {
private SourceCompiler compiler; private SourceCompiler compiler;
private boolean metaTablesInitialized; private boolean metaTablesInitialized;
private boolean flushOnEachCommit; private boolean flushOnEachCommit;
private LobStorage lobStorage;
public Database(String name, ConnectionInfo ci, String cipher) { public Database(String name, ConnectionInfo ci, String cipher) {
this.compareMode = CompareMode.getInstance(null, 0); this.compareMode = CompareMode.getInstance(null, 0);
...@@ -1044,7 +1047,7 @@ public class Database implements DataHandler { ...@@ -1044,7 +1047,7 @@ public class Database implements DataHandler {
// remove all session variables // remove all session variables
if (persistent) { if (persistent) {
try { try {
ValueLob.removeAllForTable(this, ValueLob.TABLE_ID_SESSION_VARIABLE); LobStorage.removeAllForTable(this, LobStorage.TABLE_ID_SESSION_VARIABLE);
} catch (DbException e) { } catch (DbException e) {
traceSystem.getTrace(Trace.DATABASE).error("close", e); traceSystem.getTrace(Trace.DATABASE).error("close", e);
} }
...@@ -2203,4 +2206,13 @@ public class Database implements DataHandler { ...@@ -2203,4 +2206,13 @@ public class Database implements DataHandler {
return compiler; return compiler;
} }
public LobStorage getLobStorage() {
if (lobStorage == null) {
String url = Constants.CONN_URL_INTERNAL;
Connection conn = new JdbcConnection(systemSession, systemUser.getName(), url);
lobStorage = new LobStorage(conn);
}
return lobStorage;
}
} }
...@@ -28,10 +28,10 @@ import org.h2.result.Row; ...@@ -28,10 +28,10 @@ import org.h2.result.Row;
import org.h2.schema.Schema; 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.LobStorage;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.util.New; import org.h2.util.New;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueLong; import org.h2.value.ValueLong;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
import org.h2.value.ValueString; import org.h2.value.ValueString;
...@@ -81,7 +81,7 @@ public class Session extends SessionWithState implements SessionFactory { ...@@ -81,7 +81,7 @@ public class Session extends SessionWithState implements SessionFactory {
private String currentSchemaName; private String currentSchemaName;
private String[] schemaSearchPath; private String[] schemaSearchPath;
private String traceModuleName; private String traceModuleName;
private HashMap<String, ValueLob> unlinkMap; private HashMap<String, Value> unlinkLobMap;
private int systemIdentifier; private int systemIdentifier;
private HashMap<String, Procedure> procedures; private HashMap<String, Procedure> procedures;
private boolean undoLogEnabled = true; private boolean undoLogEnabled = true;
...@@ -144,10 +144,8 @@ public class Session extends SessionWithState implements SessionFactory { ...@@ -144,10 +144,8 @@ public class Session extends SessionWithState implements SessionFactory {
if (value == ValueNull.INSTANCE) { if (value == ValueNull.INSTANCE) {
old = variables.remove(name); old = variables.remove(name);
} else { } else {
if (value instanceof ValueLob) { // link LOB values, to make sure we have our own object
// link it, to make sure we have our own file value = value.link(database, LobStorage.TABLE_ID_SESSION_VARIABLE);
value = value.link(database, ValueLob.TABLE_ID_SESSION_VARIABLE);
}
old = variables.put(name, value); old = variables.put(name, value);
} }
if (old != null) { if (old != null) {
...@@ -476,14 +474,14 @@ public class Session extends SessionWithState implements SessionFactory { ...@@ -476,14 +474,14 @@ public class Session extends SessionWithState implements SessionFactory {
autoCommitAtTransactionEnd = false; autoCommitAtTransactionEnd = false;
} }
} }
if (unlinkMap != null && unlinkMap.size() > 0) { if (unlinkLobMap != null && unlinkLobMap.size() > 0) {
// need to flush the transaction log, because we can't unlink lobs if the // need to flush the transaction log, because we can't unlink lobs if the
// commit record is not written // commit record is not written
database.flush(); database.flush();
for (Value v : unlinkMap.values()) { for (Value v : unlinkLobMap.values()) {
v.unlink(); v.unlink();
} }
unlinkMap = null; unlinkLobMap = null;
} }
unlockAll(); unlockAll();
} }
...@@ -913,14 +911,14 @@ public class Session extends SessionWithState implements SessionFactory { ...@@ -913,14 +911,14 @@ public class Session extends SessionWithState implements SessionFactory {
* *
* @param v the value * @param v the value
*/ */
public void unlinkAtCommit(ValueLob v) { public void unlinkAtCommit(Value v) {
if (SysProperties.CHECK && !v.isLinked()) { if (SysProperties.CHECK && !v.isLinked()) {
DbException.throwInternalError(); DbException.throwInternalError();
} }
if (unlinkMap == null) { if (unlinkLobMap == null) {
unlinkMap = New.hashMap(); unlinkLobMap = New.hashMap();
} }
unlinkMap.put(v.toString(), v); unlinkLobMap.put(v.toString(), v);
} }
/** /**
...@@ -929,8 +927,8 @@ public class Session extends SessionWithState implements SessionFactory { ...@@ -929,8 +927,8 @@ public class Session extends SessionWithState implements SessionFactory {
* @param v the value * @param v the value
*/ */
public void unlinkAtCommitStop(Value v) { public void unlinkAtCommitStop(Value v) {
if (unlinkMap != null) { if (unlinkLobMap != null) {
unlinkMap.remove(v.toString()); unlinkLobMap.remove(v.toString());
} }
} }
......
...@@ -23,7 +23,7 @@ import org.h2.message.TraceSystem; ...@@ -23,7 +23,7 @@ import org.h2.message.TraceSystem;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.util.Utils; 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.NetUtils; import org.h2.util.NetUtils;
...@@ -31,6 +31,7 @@ import org.h2.util.New; ...@@ -31,6 +31,7 @@ import org.h2.util.New;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
import org.h2.util.Utils;
import org.h2.value.Transfer; import org.h2.value.Transfer;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueString; import org.h2.value.ValueString;
...@@ -95,9 +96,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -95,9 +96,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
trans.setSSL(ci.isSSL()); trans.setSSL(ci.isSSL());
trans.init(); trans.init();
trans.writeInt(clientVersion); trans.writeInt(clientVersion);
if (clientVersion >= Constants.TCP_PROTOCOL_VERSION) { trans.writeInt(clientVersion);
trans.writeInt(clientVersion);
}
trans.writeString(db); trans.writeString(db);
trans.writeString(ci.getOriginalURL()); trans.writeString(ci.getOriginalURL());
trans.writeString(ci.getUserName()); trans.writeString(ci.getUserName());
...@@ -109,7 +108,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -109,7 +108,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
trans.writeString(key).writeString(ci.getProperty(key)); trans.writeString(key).writeString(ci.getProperty(key));
} }
try { try {
convert(trans); done(trans);
if (clientVersion >= Constants.TCP_PROTOCOL_VERSION) { if (clientVersion >= Constants.TCP_PROTOCOL_VERSION) {
clientVersion = trans.readInt(); clientVersion = trans.readInt();
} }
...@@ -180,7 +179,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -180,7 +179,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
try { try {
traceOperation("COMMAND_COMMIT", 0); traceOperation("COMMAND_COMMIT", 0);
transfer.writeInt(SessionRemote.COMMAND_COMMIT); transfer.writeInt(SessionRemote.COMMAND_COMMIT);
convert(transfer); done(transfer);
} catch (IOException e) { } catch (IOException e) {
removeServer(e, i--, ++count); removeServer(e, i--, ++count);
} }
...@@ -364,7 +363,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -364,7 +363,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
traceOperation("SESSION_SET_ID", 0); traceOperation("SESSION_SET_ID", 0);
transfer.writeInt(SessionRemote.SESSION_SET_ID); transfer.writeInt(SessionRemote.SESSION_SET_ID);
transfer.writeString(sessionId); transfer.writeString(sessionId);
convert(transfer); done(transfer);
} catch (Exception e) { } catch (Exception e) {
trace.error("sessionSetId", e); trace.error("sessionSetId", e);
} }
...@@ -456,7 +455,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -456,7 +455,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
try { try {
traceOperation("SESSION_CLOSE", 0); traceOperation("SESSION_CLOSE", 0);
transfer.writeInt(SessionRemote.SESSION_CLOSE); transfer.writeInt(SessionRemote.SESSION_CLOSE);
convert(transfer); done(transfer);
transfer.close(); transfer.close();
} catch (Exception e) { } catch (Exception e) {
trace.error("close", e); trace.error("close", e);
...@@ -494,7 +493,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -494,7 +493,7 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
* @throws IOException if there is a communication problem between client * @throws IOException if there is a communication problem between client
* and server * and server
*/ */
public void convert(Transfer transfer) throws IOException { public void done(Transfer transfer) throws IOException {
transfer.flush(); transfer.flush();
int status = transfer.readInt(); int status = transfer.readInt();
if (status == STATUS_ERROR) { if (status == STATUS_ERROR) {
...@@ -620,4 +619,8 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D ...@@ -620,4 +619,8 @@ public class SessionRemote extends SessionWithState implements SessionFactory, D
// nothing to do // nothing to do
} }
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -34,6 +34,7 @@ import org.h2.schema.Sequence; ...@@ -34,6 +34,7 @@ import org.h2.schema.Sequence;
import org.h2.security.BlockCipher; import org.h2.security.BlockCipher;
import org.h2.security.CipherFactory; import org.h2.security.CipherFactory;
import org.h2.security.SHA256; import org.h2.security.SHA256;
import org.h2.store.LobStorage;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.LinkSchema; import org.h2.table.LinkSchema;
...@@ -41,14 +42,14 @@ import org.h2.table.TableFilter; ...@@ -41,14 +42,14 @@ import org.h2.table.TableFilter;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.tools.Csv; import org.h2.tools.Csv;
import org.h2.util.AutoCloseInputStream; import org.h2.util.AutoCloseInputStream;
import org.h2.util.JdbcUtils;
import org.h2.util.Utils;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Utils;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -57,7 +58,6 @@ import org.h2.value.ValueBytes; ...@@ -57,7 +58,6 @@ import org.h2.value.ValueBytes;
import org.h2.value.ValueDate; import org.h2.value.ValueDate;
import org.h2.value.ValueDouble; import org.h2.value.ValueDouble;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueLob;
import org.h2.value.ValueLong; import org.h2.value.ValueLong;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
import org.h2.value.ValueResultSet; import org.h2.value.ValueResultSet;
...@@ -1114,7 +1114,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1114,7 +1114,7 @@ public class Function extends Expression implements FunctionCall {
try { try {
InputStream in = new AutoCloseInputStream(IOUtils.openFileInputStream(fileName)); InputStream in = new AutoCloseInputStream(IOUtils.openFileInputStream(fileName));
if (blob) { if (blob) {
result = ValueLob.createBlob(in, -1, database); result = LobStorage.createBlob(in, -1, database);
} else { } else {
Reader reader; Reader reader;
if (v1 == ValueNull.INSTANCE) { if (v1 == ValueNull.INSTANCE) {
...@@ -1122,7 +1122,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1122,7 +1122,7 @@ public class Function extends Expression implements FunctionCall {
} else { } else {
reader = new InputStreamReader(in, v1.getString()); reader = new InputStreamReader(in, v1.getString());
} }
result = ValueLob.createClob(reader, -1, database); result = LobStorage.createClob(reader, -1, database);
} }
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, fileName); throw DbException.convertIOException(e, fileName);
......
...@@ -13,6 +13,7 @@ import org.h2.message.DbException; ...@@ -13,6 +13,7 @@ import org.h2.message.DbException;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.LobStorage;
import org.h2.store.Page; import org.h2.store.Page;
import org.h2.store.PageStore; import org.h2.store.PageStore;
import org.h2.table.Column; import org.h2.table.Column;
...@@ -20,7 +21,6 @@ import org.h2.table.IndexColumn; ...@@ -20,7 +21,6 @@ import org.h2.table.IndexColumn;
import org.h2.table.TableData; import org.h2.table.TableData;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
/** /**
...@@ -218,7 +218,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -218,7 +218,7 @@ public class PageBtreeIndex extends PageIndex {
for (int i = 0; i < row.getColumnCount(); i++) { for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i); Value v = row.getValue(i);
if (v.isLinked()) { if (v.isLinked()) {
session.unlinkAtCommit((ValueLob) v); session.unlinkAtCommit(v);
} }
} }
} }
...@@ -253,7 +253,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -253,7 +253,7 @@ public class PageBtreeIndex extends PageIndex {
} }
removeAllRows(); removeAllRows();
if (tableData.getContainsLargeObject()) { if (tableData.getContainsLargeObject()) {
ValueLob.removeAllForTable(database, table.getId()); LobStorage.removeAllForTable(database, table.getId());
} }
tableData.setRowCount(0); tableData.setRowCount(0);
} }
......
...@@ -19,6 +19,7 @@ import org.h2.message.DbException; ...@@ -19,6 +19,7 @@ import org.h2.message.DbException;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.LobStorage;
import org.h2.store.Page; import org.h2.store.Page;
import org.h2.store.PageStore; import org.h2.store.PageStore;
import org.h2.table.Column; import org.h2.table.Column;
...@@ -27,7 +28,6 @@ import org.h2.table.TableData; ...@@ -27,7 +28,6 @@ import org.h2.table.TableData;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
/** /**
...@@ -296,7 +296,7 @@ public class PageDataIndex extends PageIndex { ...@@ -296,7 +296,7 @@ public class PageDataIndex extends PageIndex {
for (int i = 0; i < row.getColumnCount(); i++) { for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i); Value v = row.getValue(i);
if (v.isLinked()) { if (v.isLinked()) {
session.unlinkAtCommit((ValueLob) v); session.unlinkAtCommit(v);
} }
} }
} }
...@@ -347,7 +347,7 @@ public class PageDataIndex extends PageIndex { ...@@ -347,7 +347,7 @@ public class PageDataIndex extends PageIndex {
store.logTruncate(session, tableData.getId()); store.logTruncate(session, tableData.getId());
removeAllRows(); removeAllRows();
if (tableData.getContainsLargeObject() && tableData.isPersistData()) { if (tableData.getContainsLargeObject() && tableData.isPersistData()) {
ValueLob.removeAllForTable(database, table.getId()); LobStorage.removeAllForTable(database, table.getId());
} }
if (database.isMultiVersion()) { if (database.isMultiVersion()) {
sessionRowCount.clear(); sessionRowCount.clear();
......
...@@ -18,11 +18,11 @@ import org.h2.engine.UndoLogRecord; ...@@ -18,11 +18,11 @@ import org.h2.engine.UndoLogRecord;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.LobStorage;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.IndexColumn; import org.h2.table.IndexColumn;
import org.h2.table.TableData; import org.h2.table.TableData;
import org.h2.util.New; import org.h2.util.New;
import org.h2.value.ValueLob;
/** /**
* The scan index is not really an 'index' in the strict sense, because it can * The scan index is not really an 'index' in the strict sense, because it can
...@@ -55,7 +55,7 @@ public class ScanIndex extends BaseIndex { ...@@ -55,7 +55,7 @@ public class ScanIndex extends BaseIndex {
rows = New.arrayList(); rows = New.arrayList();
firstFree = -1; firstFree = -1;
if (tableData.getContainsLargeObject() && tableData.isPersistData()) { if (tableData.getContainsLargeObject() && tableData.isPersistData()) {
ValueLob.removeAllForTable(database, table.getId()); LobStorage.removeAllForTable(database, table.getId());
} }
tableData.setRowCount(0); tableData.setRowCount(0);
rowCount = 0; rowCount = 0;
......
...@@ -21,7 +21,6 @@ import java.sql.Savepoint; ...@@ -21,7 +21,6 @@ import java.sql.Savepoint;
import java.sql.Statement; import java.sql.Statement;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
...@@ -33,11 +32,11 @@ import org.h2.message.DbException; ...@@ -33,11 +32,11 @@ 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;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueLob;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
import org.h2.value.ValueString; import org.h2.value.ValueString;
...@@ -1439,7 +1438,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1439,7 +1438,7 @@ public class JdbcConnection extends TraceObject implements Connection {
debugCodeAssign("Clob", TraceObject.CLOB, id, "createClob()"); debugCodeAssign("Clob", TraceObject.CLOB, id, "createClob()");
checkClosedForWrite(); checkClosedForWrite();
try { try {
ValueLob v = ValueLob.createSmallLob(Value.CLOB, Utils.EMPTY_BYTES); Value v = LobStorage.createSmallLob(Value.CLOB, Utils.EMPTY_BYTES);
return new JdbcClob(this, v, id); return new JdbcClob(this, v, id);
} finally { } finally {
afterWriting(); afterWriting();
...@@ -1460,7 +1459,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1460,7 +1459,7 @@ public class JdbcConnection extends TraceObject implements Connection {
debugCodeAssign("Blob", TraceObject.BLOB, id, "createClob()"); debugCodeAssign("Blob", TraceObject.BLOB, id, "createClob()");
checkClosedForWrite(); checkClosedForWrite();
try { try {
ValueLob v = ValueLob.createSmallLob(Value.BLOB, Utils.EMPTY_BYTES); Value v = LobStorage.createSmallLob(Value.BLOB, Utils.EMPTY_BYTES);
return new JdbcBlob(this, v, id); return new JdbcBlob(this, v, id);
} finally { } finally {
afterWriting(); afterWriting();
...@@ -1615,7 +1614,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1615,7 +1614,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if (length <= 0) { if (length <= 0) {
length = -1; length = -1;
} }
Value v = ValueLob.createClob(x, length, session.getDataHandler()); Value v = LobStorage.createClob(x, length, session.getDataHandler());
return v; return v;
} }
...@@ -1634,7 +1633,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1634,7 +1633,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if (length <= 0) { if (length <= 0) {
length = -1; length = -1;
} }
Value v = ValueLob.createBlob(x, length, session.getDataHandler()); Value v = LobStorage.createBlob(x, length, session.getDataHandler());
return v; return v;
} }
......
...@@ -290,7 +290,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -290,7 +290,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </ul> * </ul>
* *
* @param catalogPattern null or the catalog name * @param catalogPattern null or the catalog name
* @param schemaPattern schema name (must be specified) * @param schemaPattern null (to get all objects) or a schema name
* (uppercase for unquoted names)
* @param tableName table name (must be specified) * @param tableName table name (must be specified)
* @param unique only unique indexes * @param unique only unique indexes
* @param approximate is ignored * @param approximate is ignored
...@@ -356,7 +357,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -356,7 +357,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </ul> * </ul>
* *
* @param catalogPattern null or the catalog name * @param catalogPattern null or the catalog name
* @param schemaPattern schema name (must be specified) * @param schemaPattern null (to get all objects) or a schema name
* (uppercase for unquoted names)
* @param tableName table name (must be specified) * @param tableName table name (must be specified)
* @return the list of primary key columns * @return the list of primary key columns
* @throws SQLException if the connection is closed * @throws SQLException if the connection is closed
...@@ -529,7 +531,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -529,7 +531,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </ul> * </ul>
* *
* @param catalogPattern null or the catalog name * @param catalogPattern null or the catalog name
* @param schemaPattern schema name (must be specified) * @param schemaPattern null (to get all objects) or a schema name
* (uppercase for unquoted names)
* @param procedureNamePattern the procedure name pattern * @param procedureNamePattern the procedure name pattern
* @return the procedures * @return the procedures
* @throws SQLException if the connection is closed * @throws SQLException if the connection is closed
...@@ -599,7 +602,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -599,7 +602,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </ul> * </ul>
* *
* @param catalogPattern null or the catalog name * @param catalogPattern null or the catalog name
* @param schemaPattern schema name (must be specified) * @param schemaPattern null (to get all objects) or a schema name
* (uppercase for unquoted names)
* @param procedureNamePattern the procedure name pattern * @param procedureNamePattern the procedure name pattern
* @param columnNamePattern the procedure name pattern * @param columnNamePattern the procedure name pattern
* @return the procedure columns * @return the procedure columns
...@@ -867,7 +871,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -867,7 +871,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </li></ul> * </li></ul>
* *
* @param catalogPattern null (to get all objects) or the catalog name * @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern schema name (must be specified) * @param schemaPattern null (to get all objects) or a schema name
* (uppercase for unquoted names)
* @param tableName table name (must be specified) * @param tableName table name (must be specified)
* @param scope ignored * @param scope ignored
* @param nullable ignored * @param nullable ignored
...@@ -932,7 +937,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -932,7 +937,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </li></ul> * </li></ul>
* *
* @param catalog null (to get all objects) or the catalog name * @param catalog null (to get all objects) or the catalog name
* @param schema schema name (must be specified) * @param schemaPattern null (to get all objects) or a schema name
* (uppercase for unquoted names)
* @param tableName table name (must be specified) * @param tableName table name (must be specified)
* @return an empty result set * @return an empty result set
* @throws SQLException if the connection is closed * @throws SQLException if the connection is closed
...@@ -1130,12 +1136,12 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -1130,12 +1136,12 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* </ul> * </ul>
* *
* @param primaryCatalogPattern null or the catalog name * @param primaryCatalogPattern null or the catalog name
* @param primarySchemaPattern the schema name of the primary table (must be * @param primarySchemaPattern the schema name of the primary table
* specified) * (optional)
* @param primaryTable the name of the primary table (must be specified) * @param primaryTable the name of the primary table (must be specified)
* @param foreignCatalogPattern null or the catalog name * @param foreignCatalogPattern null or the catalog name
* @param foreignSchemaPattern the schema name of the foreign table (must be * @param foreignSchemaPattern the schema name of the foreign table
* specified) * (optional)
* @param foreignTable the name of the foreign table (must be specified) * @param foreignTable the name of the foreign table (must be specified)
* @return the result set * @return the result set
* @throws SQLException if the connection is closed * @throws SQLException if the connection is closed
......
...@@ -80,8 +80,7 @@ public class DbException extends RuntimeException { ...@@ -80,8 +80,7 @@ public class DbException extends RuntimeException {
params[i] = StringUtils.quoteIdentifier(s); params[i] = StringUtils.quoteIdentifier(s);
} }
} }
Object[] o = params; message = MessageFormat.format(message, (Object[]) params);
message = MessageFormat.format(message, o);
} }
return message; return message;
} }
......
...@@ -15,7 +15,6 @@ import org.h2.store.Data; ...@@ -15,7 +15,6 @@ import org.h2.store.Data;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.util.New; import org.h2.util.New;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob;
/** /**
* A list of rows. If the list grows too large, it is buffered to disk * A list of rows. If the list grows too large, it is buffered to disk
...@@ -29,7 +28,7 @@ public class RowList { ...@@ -29,7 +28,7 @@ public class RowList {
private int index, listIndex; private int index, listIndex;
private FileStore file; private FileStore file;
private Data rowBuff; private Data rowBuff;
private ArrayList<ValueLob> lobs; private ArrayList<Value> lobs;
private int memory, maxMemory; private int memory, maxMemory;
private boolean written; private boolean written;
private boolean readUncached; private boolean readUncached;
...@@ -65,17 +64,15 @@ public class RowList { ...@@ -65,17 +64,15 @@ public class RowList {
if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) { if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) {
// need to keep a reference to temporary lobs, // need to keep a reference to temporary lobs,
// otherwise the temp file is deleted // otherwise the temp file is deleted
ValueLob lob = (ValueLob) v; if (v.getSmall() == null && v.getTableId() == 0) {
if (lob.getSmall() == null && lob.getTableId() == 0) {
if (lobs == null) { if (lobs == null) {
lobs = New.arrayList(); lobs = New.arrayList();
} }
// need to create a copy, otherwise, // need to create a copy, otherwise,
// if stored multiple times, it may be renamed // if stored multiple times, it may be renamed
// and then not found // and then not found
lob = lob.copyToTemp(); v = v.copyToTemp();
lobs.add(lob); lobs.add(v);
v = lob;
} }
} }
buff.checkCapacity(buff.getValueLen(v)); buff.checkCapacity(buff.getValueLen(v));
...@@ -182,11 +179,10 @@ public class RowList { ...@@ -182,11 +179,10 @@ public class RowList {
} else { } else {
v = buff.readValue(); v = buff.readValue();
if (v.isLinked()) { if (v.isLinked()) {
ValueLob lob = (ValueLob) v;
// the table id is 0 if it was linked when writing // the table id is 0 if it was linked when writing
// a temporary entry // a temporary entry
if (lob.getTableId() == 0) { if (v.getTableId() == 0) {
session.unlinkAtCommit(lob); session.unlinkAtCommit(v);
} }
} }
} }
......
...@@ -65,10 +65,14 @@ public class TcpServerThread implements Runnable { ...@@ -65,10 +65,14 @@ public class TcpServerThread implements Runnable {
// TODO server: should support a list of allowed databases // TODO server: should support a list of allowed databases
// and a list of allowed clients // and a list of allowed clients
try { try {
clientVersion = transfer.readInt();
if (!server.allow(transfer.getSocket())) { if (!server.allow(transfer.getSocket())) {
throw DbException.get(ErrorCode.REMOTE_CONNECTION_NOT_ALLOWED); throw DbException.get(ErrorCode.REMOTE_CONNECTION_NOT_ALLOWED);
} }
clientVersion = transfer.readInt();
if (clientVersion < Constants.TCP_PROTOCOL_VERSION) {
throw DbException.get(ErrorCode.DRIVER_VERSION_ERROR_2, "current client version: " +
clientVersion + "; minimum version: " + Constants.TCP_PROTOCOL_VERSION);
}
// max version (currently not used) // max version (currently not used)
transfer.readInt(); transfer.readInt();
String db = transfer.readString(); String db = transfer.readString();
......
...@@ -653,7 +653,7 @@ public class Data { ...@@ -653,7 +653,7 @@ public class Data {
if (smallLen >= 0) { if (smallLen >= 0) {
byte[] small = Utils.newBytes(smallLen); byte[] small = Utils.newBytes(smallLen);
read(small, 0, smallLen); read(small, 0, smallLen);
return ValueLob.createSmallLob(type, small); return LobStorage.createSmallLob(type, small);
} }
int tableId = readVarInt(); int tableId = readVarInt();
int objectId = readVarInt(); int objectId = readVarInt();
......
...@@ -91,4 +91,6 @@ public interface DataHandler { ...@@ -91,4 +91,6 @@ public interface DataHandler {
*/ */
SmallLRUCache<String, String[]> getLobFileListCache(); SmallLRUCache<String, String[]> getLobFileListCache();
LobStorage getLobStorage();
} }
差异被折叠。
...@@ -1423,7 +1423,7 @@ public class PageStore implements CacheWriter { ...@@ -1423,7 +1423,7 @@ public class PageStore implements CacheWriter {
int key = index.getId() + 1; int key = index.getId() + 1;
Row row = metaIndex.getRow(session, key); Row row = metaIndex.getRow(session, key);
if (row.getKey() != key) { if (row.getKey() != key) {
DbException.throwInternalError(); throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "key: " + key + " index: " + index + " row: " + row);
} }
metaIndex.remove(session, row); metaIndex.remove(session, row);
} }
......
...@@ -15,6 +15,7 @@ import java.io.InputStreamReader; ...@@ -15,6 +15,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Reader; import java.io.Reader;
import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
...@@ -38,11 +39,11 @@ import org.h2.store.DataReader; ...@@ -38,11 +39,11 @@ import org.h2.store.DataReader;
import org.h2.store.FileLister; 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.LobStorage;
import org.h2.store.Page; import org.h2.store.Page;
import org.h2.store.PageFreeList; import org.h2.store.PageFreeList;
import org.h2.store.PageLog; import org.h2.store.PageLog;
import org.h2.store.PageStore; import org.h2.store.PageStore;
import org.h2.util.Utils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.IntArray; import org.h2.util.IntArray;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -51,8 +52,10 @@ import org.h2.util.SmallLRUCache; ...@@ -51,8 +52,10 @@ import org.h2.util.SmallLRUCache;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
import org.h2.util.Tool; import org.h2.util.Tool;
import org.h2.util.Utils;
import org.h2.value.Value; import org.h2.value.Value;
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;
/** /**
...@@ -149,6 +152,21 @@ public class Recover extends Tool implements DataHandler { ...@@ -149,6 +152,21 @@ public class Recover extends Tool implements DataHandler {
return new BufferedInputStream(IOUtils.openFileInputStream(fileName)); return new BufferedInputStream(IOUtils.openFileInputStream(fileName));
} }
/**
* INTERNAL
*/
public static Reader readClobDb(Connection conn, long lobId) throws IOException {
return new BufferedReader(new InputStreamReader(readBlobDb(conn, lobId), "UTF-8"));
}
/**
* INTERNAL
*/
public static InputStream readBlobDb(Connection conn, long lobId) throws IOException {
return new BufferedInputStream(new LobStorage.LobInputStream(conn, lobId));
}
private void trace(String message) { private void trace(String message) {
if (trace) { if (trace) {
out.println(message); out.println(message);
...@@ -272,6 +290,16 @@ public class Recover extends Tool implements DataHandler { ...@@ -272,6 +290,16 @@ public class Recover extends Tool implements DataHandler {
} }
return "READ_CLOB('" + file + ".txt')"; return "READ_CLOB('" + file + ".txt')";
} }
} else if (v instanceof ValueLob2) {
ValueLob2 lob = (ValueLob2) v;
byte[] small = lob.getSmall();
if (small == null) {
long id = lob.getLobId();
if (lob.getType() == Value.BLOB) {
return "READ_BLOB_DB(" + id + ")";
}
return "READ_CLOB_DB(" + id + ")";
}
} }
return v.getSQL(); return v.getSQL();
} }
...@@ -292,6 +320,8 @@ public class Recover extends Tool implements DataHandler { ...@@ -292,6 +320,8 @@ public class Recover extends Tool implements DataHandler {
writer = getWriter(fileName, ".sql"); writer = getWriter(fileName, ".sql");
writer.println("CREATE ALIAS IF NOT EXISTS READ_CLOB FOR \"" + this.getClass().getName() + ".readClob\";"); writer.println("CREATE ALIAS IF NOT EXISTS READ_CLOB FOR \"" + this.getClass().getName() + ".readClob\";");
writer.println("CREATE ALIAS IF NOT EXISTS READ_BLOB FOR \"" + this.getClass().getName() + ".readBlob\";"); writer.println("CREATE ALIAS IF NOT EXISTS READ_BLOB FOR \"" + this.getClass().getName() + ".readBlob\";");
writer.println("CREATE ALIAS IF NOT EXISTS READ_CLOB_DB FOR \"" + this.getClass().getName() + ".readClobDb\";");
writer.println("CREATE ALIAS IF NOT EXISTS READ_BLOB_DB FOR \"" + this.getClass().getName() + ".readBlobDb\";");
resetSchema(); resetSchema();
store = FileStore.open(null, fileName, remove ? "rw" : "r"); store = FileStore.open(null, fileName, remove ? "rw" : "r");
long length = store.length(); long length = store.length();
...@@ -1184,4 +1214,11 @@ public class Recover extends Tool implements DataHandler { ...@@ -1184,4 +1214,11 @@ public class Recover extends Tool implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
/**
* INTERNAL
*/
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -30,6 +30,7 @@ import org.h2.jdbc.JdbcBlob; ...@@ -30,6 +30,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.LobStorage;
import org.h2.util.Utils; import org.h2.util.Utils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -539,23 +540,23 @@ public class DataType { ...@@ -539,23 +540,23 @@ public class DataType {
} }
case Value.CLOB: { case Value.CLOB: {
if (session == null) { if (session == null) {
v = ValueLob.createSmallLob(Value.CLOB, StringUtils.utf8Encode(rs.getString(columnIndex))); v = LobStorage.createSmallLob(Value.CLOB, StringUtils.utf8Encode(rs.getString(columnIndex)));
} else { } else {
Reader in = rs.getCharacterStream(columnIndex); Reader in = rs.getCharacterStream(columnIndex);
if (in == null) { if (in == null) {
v = ValueNull.INSTANCE; v = ValueNull.INSTANCE;
} else { } else {
v = ValueLob.createClob(new BufferedReader(in), -1, session.getDataHandler()); v = LobStorage.createClob(new BufferedReader(in), -1, session.getDataHandler());
} }
} }
break; break;
} }
case Value.BLOB: { case Value.BLOB: {
if (session == null) { if (session == null) {
v = ValueLob.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 : ValueLob.createBlob(in, -1, session.getDataHandler()); v = (in == null) ? (Value) ValueNull.INSTANCE : LobStorage.createBlob(in, -1, session.getDataHandler());
} }
break; break;
} }
...@@ -863,19 +864,19 @@ public class DataType { ...@@ -863,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 ValueLob.createClob(r, -1, session.getDataHandler()); return LobStorage.createClob(r, -1, session.getDataHandler());
} 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 ValueLob.createClob(r, -1, session.getDataHandler()); return LobStorage.createClob(r, -1, session.getDataHandler());
} 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 ValueLob.createBlob((java.io.InputStream) x, -1, session.getDataHandler()); return LobStorage.createBlob((java.io.InputStream) x, -1, session.getDataHandler());
} else if (x instanceof java.sql.Blob) { } else if (x instanceof java.sql.Blob) {
try { try {
return ValueLob.createBlob(((java.sql.Blob) x).getBinaryStream(), -1, session.getDataHandler()); return LobStorage.createBlob(((java.sql.Blob) x).getBinaryStream(), -1, session.getDataHandler());
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} }
......
...@@ -29,6 +29,7 @@ import org.h2.engine.Constants; ...@@ -29,6 +29,7 @@ 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.Utils;
import org.h2.util.ExactUTF8InputStreamReader; import org.h2.util.ExactUTF8InputStreamReader;
...@@ -483,7 +484,7 @@ public class Transfer { ...@@ -483,7 +484,7 @@ public class Transfer {
return ValueStringFixed.get(readString()); return ValueStringFixed.get(readString());
case Value.BLOB: { case Value.BLOB: {
long length = readLong(); long length = readLong();
ValueLob v = ValueLob.createBlob(in, length, session.getDataHandler()); Value v = LobStorage.createBlob(in, length, session.getDataHandler());
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);
...@@ -492,7 +493,7 @@ public class Transfer { ...@@ -492,7 +493,7 @@ public class Transfer {
} }
case Value.CLOB: { case Value.CLOB: {
long length = readLong(); long length = readLong();
ValueLob v = ValueLob.createClob(new ExactUTF8InputStreamReader(in), length, session.getDataHandler()); Value v = LobStorage.createClob(new ExactUTF8InputStreamReader(in), length, session.getDataHandler());
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);
......
...@@ -21,10 +21,11 @@ import org.h2.constant.ErrorCode; ...@@ -21,10 +21,11 @@ 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;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.LobStorage;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.Utils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Utils;
/** /**
* This is the base class for all value classes. * This is the base class for all value classes.
...@@ -705,7 +706,7 @@ public abstract class Value { ...@@ -705,7 +706,7 @@ public abstract class Value {
case BLOB: { case BLOB: {
switch(getType()) { switch(getType()) {
case BYTES: case BYTES:
return ValueLob.createSmallLob(Value.BLOB, getBytesNoCopy()); return LobStorage.createSmallLob(Value.BLOB, getBytesNoCopy());
} }
break; break;
} }
...@@ -763,9 +764,9 @@ public abstract class Value { ...@@ -763,9 +764,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 ValueLob.createSmallLob(CLOB, StringUtils.utf8Encode(s)); return LobStorage.createSmallLob(CLOB, StringUtils.utf8Encode(s));
case BLOB: case BLOB:
return ValueLob.createSmallLob(BLOB, Utils.convertStringToBytes(s.trim())); return LobStorage.createSmallLob(BLOB, Utils.convertStringToBytes(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: {
...@@ -978,4 +979,16 @@ public abstract class Value { ...@@ -978,4 +979,16 @@ public abstract class Value {
throw DbException.getUnsupportedException(DataType.getDataType(getType()).name); throw DbException.getUnsupportedException(DataType.getDataType(getType()).name);
} }
public int getTableId() {
return 0;
}
public byte[] getSmall() {
return null;
}
public Value copyToTemp() {
return this;
}
} }
...@@ -48,11 +48,6 @@ public class ValueLob extends Value { ...@@ -48,11 +48,6 @@ public class ValueLob extends Value {
// (to create a large blob from pieces) // (to create a large blob from pieces)
// and a getpart function (to get it in pieces) and make sure a file is created! // and a getpart function (to get it in pieces) and make sure a file is created!
/**
* The 'table id' to use for session variables.
*/
public static final int TABLE_ID_SESSION_VARIABLE = -1;
/** /**
* 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
* better than using a random number because less directories are created. * better than using a random number because less directories are created.
......
差异被折叠。
...@@ -118,6 +118,7 @@ import org.h2.test.unit.TestIntArray; ...@@ -118,6 +118,7 @@ import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap; import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestMathUtils; import org.h2.test.unit.TestMathUtils;
import org.h2.test.unit.TestNetUtils; import org.h2.test.unit.TestNetUtils;
import org.h2.test.unit.TestOldVersion;
import org.h2.test.unit.TestOverflow; import org.h2.test.unit.TestOverflow;
import org.h2.test.unit.TestPageStore; import org.h2.test.unit.TestPageStore;
import org.h2.test.unit.TestPattern; import org.h2.test.unit.TestPattern;
...@@ -292,6 +293,15 @@ java org.h2.test.TestAll timer ...@@ -292,6 +293,15 @@ java org.h2.test.TestAll timer
power failure test: larger binaries and additional index. power failure test: larger binaries and additional index.
drop table test;
create table test(id identity, name varchar(100) default space(100));
@LOOP 10 insert into test select null, null from system_range(1, 100000);
delete from test;
insert 50,000,000 tuples into table
2. execute 'delete table where (always true)'
compatibility test for tcp/ip
rename Page* classes rename Page* classes
move classes to the right packages move classes to the right packages
...@@ -400,6 +410,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -400,6 +410,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
memory = true; memory = true;
test(); test();
memory = false;
networked = false;
diskUndo = true; diskUndo = true;
diskResult = true; diskResult = true;
traceLevelFile = 3; traceLevelFile = 3;
...@@ -568,6 +580,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -568,6 +580,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new TestIntArray().runTest(this); new TestIntArray().runTest(this);
new TestIntIntHashMap().runTest(this); new TestIntIntHashMap().runTest(this);
new TestMathUtils().runTest(this); new TestMathUtils().runTest(this);
new TestOldVersion().runTest(this);
new TestNetUtils().runTest(this); new TestNetUtils().runTest(this);
new TestMultiThreadedKernel().runTest(this); new TestMultiThreadedKernel().runTest(this);
new TestOverflow().runTest(this); new TestOverflow().runTest(this);
......
...@@ -1150,30 +1150,15 @@ public abstract class TestBase { ...@@ -1150,30 +1150,15 @@ public abstract class TestBase {
*/ */
protected void eatMemory(int remainingKB) { protected void eatMemory(int remainingKB) {
byte[] reserve = new byte[remainingKB * 1024]; byte[] reserve = new byte[remainingKB * 1024];
int max = 128 * 1024 * 1024; // first, eat memory in 16 KB blocks, then eat in 16 byte blocks
int div = 2; for (int size = 16 * 1024; size > 0; size /= 1024) {
while (true) { while (true) {
long free = Runtime.getRuntime().freeMemory(); try {
long freeTry = free / div; byte[] block = new byte[16 * 1024];
int eat = (int) Math.min(max, freeTry); memory.add(block);
try { } catch (OutOfMemoryError e) {
byte[] block = new byte[eat];
memory.add(block);
} catch (OutOfMemoryError e) {
if (eat < 32) {
break; break;
} }
if (eat == max) {
max /= 2;
if (max < 128) {
break;
}
}
if (eat == freeTry) {
div += 1;
} else {
div = 2;
}
} }
} }
// silly code - makes sure there are no warnings // silly code - makes sure there are no warnings
......
...@@ -32,8 +32,8 @@ public class TestCompatibility extends TestBase { ...@@ -32,8 +32,8 @@ public class TestCompatibility extends TestBase {
public void test() throws SQLException { public void test() throws SQLException {
deleteDb("compatibility"); deleteDb("compatibility");
conn = getConnection("compatibility");
conn = getConnection("compatibility");
testDomain(); testDomain();
testColumnAlias(); testColumnAlias();
testUniqueIndexSingleNull(); testUniqueIndexSingleNull();
......
...@@ -13,6 +13,7 @@ import java.sql.Timestamp; ...@@ -13,6 +13,7 @@ import java.sql.Timestamp;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
...@@ -304,4 +305,8 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -304,4 +305,8 @@ public class TestDataPage extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -9,6 +9,7 @@ package org.h2.test.unit; ...@@ -9,6 +9,7 @@ package org.h2.test.unit;
import java.util.Random; import java.util.Random;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -169,4 +170,8 @@ public class TestFile extends TestBase implements DataHandler { ...@@ -169,4 +170,8 @@ public class TestFile extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -13,6 +13,7 @@ import java.util.HashMap; ...@@ -13,6 +13,7 @@ import java.util.HashMap;
import java.util.Random; import java.util.Random;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -147,4 +148,8 @@ public class TestValueHashMap extends TestBase implements DataHandler { ...@@ -147,4 +148,8 @@ public class TestValueHashMap extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -15,10 +15,11 @@ import java.util.IdentityHashMap; ...@@ -15,10 +15,11 @@ import java.util.IdentityHashMap;
import java.util.Random; import java.util.Random;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.Utils;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
import org.h2.util.Utils;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean; import org.h2.value.ValueBoolean;
...@@ -30,7 +31,6 @@ import org.h2.value.ValueDouble; ...@@ -30,7 +31,6 @@ import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat; 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.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;
...@@ -137,12 +137,12 @@ public class TestValueMemory extends TestBase implements DataHandler { ...@@ -137,12 +137,12 @@ public class TestValueMemory extends TestBase implements DataHandler {
case Value.BLOB: { case Value.BLOB: {
int len = (int) Math.abs(random.nextGaussian() * 10); int len = (int) Math.abs(random.nextGaussian() * 10);
byte[] data = randomBytes(len); byte[] data = randomBytes(len);
return ValueLob.createBlob(new ByteArrayInputStream(data), len, this); return LobStorage.createBlob(new ByteArrayInputStream(data), len, this);
} }
case Value.CLOB: { case Value.CLOB: {
int len = (int) Math.abs(random.nextGaussian() * 10); int len = (int) Math.abs(random.nextGaussian() * 10);
String s = randomString(len); String s = randomString(len);
return ValueLob.createClob(new StringReader(s), len, this); return LobStorage.createClob(new StringReader(s), len, this);
} }
case Value.ARRAY: { case Value.ARRAY: {
int len = random.nextInt(20); int len = random.nextInt(20);
...@@ -226,4 +226,8 @@ public class TestValueMemory extends TestBase implements DataHandler { ...@@ -226,4 +226,8 @@ public class TestValueMemory extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() {
return null;
}
} }
...@@ -532,6 +532,10 @@ public class Build extends BuildBase { ...@@ -532,6 +532,10 @@ public class Build extends BuildBase {
* Compile and run all tests. * Compile and run all tests.
*/ */
public void test() { public void test() {
// for TestOldVersion
download("ext/h2-1.2.127.jar",
"http://repo1.maven.org/maven2/com/h2database/h2/1.2.127/h2-1.2.127.jar",
"056e784c7cf009483366ab9cd8d21d02fe47031a");
compile(); compile();
java("org.h2.test.TestAll", null); java("org.h2.test.TestAll", null);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论