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

--no commit message

--no commit message
上级 ebf9cd96
......@@ -11,7 +11,7 @@ import org.h2.value.Value;
public interface DataHandler {
boolean getTextStorage();
String getDatabasePath();
FileStore openFile(String name, boolean mustExist) throws SQLException;
FileStore openFile(String name, String mode, boolean mustExist) throws SQLException;
int getChecksum(byte[] data, int start, int end);
void checkPowerOff() throws SQLException;
void checkWritingAllowed() throws SQLException;
......
......@@ -29,6 +29,7 @@ import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
import org.h2.value.ValueString;
import org.h2.value.ValueStringFixed;
import org.h2.value.ValueStringIgnoreCase;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
......@@ -199,6 +200,7 @@ public abstract class DataPage {
}
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
writeString(v.getString());
break;
case Value.DOUBLE:
......@@ -261,6 +263,7 @@ public abstract class DataPage {
return 1 + getIntLen();
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
case Value.DECIMAL:
return 1 + getStringLen(v.getString());
case Value.JAVA_OBJECT:
......@@ -353,6 +356,8 @@ public abstract class DataPage {
return ValueString.get(readString());
case Value.STRING_IGNORECASE:
return ValueStringIgnoreCase.get(readString());
case Value.STRING_FIXED:
return ValueStringFixed.get(readString());
case Value.DOUBLE:
return ValueDouble.get(Double.longBitsToDouble(readLong()));
case Value.FLOAT:
......
......@@ -59,12 +59,14 @@ public class DiskFile implements CacheWriter {
private ObjectArray redoBuffer;
private int redoBufferSize;
private int readCount, writeCount;
private String mode;
public DiskFile(Database database, String fileName, boolean dataFile, boolean logChanges, int cacheSize) throws SQLException {
public DiskFile(Database database, String fileName, String mode, boolean dataFile, boolean logChanges, int cacheSize) throws SQLException {
reset();
this.database = database;
this.log = database.getLog();
this.fileName = fileName;
this.mode = mode;
this.dataFile = dataFile;
this.logChanges = logChanges;
String cacheType = database.getCacheType();
......@@ -81,7 +83,7 @@ public class DiskFile implements CacheWriter {
freeBlock.updateChecksum();
try {
if(FileUtils.exists(fileName)) {
file = database.openFile(fileName, true);
file = database.openFile(fileName, mode, true);
long length = file.length();
database.notifyFileSize(length);
int blocks = (int)((length - OFFSET) / BLOCK_SIZE);
......@@ -118,7 +120,7 @@ public class DiskFile implements CacheWriter {
private void create() throws SQLException {
try {
file = database.openFile(fileName, false);
file = database.openFile(fileName, mode, false);
DataPage header = DataPage.create(database, OFFSET);
file.seek(FileStore.HEADER_LENGTH);
header.fill(OFFSET);
......
......@@ -29,27 +29,27 @@ public class FileStore {
private Reference autoDeleteReference;
private boolean checkedWriting = true;
public static FileStore open(DataHandler handler, String name, byte[] magic) throws SQLException {
return open(handler, name, magic, null, null, 0);
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
return open(handler, name, mode, magic, null, null, 0);
}
public static FileStore open(DataHandler handler, String name, byte[] magic, String cipher, byte[] key) throws SQLException {
return open(handler, name, magic, cipher, key, Constants.ENCRYPTION_KEY_HASH_ITERATIONS);
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic, String cipher, byte[] key) throws SQLException {
return open(handler, name, mode, magic, cipher, key, Constants.ENCRYPTION_KEY_HASH_ITERATIONS);
}
public static FileStore open(DataHandler handler, String name, byte[] magic, String cipher, byte[] key, int keyIterations) throws SQLException {
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic, String cipher, byte[] key, int keyIterations) throws SQLException {
FileStore store;
if(FileUtils.isInMemory(name)) {
store = new MemoryFileStore(handler, name, magic);
} else if(cipher == null) {
store = new FileStore(handler, name, magic);
store = new FileStore(handler, name, mode, magic);
} else {
store = new SecureFileStore(handler, name, magic, cipher, key, keyIterations);
store = new SecureFileStore(handler, name, mode, magic, cipher, key, keyIterations);
}
return store;
}
protected FileStore(DataHandler handler, String name, byte[] magic) throws SQLException {
protected FileStore(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
this.handler = handler;
this.name = name;
this.magic = magic;
......@@ -59,8 +59,7 @@ public class FileStore {
if(f.exists() && !f.canWrite()) {
file = FileUtils.openRandomAccessFile(name, "r");
} else {
// file = new RandomAccessFile(name, "rws");
file = FileUtils.openRandomAccessFile(name, "rw");
file = FileUtils.openRandomAccessFile(name, mode);
}
} catch(IOException e) {
throw Message.convert(e);
......
......@@ -59,7 +59,7 @@ public class LogFile {
this.id = id;
this.fileNamePrefix = fileNamePrefix;
fileName = getFileName();
file = log.getDatabase().openFile(fileName, false);
file = log.getDatabase().openFile(fileName, database.getWriteModeLog(), false);
rowBuff = log.getRowBuffer();
buffer = new byte[BUFFER_SIZE];
unwritten = new ObjectArray();
......@@ -333,6 +333,8 @@ public class LogFile {
if(file == null) {
throw Message.getSQLException(Message.SIMULATED_POWER_OFF);
}
int testing ;
//System.out.println("flush " + file.length() + " pos:"+file.getFilePointer()+" len:"+bufferPos);
file.write(buffer, 0, bufferPos);
for(int i=0; i<unwritten.size(); i++) {
Record r = (Record) unwritten.get(i);
......
......@@ -38,6 +38,7 @@ public class LogSystem {
private ObjectArray inDoubtTransactions;
private boolean disabled;
private int keepFiles;
private boolean closed;
public LogSystem(Database database, String fileNamePrefix, boolean readOnly) throws SQLException {
this.database = database;
......@@ -110,10 +111,13 @@ public class LogSystem {
}
public void close() throws SQLException {
if (database == null || readOnly) {
if(database == null || readOnly) {
return;
}
synchronized (database) {
if(closed) {
return;
}
// TODO refactor flushing and closing files when we know what to do exactly
SQLException closeException = null;
try {
......@@ -140,7 +144,7 @@ public class LogSystem {
}
}
}
database = null;
closed = true;
if (closeException != null) {
throw closeException;
}
......@@ -157,10 +161,13 @@ public class LogSystem {
}
public boolean recover() throws SQLException {
if (database == null) {
if(database == null) {
return false;
}
synchronized (database) {
if(closed) {
return false;
}
undo = new ObjectArray();
for (int i = 0; i < activeLogs.size(); i++) {
LogFile log = (LogFile) activeLogs.get(i);
......@@ -290,10 +297,13 @@ public class LogSystem {
}
public void prepareCommit(Session session, String transaction) throws SQLException {
if (database == null || readOnly) {
if(database == null || readOnly) {
return;
}
synchronized (database) {
if(closed) {
return;
}
currentLog.prepareCommit(session, transaction);
}
}
......@@ -303,6 +313,9 @@ public class LogSystem {
return;
}
synchronized (database) {
if(closed) {
return;
}
currentLog.commit(session);
session.setAllCommitted();
}
......@@ -313,15 +326,21 @@ public class LogSystem {
return;
}
synchronized (database) {
if(closed) {
return;
}
currentLog.flush();
}
}
public void addTruncate(Session session, DiskFile file, int storageId, int recordId, int blockCount) throws SQLException {
if (database == null || disabled) {
if(database == null) {
return;
}
synchronized (database) {
if(disabled || closed) {
return;
}
database.checkWritingAllowed();
if (!file.isDataFile()) {
storageId = -storageId;
......@@ -334,10 +353,13 @@ public class LogSystem {
}
public void add(Session session, DiskFile file, Record record) throws SQLException {
if (database == null || disabled) {
if(database == null) {
return;
}
}
synchronized (database) {
if(disabled || closed) {
return;
}
database.checkWritingAllowed();
int storageId = record.getStorageId();
if (!file.isDataFile()) {
......@@ -355,10 +377,13 @@ public class LogSystem {
}
public void checkpoint() throws SQLException {
if (database == null || readOnly || disabled) {
if(readOnly || database == null) {
return;
}
synchronized (database) {
if(closed || disabled) {
return;
}
flushAndCloseUnused();
currentLog = new LogFile(this, currentLog.getId() + 1, fileNamePrefix);
activeLogs.add(currentLog);
......@@ -376,9 +401,6 @@ public class LogSystem {
}
private void writeSummary() throws SQLException {
if (database == null || readOnly || disabled) {
return;
}
byte[] summary;
DiskFile file;
file = database.getDataFile();
......@@ -415,6 +437,9 @@ public class LogSystem {
}
public void sync() throws SQLException {
if(database == null || readOnly) {
return;
}
synchronized (database) {
if (currentLog != null) {
currentLog.flush();
......
......@@ -72,7 +72,7 @@ public class UndoLog {
if(memoryUndo > database.getMaxMemoryUndo() && database.isPersistent()) {
if(file == null) {
String fileName = database.createTempFile();
file = database.openFile(fileName, false);
file = database.openFile(fileName, "rw", false);
file.autoDelete();
file.seek(FileStore.HEADER_LENGTH);
rowBuff = DataPage.create(database, Constants.DEFAULT_DATA_PAGE_SIZE);
......
......@@ -276,6 +276,7 @@ public class Column {
case Value.BYTES:
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
buff.append("(");
buff.append(precision);
buff.append(")");
......
......@@ -112,7 +112,7 @@ public class FunctionTable extends Table {
return false;
}
public int getRowCount() throws SQLException {
public long getRowCount() throws SQLException {
throw Message.getInternalError();
}
......
......@@ -87,7 +87,8 @@ public class MetaTable extends Table {
// extensions
"STORAGE_TYPE",
"SQL",
"REMARKS"
"REMARKS",
"ID INT"
});
indexColumnName = "TABLE_NAME";
break;
......@@ -534,7 +535,8 @@ public class MetaTable extends Table {
table.getTableType(), // TABLE_TYPE
storageType, // STORAGE_TYPE
table.getCreateSQL(), // SQL
replaceNullWithEmpty(table.getComment()) // REMARKS
replaceNullWithEmpty(table.getComment()), // REMARKS
"" + table.getId() // ID
});
}
break;
......@@ -696,7 +698,7 @@ public class MetaTable extends Table {
String.valueOf(t.minScale), // MINIMUM_SCALE
String.valueOf(t.maxScale), // MAXIMUM_SCALE
t.decimal ? "10" : null, // RADIX
String.valueOf(t.order), // POS
String.valueOf(t.sqlTypePos), // POS
String.valueOf(t.caseSensitive), // CASE_SENSITIVE
"" + DatabaseMetaData.typeNullable, // NULLABLE
"" + DatabaseMetaData.typeSearchable // SEARCHABLE
......@@ -1216,7 +1218,7 @@ public class MetaTable extends Table {
throw Message.getUnsupportedException();
}
public int getRowCount() {
public long getRowCount() {
throw Message.getInternalError();
}
......
......@@ -84,9 +84,8 @@ public class RangeTable extends Table {
return false;
}
public int getRowCount() throws SQLException {
// TODO document system_range: count(*) for system_range could be wrong (long to int conversion)
return (int)(max - min);
public long getRowCount() throws SQLException {
return max - min;
}
public String getTableType() {
......
......@@ -250,7 +250,7 @@ public abstract class Table extends SchemaObject {
ObjectArray indexes = getIndexes();
for (int i = 1; indexes != null && masks != null && i < indexes.size(); i++) {
Index index = (Index) indexes.get(i);
int cost = index.getCost(masks);
long cost = index.getCost(masks);
if (cost < item.cost) {
item.cost = cost;
item.setIndex(index);
......@@ -432,7 +432,7 @@ public abstract class Table extends SchemaObject {
public abstract boolean canGetRowCount();
public abstract boolean canDrop();
public abstract int getRowCount() throws SQLException;
public abstract long getRowCount() throws SQLException;
public boolean getGlobalTemporary() {
return false;
......
......@@ -29,6 +29,7 @@ import org.h2.schema.Schema;
import org.h2.store.DataPage;
import org.h2.store.Record;
import org.h2.store.RecordReader;
import org.h2.util.MathUtils;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.Value;
......@@ -38,7 +39,7 @@ import org.h2.value.Value;
*/
public class TableData extends Table implements RecordReader {
private ScanIndex scanIndex;
private int rowCount;
private long rowCount;
private Session lockExclusive;
private HashSet lockShared = new HashSet();
private Trace traceLock;
......@@ -76,7 +77,7 @@ public class TableData extends Table implements RecordReader {
Index index = (Index) indexes.get(i);
index.add(session, row);
if(Constants.CHECK) {
int rc = index.getRowCount();
long rc = index.getRowCount();
if(rc != rowCount+1) {
throw Message.getInternalError("rowCount expected "+(rowCount+1)+" got "+rc);
}
......@@ -89,7 +90,7 @@ public class TableData extends Table implements RecordReader {
Index index = (Index) indexes.get(i);
index.remove(session, row);
if(Constants.CHECK) {
int rc = index.getRowCount();
long rc = index.getRowCount();
if(rc != rowCount) {
throw Message.getInternalError("rowCount expected "+(rowCount)+" got "+rc);
}
......@@ -152,14 +153,16 @@ public class TableData extends Table implements RecordReader {
if(index.needRebuild()) {
try {
Index scan = getScanIndex(session);
int remaining = scan.getRowCount();
int total = remaining;
long remaining = scan.getRowCount();
long total = remaining;
Cursor cursor = scan.find(session, null, null);
int i = 0;
long i = 0;
int bufferSize = Constants.DEFAULT_MAX_MEMORY_ROWS;
ObjectArray buffer = new ObjectArray(bufferSize);
while (cursor.next()) {
database.setProgress(DatabaseEventListener.STATE_CREATE_INDEX, getName(), i++, total);
database.setProgress(DatabaseEventListener.STATE_CREATE_INDEX, getName(),
MathUtils.convertLongToInt(i++),
MathUtils.convertLongToInt(total));
Row row = cursor.get();
// index.add(session, row);
buffer.add(row);
......@@ -234,7 +237,7 @@ public class TableData extends Table implements RecordReader {
return true;
}
public int getRowCount() {
public long getRowCount() {
return rowCount;
}
......@@ -244,7 +247,7 @@ public class TableData extends Table implements RecordReader {
Index index = (Index) indexes.get(i);
index.remove(session, row);
if(Constants.CHECK) {
int rc = index.getRowCount();
long rc = index.getRowCount();
if(rc != rowCount-1) {
throw Message.getInternalError("rowCount expected "+(rowCount-1)+" got "+rc);
}
......@@ -259,7 +262,7 @@ public class TableData extends Table implements RecordReader {
Index index = (Index) indexes.get(i);
index.truncate(session);
if(Constants.CHECK) {
int rc = index.getRowCount();
long rc = index.getRowCount();
if(rc != 0) {
throw Message.getInternalError("rowCount expected 0 got "+rc);
}
......
......@@ -387,17 +387,21 @@ public class TableFilter implements ColumnResolver {
buff.append(alias);
}
buff.append(" /* ");
buff.append(index.getPlanSQL());
StringBuffer planBuff = new StringBuffer();
planBuff.append(index.getPlanSQL());
if(indexConditions.size() > 0) {
buff.append(": ");
planBuff.append(": ");
for (int i = 0; i < indexConditions.size(); i++) {
IndexCondition condition = (IndexCondition) indexConditions.get(i);
if(i>0) {
buff.append(" AND ");
planBuff.append(" AND ");
}
buff.append(condition.getSQL());
planBuff.append(condition.getSQL());
}
}
String plan = planBuff.toString();
plan = StringUtils.quoteRemarkSQL(plan);
buff.append(plan);
buff.append(" */");
if(joinCondition != null) {
buff.append(" ON ");
......@@ -405,7 +409,9 @@ public class TableFilter implements ColumnResolver {
}
if(filterCondition != null) {
buff.append(" /* WHERE ");
buff.append(StringUtils.unEnclose(filterCondition.getSQL()));
String condition = StringUtils.unEnclose(filterCondition.getSQL());
condition = StringUtils.quoteRemarkSQL(condition);
buff.append(condition);
buff.append("*/");
}
return buff.toString();
......
......@@ -39,9 +39,10 @@ public class TableLink extends Table {
private ObjectArray indexes = new ObjectArray();
private boolean emitUpdates;
private LinkedIndex linkedIndex;
private SQLException connectException;
public TableLink(Schema schema, int id, String name, String driver, String url,
String user, String password, String originalTable, boolean emitUpdates) throws SQLException {
String user, String password, String originalTable, boolean emitUpdates, boolean force) throws SQLException {
super(schema, id, name, false);
this.driver = driver;
this.url = url;
......@@ -49,6 +50,21 @@ public class TableLink extends Table {
this.password = password;
this.originalTable = originalTable;
this.emitUpdates = emitUpdates;
try {
connect();
} catch(SQLException e) {
connectException = e;
if(!force) {
throw e;
}
Column[] cols = new Column[0];
setColumns(cols);
linkedIndex = new LinkedIndex(this, id, cols, IndexType.createNonUnique(false));
indexes.add(linkedIndex);
}
}
private void connect() throws SQLException {
conn = JdbcUtils.getConnection(driver, url, user, password);
DatabaseMetaData meta = conn.getMetaData();
boolean storesLowerCase = meta.storesLowerCaseIdentifiers();
......@@ -99,6 +115,7 @@ public class TableLink extends Table {
Column[] cols = new Column[columnList.size()];
columnList.toArray(cols);
setColumns(cols);
int id = getId();
linkedIndex = new LinkedIndex(this, id, cols, IndexType.createNonUnique(false));
indexes.add(linkedIndex);
rs = meta.getPrimaryKeys(null, null, originalTable);
......@@ -167,7 +184,7 @@ public class TableLink extends Table {
public String getCreateSQL() {
StringBuffer buff = new StringBuffer();
buff.append("CREATE LINKED TABLE ");
buff.append("CREATE FORCE LINKED TABLE ");
buff.append(getSQL());
if(comment != null) {
buff.append(" COMMENT ");
......@@ -224,11 +241,11 @@ public class TableLink extends Table {
}
}
public int getRowCount() throws SQLException {
public long getRowCount() throws SQLException {
PreparedStatement prep = getPreparedStatement("SELECT COUNT(*) FROM "+originalTable);
ResultSet rs = prep.executeQuery();
rs.next();
int count = rs.getInt(1);
long count = rs.getLong(1);
rs.close();
return count;
}
......@@ -238,6 +255,9 @@ public class TableLink extends Table {
}
public PreparedStatement getPreparedStatement(String sql) throws SQLException {
if(conn == null) {
throw connectException;
}
PreparedStatement prep = (PreparedStatement) prepared.get(sql);
if(prep==null) {
prep = conn.prepareStatement(sql);
......
......@@ -8,6 +8,7 @@ import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.command.dml.Query;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.index.Index;
......@@ -17,6 +18,7 @@ import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.schema.Schema;
import org.h2.util.ObjectArray;
import org.h2.util.SmallLRUCache;
import org.h2.util.StringUtils;
import org.h2.value.Value;
......@@ -28,7 +30,7 @@ public class TableView extends Table {
private Query viewQuery;
private ViewIndex index;
private boolean recursive;
private SQLException createException;
private SQLException createException;
public TableView(Schema schema, int id, String name, String querySQL, ObjectArray params, String[] columnNames, Session session, boolean recursive) throws SQLException {
super(schema, id, name, false);
......@@ -103,7 +105,14 @@ public class TableView extends Table {
public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException {
PlanItem item = new PlanItem();
item.cost = index.getCost(session, masks);
item.setIndex(index);
Index i2 = new ViewIndex(this, index, session, masks);
item.setIndex(i2);
int testing;
// item.setIndex(index);
return item;
}
......@@ -176,7 +185,7 @@ public class TableView extends Table {
throw Message.getUnsupportedException();
}
public int getRowCount() {
public long getRowCount() {
throw Message.getInternalError();
}
......
......@@ -138,9 +138,9 @@ public class ChangePassword {
byte[] magic = Database.getMagic(textStorage);
FileStore in;
if(decrypt == null) {
in = FileStore.open(null, fileName, magic);
in = FileStore.open(null, fileName, "r", magic);
} else {
in = FileStore.open(null, fileName, magic, cipher, decrypt);
in = FileStore.open(null, fileName, "r", magic, cipher, decrypt);
}
in.init();
copy(fileName, textStorage, in, encrypt);
......@@ -152,9 +152,9 @@ public class ChangePassword {
byte[] magic = Database.getMagic(textStorage);
FileStore out;
if(key == null) {
out = FileStore.open(null, temp, magic);
out = FileStore.open(null, temp, "rw", magic);
} else {
out = FileStore.open(null, temp, magic, cipher, key);
out = FileStore.open(null, temp, "rw", magic, cipher, key);
}
out.init();
byte[] buffer = new byte[4 * 1024];
......
......@@ -193,19 +193,6 @@ public class Csv implements SimpleRowSource {
throw e;
}
}
if(columnNames != null) {
writeHeader();
}
}
private void writeHeader() {
for(int i=0; i<columnNames.length; i++) {
if(i>0) {
writer.print(fieldSeparatorWrite);
}
writer.print(columnNames[i]);
}
writer.println();
}
private void writeRow(String[] values) {
......@@ -501,8 +488,7 @@ public class Csv implements SimpleRowSource {
}
/**
* Reset the position (before the first row).
* This is not supported at this time, and this methods throws a SQLException
* INTERNAL
*/
public void reset() throws SQLException {
throw new SQLException("Method is not supported", "CSV");
......
......@@ -133,7 +133,7 @@ public class Recover implements DataHandler {
databaseName = fileName.substring(fileName.length() - Constants.SUFFIX_DATA_FILE.length());
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
FileStore store = FileStore.open(null, fileName, magic);
FileStore store = FileStore.open(null, fileName, "rw", magic);
long length = store.length();
int offset = FileStore.HEADER_LENGTH;
int blockSize = DiskFile.BLOCK_SIZE;
......@@ -311,7 +311,7 @@ public class Recover implements DataHandler {
out = new FileOutputStream(n);
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, magic);
store = FileStore.open(null, fileName, "r", magic);
store.init();
in = new BufferedInputStream(new FileStoreInputStream(store, this, lobCompression));
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
......@@ -393,7 +393,7 @@ public class Recover implements DataHandler {
writer = getWriter(fileName, ".txt");
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, magic);
store = FileStore.open(null, fileName, "r", magic);
long length = store.length();
writer.println("// length: " + length);
int offset = FileStore.HEADER_LENGTH;
......@@ -549,7 +549,7 @@ public class Recover implements DataHandler {
writer = getWriter(fileName, ".txt");
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, magic);
store = FileStore.open(null, fileName, "r", magic);
long length = store.length();
int offset = FileStore.HEADER_LENGTH;
int blockSize = DiskFile.BLOCK_SIZE;
......@@ -627,7 +627,7 @@ public class Recover implements DataHandler {
HashMap tableMap = new HashMap();
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, magic);
store = FileStore.open(null, fileName, "r", magic);
long length = store.length();
int offset = FileStore.HEADER_LENGTH;
int blockSize = DiskFile.BLOCK_SIZE;
......@@ -812,7 +812,7 @@ public class Recover implements DataHandler {
/**
* INTERNAL
*/
public FileStore openFile(String name, boolean mustExist) throws SQLException {
public FileStore openFile(String name, String mode, boolean mustExist) throws SQLException {
return null;
}
......
......@@ -200,7 +200,9 @@ public class RunScript {
}
} else {
try {
stat.execute(sql);
if(sql.trim().length()>0) {
stat.execute(sql);
}
} catch (SQLException e) {
if (continueOnError) {
e.printStackTrace();
......
......@@ -605,4 +605,22 @@ public class StringUtils {
return s == null || s.length() == 0;
}
public static String quoteRemarkSQL(String sql) {
while(true) {
int idx = sql.indexOf("*/");
if(idx < 0) {
break;
}
sql = sql.substring(0, idx) + "++/" + sql.substring(idx + 2);
}
while(true) {
int idx = sql.indexOf("/*");
if(idx < 0) {
break;
}
sql = sql.substring(0, idx) + "/++" + sql.substring(idx + 2);
}
return sql;
}
}
......@@ -7,6 +7,7 @@ package org.h2.value;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Clob;
import java.sql.Date;
import java.sql.ResultSet;
......@@ -37,7 +38,7 @@ public class DataType {
public String jdbc;
// how closely the data type maps to the corresponding JDBC SQL type (low is best)
public int order;
public int sqlTypePos;
public int maxPrecision;
public int minScale, maxScale;
......@@ -51,8 +52,12 @@ public class DataType {
public int defaultScale;
public boolean hidden;
// for operations that include different types, convert both to the higher order
public int order;
// JDK 1.3 compatibility: Types.BOOLEAN
public static final int TYPE_BOOLEAN = 16;
// JDK 1.3 compatibility: Types.DATALINK
public static final int TYPE_DATALINK = 70;
......@@ -64,11 +69,28 @@ public class DataType {
if(TYPE_DATALINK != Types.DATALINK) {
new Exception("Types.DATALINK: " + Types.DATALINK).printStackTrace();
}
//#endif
add(Value.NULL, Types.NULL, "Null",
new DataType(),
new String[]{"NULL"}
);
add(Value.STRING, Types.VARCHAR, "String",
createString(true),
new String[]{"VARCHAR", "VARCHAR2", "NVARCHAR", "NVARCHAR2", "VARCHAR_CASESENSITIVE", "CHARACTER VARYING"}
);
add(Value.STRING, Types.LONGVARCHAR, "String",
createString(true),
new String[]{"LONGVARCHAR"}
);
add(Value.STRING_FIXED, Types.CHAR, "String",
createString(true),
new String[]{"CHAR", "CHARACTER", "NCHAR"}
);
add(Value.STRING_IGNORECASE, Types.VARCHAR, "String",
createString(false),
new String[]{"VARCHAR_IGNORECASE"}
);
add(Value.BOOLEAN, DataType.TYPE_BOOLEAN, "Boolean",
createDecimal(ValueBoolean.PRECISION, ValueBoolean.PRECISION, 0, false, false),
new String[]{"BOOLEAN", "BIT", "BOOL"}
......@@ -103,6 +125,10 @@ public class DataType {
new String[]{"NUMERIC", "NUMBER"}
// TODO value: are NaN, Inf, -Inf,... supported as well?
);
add(Value.FLOAT, Types.REAL, "Float",
createDecimal(ValueFloat.PRECISION, ValueFloat.PRECISION, 0, false, false),
new String[] {"REAL", "FLOAT4"}
);
add(Value.DOUBLE, Types.DOUBLE, "Double",
createDecimal(ValueDouble.PRECISION, ValueDouble.PRECISION, 0, false, false),
new String[] { "DOUBLE", "DOUBLE PRECISION" }
......@@ -112,10 +138,6 @@ public class DataType {
new String[] {"FLOAT", "FLOAT8" }
// TODO value: show min and max values, E format if supported
);
add(Value.FLOAT, Types.REAL, "Float",
createDecimal(ValueFloat.PRECISION, ValueFloat.PRECISION, 0, false, false),
new String[] {"REAL", "FLOAT4"}
);
add(Value.TIME, Types.TIME, "Time",
createDate(ValueTime.PRECISION, "TIME", 0),
new String[]{"TIME"}
......@@ -139,33 +161,17 @@ public class DataType {
createString(false),
new String[]{"BINARY", "RAW", "BYTEA", "LONG RAW"}
);
add(Value.UUID, Types.BINARY, "Bytes",
createString(false),
new String[]{"UUID"}
);
add(Value.BYTES, Types.LONGVARBINARY, "Bytes",
createString(false),
new String[]{"LONGVARBINARY"}
);
add(Value.JAVA_OBJECT, Types.OTHER, "Object",
add(Value.UUID, Types.BINARY, "Bytes",
createString(false),
new String[]{"OTHER", "OBJECT", "JAVA_OBJECT"}
);
add(Value.STRING, Types.VARCHAR, "String",
createString(true),
new String[]{"VARCHAR", "VARCHAR2", "NVARCHAR", "NVARCHAR2", "VARCHAR_CASESENSITIVE"}
);
add(Value.STRING, Types.LONGVARCHAR, "String",
createString(true),
new String[]{"LONGVARCHAR"}
);
add(Value.STRING, Types.CHAR, "String",
createString(true),
new String[]{"CHAR", "CHARACTER", "NCHAR"}
new String[]{"UUID"}
);
add(Value.STRING_IGNORECASE, Types.VARCHAR, "String",
add(Value.JAVA_OBJECT, Types.OTHER, "Object",
createString(false),
new String[]{"VARCHAR_IGNORECASE"}
new String[]{"OTHER", "OBJECT", "JAVA_OBJECT"}
);
add(Value.BLOB, Types.BLOB, "Bytes",
createString(false),
......@@ -182,6 +188,18 @@ public class DataType {
dataType,
new String[]{"ARRAY"}
);
dataType = new DataType();
add(Value.RESULT_SET, 0, "ResultSet",
dataType,
new String[]{"RESULT_SET"}
);
for(int i=0; i<typesByValueType.length; i++) {
DataType dt = typesByValueType[i];
if(dt == null) {
throw Message.getInternalError("unmapped type " + i);
}
Value.getOrder(i);
}
// TODO data types: try to support other types as well (longvarchar for odbc/access,...) - maybe map them to regular types?
}
......@@ -209,7 +227,7 @@ public class DataType {
for(int j=0; j<types.size(); j++) {
DataType t2 = (DataType) types.get(j);
if(t2.sqlType == dt.sqlType) {
dt.order++;
dt.sqlTypePos++;
}
}
typesByName.put(dt.name, dt);
......@@ -338,7 +356,16 @@ public class DataType {
v = rs.wasNull() ? (Value)ValueNull.INSTANCE : ValueShort.get(value);
break;
}
case Value.STRING_IGNORECASE:
case Value.STRING_IGNORECASE: {
String s = rs.getString(columnIndex);
v = (s == null) ? (Value)ValueNull.INSTANCE : ValueStringIgnoreCase.get(s);
break;
}
case Value.STRING_FIXED: {
String s = rs.getString(columnIndex);
v = (s == null) ? (Value)ValueNull.INSTANCE : ValueStringFixed.get(s);
break;
}
case Value.STRING: {
String s = rs.getString(columnIndex);
v = (s == null) ? (Value)ValueNull.INSTANCE : ValueString.get(s);
......@@ -367,6 +394,22 @@ public class DataType {
v = buff==null ? (Value)ValueNull.INSTANCE : ValueJavaObject.getNoCopy(buff);
break;
}
case Value.ARRAY: {
Array array = rs.getArray(columnIndex);
if(array == null) {
return ValueNull.INSTANCE;
}
Object[] list = (Object[])array.getArray();
if(list == null) {
return ValueNull.INSTANCE;
}
Value[] values = new Value[list.length];
for(int i=0; i<list.length; i++) {
values[i] = DataType.convertToValue(session, list[i], Value.NULL);
}
v = array ==null ? (Value)ValueNull.INSTANCE : ValueArray.get(values);
break;
}
default:
throw Message.getInternalError("type="+type);
}
......@@ -398,6 +441,7 @@ public class DataType {
return byte[].class.getName(); // "[B", not "byte[]";
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
return String.class.getName(); // "java.lang.String";
case Value.BLOB:
return java.sql.Blob.class.getName(); // "java.sql.Blob";
......@@ -430,8 +474,9 @@ public class DataType {
public static int convertSQLTypeToValueType(int sqlType) throws SQLException {
switch(sqlType) {
case Types.VARCHAR:
case Types.CHAR:
return Value.STRING_FIXED;
case Types.VARCHAR:
case Types.LONGVARCHAR:
return Value.STRING;
case Types.NUMERIC:
......
......@@ -239,6 +239,7 @@ public class Transfer {
break;
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
writeString(v.getString());
break;
case Value.BLOB: {
......@@ -354,6 +355,8 @@ public class Transfer {
return ValueString.get(readString());
case Value.STRING_IGNORECASE:
return ValueStringIgnoreCase.get(readString());
case Value.STRING_FIXED:
return ValueStringFixed.get(readString());
case Value.BLOB: {
long length = readLong();
ValueLob v = ValueLob.createBlob(in, length, session.getDataHandler());
......
......@@ -38,9 +38,9 @@ public abstract class Value {
public static final int NULL = 0, BOOLEAN = 1, BYTE = 2, SHORT = 3, INT = 4, LONG = 5, DECIMAL = 6;
public static final int DOUBLE = 7, FLOAT = 8, TIME = 9, DATE = 10, TIMESTAMP = 11, BYTES = 12;
public static final int STRING = 13, STRING_IGNORECASE = 14, BLOB = 15, CLOB = 16;
public static final int ARRAY = 17, RESULT_SET = 18, JAVA_OBJECT = 19, UUID = 20;
public static final int ARRAY = 17, RESULT_SET = 18, JAVA_OBJECT = 19, UUID = 20, STRING_FIXED = 21;
public static final int TYPE_COUNT = UUID + 1;
public static final int TYPE_COUNT = STRING_FIXED + 1;
private static WeakReference weakCache = new WeakReference(null);
// private static int cacheCleaner = 0;
......@@ -49,9 +49,73 @@ public abstract class Value {
// private static Value[] cache = new Value[Constants.OBJECT_CACHE_SIZE];
private static final BigDecimal MAX_LONG_DECIMAL = new BigDecimal("" + Long.MAX_VALUE);
private static final BigDecimal MIN_LONG_DECIMAL = new BigDecimal("" + Long.MIN_VALUE);
public static int getOrder(int type) {
switch(type) {
case UNKNOWN:
return 1;
case NULL:
return 2;
case STRING:
return 10;
case CLOB:
return 11;
case STRING_FIXED:
return 12;
case STRING_IGNORECASE:
return 13;
case BOOLEAN:
return 20;
case BYTE:
return 21;
case SHORT:
return 22;
case INT:
return 23;
case LONG:
return 24;
case DECIMAL:
return 25;
case FLOAT:
return 26;
case DOUBLE:
return 27;
case TIME:
return 30;
case DATE:
return 31;
case TIMESTAMP:
return 32;
case BYTES:
return 40;
case BLOB:
return 41;
case UUID:
return 42;
case JAVA_OBJECT:
return 43;
case ARRAY:
return 50;
case RESULT_SET:
return 51;
default:
throw Message.getInternalError("type:"+type);
}
}
public static int getHigherOrder(int t1, int t2) throws SQLException {
if(t1 == t2) {
if(t1 == Value.UNKNOWN) {
throw Message.getSQLException(Message.UNKNOWN_DATA_TYPE_1, "?, ?");
}
return t1;
}
int o1 = getOrder(t1);
int o2 = getOrder(t2);
return o1 > o2 ? t1 : t2;
}
static Value cache(Value v) {
if (Constants.OBJECT_CACHE) {
Value[] cache = (Value[]) weakCache.get();
......@@ -81,7 +145,6 @@ public abstract class Value {
public abstract long getPrecision();
public abstract int getDisplaySize();
public abstract String getString() throws SQLException;
// public abstract String getJavaString();
protected abstract int compareSecure(Value v, CompareMode mode) throws SQLException;
protected abstract boolean isEqual(Value v);
public abstract Object getObject() throws SQLException;
......@@ -183,33 +246,6 @@ public abstract class Value {
throw Message.getUnsupportedException();
}
public static int getHigherOrder(int t1, int t2) throws SQLException {
if(t1 == t2) {
if(t1 == Value.UNKNOWN) {
throw Message.getSQLException(Message.UNKNOWN_DATA_TYPE_1, "?, ?");
}
return t1;
}
int type = Math.max(t1, t2);
switch(type) {
case Value.STRING:
case Value.STRING_IGNORECASE: {
int b = Math.min(t1, t2);
switch(b) {
case Value.BLOB:
case Value.BYTES:
case Value.DATE:
case Value.JAVA_OBJECT:
case Value.TIME:
case Value.TIMESTAMP:
case Value.UUID:
return b;
}
}
}
return type;
}
public Value convertTo(int type) throws SQLException {
// converting NULL done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob
......@@ -482,6 +518,8 @@ public abstract class Value {
return ValueString.get(s);
case STRING_IGNORECASE:
return ValueStringIgnoreCase.get(s);
case STRING_FIXED:
return ValueStringFixed.get(s);
case DOUBLE:
return ValueDouble.get(Double.parseDouble(s.trim()));
case FLOAT:
......@@ -615,6 +653,6 @@ public abstract class Value {
}
public void close() throws SQLException {
}
}
}
......@@ -78,6 +78,6 @@ public class ValueBoolean extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueBoolean && value.booleanValue() == ((ValueBoolean)v).value.booleanValue();
}
}
}
......@@ -124,6 +124,6 @@ public class ValueByte extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueByte && value == ((ValueByte)v).value;
}
}
}
......@@ -90,6 +90,6 @@ public class ValueDate extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueDate && value.equals(((ValueDate)v).value);
}
}
}
......@@ -177,6 +177,6 @@ public class ValueDecimal extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueDecimal && value.equals(((ValueDecimal)v).value);
}
}
}
......@@ -122,6 +122,6 @@ public class ValueDouble extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueDouble && value == ((ValueDouble)v).value;
}
}
}
......@@ -122,6 +122,6 @@ public class ValueFloat extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueFloat && value == ((ValueFloat)v).value;
}
}
}
......@@ -148,6 +148,6 @@ public class ValueInt extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueInt && value == ((ValueInt)v).value;
}
}
}
......@@ -288,7 +288,7 @@ public class ValueLob extends Value {
objectId = handler.allocateObjectId(false, true);
fileName = handler.createTempFile();
}
tempFile = handler.openFile(fileName, false);
tempFile = handler.openFile(fileName, "rw", false);
tempFile.autoDelete();
}
FileStoreOutputStream out = new FileStoreOutputStream(tempFile, handler, compressionAlgorithm);
......@@ -360,7 +360,7 @@ public class ValueLob extends Value {
}
deleteFile(handler, temp);
renameFile(handler, fileName, temp);
tempFile = FileStore.open(handler, temp, null);
tempFile = FileStore.open(handler, temp, "rw", null);
tempFile.autoDelete();
tempFile.closeSilently();
fileName = temp;
......@@ -491,7 +491,7 @@ public class ValueLob extends Value {
if (fileName == null) {
return new ByteArrayInputStream(small);
}
FileStore store = handler.openFile(fileName, true);
FileStore store = handler.openFile(fileName, "r", true);
return new BufferedInputStream(new FileStoreInputStream(store, handler, compression), Constants.IO_BUFFER_SIZE);
}
......
......@@ -179,6 +179,6 @@ public class ValueLong extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueLong && value == ((ValueLong)v).value;
}
}
}
......@@ -106,6 +106,6 @@ public class ValueResultSet extends Value {
public String getSQL() {
return "";
}
}
}
......@@ -124,6 +124,6 @@ public class ValueShort extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueShort && value == ((ValueShort)v).value;
}
}
}
......@@ -85,6 +85,6 @@ public class ValueTime extends Value {
protected boolean isEqual(Value v) {
return v instanceof ValueTime && value.equals(((ValueTime)v).value);
}
}
}
......@@ -137,6 +137,15 @@ class Database {
} finally {
JdbcUtils.closeSilently(stat);
}
} else if(url.startsWith("jdbc:hsqldb:")) {
// HSQLDB: use a WRITE_DELAY of 1 second
Statement stat = null;
try {
stat = conn.createStatement();
stat.execute("SET WRITE_DELAY 1");
} finally {
JdbcUtils.closeSilently(stat);
}
}
return conn;
}
......
......@@ -2,7 +2,7 @@ db1 = H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000, sa, sa
xdb2 = H2 (XTEA), org.h2.Driver, jdbc:h2:data/test_xtea;LOCK_TIMEOUT=10000;CIPHER=XTEA, sa, sa 123
xdb3 = H2 (AES), org.h2.Driver, jdbc:h2:data/test_aes;LOCK_TIMEOUT=10000;CIPHER=AES, sa, sa 123
db2 = HSQLDB, org.hsqldb.jdbcDriver, jdbc:hsqldb:data/test;hsqldb.default_table_type=cached, sa
db2 = HSQLDB, org.hsqldb.jdbcDriver, jdbc:hsqldb:data/test;hsqldb.default_table_type=cached;sql.enforce_size=true, sa
db3 = Derby, org.apache.derby.jdbc.EmbeddedDriver, jdbc:derby:data/test;create=true, sa, sa
db4 = H2, org.h2.Driver, jdbc:h2:tcp://localhost/data/testServer;LOCK_TIMEOUT=10000, sa, sa
......@@ -11,11 +11,11 @@ db6 = Derby, org.apache.derby.jdbc.ClientDriver, jdbc:derby://localhost/data/tes
db7 = PostgreSQL, org.postgresql.Driver, jdbc:postgresql:test, sa, sa
db8 = MySQL, com.mysql.jdbc.Driver, jdbc:mysql://localhost/test?jdbcCompliantTruncation=false, sa, sa
#db2 = Firebird, org.firebirdsql.jdbc.FBDriver, jdbc:firebirdsql:localhost:c:/temp/firebird/test, sysdba, masterkey
#db2 = MSSQLServer, com.microsoft.jdbc.sqlserver.SQLServerDriver, jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=test, test, test
#db2 = Oracle, oracle.jdbc.driver.OracleDriver, jdbc:oracle:thin:@localhost:1521:XE, client, client
#db2 = OneDollarDB, in.co.daffodil.db.jdbc.DaffodilDBDriver, jdbc:daffodilDB_embedded:school;path=C:/temp;create=true, sa
#db2 = Firebird, org.firebirdsql.jdbc.FBDriver, jdbc:firebirdsql:localhost:c:/temp/firebird/test, sysdba, masterkey
#db2 = DB2, COM.ibm.db2.jdbc.net.DB2Driver, jdbc:db2://localhost/test, test, test
#db2 = MSSQLServer, com.microsoft.jdbc.sqlserver.SQLServerDriver, jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=test, test, test
#db2 = OneDollarDB, in.co.daffodil.db.jdbc.DaffodilDBDriver, jdbc:daffodilDB_embedded:school;path=C:/temp;create=true, sa
firebirdsql.datetime = TIMESTAMP
postgresql.datetime = TIMESTAMP
......
......@@ -7,6 +7,7 @@ package org.h2.test.db;
import java.io.File;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
......@@ -34,6 +35,14 @@ public class TestCsv extends TestBase {
check(rs.getString(2), "Hello");
checkFalse(rs.next());
new File(BASE_DIR+"/test.csv").delete();
int testing;
// PreparedStatement prep = conn.prepareStatement("select * from csvread(?, null, ?, ?)");
// prep.setString(1, BASE_DIR+"/test.csv");
// prep.setString(2, "utf-8");
// prep.setString(3, "|");
// rs = prep.executeQuery();
conn.close();
}
......
......@@ -26,6 +26,8 @@ public class TestMemoryUsage extends TestBase {
}
public void test() throws Exception {
deleteDb("memoryUsage");
testReconnectOften();
deleteDb("memoryUsage");
reconnect();
insertUpdateSelectDelete();
......@@ -34,6 +36,22 @@ public class TestMemoryUsage extends TestBase {
conn.close();
}
private void testReconnectOften() throws Exception {
int len = getSize(1, 2000);
Connection conn1 = getConnection("memoryUsage");
printTimeMemory("start", 0);
long time = System.currentTimeMillis();
for(int i=0; i<len; i++) {
Connection conn2 = getConnection("memoryUsage");
conn2.close();
if(i % 10000 == 0) {
printTimeMemory("connect", System.currentTimeMillis()-time);
}
}
printTimeMemory("connect", System.currentTimeMillis()-time);
conn1.close();
}
void insertUpdateSelectDelete() throws Exception {
Statement stat = conn.createStatement();
long time;
......
--- special grammar and test cases ---------------------------------------------------------------------------------------------
create table d(d double, r real);
> ok
insert into d values(1.1234567890123456789, 1.1234567890123456789);
> update count: 1
select r+d, r+r, d+d from d;
> R + D R + R D + D
> ----------------- --------- ------------------
> 2.246913624759111 2.2469137 2.2469135780246914
> rows: 1
drop table d;
> ok
create table test(id int, c char(5), v varchar(5));
> ok
insert into test values(1, 'a', 'a');
> update count: 1
insert into test values(2, 'a ', 'a ');
> update count: 1
insert into test values(3, 'abcde ', 'abcde');
> update count: 1
select distinct length(c) from test order by length(c);
> LENGTH(C)
> ---------
> 1
> 5
> rows (ordered): 2
select id, c, v, length(c), length(v) from test order by id;
> ID C V LENGTH(C) LENGTH(V)
> -- ----- ----- --------- ---------
> 1 a a 1 1
> 2 a a 1 2
> 3 abcde abcde 5 5
> rows (ordered): 3
select id from test where c='a' order by id;
> ID
> --
> 1
> 2
> rows (ordered): 2
select id from test where c='a ' order by id;
> ID
> --
> 1
> 2
> rows (ordered): 2
select id from test where c=v order by id;
> ID
> --
> 1
> 2
> 3
> rows (ordered): 3
drop table test;
> ok
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), C INT);
> ok
......@@ -28,7 +95,7 @@ insert into cars values(2, 1), (2, 2), (3, 1), (3, 2), (3, 3), (4, 1);
> update count: 6
select family, (select count(car) from cars where cars.family = people.family) as x
from people group by family order by family;
from people group by family order by family;
> FAMILY X
> ------ -
> 1 0
......@@ -215,8 +282,8 @@ script nopasswords nosettings blocksize 10;
> ------------------------------------------------------------------------------------------------------------------
> -- 1 = SELECT COUNT(*) FROM PUBLIC.TEST
> CALL SYSTEM_COMBINE_BLOB(-1)
> CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_BLOB FOR "org.h2.command.dml.Script.combineBlob"
> CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_CLOB FOR "org.h2.command.dml.Script.combineClob"
> CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_BLOB FOR "org.h2.command.dml.ScriptCommand.combineBlob"
> CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_CLOB FOR "org.h2.command.dml.ScriptCommand.combineClob"
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT NOT NULL, DATA CLOB )
> CREATE PRIMARY KEY ON PUBLIC.TEST(ID)
> CREATE TABLE IF NOT EXISTS SYSTEM_LOB_STREAM(ID INT, PART INT, CDATA VARCHAR, BDATA BINARY, PRIMARY KEY(ID, PART))
......@@ -4373,8 +4440,8 @@ SELECT * FROM V_UNION WHERE ID=1;
EXPLAIN SELECT * FROM V_UNION WHERE ID=1;
> PLAN
> -----------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT V_UNION.ID, V_UNION.NAME, V_UNION.CLASS FROM PUBLIC.V_UNION /* SELECT * FROM CHILDREN UNION ALL SELECT * FROM CHILDREN: ID = 1 */ WHERE ID = 1
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT V_UNION.ID, V_UNION.NAME, V_UNION.CLASS FROM PUBLIC.V_UNION /* (SELECT CHILDREN.ID, CHILDREN.NAME, CHILDREN.CLASS FROM PUBLIC.CHILDREN /++ PUBLIC.PRIMARY_KEY_1: ID = CAST(?1 AS INTEGER) ++/ WHERE CHILDREN.ID = CAST(?1 AS INTEGER)) UNION ALL (SELECT CHILDREN.ID, CHILDREN.NAME, CHILDREN.CLASS FROM PUBLIC.CHILDREN /++ PUBLIC.PRIMARY_KEY_1: ID = CAST(?1 AS INTEGER) ++/ WHERE CHILDREN.ID = CAST(?1 AS INTEGER)): ID = 1 */ WHERE ID = 1
> rows: 1
CREATE VIEW V_EXCEPT AS SELECT * FROM CHILDREN EXCEPT SELECT * FROM CHILDREN WHERE ID=2;
......@@ -4388,8 +4455,8 @@ SELECT * FROM V_EXCEPT WHERE ID=1;
EXPLAIN SELECT * FROM V_EXCEPT WHERE ID=1;
> PLAN
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT V_EXCEPT.ID, V_EXCEPT.NAME, V_EXCEPT.CLASS FROM PUBLIC.V_EXCEPT /* SELECT * FROM CHILDREN EXCEPT SELECT * FROM CHILDREN WHERE ID=2: ID = 1 */ WHERE ID = 1
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT V_EXCEPT.ID, V_EXCEPT.NAME, V_EXCEPT.CLASS FROM PUBLIC.V_EXCEPT /* (SELECT CHILDREN.ID, CHILDREN.NAME, CHILDREN.CLASS FROM PUBLIC.CHILDREN /++ PUBLIC.PRIMARY_KEY_1: ID = CAST(?1 AS INTEGER) ++/ WHERE CHILDREN.ID = CAST(?1 AS INTEGER)) EXCEPT (SELECT CHILDREN.ID, CHILDREN.NAME, CHILDREN.CLASS FROM PUBLIC.CHILDREN /++ PUBLIC.PRIMARY_KEY_1: ID = 2 ++/ WHERE ID = 2): ID = 1 */ WHERE ID = 1
> rows: 1
CREATE VIEW V_INTERSECT AS SELECT ID, NAME FROM CHILDREN INTERSECT SELECT * FROM CLASSES;
......@@ -4402,8 +4469,8 @@ SELECT * FROM V_INTERSECT WHERE ID=1;
EXPLAIN SELECT * FROM V_INTERSECT WHERE ID=1;
> PLAN
> --------------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT V_INTERSECT.ID, V_INTERSECT.NAME FROM PUBLIC.V_INTERSECT /* SELECT ID, NAME FROM CHILDREN INTERSECT SELECT * FROM CLASSES: ID = 1 */ WHERE ID = 1
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT V_INTERSECT.ID, V_INTERSECT.NAME FROM PUBLIC.V_INTERSECT /* (SELECT ID, NAME FROM PUBLIC.CHILDREN /++ PUBLIC.PRIMARY_KEY_1: ID = CAST(?1 AS INTEGER) ++/ WHERE ID = CAST(?1 AS INTEGER)) INTERSECT (SELECT CLASSES.ID, CLASSES.NAME FROM PUBLIC.CLASSES /++ PUBLIC.PRIMARY_KEY_2: ID = CAST(?1 AS INTEGER) ++/ WHERE CLASSES.ID = CAST(?1 AS INTEGER)): ID = 1 */ WHERE ID = 1
> rows: 1
DROP VIEW V_UNION;
......@@ -4510,10 +4577,10 @@ CREATE VIEW TEST_A_SUB AS SELECT * FROM TEST_A WHERE ID < 2;
> ok
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='VIEW';
> TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE STORAGE_TYPE SQL REMARKS
> ------------- ------------ ---------- ---------- ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------- -------
> SCRIPT PUBLIC TEST_ALL VIEW MEMORY CREATE FORCE VIEW PUBLIC.TEST_ALL(AID, A_NAME, BID, B_NAME) AS SELECT A.ID AID, A.NAME A_NAME, B.ID BID, B.NAME B_NAME FROM TEST_A A, TEST_B B WHERE A.ID = B.ID
> SCRIPT PUBLIC TEST_A_SUB VIEW MEMORY CREATE FORCE VIEW PUBLIC.TEST_A_SUB(ID, NAME) AS SELECT * FROM TEST_A WHERE ID < 2
> TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE STORAGE_TYPE SQL REMARKS ID
> ------------- ------------ ---------- ---------- ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------- ------- ---
> SCRIPT PUBLIC TEST_ALL VIEW MEMORY CREATE FORCE VIEW PUBLIC.TEST_ALL(AID, A_NAME, BID, B_NAME) AS SELECT A.ID AID, A.NAME A_NAME, B.ID BID, B.NAME B_NAME FROM TEST_A A, TEST_B B WHERE A.ID = B.ID 513
> SCRIPT PUBLIC TEST_A_SUB VIEW MEMORY CREATE FORCE VIEW PUBLIC.TEST_A_SUB(ID, NAME) AS SELECT * FROM TEST_A WHERE ID < 2 515
> rows: 2
SELECT * FROM TEST_A_SUB WHERE NAME IS NOT NULL;
......
......@@ -93,7 +93,7 @@ public class TestDataPage extends TestBase implements DataHandler {
return null;
}
public FileStore openFile(String name, boolean mustExist) throws SQLException {
public FileStore openFile(String name, String mode, boolean mustExist) throws SQLException {
return null;
}
......
......@@ -88,7 +88,7 @@ public class TestValueHashMap extends TestBase implements DataHandler {
return null;
}
public FileStore openFile(String name, boolean mustExist) throws SQLException {
public FileStore openFile(String name, String mode, boolean mustExist) throws SQLException {
return null;
}
......
......@@ -88,7 +88,7 @@ public class XMLChecker {
}
private static void checkXML(String xml, boolean html) throws Exception {
String lastElement = null;
// String lastElement = null;
// <li>: replace <li>([^\r]*[^<]*) with <li>$1</li>
// use this for html file, for example if <li> is not closed
String[] noClose = new String[]{};
......@@ -107,9 +107,6 @@ public class XMLChecker {
rootElement = true;
}
String name = parser.getName();
if(html && name.equals("table") && lastElement.trim().length() > 0) {
throw new Exception("Test before table: " + lastElement);
}
for(int i=0; html && i<noClose.length; i++) {
if(name.equals(noClose[i])) {
name = null;
......@@ -134,7 +131,7 @@ public class XMLChecker {
throw new Exception("Unclosed element " + pop + " at " + parser.getRemaining());
}
} else if(event == XMLParser.CHARACTERS) {
lastElement = parser.getText();
// lastElement = parser.getText();
} else if(event == XMLParser.DTD) {
} else if(event == XMLParser.COMMENT) {
} else {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论