提交 6e13b867 authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental LOB storage.

上级 f8296473
...@@ -18,14 +18,19 @@ Change Log ...@@ -18,14 +18,19 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>The Shell tool threw a NumberFormatException on a empty statement. <ul><li>A new experimental LOB storage mechanism is available.
When enabled, CLOB and BLOB data is stored in hidden tables in the database.
To use it, set the system property "h2.lobInDatabase" to "true".
Compression is not yet implemented. Duplicate objects are only stored once.
Usually writing is slower, but reading is faster (mainly because of caching).
</li><li>The Shell tool threw a NumberFormatException on a empty statement.
</li><li>The h2small-*.jar did not support "drop all objects delete files". </li><li>The h2small-*.jar did not support "drop all objects delete files".
Now it is supported (the DeleteDbFiles tool is now included). Now it is supported (the DeleteDbFiles tool is now included).
</li><li>Operations that don't fit in memory are now faster. </li><li>Operations that don't fit in memory are now faster.
Temporary file handling was changed. Temporary file handling was changed.
</li><li>The default maximum log stream size is now 2 MB. This is a good value </li><li>The default maximum log stream size is now 2 MB. This is a good value
according to some performance tests. according to some performance tests.
</li><li>New system property "h2.syncMethod" to configure what method to call when </li><li>New system property "h2.syncMethod" to configure what method to call when
closing the database, on checkpoint, and on CHECKPOINT SYNC. The default is "sync" which closing the database, on checkpoint, and on CHECKPOINT SYNC. The default is "sync" which
calls RandomAccessFile.getFD().sync(). calls RandomAccessFile.getFD().sync().
</li><li>ROWNUM could not be used for pagination. The follow query returned no rows: </li><li>ROWNUM could not be used for pagination. The follow query returned no rows:
......
...@@ -4810,6 +4810,9 @@ public class Parser { ...@@ -4810,6 +4810,9 @@ public class Parser {
read("PERSISTENT"); read("PERSISTENT");
command.setPersistData(false); command.setPersistData(false);
} }
if (readIf("HIDDEN")) {
command.setHidden(true);
}
return command; return command;
} }
......
...@@ -267,4 +267,8 @@ public class CreateTable extends SchemaCommand { ...@@ -267,4 +267,8 @@ public class CreateTable extends SchemaCommand {
data.tableEngine = tableEngine; data.tableEngine = tableEngine;
} }
public void setHidden(boolean isHidden) {
data.isHidden = isHidden;
}
} }
...@@ -72,4 +72,9 @@ public class CreateTableData { ...@@ -72,4 +72,9 @@ public class CreateTableData {
*/ */
public String tableEngine; public String tableEngine;
/**
* The table is hidden.
*/
public boolean isHidden;
} }
...@@ -180,6 +180,9 @@ public class ScriptCommand extends ScriptBase { ...@@ -180,6 +180,9 @@ public class ScriptCommand extends ScriptBase {
} }
}); });
for (Table table : tables) { for (Table table : tables) {
if (table.isHidden()) {
continue;
}
table.lock(session, false, false); table.lock(session, false, false);
String sql = table.getCreateSQL(); String sql = table.getCreateSQL();
if (sql == null) { if (sql == null) {
...@@ -198,6 +201,9 @@ public class ScriptCommand extends ScriptBase { ...@@ -198,6 +201,9 @@ public class ScriptCommand extends ScriptBase {
add(sequence.getCreateSQL(), false); add(sequence.getCreateSQL(), false);
} }
for (Table table : tables) { for (Table table : tables) {
if (table.isHidden()) {
continue;
}
table.lock(session, false, false); table.lock(session, false, false);
String sql = table.getCreateSQL(); String sql = table.getCreateSQL();
if (sql == null) { if (sql == null) {
...@@ -299,6 +305,9 @@ public class ScriptCommand extends ScriptBase { ...@@ -299,6 +305,9 @@ public class ScriptCommand extends ScriptBase {
}); });
for (SchemaObject obj : constraints) { for (SchemaObject obj : constraints) {
Constraint constraint = (Constraint) obj; Constraint constraint = (Constraint) obj;
if (constraint.getTable().isHidden()) {
continue;
}
if (!Constraint.PRIMARY_KEY.equals(constraint.getConstraintType())) { if (!Constraint.PRIMARY_KEY.equals(constraint.getConstraintType())) {
add(constraint.getCreateSQLWithoutIndexes(), false); add(constraint.getCreateSQLWithoutIndexes(), false);
} }
......
...@@ -45,7 +45,11 @@ public class ConstraintCheck extends Constraint { ...@@ -45,7 +45,11 @@ public class ConstraintCheck extends Constraint {
public String getCreateSQLForCopy(Table forTable, String quotedName) { public String getCreateSQLForCopy(Table forTable, String quotedName) {
StringBuilder buff = new StringBuilder("ALTER TABLE "); StringBuilder buff = new StringBuilder("ALTER TABLE ");
buff.append(forTable.getSQL()).append(" ADD CONSTRAINT ").append(quotedName); buff.append(forTable.getSQL()).append(" ADD CONSTRAINT ");
if (forTable.isHidden()) {
buff.append("IF NOT EXISTS ");
}
buff.append(quotedName);
if (comment != null) { if (comment != null) {
buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment)); buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment));
} }
......
...@@ -112,7 +112,11 @@ public class ConstraintReferential extends Constraint { ...@@ -112,7 +112,11 @@ public class ConstraintReferential extends Constraint {
public String getCreateSQLForCopy(Table forTable, Table forRefTable, String quotedName, boolean internalIndex) { public String getCreateSQLForCopy(Table forTable, Table forRefTable, String quotedName, boolean internalIndex) {
StatementBuilder buff = new StatementBuilder("ALTER TABLE "); StatementBuilder buff = new StatementBuilder("ALTER TABLE ");
String mainTable = forTable.getSQL(); String mainTable = forTable.getSQL();
buff.append(mainTable).append(" ADD CONSTRAINT ").append(quotedName); buff.append(mainTable).append(" ADD CONSTRAINT ");
if (forTable.isHidden()) {
buff.append("IF NOT EXISTS ");
}
buff.append(quotedName);
if (comment != null) { if (comment != null) {
buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment)); buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment));
} }
......
...@@ -42,7 +42,11 @@ public class ConstraintUnique extends Constraint { ...@@ -42,7 +42,11 @@ public class ConstraintUnique extends Constraint {
private String getCreateSQLForCopy(Table forTable, String quotedName, boolean internalIndex) { private String getCreateSQLForCopy(Table forTable, String quotedName, boolean internalIndex) {
StatementBuilder buff = new StatementBuilder("ALTER TABLE "); StatementBuilder buff = new StatementBuilder("ALTER TABLE ");
buff.append(forTable.getSQL()).append(" ADD CONSTRAINT ").append(quotedName); buff.append(forTable.getSQL()).append(" ADD CONSTRAINT ");
if (forTable.isHidden()) {
buff.append("IF NOT EXISTS ");
}
buff.append(quotedName);
if (comment != null) { if (comment != null) {
buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment)); buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment));
} }
......
...@@ -2233,7 +2233,9 @@ public class Database implements DataHandler { ...@@ -2233,7 +2233,9 @@ public class Database implements DataHandler {
public Connection getLobConnection() { public Connection getLobConnection() {
if (SysProperties.LOB_IN_DATABASE) { if (SysProperties.LOB_IN_DATABASE) {
String url = Constants.CONN_URL_INTERNAL; String url = Constants.CONN_URL_INTERNAL;
return new JdbcConnection(systemSession, systemUser.getName(), url); JdbcConnection conn = new JdbcConnection(systemSession, systemUser.getName(), url);
conn.setTraceLevel(TraceSystem.OFF);
return conn;
} }
return null; return null;
} }
......
...@@ -322,7 +322,11 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -322,7 +322,11 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
public String getCreateSQLForCopy(Table targetTable, String quotedName) { public String getCreateSQLForCopy(Table targetTable, String quotedName) {
StringBuilder buff = new StringBuilder("CREATE "); StringBuilder buff = new StringBuilder("CREATE ");
buff.append(indexType.getSQL()); buff.append(indexType.getSQL());
buff.append(' ').append(quotedName); buff.append(' ');
if (table.isHidden()) {
buff.append("IF NOT EXISTS ");
}
buff.append(quotedName);
buff.append(" ON ").append(targetTable.getSQL()); buff.append(" ON ").append(targetTable.getSQL());
if (comment != null) { if (comment != null) {
buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment)); buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment));
......
...@@ -1700,4 +1700,11 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1700,4 +1700,11 @@ public class JdbcConnection extends TraceObject implements Connection {
return compareMode; return compareMode;
} }
/**
* INTERNAL
*/
public void setTraceLevel(int level) {
trace.setLevel(level);
}
} }
...@@ -141,16 +141,25 @@ public class Data { ...@@ -141,16 +141,25 @@ public class Data {
} }
/** /**
* Get the length of a String value. * Get the length of a String. This includes the bytes required to encode
* the length.
* *
* @param s the value * @param s the string
* @return the length * @return the number of bytes required
*/ */
public static int getStringLen(String s) { public static int getStringLen(String s) {
int len = s.length(); int len = s.length();
return getStringWithoutLengthLen(s, len) + getVarIntLen(len); return getStringWithoutLengthLen(s, len) + getVarIntLen(len);
} }
/**
* Calculate the length of String, excluding the bytes required to encode
* the length.
*
* @param s the string
* @param len the length of the string
* @return the number of bytes required
*/
public static int getStringWithoutLengthLen(String s, int len) { public static int getStringWithoutLengthLen(String s, int len) {
int plus = 0; int plus = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
...@@ -298,7 +307,7 @@ public class Data { ...@@ -298,7 +307,7 @@ public class Data {
System.arraycopy(buff, off, data, pos, len); System.arraycopy(buff, off, data, pos, len);
pos += len; pos += len;
} }
/** /**
* Append a number of bytes to this buffer. * Append a number of bytes to this buffer.
* *
...@@ -320,7 +329,7 @@ public class Data { ...@@ -320,7 +329,7 @@ public class Data {
System.arraycopy(data, pos, buff, off, len); System.arraycopy(data, pos, buff, off, len);
pos += len; pos += len;
} }
/** /**
* Copy a number of bytes to the given buffer from the current position. The * Copy a number of bytes to the given buffer from the current position. The
* current position is incremented accordingly. * current position is incremented accordingly.
...@@ -330,7 +339,7 @@ public class Data { ...@@ -330,7 +339,7 @@ public class Data {
public void read(byte[] buff) { public void read(byte[] buff) {
read(buff, 0, buff.length); read(buff, 0, buff.length);
} }
/** /**
* Append one single byte. * Append one single byte.
* *
...@@ -745,7 +754,7 @@ public class Data { ...@@ -745,7 +754,7 @@ public class Data {
public int getValueLen(Value v) { public int getValueLen(Value v) {
return getValueLen(v, handler); return getValueLen(v, handler);
} }
/** /**
* Calculate the number of bytes required to encode the given value. * Calculate the number of bytes required to encode the given value.
* *
......
...@@ -74,10 +74,10 @@ public class LobStorage { ...@@ -74,10 +74,10 @@ public class LobStorage {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
// stat.execute("SET UNDO_LOG 0"); // stat.execute("SET UNDO_LOG 0");
// stat.execute("SET REDO_LOG_BINARY 0"); // stat.execute("SET REDO_LOG_BINARY 0");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOBS + "(ID BIGINT PRIMARY KEY, LENGTH BIGINT, TABLE INT)"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOBS + "(ID BIGINT PRIMARY KEY, LENGTH BIGINT, TABLE INT) HIDDEN");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_MAP + "(LOB BIGINT, SEQ INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ))"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_MAP + "(LOB BIGINT, SEQ INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ)) HIDDEN");
stat.execute("CREATE INDEX IF NOT EXISTS INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON " + LOB_MAP + "(BLOCK, LOB)"); stat.execute("CREATE INDEX IF NOT EXISTS INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON " + LOB_MAP + "(BLOCK, LOB)");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_DATA + "(BLOCK BIGINT PRIMARY KEY, DATA BINARY)"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_DATA + "(BLOCK BIGINT PRIMARY KEY, DATA BINARY) HIDDEN");
ResultSet rs; ResultSet rs;
rs = stat.executeQuery("SELECT MAX(BLOCK) FROM " + LOB_DATA); rs = stat.executeQuery("SELECT MAX(BLOCK) FROM " + LOB_DATA);
rs.next(); rs.next();
...@@ -166,7 +166,7 @@ public class LobStorage { ...@@ -166,7 +166,7 @@ public class LobStorage {
} }
public int read(byte[] buff, int off, int length) throws IOException { public int read(byte[] buff, int off, int length) throws IOException {
return readFully(buff, 0, buff.length); return readFully(buff, off, length);
} }
private int readFully(byte[] buff, int off, int length) throws IOException { private int readFully(byte[] buff, int off, int length) throws IOException {
...@@ -182,6 +182,7 @@ public class LobStorage { ...@@ -182,6 +182,7 @@ public class LobStorage {
int len = (int) Math.min(length, remaining); int len = (int) Math.min(length, remaining);
len = Math.min(len, buffer.length - pos); len = Math.min(len, buffer.length - pos);
System.arraycopy(buffer, pos, buff, off, len); System.arraycopy(buffer, pos, buff, off, len);
pos += len;
read += len; read += len;
remaining -= len; remaining -= len;
off += len; off += len;
...@@ -263,6 +264,8 @@ public class LobStorage { ...@@ -263,6 +264,8 @@ public class LobStorage {
} }
private ValueLob2 addLob(InputStream in, long maxLength, int type) { private ValueLob2 addLob(InputStream in, long maxLength, int type) {
int todo;
// TODO support in-place lobs, and group lobs much smaller than the page size
byte[] buff = new byte[BLOCK_LENGTH]; byte[] buff = new byte[BLOCK_LENGTH];
if (maxLength < 0) { if (maxLength < 0) {
maxLength = Long.MAX_VALUE; maxLength = Long.MAX_VALUE;
...@@ -272,7 +275,8 @@ public class LobStorage { ...@@ -272,7 +275,8 @@ public class LobStorage {
try { try {
try { try {
for (int seq = 0; maxLength > 0; seq++) { for (int seq = 0; maxLength > 0; seq++) {
int len = IOUtils.readFully(in, buff, 0, BLOCK_LENGTH); int len = (int) Math.min(BLOCK_LENGTH, maxLength);
len = IOUtils.readFully(in, buff, 0, len);
if (len <= 0) { if (len <= 0) {
break; break;
} }
...@@ -344,16 +348,21 @@ public class LobStorage { ...@@ -344,16 +348,21 @@ public class LobStorage {
private final Reader reader; private final Reader reader;
private long length; private long length;
private long remaining;
private int pos; private int pos;
private char[] charBuffer = new char[Constants.IO_BUFFER_SIZE]; private char[] charBuffer = new char[Constants.IO_BUFFER_SIZE];
private byte[] buffer; private byte[] buffer;
CountingReaderInputStream(Reader reader) { CountingReaderInputStream(Reader reader, long maxLength) {
this.reader = reader; this.reader = reader;
this.remaining = maxLength;
buffer = Utils.EMPTY_BYTES; buffer = Utils.EMPTY_BYTES;
} }
public int read(byte[] buff, int offset, int len) throws IOException { public int read(byte[] buff, int offset, int len) throws IOException {
if (buffer == null) {
return -1;
}
if (pos >= buffer.length) { if (pos >= buffer.length) {
fillBuffer(); fillBuffer();
if (buffer == null) { if (buffer == null) {
...@@ -362,10 +371,14 @@ public class LobStorage { ...@@ -362,10 +371,14 @@ public class LobStorage {
} }
len = Math.min(len, buffer.length - pos); len = Math.min(len, buffer.length - pos);
System.arraycopy(buffer, pos, buff, offset, len); System.arraycopy(buffer, pos, buff, offset, len);
pos += len;
return len; return len;
} }
public int read() throws IOException { public int read() throws IOException {
if (buffer == null) {
return -1;
}
if (pos >= buffer.length) { if (pos >= buffer.length) {
fillBuffer(); fillBuffer();
if (buffer == null) { if (buffer == null) {
...@@ -376,13 +389,20 @@ public class LobStorage { ...@@ -376,13 +389,20 @@ public class LobStorage {
} }
private void fillBuffer() throws IOException { private void fillBuffer() throws IOException {
int len = reader.read(charBuffer); int len = (int) Math.min(charBuffer.length, remaining);
if (len > 0) {
len = reader.read(charBuffer, 0, len);
} else {
len = -1;
}
if (len < 0) { if (len < 0) {
buffer = null; buffer = null;
} else { } else {
buffer = StringUtils.utf8Encode(new String(charBuffer, 0, len)); buffer = StringUtils.utf8Encode(new String(charBuffer, 0, len));
length += len; length += len;
remaining -= len;
} }
pos = 0;
} }
public long getLength() { public long getLength() {
...@@ -426,8 +446,9 @@ public class LobStorage { ...@@ -426,8 +446,9 @@ public class LobStorage {
if (conn == null) { if (conn == null) {
return ValueLob2.createTempClob(reader, maxLength, handler); return ValueLob2.createTempClob(reader, maxLength, handler);
} }
CountingReaderInputStream in = new CountingReaderInputStream(reader); long max = maxLength == -1 ? Long.MAX_VALUE : maxLength;
ValueLob2 lob = addLob(in, maxLength, Value.BLOB); CountingReaderInputStream in = new CountingReaderInputStream(reader, max);
ValueLob2 lob = addLob(in, Long.MAX_VALUE, Value.CLOB);
lob.setPrecision(in.getLength()); lob.setPrecision(in.getLength());
return lob; return lob;
} }
......
...@@ -316,9 +316,9 @@ public abstract class FileSystem { ...@@ -316,9 +316,9 @@ public abstract class FileSystem {
* @param inTempDir if the file should be stored in the temporary directory * @param inTempDir if the file should be stored in the temporary directory
* @return the name of the created file * @return the name of the created file
*/ */
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException { public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException {
while (true) { while (true) {
String n = name + getNextTempFileNamePart(false) + suffix; String n = prefix + getNextTempFileNamePart(false) + suffix;
if (exists(n)) { if (exists(n)) {
// in theory, the random number could collide // in theory, the random number could collide
getNextTempFileNamePart(true); getNextTempFileNamePart(true);
......
...@@ -619,6 +619,9 @@ public class MetaTable extends Table { ...@@ -619,6 +619,9 @@ public class MetaTable extends Table {
if (!checkIndex(session, tableName, indexFrom, indexTo)) { if (!checkIndex(session, tableName, indexFrom, indexTo)) {
continue; continue;
} }
if (table.isHidden()) {
continue;
}
String storageType; String storageType;
if (table.isTemporary()) { if (table.isTemporary()) {
if (table.isGlobalTemporary()) { if (table.isGlobalTemporary()) {
...@@ -660,6 +663,9 @@ public class MetaTable extends Table { ...@@ -660,6 +663,9 @@ public class MetaTable extends Table {
if (!checkIndex(session, tableName, indexFrom, indexTo)) { if (!checkIndex(session, tableName, indexFrom, indexTo)) {
continue; continue;
} }
if (table.isHidden()) {
continue;
}
Column[] cols = table.getColumns(); Column[] cols = table.getColumns();
String collation = database.getCompareMode().getName(); String collation = database.getCompareMode().getName();
for (int j = 0; j < cols.length; j++) { for (int j = 0; j < cols.length; j++) {
...@@ -723,6 +729,9 @@ public class MetaTable extends Table { ...@@ -723,6 +729,9 @@ public class MetaTable extends Table {
if (!checkIndex(session, tableName, indexFrom, indexTo)) { if (!checkIndex(session, tableName, indexFrom, indexTo)) {
continue; continue;
} }
if (table.isHidden()) {
continue;
}
ArrayList<Index> indexes = table.getIndexes(); ArrayList<Index> indexes = table.getIndexes();
ArrayList<Constraint> constraints = table.getConstraints(); ArrayList<Constraint> constraints = table.getConstraints();
for (int j = 0; indexes != null && j < indexes.size(); j++) { for (int j = 0; indexes != null && j < indexes.size(); j++) {
...@@ -1175,7 +1184,7 @@ public class MetaTable extends Table { ...@@ -1175,7 +1184,7 @@ public class MetaTable extends Table {
case TABLE_PRIVILEGES: { case TABLE_PRIVILEGES: {
for (Right r : database.getAllRights()) { for (Right r : database.getAllRights()) {
Table table = r.getGrantedTable(); Table table = r.getGrantedTable();
if (table == null) { if (table == null || table.isHidden()) {
continue; continue;
} }
String tableName = identifier(table.getName()); String tableName = identifier(table.getName());
...@@ -1189,7 +1198,7 @@ public class MetaTable extends Table { ...@@ -1189,7 +1198,7 @@ public class MetaTable extends Table {
case COLUMN_PRIVILEGES: { case COLUMN_PRIVILEGES: {
for (Right r : database.getAllRights()) { for (Right r : database.getAllRights()) {
Table table = r.getGrantedTable(); Table table = r.getGrantedTable();
if (table == null) { if (table == null || table.isHidden()) {
continue; continue;
} }
String tableName = identifier(table.getName()); String tableName = identifier(table.getName());
...@@ -1321,6 +1330,9 @@ public class MetaTable extends Table { ...@@ -1321,6 +1330,9 @@ public class MetaTable extends Table {
String checkExpression = null; String checkExpression = null;
IndexColumn[] indexColumns = null; IndexColumn[] indexColumns = null;
Table table = constraint.getTable(); Table table = constraint.getTable();
if (table.isHidden()) {
continue;
}
Index index = constraint.getUniqueIndex(); Index index = constraint.getUniqueIndex();
String uniqueIndexName = null; String uniqueIndexName = null;
if (index != null) { if (index != null) {
......
...@@ -67,6 +67,7 @@ public class RegularTable extends TableBase { ...@@ -67,6 +67,7 @@ public class RegularTable extends TableBase {
public RegularTable(CreateTableData data) { public RegularTable(CreateTableData data) {
super(data); super(data);
this.isHidden = data.isHidden;
if (data.persistData && database.isPersistent()) { if (data.persistData && database.isPersistent()) {
mainIndex = new PageDataIndex(this, data.id, IndexColumn.wrap(getColumns()), IndexType.createScan(data.persistData), data.create, data.session); mainIndex = new PageDataIndex(this, data.id, IndexColumn.wrap(getColumns()), IndexType.createScan(data.persistData), data.create, data.session);
scanIndex = mainIndex; scanIndex = mainIndex;
......
...@@ -95,6 +95,12 @@ public abstract class Table extends SchemaObjectBase { ...@@ -95,6 +95,12 @@ public abstract class Table extends SchemaObjectBase {
*/ */
protected CompareMode compareMode; protected CompareMode compareMode;
/**
* Protected tables are not listed in the meta data and are excluded when
* using the SCRIPT command.
*/
protected boolean isHidden;
private final HashMap<String, Column> columnMap = New.hashMap(); private final HashMap<String, Column> columnMap = New.hashMap();
private boolean persistIndexes; private boolean persistIndexes;
private boolean persistData; private boolean persistData;
...@@ -966,4 +972,14 @@ public abstract class Table extends SchemaObjectBase { ...@@ -966,4 +972,14 @@ public abstract class Table extends SchemaObjectBase {
return column.convert(v); return column.convert(v);
} }
/**
* Check whether this is a hidden table that doesn't appear in the meta
* data and in the script.
*
* @return true if it is hidden
*/
public boolean isHidden() {
return isHidden;
}
} }
...@@ -53,7 +53,11 @@ public abstract class TableBase extends Table { ...@@ -53,7 +53,11 @@ public abstract class TableBase extends Table {
} else { } else {
buff.append("MEMORY "); buff.append("MEMORY ");
} }
buff.append("TABLE ").append(getSQL()); buff.append("TABLE ");
if (isHidden) {
buff.append("IF NOT EXISTS ");
}
buff.append(getSQL());
if (comment != null) { if (comment != null) {
buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment)); buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment));
} }
...@@ -71,6 +75,9 @@ public abstract class TableBase extends Table { ...@@ -71,6 +75,9 @@ public abstract class TableBase extends Table {
if (!isPersistIndexes() && !isPersistData()) { if (!isPersistIndexes() && !isPersistData()) {
buff.append("\nNOT PERSISTENT"); buff.append("\nNOT PERSISTENT");
} }
if (isHidden) {
buff.append("\nHIDDEN");
}
return buff.toString(); return buff.toString();
} }
......
...@@ -102,11 +102,15 @@ public class ValueLob2 extends Value { ...@@ -102,11 +102,15 @@ public class ValueLob2 extends Value {
if (t == type) { if (t == type) {
return this; return this;
} else if (t == Value.CLOB) { } else if (t == Value.CLOB) {
Value copy = handler.getLobStorage().createClob(getReader(), -1); if (lobStorage != null) {
return copy; Value copy = lobStorage.createClob(getReader(), -1);
return copy;
}
} else if (t == Value.BLOB) { } else if (t == Value.BLOB) {
Value copy = handler.getLobStorage().createBlob(getInputStream(), -1); if (lobStorage != null) {
return copy; Value copy = lobStorage.createBlob(getInputStream(), -1);
return copy;
}
} }
return super.convertTo(t); return super.convertTo(t);
} }
...@@ -474,6 +478,7 @@ public class ValueLob2 extends Value { ...@@ -474,6 +478,7 @@ public class ValueLob2 extends Value {
private FileStoreOutputStream initTemp(DataHandler h) { private FileStoreOutputStream initTemp(DataHandler h) {
this.precision = 0; this.precision = 0;
this.handler = h; this.handler = h;
this.lobStorage = h.getLobStorage();
this.small = null; this.small = null;
try { try {
String path = h.getDatabasePath(); String path = h.getDatabasePath();
......
...@@ -290,6 +290,10 @@ java org.h2.test.TestAll timer ...@@ -290,6 +290,10 @@ java org.h2.test.TestAll timer
System.setProperty("h2.maxMemoryRowsDistinct", "128"); System.setProperty("h2.maxMemoryRowsDistinct", "128");
System.setProperty("h2.check2", "true"); System.setProperty("h2.check2", "true");
int testing;
System.setProperty("h2.lobInDatabase", "true");
/* /*
power failure test power failure test
...@@ -304,8 +308,6 @@ delete from test; ...@@ -304,8 +308,6 @@ delete from test;
rename Page* classes rename Page* classes
move classes to the right packages move classes to the right packages
Fix the default value and documentation for MAX_LOG_SIZE.
// System.setProperty("h2.pageSize", "64"); // System.setProperty("h2.pageSize", "64");
test with small freeList pages, page size 64 test with small freeList pages, page size 64
...@@ -351,12 +353,12 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -351,12 +353,12 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
} else { } else {
test.runTests(); test.runTests();
Profiler prof = new Profiler(); Profiler prof = new Profiler();
prof.depth = 10; prof.depth = 4;
prof.interval = 1; prof.interval = 1;
prof.startCollecting(); prof.startCollecting();
TestPerformance.main("-init", "-db", "1"); TestPerformance.main("-init", "-db", "1");
prof.stopCollecting(); prof.stopCollecting();
System.out.println(prof.getTop(2)); System.out.println(prof.getTop(3));
// Recover.execute("data", null); // Recover.execute("data", null);
// RunScript.execute("jdbc:h2:data/test2", // RunScript.execute("jdbc:h2:data/test2",
// "sa1", "sa1", "data/test.h2.sql", null, false); // "sa1", "sa1", "data/test.h2.sql", null, false);
......
...@@ -138,6 +138,9 @@ public class TestLob extends TestBase { ...@@ -138,6 +138,9 @@ public class TestLob extends TestBase {
} }
private void testLobDeleteTemp() throws SQLException { private void testLobDeleteTemp() throws SQLException {
if (SysProperties.LOB_IN_DATABASE) {
return;
}
deleteDb("lob"); deleteDb("lob");
Connection conn = getConnection("lob"); Connection conn = getConnection("lob");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
...@@ -161,7 +164,7 @@ public class TestLob extends TestBase { ...@@ -161,7 +164,7 @@ public class TestLob extends TestBase {
} }
private void testLobDelete() throws SQLException { private void testLobDelete() throws SQLException {
if (config.memory) { if (config.memory || SysProperties.LOB_IN_DATABASE) {
return; return;
} }
deleteDb("lob"); deleteDb("lob");
......
...@@ -367,6 +367,7 @@ public class TestTools extends TestBase { ...@@ -367,6 +367,7 @@ public class TestTools extends TestBase {
assertTrue(trace.exists()); assertTrue(trace.exists());
File newTrace = new File(baseDir + "/test.trace.db"); File newTrace = new File(baseDir + "/test.trace.db");
newTrace.delete(); newTrace.delete();
assertFalse(newTrace.exists());
assertTrue(trace.renameTo(newTrace)); assertTrue(trace.renameTo(newTrace));
deleteDb("toolsConvertTraceFile"); deleteDb("toolsConvertTraceFile");
Player.main(baseDir + "/test.trace.db"); Player.main(baseDir + "/test.trace.db");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论