提交 476b0169 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 2ceb8a1f
...@@ -1365,14 +1365,14 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1365,14 +1365,14 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Change Constants.DEFAULT_MAX_MEMORY_UNDO to 10000 (and change the docs). Test. <li>Change Constants.DEFAULT_MAX_MEMORY_UNDO to 10000 (and change the docs). Test.
<li>Enable and document optimizations, LOB files in directories <li>Enable and document optimizations, LOB files in directories
<li>Special methods for DataPage.writeByte / writeShort and so on <li>Special methods for DataPage.writeByte / writeShort and so on
<li>Index organized tables CREATE TABLE...(...) ORGANIZATION INDEX (store in data file) (probably file format changes are required for rowId)
</ul> </ul>
<h3>Priority 1</h3> <h3>Priority 1</h3>
<ul> <ul>
<li>More tests with MULTI_THREADED=1 <li>Test read committed transaction isolation (Hibernate)
<li>Test read committed transaction isolation
<li>Hot backup (incremental backup, online backup) <li>Hot backup (incremental backup, online backup)
<li>Documentation (FAQ) for how to connect to H2 <li>More tests with MULTI_THREADED=1
<li>Improve performance for create table (if this is possible) <li>Improve performance for create table (if this is possible)
<li>Test with Spatial DB in a box / JTS (http://docs.codehaus.org/display/GEOS/SpatialDBBox) <li>Test with Spatial DB in a box / JTS (http://docs.codehaus.org/display/GEOS/SpatialDBBox)
<li>Document how to use H2 with PHP (generic database API) <li>Document how to use H2 with PHP (generic database API)
...@@ -1381,11 +1381,10 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1381,11 +1381,10 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Server side cursors <li>Server side cursors
<li>Row level locking <li>Row level locking
<li>System table: open sessions and locks of a database <li>System table: open sessions and locks of a database
<li>System table: open connections and databases of a (TCP) server
<li>System table / function: cache usage <li>System table / function: cache usage
<li>Function in management db: open connections and databases of a (TCP) server
<li>Fix right outer joins <li>Fix right outer joins
<li>Full outer joins <li>Full outer joins
<li>Index organized tables: CREATE TABLE...(...) ORGANIZATION INDEX
<li>Long running queries / errors / trace system table <li>Long running queries / errors / trace system table
<li>Migrate database tool (also from other database engines) <li>Migrate database tool (also from other database engines)
<li>Shutdown compact <li>Shutdown compact
...@@ -1399,7 +1398,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1399,7 +1398,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>SET variable { TO | = } { value | 'value' | DEFAULT } <li>SET variable { TO | = } { value | 'value' | DEFAULT }
<li>Running totals: select @running:=if(@previous=t.ID,@running,0)+t.NUM as TOTAL, @previous:=t.ID <li>Running totals: select @running:=if(@previous=t.ID,@running,0)+t.NUM as TOTAL, @previous:=t.ID
<li>Support SET REFERENTIAL_INTEGRITY {TRUE|FALSE} <li>Support SET REFERENTIAL_INTEGRITY {TRUE|FALSE}
<li>Backup of BLOB / CLOB: use a stream for backup, use a block append function to restore. <li>Support CHAR data type (internally use VARCHAR, but report CHAR for JPox)
<li>Recovery for BLOB / CLOB: support functions
</ul> </ul>
<h3>Priority 2</h3> <h3>Priority 2</h3>
...@@ -1412,7 +1412,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1412,7 +1412,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Compression performance: don't allocate buffers, compress / expand in to out buffer <li>Compression performance: don't allocate buffers, compress / expand in to out buffer
<li>Start / stop server with database URL <li>Start / stop server with database URL
<li># is the start of a single line comment (MySQL) but date quote (Access). Mode specific <li># is the start of a single line comment (MySQL) but date quote (Access). Mode specific
<li>Run benchmarks with JDK 1.5, Server <li>Run benchmarks with JDK 1.5, JDK 1.6, Server
<li>Rebuild index functionality (other than delete the index file) <li>Rebuild index functionality (other than delete the index file)
<li>Don't use deleteOnExit (bug 4513817: File.deleteOnExit consumes memory) <li>Don't use deleteOnExit (bug 4513817: File.deleteOnExit consumes memory)
<li>Console: add accesskey to most important commands (A, AREA, BUTTON, INPUT, LABEL, LEGEND, TEXTAREA) <li>Console: add accesskey to most important commands (A, AREA, BUTTON, INPUT, LABEL, LEGEND, TEXTAREA)
...@@ -1512,6 +1512,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1512,6 +1512,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Clustering: recovery needs to becomes fully automatic. <li>Clustering: recovery needs to becomes fully automatic.
<li>Date: default date is '1970-01-01' (is it 1900-01-01 in the standard / other databases?) <li>Date: default date is '1970-01-01' (is it 1900-01-01 in the standard / other databases?)
<li>Test and document UPDATE TEST SET (ID, NAME) = (SELECT ID*10, NAME || '!' FROM TEST T WHERE T.ID=TEST.ID); <li>Test and document UPDATE TEST SET (ID, NAME) = (SELECT ID*10, NAME || '!' FROM TEST T WHERE T.ID=TEST.ID);
<li>Support home directory as ~ in database URL (jdbc:h2:file:~/.mydir/myDB)
<li>Document EXISTS and so on, provide more samples. <li>Document EXISTS and so on, provide more samples.
<li>Modular build (multiple independent jars). <li>Modular build (multiple independent jars).
<li>Better space re-use in the files after deleting data (shrink the files) <li>Better space re-use in the files after deleting data (shrink the files)
...@@ -1554,19 +1555,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1554,19 +1555,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Console: Allow setting Null value; Alternative display format two column (for copy and paste as well) <li>Console: Allow setting Null value; Alternative display format two column (for copy and paste as well)
<li>Console: Improve editing data (Tab, Shift-Tab, Enter, Up, Down, Shift+Del?) <li>Console: Improve editing data (Tab, Shift-Tab, Enter, Up, Down, Shift+Del?)
<li>Console: Autocomplete Ctrl+Space inserts template <li>Console: Autocomplete Ctrl+Space inserts template
<li>Console: SQL statement formatter (newline before FROM, join, WHERE, AND, GROUP, ORDER, SELECT)
<li>Google Code http://code.google.com/p/h2database/issues/list# <li>Google Code http://code.google.com/p/h2database/issues/list#
<li>Simplify translation ('Donate a translation') <li>Simplify translation ('Donate a translation')
<li>Option to encrypt .trace.db file <li>Option to encrypt .trace.db file
<li>Write Behind Cache on SATA leads to data corruption <li>Write Behind Cache on SATA leads to data corruption
See also http://sr5tech.com/write_back_cache_experiments.htm See also http://sr5tech.com/write_back_cache_experiments.htm
and http://www.jasonbrome.com/blog/archives/2004/04/03/writecache_enabled.html and http://www.jasonbrome.com/blog/archives/2004/04/03/writecache_enabled.html
<li>Support home directory as ~ in database URL (jdbc:h2:file:~/.mydir/myDB)
<li>Functions with unknown return or parameter data types: serialize / deserialize <li>Functions with unknown return or parameter data types: serialize / deserialize
<li>Test if idle TCP connections are closed, and how to disable that <li>Test if idle TCP connections are closed, and how to disable that
<li>Compare with Daffodil One$DB
<li>Try using a factory for Row, Value[] (faster?), http://javolution.org/, alternative ObjectArray / IntArray <li>Try using a factory for Row, Value[] (faster?), http://javolution.org/, alternative ObjectArray / IntArray
<li>Auto-Update feature <li>Auto-Update feature for database, .jar file
<li>ResultSet SimpleResultSet.readFromURL(String url): id varchar, state varchar, released timestamp <li>ResultSet SimpleResultSet.readFromURL(String url): id varchar, state varchar, released timestamp
<li>RANK() and DENSE_RANK(), Partition using OVER() <li>RANK() and DENSE_RANK(), Partition using OVER()
<li>ROW_NUMBER (not the same as ROWNUM) <li>ROW_NUMBER (not the same as ROWNUM)
...@@ -1583,7 +1581,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1583,7 +1581,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Console: -ifExists doesn't work for the console. Add a flag to disable other dbs <li>Console: -ifExists doesn't work for the console. Add a flag to disable other dbs
<li>Maybe use Fowler Noll Vo hash function <li>Maybe use Fowler Noll Vo hash function
<li>Improved full text search (supports LOBs, readers / tokenizers / filters). <li>Improved full text search (supports LOBs, readers / tokenizers / filters).
<li>Update in-place <li>Performance: Update in-place
<li>Check if 'FSUTIL behavior set disablelastaccess 1' improves the performance (fsutil behavior query disablelastaccess) <li>Check if 'FSUTIL behavior set disablelastaccess 1' improves the performance (fsutil behavior query disablelastaccess)
<li>Remove finally() (almost) everywhere <li>Remove finally() (almost) everywhere
<li>Java static code analysis: http://pmd.sourceforge.net/ <li>Java static code analysis: http://pmd.sourceforge.net/
...@@ -1613,7 +1611,6 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1613,7 +1611,6 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Support ARRAY data type <li>Support ARRAY data type
<li>Implement more JDBC 4.0 features <li>Implement more JDBC 4.0 features
<li>H2 Console: implement a servlet to allow simple web app integration <li>H2 Console: implement a servlet to allow simple web app integration
<li>Support CHAR data type (internally use VARCHAR, but report CHAR for JPox)
<li>Option to globally disable / enable referential integrity checks <li>Option to globally disable / enable referential integrity checks
<li>Support ISO 8601 timestamp / date / time with timezone <li>Support ISO 8601 timestamp / date / time with timezone
<li>Support TRANSFORM / PIVOT as in MS Access <li>Support TRANSFORM / PIVOT as in MS Access
......
...@@ -284,9 +284,8 @@ public class Bnf { ...@@ -284,9 +284,8 @@ public class Bnf {
public void linkStatements() { public void linkStatements() {
HashMap ruleMap = getRuleMap(); HashMap ruleMap = getRuleMap();
for(Iterator it = ruleMap.keySet().iterator(); it.hasNext(); ) { for(Iterator it = ruleMap.values().iterator(); it.hasNext(); ) {
String key = (String)it.next(); RuleHead r = (RuleHead) it.next();
RuleHead r = (RuleHead) ruleMap.get(key);
r.getRule().setLinks(ruleMap); r.getRule().setLinks(ruleMap);
} }
} }
......
...@@ -35,7 +35,7 @@ public class CommandContainer extends Command { ...@@ -35,7 +35,7 @@ public class CommandContainer extends Command {
} }
private void recompileIfRequired() throws SQLException { private void recompileIfRequired() throws SQLException {
if(prepared == null || prepared.needRecompile()) { if(prepared.needRecompile()) {
// TODO test with 'always recompile' // TODO test with 'always recompile'
prepared.setModificationId(0); prepared.setModificationId(0);
String sql = prepared.getSQL(); String sql = prepared.getSQL();
......
...@@ -3134,7 +3134,6 @@ public class Parser { ...@@ -3134,7 +3134,6 @@ public class Parser {
boolean ifNotExists = readIfNoExists(); boolean ifNotExists = readIfNoExists();
String viewName = readIdentifierWithSchema(); String viewName = readIdentifierWithSchema();
CreateView command = new CreateView(session, getSchema()); CreateView command = new CreateView(session, getSchema());
command.setForce(force);
command.setViewName(viewName); command.setViewName(viewName);
command.setIfNotExists(ifNotExists); command.setIfNotExists(ifNotExists);
String select = StringCache.getNew(sqlCommand.substring(parseIndex)); String select = StringCache.getNew(sqlCommand.substring(parseIndex));
......
...@@ -280,7 +280,6 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -280,7 +280,6 @@ public class AlterTableAddConstraint extends SchemaCommand {
public void setColumnNames(String[] columnNames) { public void setColumnNames(String[] columnNames) {
this.columnNames = columnNames; this.columnNames = columnNames;
} }
public void setRefTableName(Schema refSchema, String ref) { public void setRefTableName(Schema refSchema, String ref) {
......
...@@ -18,7 +18,6 @@ public class CreateView extends SchemaCommand { ...@@ -18,7 +18,6 @@ public class CreateView extends SchemaCommand {
private Query select; private Query select;
private String viewName; private String viewName;
private boolean ifNotExists; private boolean ifNotExists;
private boolean force;
private String selectSQL; private String selectSQL;
private String[] columnNames; private String[] columnNames;
private String comment; private String comment;
...@@ -48,7 +47,7 @@ public class CreateView extends SchemaCommand { ...@@ -48,7 +47,7 @@ public class CreateView extends SchemaCommand {
} }
int id = getObjectId(true, true); int id = getObjectId(true, true);
String querySQL; String querySQL;
if(select == null && force) { if(select == null) {
querySQL = selectSQL; querySQL = selectSQL;
} else { } else {
querySQL = select.getSQL(); querySQL = select.getSQL();
...@@ -63,10 +62,6 @@ public class CreateView extends SchemaCommand { ...@@ -63,10 +62,6 @@ public class CreateView extends SchemaCommand {
this.ifNotExists = ifNotExists; this.ifNotExists = ifNotExists;
} }
public void setForce(boolean force) {
this.force = force;
}
public void setSelectSQL(String selectSQL) { public void setSelectSQL(String selectSQL) {
this.selectSQL = selectSQL; this.selectSQL = selectSQL;
} }
......
...@@ -6,7 +6,6 @@ package org.h2.command.dml; ...@@ -6,7 +6,6 @@ package org.h2.command.dml;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.BitSet; import java.util.BitSet;
import java.util.Enumeration;
import java.util.Random; import java.util.Random;
import org.h2.engine.Session; import org.h2.engine.Session;
...@@ -92,14 +91,9 @@ public class Optimizer { ...@@ -92,14 +91,9 @@ public class Optimizer {
} }
private void calculateBruteForceAll() throws SQLException { private void calculateBruteForceAll() throws SQLException {
Enumeration en = new Permutations(filters); TableFilter[] ftry = new TableFilter[filters.length];
for(int x=0; en.hasMoreElements(); x++) { Permutations perm = new Permutations(filters, ftry);
if(canStop(x)) { for(int x=0; !canStop(x) && perm.next(); x++) {
break;
}
Object[] f = (Object[]) en.nextElement();
TableFilter[] ftry = new TableFilter[filters.length];
System.arraycopy(f, 0, ftry, 0, filters.length);
testPlan(ftry); testPlan(ftry);
} }
} }
...@@ -107,18 +101,13 @@ public class Optimizer { ...@@ -107,18 +101,13 @@ public class Optimizer {
private void calculateBruteForceSome() throws SQLException { private void calculateBruteForceSome() throws SQLException {
int bruteForce = getMaxBruteForceFilters(filters.length); int bruteForce = getMaxBruteForceFilters(filters.length);
TableFilter[] ftry = new TableFilter[filters.length]; TableFilter[] ftry = new TableFilter[filters.length];
Enumeration en = new Permutations(filters, bruteForce); Permutations perm = new Permutations(filters, ftry, bruteForce);
for(int x=0; en.hasMoreElements(); x++) { for(int x=0; !canStop(x) && perm.next(); x++) {
if(canStop(x)) {
break;
}
Object[] f = (Object[]) en.nextElement();
System.arraycopy(f, 0, ftry, 0, bruteForce);
// find out what filters are not used yet // find out what filters are not used yet
for(int i=0; i<filters.length; i++) { for(int i=0; i<filters.length; i++) {
filters[i].setUsed(false); filters[i].setUsed(false);
} }
for(int i=0; i<f.length; i++) { for(int i=0; i<bruteForce; i++) {
ftry[i].setUsed(true); ftry[i].setUsed(true);
} }
// fill the remaining elements with the unused elements (greedy) // fill the remaining elements with the unused elements (greedy)
......
...@@ -5,11 +5,14 @@ ...@@ -5,11 +5,14 @@
package org.h2.command.dml; package org.h2.command.dml;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.store.DiskFile;
/** /**
...@@ -29,6 +32,7 @@ public class TransactionCommand extends Prepared { ...@@ -29,6 +32,7 @@ public class TransactionCommand extends Prepared {
public static final int ROLLBACK_TRANSACTION = 11; public static final int ROLLBACK_TRANSACTION = 11;
public static final int SHUTDOWN = 12; public static final int SHUTDOWN = 12;
public static final int SHUTDOWN_IMMEDIATELY = 13; public static final int SHUTDOWN_IMMEDIATELY = 13;
public static final int BACKUP = 14;
private int type; private int type;
private String savepointName; private String savepointName;
...@@ -111,12 +115,28 @@ public class TransactionCommand extends Prepared { ...@@ -111,12 +115,28 @@ public class TransactionCommand extends Prepared {
session.close(); session.close();
break; break;
} }
case BACKUP: {
session.getUser().checkAdmin();
session.commit();
backupTo("backup.zip");
break;
}
default: default:
throw Message.getInternalError("type=" + type); throw Message.getInternalError("type=" + type);
} }
return 0; return 0;
} }
private void backupTo(String fileName) {
// ZipOutputStream out = new ZipOutputStream("test.zip");
// out.putNextEntry(arg0)
// DiskFile file = session.getDatabase().getDataFile();
//// session.getDatabase().getLog().incStopDeleteFiles(true);
// // TODO Auto-generated method stub
//// session.getDatabase().getLog().setStopDeleteFiles(false);
//
}
public boolean isTransactional() { public boolean isTransactional() {
return true; return true;
} }
......
...@@ -809,9 +809,7 @@ public class Database implements DataHandler { ...@@ -809,9 +809,7 @@ public class Database implements DataHandler {
traceSystem.getTrace(Trace.DATABASE).error("close", e); traceSystem.getTrace(Trace.DATABASE).error("close", e);
} }
traceSystem.getTrace(Trace.DATABASE).info("closed"); traceSystem.getTrace(Trace.DATABASE).info("closed");
if(traceSystem != null) { traceSystem.close();
traceSystem.close();
}
Engine.getInstance().close(databaseName); Engine.getInstance().close(databaseName);
if(deleteFilesOnDisconnect && persistent) { if(deleteFilesOnDisconnect && persistent) {
deleteFilesOnDisconnect = false; deleteFilesOnDisconnect = false;
......
...@@ -71,7 +71,7 @@ public abstract class DbObject { ...@@ -71,7 +71,7 @@ public abstract class DbObject {
this.trace = database.getTrace(traceModule); this.trace = database.getTrace(traceModule);
this.id = id; this.id = id;
this.objectName = name; this.objectName = name;
this.modificationId = database == null ? -1 : database.getModificationMetaId(); this.modificationId = database.getModificationMetaId();
} }
public void setModified() { public void setModified() {
......
...@@ -11,7 +11,7 @@ import org.h2.util.StringUtils; ...@@ -11,7 +11,7 @@ import org.h2.util.StringUtils;
public class Mode { public class Mode {
// TODO isolation: this setting should not be global // TODO isolation: this setting should not be global
public static Mode currentMode; private static Mode currentMode;
public static final String REGULAR_NAME = "REGULAR"; public static final String REGULAR_NAME = "REGULAR";
public boolean nullConcatIsNull; public boolean nullConcatIsNull;
......
...@@ -103,7 +103,7 @@ public class Session implements SessionInterface { ...@@ -103,7 +103,7 @@ public class Session implements SessionInterface {
table.removeChildrenAndResources(this); table.removeChildrenAndResources(this);
} }
public void finalize() { protected void finalize() {
if(!Constants.RUN_FINALIZERS) { if(!Constants.RUN_FINALIZERS) {
return; return;
} }
...@@ -450,7 +450,7 @@ public class Session implements SessionInterface { ...@@ -450,7 +450,7 @@ public class Session implements SessionInterface {
public JdbcConnection createConnection(boolean columnList) throws SQLException { public JdbcConnection createConnection(boolean columnList) throws SQLException {
String url; String url;
if(columnList) { if(columnList) {
url = Constants.CONN_URL_INTERNAL; url = Constants.CONN_URL_COLUMNLIST;
} else { } else {
url = Constants.CONN_URL_INTERNAL; url = Constants.CONN_URL_INTERNAL;
} }
......
...@@ -18,7 +18,7 @@ import org.h2.value.ValueNull; ...@@ -18,7 +18,7 @@ import org.h2.value.ValueNull;
public class ValueExpression extends Expression { public class ValueExpression extends Expression {
private Value value; private Value value;
public static ValueExpression NULL = new ValueExpression(ValueNull.INSTANCE); public static final ValueExpression NULL = new ValueExpression(ValueNull.INSTANCE);
public static ValueExpression get(Value v) { public static ValueExpression get(Value v) {
if(v == ValueNull.INSTANCE) { if(v == ValueNull.INSTANCE) {
......
...@@ -582,8 +582,13 @@ public class FullText implements Trigger { ...@@ -582,8 +582,13 @@ public class FullText implements Trigger {
String key = rs.getString(1); String key = rs.getString(1);
long indexId = rs.getLong(2); long indexId = rs.getLong(2);
IndexInfo index = setting.getIndexInfo(indexId); IndexInfo index = setting.getIndexInfo(indexId);
String query = StringUtils.quoteIdentifier(index.schemaName)+"."+StringUtils.quoteIdentifier(index.tableName); StringBuffer buff = new StringBuffer();
query +=" WHERE " + key; buff.append(StringUtils.quoteIdentifier(index.schemaName));
buff.append('.');
buff.append(StringUtils.quoteIdentifier(index.tableName));
buff.append(" WHERE ");
buff.append(key);
String query = buff.toString();
result.addRow(new String[]{query}); result.addRow(new String[]{query});
rowCount++; rowCount++;
if(limit > 0 && rowCount >= limit) { if(limit > 0 && rowCount >= limit) {
......
...@@ -102,8 +102,6 @@ public class BtreeIndex extends Index implements RecordReader { ...@@ -102,8 +102,6 @@ public class BtreeIndex extends Index implements RecordReader {
} }
} }
int count;
void deletePage(Session session, Record p) throws SQLException { void deletePage(Session session, Record p) throws SQLException {
if(database.getLogIndexChanges()) { if(database.getLogIndexChanges()) {
storage.removeRecord(session, p.getPos()); storage.removeRecord(session, p.getPos());
......
...@@ -322,8 +322,8 @@ public class BtreeNode extends BtreePage { ...@@ -322,8 +322,8 @@ public class BtreeNode extends BtreePage {
int size = 2 + dummy.getIntLen() + dummy.getIntLen() * len; int size = 2 + dummy.getIntLen() + dummy.getIntLen() * len;
len = pageData.size(); len = pageData.size();
size += dummy.getIntLen(); size += dummy.getIntLen();
size += pageData.size() * dummy.getIntLen(); size += len * dummy.getIntLen();
for (int i = 0; i < pageData.size(); i++) { for (int i = 0; i < len; i++) {
SearchRow row = getData(i); SearchRow row = getData(i);
size += getRowSize(dummy, row); size += getRowSize(dummy, row);
} }
......
...@@ -277,7 +277,7 @@ public class TreeIndex extends Index { ...@@ -277,7 +277,7 @@ public class TreeIndex extends Index {
} }
x = n; x = n;
} }
return new TreeCursor(this, x, first, last); return new TreeCursor(this, x, null, last);
} else { } else {
TreeNode x = findFirstNode(first, false); TreeNode x = findFirstNode(first, false);
return new TreeCursor(this, x, first, last); return new TreeCursor(this, x, first, last);
......
...@@ -296,9 +296,13 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -296,9 +296,13 @@ public class JdbcConnection extends TraceObject implements Connection {
* @throws SQLException * @throws SQLException
* if the connection is closed * if the connection is closed
*/ */
public boolean getAutoCommit() throws SQLException { public synchronized boolean getAutoCommit() throws SQLException {
debugCodeCall("getAutoCommit");
return getInternalAutoCommit();
}
private boolean getInternalAutoCommit() throws SQLException {
try { try {
debugCodeCall("getAutoCommit");
checkClosed(); checkClosed();
getAutoCommit = prepareCommand("CALL AUTOCOMMIT()", getAutoCommit); getAutoCommit = prepareCommand("CALL AUTOCOMMIT()", getAutoCommit);
ResultInterface result = getAutoCommit.executeQuery(0, false); ResultInterface result = getAutoCommit.executeQuery(0, false);
...@@ -663,11 +667,12 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -663,11 +667,12 @@ public class JdbcConnection extends TraceObject implements Connection {
StringBuffer buff = new StringBuffer("new Map() /* "); StringBuffer buff = new StringBuffer("new Map() /* ");
try { try {
// Map<String, Class> // Map<String, Class>
for(Iterator it = map.keySet().iterator(); it.hasNext(); ) { for(Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
String key = (String)it.next(); Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
buff.append(key); buff.append(key);
buff.append(':'); buff.append(':');
Class clazz = (Class)map.get(key); Class clazz = (Class) entry.getValue();
buff.append(clazz.getName()); buff.append(clazz.getName());
} }
} catch(Exception e) { } catch(Exception e) {
...@@ -971,7 +976,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -971,7 +976,7 @@ public class JdbcConnection extends TraceObject implements Connection {
//#ifdef JDK14 //#ifdef JDK14
// check for existence of this class (avoiding Class . forName) // check for existence of this class (avoiding Class . forName)
Class clazz = java.sql.Savepoint.class; Class clazz = java.sql.Savepoint.class;
clazz = clazz == null ? null : clazz; clazz.getClass();
//#endif //#endif
} catch(Throwable e) { } catch(Throwable e) {
throw Message.getSQLException(Message.UNSUPPORTED_JAVA_VERSION); throw Message.getSQLException(Message.UNSUPPORTED_JAVA_VERSION);
...@@ -1192,7 +1197,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1192,7 +1197,7 @@ public class JdbcConnection extends TraceObject implements Connection {
return user; return user;
} }
public void finalize() { protected void finalize() {
if(!Constants.RUN_FINALIZERS) { if(!Constants.RUN_FINALIZERS) {
return; return;
} }
...@@ -1349,11 +1354,11 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1349,11 +1354,11 @@ public class JdbcConnection extends TraceObject implements Connection {
* *
* @return true if the connection is valid. * @return true if the connection is valid.
*/ */
public boolean isValid(int timeout) { public synchronized boolean isValid(int timeout) {
try { try {
debugCodeCall("isValid", timeout); debugCodeCall("isValid", timeout);
checkClosed(); checkClosed();
getAutoCommit(); getInternalAutoCommit();
return true; return true;
} catch(Throwable e) { } catch(Throwable e) {
// this method doesn't throw an exception, but it logs it // this method doesn't throw an exception, but it logs it
......
...@@ -113,14 +113,15 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -113,14 +113,15 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
checkClosed(); checkClosed();
String tableType; String tableType;
if (types != null && types.length>0) { if (types != null && types.length>0) {
tableType = "TABLE_TYPE IN("; StringBuffer buff = new StringBuffer("TABLE_TYPE IN(");
for (int i = 0; i < types.length; i++) { for (int i = 0; i < types.length; i++) {
if (i>0) { if (i>0) {
tableType += ", "; buff.append(", ");
} }
tableType += "?"; buff.append("?");
} }
tableType += ")"; buff.append(")");
tableType = buff.toString();
} else { } else {
tableType = "TRUE"; tableType = "TRUE";
} }
...@@ -1172,7 +1173,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -1172,7 +1173,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
try { try {
debugCodeCall("getTypeInfo"); debugCodeCall("getTypeInfo");
checkClosed(); checkClosed();
return conn.createStatement().executeQuery("SELECT " PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
+ "TYPE_NAME, " + "TYPE_NAME, "
+ "DATA_TYPE, " + "DATA_TYPE, "
+ "PRECISION, " + "PRECISION, "
...@@ -1193,6 +1194,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -1193,6 +1194,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "RADIX NUM_PREC_RADIX " + "RADIX NUM_PREC_RADIX "
+ "FROM INFORMATION_SCHEMA.TYPE_INFO " + "FROM INFORMATION_SCHEMA.TYPE_INFO "
+ "ORDER BY DATA_TYPE, POS"); + "ORDER BY DATA_TYPE, POS");
ResultSet rs = prep.executeQuery();
return rs;
} catch(Throwable e) { } catch(Throwable e) {
throw logAndConvert(e); throw logAndConvert(e);
} }
......
...@@ -38,9 +38,9 @@ public class JdbcDataSource extends TraceObject implements XADataSource, DataSou ...@@ -38,9 +38,9 @@ public class JdbcDataSource extends TraceObject implements XADataSource, DataSou
private static final long serialVersionUID = 1288136338451857771L; private static final long serialVersionUID = 1288136338451857771L;
private JdbcDataSourceFactory factory; private transient JdbcDataSourceFactory factory;
private transient PrintWriter logWriter;
private int timeout; private int timeout;
private PrintWriter logWriter;
private String user; private String user;
private String password; private String password;
private String url; private String url;
......
...@@ -21,6 +21,7 @@ import javax.transaction.xa.Xid; ...@@ -21,6 +21,7 @@ import javax.transaction.xa.Xid;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.TraceObject; import org.h2.message.TraceObject;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.JdbcUtils;
//#ifdef JDK16 //#ifdef JDK16
/* /*
...@@ -115,8 +116,9 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, JdbcC ...@@ -115,8 +116,9 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, JdbcC
public Xid[] recover(int flag) throws XAException { public Xid[] recover(int flag) throws XAException {
debugCodeCall("recover", quoteFlags(flag)); debugCodeCall("recover", quoteFlags(flag));
checkOpen(); checkOpen();
Statement stat = null;
try { try {
Statement stat = conn.createStatement(); stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.IN_DOUBT ORDER BY ID"); ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.IN_DOUBT ORDER BY ID");
ArrayList list = new ArrayList(); ArrayList list = new ArrayList();
while(rs.next()) { while(rs.next()) {
...@@ -125,12 +127,15 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, JdbcC ...@@ -125,12 +127,15 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, JdbcC
Xid xid = new JdbcXid(factory, id, tid); Xid xid = new JdbcXid(factory, id, tid);
list.add(xid); list.add(xid);
} }
rs.close();
Xid[] result = new Xid[list.size()]; Xid[] result = new Xid[list.size()];
list.toArray(result); list.toArray(result);
return result; return result;
} catch(SQLException e) { } catch(SQLException e) {
getTrace().debug("throw XAException.XAER_OUTSIDE", e); getTrace().debug("throw XAException.XAER_OUTSIDE", e);
throw new XAException(XAException.XAER_OUTSIDE); throw new XAException(XAException.XAER_OUTSIDE);
} finally {
JdbcUtils.closeSilently(stat);
} }
} }
...@@ -148,10 +153,14 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, JdbcC ...@@ -148,10 +153,14 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, JdbcC
getTrace().debug("throw XAException.XAER_INVAL"); getTrace().debug("throw XAException.XAER_INVAL");
throw new XAException(XAException.XAER_INVAL); throw new XAException(XAException.XAER_INVAL);
} }
Statement stat = null;
try { try {
conn.createStatement().execute("PREPARE COMMIT"); stat = conn.createStatement();
stat.execute("PREPARE COMMIT");
} catch(SQLException e) { } catch(SQLException e) {
throw convertException(e); throw convertException(e);
} finally {
JdbcUtils.closeSilently(stat);
} }
getTrace().debug("return TMSUCCESS"); getTrace().debug("return TMSUCCESS");
return TMSUCCESS; return TMSUCCESS;
......
...@@ -32,7 +32,7 @@ public class JdbcXid extends TraceObject implements Xid { ...@@ -32,7 +32,7 @@ public class JdbcXid extends TraceObject implements Xid {
formatId = Integer.parseInt(tokenizer.nextToken()); formatId = Integer.parseInt(tokenizer.nextToken());
branchQualifier = ByteUtils.convertStringToBytes(tokenizer.nextToken()); branchQualifier = ByteUtils.convertStringToBytes(tokenizer.nextToken());
globalTransactionId = ByteUtils.convertStringToBytes(tokenizer.nextToken()); globalTransactionId = ByteUtils.convertStringToBytes(tokenizer.nextToken());
} catch(Exception e) { } catch(Throwable e) {
throw Message.getSQLException(Message.WRONG_XID_FORMAT_1, tid); throw Message.getSQLException(Message.WRONG_XID_FORMAT_1, tid);
} }
} }
......
...@@ -217,7 +217,7 @@ public class TraceSystem { ...@@ -217,7 +217,7 @@ public class TraceSystem {
closed = true; closed = true;
} }
public void finalize() { protected void finalize() {
if(!Constants.RUN_FINALIZERS) { if(!Constants.RUN_FINALIZERS) {
return; return;
} }
......
...@@ -156,7 +156,7 @@ class ResultDiskBuffer { ...@@ -156,7 +156,7 @@ class ResultDiskBuffer {
return sort.compare(va, vb); return sort.compare(va, vb);
} }
public void finalize() { protected void finalize() {
if(!Constants.RUN_FINALIZERS) { if(!Constants.RUN_FINALIZERS) {
return; return;
} }
......
...@@ -25,7 +25,7 @@ public class Sequence extends SchemaObject { ...@@ -25,7 +25,7 @@ public class Sequence extends SchemaObject {
this.belongsToTable = belongsToTable; this.belongsToTable = belongsToTable;
} }
public void setStartValue(long value) { public synchronized void setStartValue(long value) {
this.value = value; this.value = value;
this.valueWithMargin = value; this.valueWithMargin = value;
} }
......
...@@ -25,6 +25,7 @@ import java.util.HashMap; ...@@ -25,6 +25,7 @@ import java.util.HashMap;
import org.h2.engine.ConnectionInfo; import org.h2.engine.ConnectionInfo;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -206,8 +207,9 @@ public class OdbcServerThread implements Runnable { ...@@ -206,8 +207,9 @@ public class OdbcServerThread implements Runnable {
if(columnNamePattern ==null || columnNamePattern.length()==0) { if(columnNamePattern ==null || columnNamePattern.length()==0) {
columnNamePattern = "%"; columnNamePattern = "%";
} }
PreparedStatement prep = null;
try { try {
PreparedStatement prep = conn.prepareStatement("SELECT " prep = conn.prepareStatement("SELECT "
+ "TABLE_CATALOG TABLE_CAT, " + "TABLE_CATALOG TABLE_CAT, "
+ "TABLE_SCHEMA TABLE_SCHEM, " + "TABLE_SCHEMA TABLE_SCHEM, "
+ "TABLE_NAME, " + "TABLE_NAME, "
...@@ -239,6 +241,8 @@ public class OdbcServerThread implements Runnable { ...@@ -239,6 +241,8 @@ public class OdbcServerThread implements Runnable {
processResultSet(rs); processResultSet(rs);
} catch(SQLException e) { } catch(SQLException e) {
sendError(e); sendError(e);
} finally {
JdbcUtils.closeSilently(prep);
} }
break; break;
} }
...@@ -250,8 +254,10 @@ public class OdbcServerThread implements Runnable { ...@@ -250,8 +254,10 @@ public class OdbcServerThread implements Runnable {
int type = transfer.readInt(); int type = transfer.readInt();
where = " WHERE TYPE="+type+" "; where = " WHERE TYPE="+type+" ";
} }
Statement stat = null;
try { try {
ResultSet rs = conn.createStatement().executeQuery("SELECT " stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT "
+ "TYPE_NAME, " + "TYPE_NAME, "
+ "DATA_TYPE, " + "DATA_TYPE, "
+ "PRECISION COLUMN_SIZE, " + "PRECISION COLUMN_SIZE, "
...@@ -277,6 +283,8 @@ public class OdbcServerThread implements Runnable { ...@@ -277,6 +283,8 @@ public class OdbcServerThread implements Runnable {
processResultSet(rs); processResultSet(rs);
} catch(SQLException e) { } catch(SQLException e) {
sendError(e); sendError(e);
} finally {
JdbcUtils.closeSilently(stat);
} }
break; break;
} }
...@@ -289,10 +297,11 @@ public class OdbcServerThread implements Runnable { ...@@ -289,10 +297,11 @@ public class OdbcServerThread implements Runnable {
} }
// boolean unique = transfer.readBoolean(); // boolean unique = transfer.readBoolean();
// boolean approximate = transfer.readBoolean(); // boolean approximate = transfer.readBoolean();
PreparedStatement prep = null;
try { try {
//ResultSet rs = meta.getIndexInfo(catalog, schemaPattern, tableNamePattern, unique, approximate); //ResultSet rs = meta.getIndexInfo(catalog, schemaPattern, tableNamePattern, unique, approximate);
PreparedStatement prep = conn.prepareStatement("SELECT " prep = conn.prepareStatement("SELECT "
+ "TABLE_CATALOG TABLE_CAT, " + "TABLE_CATALOG TABLE_CAT, "
+ "TABLE_SCHEMA TABLE_SCHEM, " + "TABLE_SCHEMA TABLE_SCHEM, "
+ "TABLE_NAME, " + "TABLE_NAME, "
...@@ -316,6 +325,8 @@ public class OdbcServerThread implements Runnable { ...@@ -316,6 +325,8 @@ public class OdbcServerThread implements Runnable {
processResultSet(rs); processResultSet(rs);
} catch(SQLException e) { } catch(SQLException e) {
sendError(e); sendError(e);
} finally {
JdbcUtils.closeSilently(prep);
} }
break; break;
} }
...@@ -337,10 +348,11 @@ public class OdbcServerThread implements Runnable { ...@@ -337,10 +348,11 @@ public class OdbcServerThread implements Runnable {
server.log(" catalog="+catalog+" schema="+schema+" table="+table+" tableTypes="+tableTypes); server.log(" catalog="+catalog+" schema="+schema+" table="+table+" tableTypes="+tableTypes);
ResultSet rs; ResultSet rs;
String[] types = null; String[] types = null;
PreparedStatement prep = null;
try { try {
if(catalog.equals("%") && schema.length()==0 && table.length()==0) { if(catalog.equals("%") && schema.length()==0 && table.length()==0) {
server.log(" allCatalogs"); server.log(" allCatalogs");
PreparedStatement prep = conn.prepareStatement("SELECT " prep = conn.prepareStatement("SELECT "
+ "CATALOG_NAME TABLE_CAT, " + "CATALOG_NAME TABLE_CAT, "
+ "NULL TABLE_SCHEM, " + "NULL TABLE_SCHEM, "
+ "NULL TABLE_NAME, " + "NULL TABLE_NAME, "
...@@ -350,7 +362,7 @@ public class OdbcServerThread implements Runnable { ...@@ -350,7 +362,7 @@ public class OdbcServerThread implements Runnable {
rs = prep.executeQuery(); rs = prep.executeQuery();
} else if(catalog.length()==0 && schema.equals("%") && table.length()==0) { } else if(catalog.length()==0 && schema.equals("%") && table.length()==0) {
server.log(" allSchemas"); server.log(" allSchemas");
PreparedStatement prep = conn.prepareStatement("SELECT " prep = conn.prepareStatement("SELECT "
+ "CATALOG_NAME TABLE_CAT, " + "CATALOG_NAME TABLE_CAT, "
+ "SCHEMA_NAME TABLE_SCHEM, " + "SCHEMA_NAME TABLE_SCHEM, "
+ "NULL TABLE_NAME, " + "NULL TABLE_NAME, "
...@@ -360,7 +372,7 @@ public class OdbcServerThread implements Runnable { ...@@ -360,7 +372,7 @@ public class OdbcServerThread implements Runnable {
rs = prep.executeQuery(); rs = prep.executeQuery();
} else if(catalog.length()==0 && schema.length()==0 && table.length()==0 && tableTypes.equals("%")) { } else if(catalog.length()==0 && schema.length()==0 && table.length()==0 && tableTypes.equals("%")) {
server.log(" allTableTypes"); server.log(" allTableTypes");
PreparedStatement prep = conn.prepareStatement("SELECT " prep = conn.prepareStatement("SELECT "
+ "NULL TABLE_CAT, " + "NULL TABLE_CAT, "
+ "NULL TABLE_SCHEM, " + "NULL TABLE_SCHEM, "
+ "NULL TABLE_NAME, " + "NULL TABLE_NAME, "
...@@ -391,6 +403,8 @@ public class OdbcServerThread implements Runnable { ...@@ -391,6 +403,8 @@ public class OdbcServerThread implements Runnable {
processResultSet(rs); processResultSet(rs);
} catch(SQLException e) { } catch(SQLException e) {
sendError(e); sendError(e);
} finally {
JdbcUtils.closeSilently(prep);
} }
break; break;
} }
...@@ -501,15 +515,20 @@ public class OdbcServerThread implements Runnable { ...@@ -501,15 +515,20 @@ public class OdbcServerThread implements Runnable {
transfer.writeInt(id); transfer.writeInt(id);
transfer.writeInt(params); transfer.writeInt(params);
} else { } else {
Statement stat = conn.createStatement(); Statement stat = null;
boolean isResultSet = stat.execute(sql); try {
if(isResultSet) { stat = conn.createStatement();
transfer.writeByte((byte)'R'); boolean isResultSet = stat.execute(sql);
ResultSet rs = stat.getResultSet(); if(isResultSet) {
processResultSet(rs); transfer.writeByte((byte)'R');
} else { ResultSet rs = stat.getResultSet();
transfer.writeByte((byte)'U'); processResultSet(rs);
transfer.writeInt(stat.getUpdateCount()); } else {
transfer.writeByte((byte)'U');
transfer.writeInt(stat.getUpdateCount());
}
} finally {
JdbcUtils.closeSilently(stat);
} }
} }
} catch(SQLException e) { } catch(SQLException e) {
......
...@@ -17,6 +17,7 @@ import java.util.HashSet; ...@@ -17,6 +17,7 @@ import java.util.HashSet;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
...@@ -52,43 +53,29 @@ public class TcpServer implements Service { ...@@ -52,43 +53,29 @@ public class TcpServer implements Service {
private void initManagementDb() throws SQLException { private void initManagementDb() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:h2:" + getManagementDbName(port), "sa", managementPassword); Connection conn = DriverManager.getConnection("jdbc:h2:" + getManagementDbName(port), "sa", managementPassword);
managementDb = conn; managementDb = conn;
Statement stat = conn.createStatement(); Statement stat = null;
stat.execute("CREATE ALIAS IF NOT EXISTS STOP_SERVER FOR \"" + TcpServer.class.getName() +".stopServer\""); try {
stat = conn.createStatement();
stat.execute("CREATE ALIAS IF NOT EXISTS STOP_SERVER FOR \"" + TcpServer.class.getName() +".stopServer\"");
} finally {
JdbcUtils.closeSilently(stat);
}
servers.put(""+port, this); servers.put(""+port, this);
} }
private void stopManagementDb() { private void stopManagementDb() {
if(managementDb != null) { synchronized(TcpServer.class) {
try { if(managementDb != null) {
managementDb.close(); try {
} catch (SQLException e) { managementDb.close();
TraceSystem.traceThrowable(e); } catch (SQLException e) {
TraceSystem.traceThrowable(e);
}
managementDb = null;
} }
managementDb = null;
} }
} }
public static synchronized void stopServer(int port, String password, int shutdownMode) {
TcpServer server = (TcpServer) servers.get("" + port);
if(server == null) {
return;
}
if(!server.managementPassword.equals(password)) {
return;
}
if(shutdownMode == TcpServer.SHUTDOWN_NORMAL) {
server.stop = true;
try {
Socket s = new Socket("localhost", port);
s.close();
} catch (Exception e) {
// try to connect - so that accept returns
}
} else if(shutdownMode == TcpServer.SHUTDOWN_FORCE) {
server.stop();
}
}
public void init(String[] args) throws Exception { public void init(String[] args) throws Exception {
port = DEFAULT_PORT; port = DEFAULT_PORT;
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
...@@ -126,8 +113,8 @@ public class TcpServer implements Service { ...@@ -126,8 +113,8 @@ public class TcpServer implements Service {
public void start() throws SQLException { public void start() throws SQLException {
synchronized(TcpServer.class) { synchronized(TcpServer.class) {
initManagementDb();
serverSocket = NetUtils.createServerSocket(port, ssl); serverSocket = NetUtils.createServerSocket(port, ssl);
initManagementDb();
} }
} }
...@@ -148,9 +135,7 @@ public class TcpServer implements Service { ...@@ -148,9 +135,7 @@ public class TcpServer implements Service {
TraceSystem.traceThrowable(e); TraceSystem.traceThrowable(e);
} }
} }
synchronized(TcpServer.class) { stopManagementDb();
stopManagementDb();
}
} }
public boolean isRunning() { public boolean isRunning() {
...@@ -169,6 +154,7 @@ public class TcpServer implements Service { ...@@ -169,6 +154,7 @@ public class TcpServer implements Service {
public synchronized void stop() { public synchronized void stop() {
// TODO server: share code between web and tcp servers // TODO server: share code between web and tcp servers
if(!stop) { if(!stop) {
stopManagementDb();
stop = true; stop = true;
if(serverSocket != null) { if(serverSocket != null) {
try { try {
...@@ -193,6 +179,28 @@ public class TcpServer implements Service { ...@@ -193,6 +179,28 @@ public class TcpServer implements Service {
servers.remove(""+port); servers.remove(""+port);
} }
public static synchronized void stopServer(int port, String password, int shutdownMode) {
TcpServer server = (TcpServer) servers.get("" + port);
if(server == null) {
return;
}
if(!server.managementPassword.equals(password)) {
return;
}
if(shutdownMode == TcpServer.SHUTDOWN_NORMAL) {
server.stopManagementDb();
server.stop = true;
try {
Socket s = new Socket("localhost", port);
s.close();
} catch (Exception e) {
// try to connect - so that accept returns
}
} else if(shutdownMode == TcpServer.SHUTDOWN_FORCE) {
server.stop();
}
}
synchronized void remove(TcpServerThread t) { synchronized void remove(TcpServerThread t) {
running.remove(t); running.remove(t);
} }
...@@ -212,7 +220,7 @@ public class TcpServer implements Service { ...@@ -212,7 +220,7 @@ public class TcpServer implements Service {
} }
} }
void logError(Exception e) { void logError(Throwable e) {
if (log) { if (log) {
e.printStackTrace(); e.printStackTrace();
} }
......
...@@ -89,7 +89,7 @@ public class TcpServerThread implements Runnable { ...@@ -89,7 +89,7 @@ public class TcpServerThread implements Runnable {
} }
} }
server.log("Disconnect"); server.log("Disconnect");
} catch(Exception e) { } catch(Throwable e) {
server.logError(e); server.logError(e);
} finally { } finally {
close(); close();
......
...@@ -141,8 +141,8 @@ public class FtpServer implements Service { ...@@ -141,8 +141,8 @@ public class FtpServer implements Service {
return buff.toString(); return buff.toString();
} }
public boolean checkUserPassword(String userName, String param) { public boolean checkUserPassword(String userName, String password) {
return userName.equals(this.writeUserName) && writePassword.equals(this.writePassword); return userName.equals(this.writeUserName) && password.equals(this.writePassword);
} }
public boolean checkUserPasswordReadOnly(String userName, String param) { public boolean checkUserPasswordReadOnly(String userName, String param) {
......
...@@ -7,11 +7,8 @@ package org.h2.server.web; ...@@ -7,11 +7,8 @@ package org.h2.server.web;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection; import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
...@@ -21,7 +18,6 @@ import org.h2.engine.Constants; ...@@ -21,7 +18,6 @@ import org.h2.engine.Constants;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.StringUtils;
public class AppServer { public class AppServer {
...@@ -40,7 +36,7 @@ public class AppServer { ...@@ -40,7 +36,7 @@ public class AppServer {
"Generic H2|org.h2.Driver|jdbc:h2:test|sa", "Generic H2|org.h2.Driver|jdbc:h2:test|sa",
}; };
private URLClassLoader urlClassLoader; // private URLClassLoader urlClassLoader;
private String driverList; private String driverList;
private static int ticker; private static int ticker;
private int port; private int port;
...@@ -64,20 +60,20 @@ public class AppServer { ...@@ -64,20 +60,20 @@ public class AppServer {
} }
} }
// TODO gcj: don't load drivers in case of GCJ // TODO gcj: don't load drivers in case of GCJ
if(false) { // if(false) {
if(driverList != null) { // if(driverList != null) {
try { // try {
String[] drivers = StringUtils.arraySplit(driverList, ',', false); // String[] drivers = StringUtils.arraySplit(driverList, ',', false);
URL[] urls = new URL[drivers.length]; // URL[] urls = new URL[drivers.length];
for(int i=0; i<drivers.length; i++) { // for(int i=0; i<drivers.length; i++) {
urls[i] = new URL(drivers[i]); // urls[i] = new URL(drivers[i]);
} // }
urlClassLoader = URLClassLoader.newInstance(urls); // urlClassLoader = URLClassLoader.newInstance(urls);
} catch (MalformedURLException e) { // } catch (MalformedURLException e) {
TraceSystem.traceThrowable(e); // TraceSystem.traceThrowable(e);
} // }
} // }
} // }
} }
void setAllowOthers(boolean b) { void setAllowOthers(boolean b) {
...@@ -212,22 +208,16 @@ public class AppServer { ...@@ -212,22 +208,16 @@ public class AppServer {
user = user.trim(); user = user.trim();
password = password.trim(); password = password.trim();
org.h2.Driver.load(); org.h2.Driver.load();
try { Class.forName(driver);
Class.forName(driver); // try {
} catch(ClassNotFoundException e) { // Driver dr = (Driver) urlClassLoader.loadClass(driver).newInstance();
if(urlClassLoader == null) { // Properties p = new Properties();
throw e; // p.setProperty("user", user);
} // p.setProperty("password", password);
try { // return dr.connect(url, p);
Driver dr = (Driver) urlClassLoader.loadClass(driver).newInstance(); // } catch(ClassNotFoundException e2) {
Properties p = new Properties(); // throw e2;
p.setProperty("user", user); // }
p.setProperty("password", password);
return dr.connect(url, p);
} catch(ClassNotFoundException e2) {
throw e2;
}
}
return DriverManager.getConnection(url, user, password); return DriverManager.getConnection(url, user, password);
} }
......
...@@ -21,10 +21,13 @@ import java.util.Collections; ...@@ -21,10 +21,13 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Map.Entry;
import org.h2.bnf.Bnf; import org.h2.bnf.Bnf;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.MemoryUtils; import org.h2.util.MemoryUtils;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
...@@ -136,11 +139,12 @@ public class AppThread extends WebServerThread { ...@@ -136,11 +139,12 @@ public class AppThread extends WebServerThread {
} }
} }
ArrayList list = new ArrayList(map.size()); ArrayList list = new ArrayList(map.size());
Iterator it = map.keySet().iterator(); Iterator it = map.entrySet().iterator();
while(it.hasNext()) { while(it.hasNext()) {
String key = (String)it.next(); Map.Entry entry = (Entry) it.next();
String key = (String) entry.getKey();
String type = "" + key.charAt(0); String type = "" + key.charAt(0);
String value = (String) map.get(key); String value = (String) entry.getValue();
key = key.substring(2); key = key.substring(2);
if(Character.isLetter(key.charAt(0)) && lowercase) { if(Character.isLetter(key.charAt(0)) && lowercase) {
key = StringUtils.toLowerEnglish(key); key = StringUtils.toLowerEnglish(key);
...@@ -192,7 +196,7 @@ public class AppThread extends WebServerThread { ...@@ -192,7 +196,7 @@ public class AppThread extends WebServerThread {
app.setSSL(Boolean.valueOf((String)attributes.get("ssl")).booleanValue()); app.setSSL(Boolean.valueOf((String)attributes.get("ssl")).booleanValue());
app.saveSettings(); app.saveSettings();
} catch(Exception e) { } catch(Exception e) {
// TODO ignore error? server.trace(e.toString());
} }
return admin(); return admin();
} }
...@@ -368,13 +372,18 @@ public class AppThread extends WebServerThread { ...@@ -368,13 +372,18 @@ public class AppThread extends WebServerThread {
StringBuffer columnsBuffer = new StringBuffer(); StringBuffer columnsBuffer = new StringBuffer();
treeIndex = addColumns(view, buff, treeIndex, showColumnTypes, columnsBuffer); treeIndex = addColumns(view, buff, treeIndex, showColumnTypes, columnsBuffer);
if(schema.contents.isH2) { if(schema.contents.isH2) {
PreparedStatement prep = conn.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?"); PreparedStatement prep = null;
prep.setString(1, view.name); try {
ResultSet rs = prep.executeQuery(); prep = conn.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?");
if(rs.next()) { prep.setString(1, view.name);
String sql = rs.getString("SQL"); ResultSet rs = prep.executeQuery();
buff.append("setNode("+treeIndex+ identNode + " 'type', '" + PageParser.escapeJavaScript(sql)+ "', null);\n"); if(rs.next()) {
treeIndex++; String sql = rs.getString("SQL");
buff.append("setNode("+treeIndex+ identNode + " 'type', '" + PageParser.escapeJavaScript(sql)+ "', null);\n");
treeIndex++;
}
} finally {
JdbcUtils.closeSilently(prep);
} }
} }
buff.append("addTable('"+PageParser.escapeJavaScript(view.name)+"', '"+PageParser.escapeJavaScript(columnsBuffer.toString())+"', "+tableId+");\n"); buff.append("addTable('"+PageParser.escapeJavaScript(view.name)+"', '"+PageParser.escapeJavaScript(columnsBuffer.toString())+"', "+tableId+");\n");
...@@ -414,38 +423,44 @@ public class AppThread extends WebServerThread { ...@@ -414,38 +423,44 @@ public class AppThread extends WebServerThread {
treeIndex = addTablesAndViews(schema, false, buff, treeIndex); treeIndex = addTablesAndViews(schema, false, buff, treeIndex);
} }
if(isH2) { if(isH2) {
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM INFORMATION_SCHEMA.SEQUENCES ORDER BY SEQUENCE_NAME"); Statement stat = null;
for(int i=0; rs.next(); i++) { try {
if(i==0) { stat = conn.createStatement();
buff.append("setNode("+treeIndex+", 0, 1, 'sequences', '${text.tree.sequences}', null);\n"); ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.SEQUENCES ORDER BY SEQUENCE_NAME");
treeIndex++; for(int i=0; rs.next(); i++) {
} if(i==0) {
String name = rs.getString("SEQUENCE_NAME"); buff.append("setNode("+treeIndex+", 0, 1, 'sequences', '${text.tree.sequences}', null);\n");
String current = rs.getString("CURRENT_VALUE"); treeIndex++;
String increment = rs.getString("INCREMENT"); }
buff.append("setNode("+treeIndex+", 1, 1, 'sequence', '" + PageParser.escapeJavaScript(name)+ "', null);\n"); String name = rs.getString("SEQUENCE_NAME");
treeIndex++; String current = rs.getString("CURRENT_VALUE");
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.current}: " + PageParser.escapeJavaScript(current)+ "', null);\n"); String increment = rs.getString("INCREMENT");
treeIndex++; buff.append("setNode("+treeIndex+", 1, 1, 'sequence', '" + PageParser.escapeJavaScript(name)+ "', null);\n");
if(!increment.equals("1")) {
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.increment}: " + PageParser.escapeJavaScript(increment)+ "', null);\n");
treeIndex++; treeIndex++;
} buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.current}: " + PageParser.escapeJavaScript(current)+ "', null);\n");
}
rs = conn.createStatement().executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS ORDER BY NAME");
for(int i=0; rs.next(); i++) {
if(i==0) {
buff.append("setNode("+treeIndex+", 0, 1, 'users', '${text.tree.users}', null);\n");
treeIndex++; treeIndex++;
if(!increment.equals("1")) {
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.increment}: " + PageParser.escapeJavaScript(increment)+ "', null);\n");
treeIndex++;
}
} }
String name = rs.getString("NAME"); rs = conn.createStatement().executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS ORDER BY NAME");
String admin = rs.getString("ADMIN"); for(int i=0; rs.next(); i++) {
buff.append("setNode("+treeIndex+", 1, 1, 'user', '" + PageParser.escapeJavaScript(name)+ "', null);\n"); if(i==0) {
treeIndex++; buff.append("setNode("+treeIndex+", 0, 1, 'users', '${text.tree.users}', null);\n");
if(admin.equalsIgnoreCase("TRUE")) { treeIndex++;
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.admin}', null);\n"); }
String name = rs.getString("NAME");
String admin = rs.getString("ADMIN");
buff.append("setNode("+treeIndex+", 1, 1, 'user', '" + PageParser.escapeJavaScript(name)+ "', null);\n");
treeIndex++; treeIndex++;
if(admin.equalsIgnoreCase("TRUE")) {
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.admin}', null);\n");
treeIndex++;
}
} }
} finally {
JdbcUtils.closeSilently(stat);
} }
} }
String version = meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion(); String version = meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion();
...@@ -542,7 +557,7 @@ public class AppThread extends WebServerThread { ...@@ -542,7 +557,7 @@ public class AppThread extends WebServerThread {
conn.close(); conn.close();
} }
} catch(Exception e) { } catch(Exception e) {
// TODO log error server.trace(e.toString());
} }
return "index.do"; return "index.do";
} }
...@@ -1016,12 +1031,14 @@ public class AppThread extends WebServerThread { ...@@ -1016,12 +1031,14 @@ public class AppThread extends WebServerThread {
result += "(Statement) "; result += "(Statement) ";
} }
result+="("; result+="(";
StringBuffer buff = new StringBuffer();
for(int i=0; i<params.size(); i++) { for(int i=0; i<params.size(); i++) {
if(i>0) { if(i>0) {
result+=", "; buff.append(", ");
} }
result += ((Integer)params.get(i)).intValue() == 0 ? "i" : "rnd"; buff.append(((Integer)params.get(i)).intValue() == 0 ? "i" : "rnd");
} }
result += buff.toString();
result+=") " + sql; result+=") " + sql;
return result; return result;
} }
......
...@@ -25,7 +25,7 @@ public class DbContents { ...@@ -25,7 +25,7 @@ public class DbContents {
isH2 = url.startsWith("jdbc:h2:"); isH2 = url.startsWith("jdbc:h2:");
isOracle = url.startsWith("jdbc:oracle:"); isOracle = url.startsWith("jdbc:oracle:");
isPostgreSQL = url.startsWith("jdbc:postgresql:"); isPostgreSQL = url.startsWith("jdbc:postgresql:");
isHSQLDB = url.startsWith("jdbc:hsqldb:"); // isHSQLDB = url.startsWith("jdbc:hsqldb:");
isMySQL = url.startsWith("jdbc:mysql:"); isMySQL = url.startsWith("jdbc:mysql:");
isDerby = url.startsWith("jdbc:derby:"); isDerby = url.startsWith("jdbc:derby:");
isFirebird = url.startsWith("jdbc:firebirdsql:"); isFirebird = url.startsWith("jdbc:firebirdsql:");
...@@ -45,8 +45,8 @@ public class DbContents { ...@@ -45,8 +45,8 @@ public class DbContents {
schema.readTables(meta, tableTypes); schema.readTables(meta, tableTypes);
} }
if(defaultSchema == null) { if(defaultSchema == null) {
String best = null;
for(int i=0; i<schemas.length; i++) { for(int i=0; i<schemas.length; i++) {
String best = null;
if("dbo".equals(schemas[i].name)) { if("dbo".equals(schemas[i].name)) {
// MS SQL Server // MS SQL Server
defaultSchema = schemas[i]; defaultSchema = schemas[i];
......
...@@ -7,6 +7,8 @@ package org.h2.server.web; ...@@ -7,6 +7,8 @@ package org.h2.server.web;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.h2.bnf.Bnf; import org.h2.bnf.Bnf;
import org.h2.bnf.Rule; import org.h2.bnf.Rule;
...@@ -68,9 +70,10 @@ public class DbContextRule implements Rule { ...@@ -68,9 +70,10 @@ public class DbContextRule implements Rule {
HashMap map = sentence.getAliases(); HashMap map = sentence.getAliases();
HashSet set = new HashSet(); HashSet set = new HashSet();
if(map != null) { if(map != null) {
for(Iterator it = map.keySet().iterator(); it.hasNext();) { for(Iterator it = map.entrySet().iterator(); it.hasNext();) {
String alias = (String)it.next(); Map.Entry entry = (Entry) it.next();
DbTableOrView table = (DbTableOrView)map.get(alias); String alias = (String) entry.getKey();
DbTableOrView table = (DbTableOrView) entry.getValue();
set.add(StringUtils.toUpperEnglish(table.name)); set.add(StringUtils.toUpperEnglish(table.name));
if(q.length()==0 || alias.startsWith(q)) { if(q.length()==0 || alias.startsWith(q)) {
if(q.length() < alias.length()) { if(q.length() < alias.length()) {
...@@ -112,12 +115,14 @@ public class DbContextRule implements Rule { ...@@ -112,12 +115,14 @@ public class DbContextRule implements Rule {
HashMap map = sentence.getAliases(); HashMap map = sentence.getAliases();
String shortName = lastTableName.substring(0, 1); String shortName = lastTableName.substring(0, 1);
if (map != null && map.containsKey(shortName)) { if (map != null && map.containsKey(shortName)) {
int result = 0;
for (int i = 1;; i++) { for (int i = 1;; i++) {
if (!map.containsKey(shortName + i)) { if (!map.containsKey(shortName + i)) {
shortName += i; result = i;
break; break;
} }
} }
shortName += result;
} }
String q = StringUtils.toUpperEnglish(query.trim()); String q = StringUtils.toUpperEnglish(query.trim());
if (q.length() == 0 || StringUtils.toUpperEnglish(shortName).startsWith(q)) { if (q.length() == 0 || StringUtils.toUpperEnglish(shortName).startsWith(q)) {
......
...@@ -153,7 +153,7 @@ public class WebServer implements Service { ...@@ -153,7 +153,7 @@ public class WebServer implements Service {
c.start(); c.start();
} }
} catch (Exception e) { } catch (Exception e) {
// TODO log exception trace(e.toString());
} }
} }
...@@ -192,7 +192,7 @@ public class WebServer implements Service { ...@@ -192,7 +192,7 @@ public class WebServer implements Service {
try { try {
trace("translation: "+language); trace("translation: "+language);
byte[] trans = getFile("_text_"+language+".properties"); byte[] trans = getFile("_text_"+language+".properties");
trace(" "+trans); trace(" "+new String(trans));
text.load(new ByteArrayInputStream(trans)); text.load(new ByteArrayInputStream(trans));
} catch (IOException e) { } catch (IOException e) {
TraceSystem.traceThrowable(e); TraceSystem.traceThrowable(e);
......
...@@ -389,39 +389,35 @@ public class DiskFile implements CacheWriter { ...@@ -389,39 +389,35 @@ public class DiskFile implements CacheWriter {
return record; return record;
} }
readCount++; readCount++;
try { go(pos);
go(pos); rowBuff.reset();
rowBuff.reset(); byte[] buff = rowBuff.getBytes();
byte[] buff = rowBuff.getBytes(); file.readFully(buff, 0, BLOCK_SIZE);
file.readFully(buff, 0, BLOCK_SIZE); DataPage s = DataPage.create(database, buff);
DataPage s = DataPage.create(database, buff); int blockCount = s.readInt();
int blockCount = s.readInt(); int id = s.readInt();
int id = s.readInt(); if(Constants.CHECK && storageId != id) {
if(Constants.CHECK && storageId != id) { throw Message.getInternalError("File ID mismatch got="+id+" expected="+storageId+" pos="+pos+" "+logChanges+" "+this +" blockCount:"+blockCount);
throw Message.getInternalError("File ID mismatch got="+id+" expected="+storageId+" pos="+pos+" "+logChanges+" "+this +" blockCount:"+blockCount); }
} if(Constants.CHECK && blockCount == 0) {
if(Constants.CHECK && blockCount == 0) { throw Message.getInternalError("0 blocks to read pos="+pos);
throw Message.getInternalError("0 blocks to read pos="+pos); }
} if(blockCount > 1) {
if(blockCount > 1) { byte[] b2 = new byte[blockCount * BLOCK_SIZE];
byte[] b2 = new byte[blockCount * BLOCK_SIZE]; System.arraycopy(buff, 0, b2, 0, BLOCK_SIZE);
System.arraycopy(buff, 0, b2, 0, BLOCK_SIZE); buff = b2;
buff = b2; file.readFully(buff, BLOCK_SIZE, blockCount * BLOCK_SIZE - BLOCK_SIZE);
file.readFully(buff, BLOCK_SIZE, blockCount * BLOCK_SIZE - BLOCK_SIZE); s = DataPage.create(database, buff);
s = DataPage.create(database, buff); s.readInt();
s.readInt(); s.readInt();
s.readInt();
}
s.check(blockCount*BLOCK_SIZE);
Record r = reader.read(s);
r.setStorageId(storageId);
r.setPos(pos);
r.setBlockCount(blockCount);
cache.put(r);
return r;
} catch (Exception e) {
throw Message.convert(e);
} }
s.check(blockCount*BLOCK_SIZE);
Record r = reader.read(s);
r.setStorageId(storageId);
r.setPos(pos);
r.setBlockCount(blockCount);
cache.put(r);
return r;
} }
} }
...@@ -511,7 +507,7 @@ public class DiskFile implements CacheWriter { ...@@ -511,7 +507,7 @@ public class DiskFile implements CacheWriter {
return pageOwners.get(page); return pageOwners.get(page);
} }
synchronized void setPageOwner(int page, int storageId) throws SQLException { void setPageOwner(int page, int storageId) throws SQLException {
int old = pageOwners.get(page); int old = pageOwners.get(page);
if(old == storageId) { if(old == storageId) {
return; return;
...@@ -737,7 +733,7 @@ public class DiskFile implements CacheWriter { ...@@ -737,7 +733,7 @@ public class DiskFile implements CacheWriter {
return dataFile; return dataFile;
} }
public void setLogChanges(boolean b) { public synchronized void setLogChanges(boolean b) {
this.logChanges = b; this.logChanges = b;
} }
......
...@@ -67,7 +67,7 @@ public class FileLock { ...@@ -67,7 +67,7 @@ public class FileLock {
locked = true; locked = true;
} }
public void finalize() { protected void finalize() {
if (!Constants.RUN_FINALIZERS) { if (!Constants.RUN_FINALIZERS) {
return; return;
} }
......
...@@ -131,7 +131,7 @@ public class FileStoreInputStream extends InputStream { ...@@ -131,7 +131,7 @@ public class FileStoreInputStream extends InputStream {
} }
} }
public void finalize() { protected void finalize() {
if (!Constants.RUN_FINALIZERS) { if (!Constants.RUN_FINALIZERS) {
return; return;
} }
......
...@@ -16,4 +16,8 @@ public class SessionState { ...@@ -16,4 +16,8 @@ public class SessionState {
} }
return lastCommitPos >= pos; return lastCommitPos >= pos;
} }
public String toString() {
return "sessionId:" + sessionId + " log:" + lastCommitLog + " pos:" + lastCommitPos + " inDoubt:" + inDoubtTransaction;
}
} }
...@@ -461,7 +461,7 @@ public class MetaTable extends Table { ...@@ -461,7 +461,7 @@ public class MetaTable extends Table {
private String identifier(String s) { private String identifier(String s) {
if(Mode.getCurrentMode().lowerCaseIdentifiers) { if(Mode.getCurrentMode().lowerCaseIdentifiers) {
s = (s==null ? s : StringUtils.toLowerEnglish(s)); s = (s==null ? null : StringUtils.toLowerEnglish(s));
} }
return s; return s;
} }
...@@ -478,7 +478,7 @@ public class MetaTable extends Table { ...@@ -478,7 +478,7 @@ public class MetaTable extends Table {
return true; return true;
} }
Database db = session.getDatabase(); Database db = session.getDatabase();
Value v = value == null ? (Value)ValueNull.INSTANCE : ValueString.get(value); Value v = ValueString.get(value);
if(indexFrom != null && db.compare(v, indexFrom) < 0) { if(indexFrom != null && db.compare(v, indexFrom) < 0) {
return false; return false;
} }
......
...@@ -292,13 +292,13 @@ public class TableFilter implements ColumnResolver { ...@@ -292,13 +292,13 @@ public class TableFilter implements ColumnResolver {
} }
public void addJoin(TableFilter filter, boolean outer, Expression on) throws SQLException { public void addJoin(TableFilter filter, boolean outer, Expression on) throws SQLException {
if(on!=null) { if(on != null) {
on.mapColumns(this, 0); on.mapColumns(this, 0);
} }
if(join==null) { if(join == null) {
this.join = filter; this.join = filter;
filter.outerJoin = outer; filter.outerJoin = outer;
if(on!=null) { if(on != null) {
TableFilter f = filter; TableFilter f = filter;
do { do {
on.mapColumns(f, 0); on.mapColumns(f, 0);
...@@ -311,7 +311,7 @@ public class TableFilter implements ColumnResolver { ...@@ -311,7 +311,7 @@ public class TableFilter implements ColumnResolver {
join.addJoin(filter, outer, on); join.addJoin(filter, outer, on);
} }
if(on != null) { if(on != null) {
on = on.optimize(session); on.optimize(session);
} }
} }
......
...@@ -11,6 +11,7 @@ import java.sql.PreparedStatement; ...@@ -11,6 +11,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap; import java.util.HashMap;
import org.h2.engine.Session; import org.h2.engine.Session;
...@@ -20,6 +21,7 @@ import org.h2.index.LinkedIndex; ...@@ -20,6 +21,7 @@ import org.h2.index.LinkedIndex;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.util.JdbcUtils;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.DataType; import org.h2.value.DataType;
...@@ -71,8 +73,10 @@ public class TableLink extends Table { ...@@ -71,8 +73,10 @@ public class TableLink extends Table {
columnMap.put(n, col); columnMap.put(n, col);
} }
if(columnList.size()==0) { if(columnList.size()==0) {
Statement stat = null;
try { try {
rs = conn.createStatement().executeQuery("SELECT * FROM " + originalTable + " T WHERE 1=0"); stat = conn.createStatement();
rs = stat.executeQuery("SELECT * FROM " + originalTable + " T WHERE 1=0");
ResultSetMetaData rsm = rs.getMetaData(); ResultSetMetaData rsm = rs.getMetaData();
for(i=0; i<rsm.getColumnCount();) { for(i=0; i<rsm.getColumnCount();) {
String n = rsm.getColumnName(i+1); String n = rsm.getColumnName(i+1);
...@@ -91,6 +95,8 @@ public class TableLink extends Table { ...@@ -91,6 +95,8 @@ public class TableLink extends Table {
} }
} catch(SQLException e) { } catch(SQLException e) {
throw Message.getSQLException(Message.TABLE_OR_VIEW_NOT_FOUND_1, new String[]{originalTable}, e); throw Message.getSQLException(Message.TABLE_OR_VIEW_NOT_FOUND_1, new String[]{originalTable}, e);
} finally {
JdbcUtils.closeSilently(stat);
} }
} }
Column[] cols = new Column[columnList.size()]; Column[] cols = new Column[columnList.size()];
......
...@@ -199,7 +199,7 @@ public class TableView extends Table { ...@@ -199,7 +199,7 @@ public class TableView extends Table {
} }
public void recompile(Session session) throws SQLException { public void recompile(Session session) throws SQLException {
for(int i=0; tables != null && i<tables.size(); i++) { for(int i=0; i<tables.size(); i++) {
Table t = (Table)tables.get(i); Table t = (Table)tables.get(i);
t.removeView(this); t.removeView(this);
} }
......
...@@ -14,6 +14,8 @@ import java.sql.SQLException; ...@@ -14,6 +14,8 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -101,18 +103,19 @@ public class Backup { ...@@ -101,18 +103,19 @@ public class Backup {
* INTERNAL * INTERNAL
*/ */
public static void executeScript(String url, String user, String password, String fileName, String options1, String options2) throws SQLException { public static void executeScript(String url, String user, String password, String fileName, String options1, String options2) throws SQLException {
Connection conn = null;
Statement stat = null;
try { try {
org.h2.Driver.load(); org.h2.Driver.load();
Connection conn = DriverManager.getConnection(url, user, password); conn = DriverManager.getConnection(url, user, password);
Statement stat = conn.createStatement(); stat = conn.createStatement();
String sql = "SCRIPT " + options1 + " TO '" + fileName + "' " + options2; String sql = "SCRIPT " + options1 + " TO '" + fileName + "' " + options2;
try { stat.execute(sql);
stat.execute(sql);
} finally {
conn.close();
}
} catch(Exception e) { } catch(Exception e) {
throw Message.convert(e); throw Message.convert(e);
} finally {
JdbcUtils.closeSilently(stat);
JdbcUtils.closeSilently(conn);
} }
} }
...@@ -126,11 +129,14 @@ public class Backup { ...@@ -126,11 +129,14 @@ public class Backup {
* @throws SQLException * @throws SQLException
*/ */
public static void execute(String url, String user, String password, String script) throws SQLException { public static void execute(String url, String user, String password, String script) throws SQLException {
Connection conn = null;
Statement stat = null;
FileWriter fileWriter = null;
try { try {
org.h2.Driver.load(); org.h2.Driver.load();
Connection conn = DriverManager.getConnection(url, user, password); conn = DriverManager.getConnection(url, user, password);
Statement stat = conn.createStatement(); stat = conn.createStatement();
FileWriter fileWriter = new FileWriter(script); fileWriter = new FileWriter(script);
PrintWriter writer = new PrintWriter(new BufferedWriter(fileWriter)); PrintWriter writer = new PrintWriter(new BufferedWriter(fileWriter));
ResultSet rs = stat.executeQuery("SCRIPT"); ResultSet rs = stat.executeQuery("SCRIPT");
while(rs.next()) { while(rs.next()) {
...@@ -138,10 +144,12 @@ public class Backup { ...@@ -138,10 +144,12 @@ public class Backup {
writer.println(s + ";"); writer.println(s + ";");
} }
writer.close(); writer.close();
fileWriter.close();
conn.close();
} catch(Exception e) { } catch(Exception e) {
throw Message.convert(e); throw Message.convert(e);
} finally {
JdbcUtils.closeSilently(stat);
JdbcUtils.closeSilently(conn);
IOUtils.closeSilently(fileWriter);
} }
} }
......
...@@ -10,6 +10,7 @@ import java.sql.DriverManager; ...@@ -10,6 +10,7 @@ import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.JdbcUtils;
/** /**
* Tool to create a database cluster. * Tool to create a database cluster.
...@@ -82,9 +83,11 @@ public class CreateCluster { ...@@ -82,9 +83,11 @@ public class CreateCluster {
* @throws SQLException * @throws SQLException
*/ */
public static void execute(String urlSource, String urlTarget, String user, String password, String serverlist) throws SQLException { public static void execute(String urlSource, String urlTarget, String user, String password, String serverlist) throws SQLException {
Connection conn = null;
Statement stat = null;
try { try {
org.h2.Driver.load(); org.h2.Driver.load();
Connection conn;
// use cluster='' so connecting is possible even if the cluster is enabled // use cluster='' so connecting is possible even if the cluster is enabled
conn = DriverManager.getConnection(urlSource + ";CLUSTER=''", user, password); conn = DriverManager.getConnection(urlSource + ";CLUSTER=''", user, password);
...@@ -107,16 +110,17 @@ public class CreateCluster { ...@@ -107,16 +110,17 @@ public class CreateCluster {
// set the cluster to the serverlist on both databases // set the cluster to the serverlist on both databases
conn = DriverManager.getConnection(urlSource, user, password); conn = DriverManager.getConnection(urlSource, user, password);
Statement stat;
stat = conn.createStatement(); stat = conn.createStatement();
stat.executeUpdate("SET CLUSTER '" + serverlist + "'"); stat.executeUpdate("SET CLUSTER '" + serverlist + "'");
conn.close(); conn.close();
conn = DriverManager.getConnection(urlTarget, user, password); conn = DriverManager.getConnection(urlTarget, user, password);
stat = conn.createStatement(); stat = conn.createStatement();
stat.executeUpdate("SET CLUSTER '" + serverlist + "'"); stat.executeUpdate("SET CLUSTER '" + serverlist + "'");
conn.close();
} catch(Exception e) { } catch(Exception e) {
throw Message.convert(e); throw Message.convert(e);
} finally {
JdbcUtils.closeSilently(conn);
JdbcUtils.closeSilently(stat);
} }
} }
......
...@@ -48,7 +48,7 @@ public class ByteUtils { ...@@ -48,7 +48,7 @@ public class ByteUtils {
public static byte[] convertStringToBytes(String s) throws SQLException { public static byte[] convertStringToBytes(String s) throws SQLException {
int len = s.length(); int len = s.length();
if (len % 2 == 1) { if (len < 0 || len % 2 == 1) {
throw Message.getSQLException(Message.HEX_STRING_ODD_1, s); throw Message.getSQLException(Message.HEX_STRING_ODD_1, s);
} }
len /= 2; len /= 2;
......
...@@ -15,7 +15,7 @@ import org.h2.message.Message; ...@@ -15,7 +15,7 @@ import org.h2.message.Message;
*/ */
public class Cache2Q implements Cache { public class Cache2Q implements Cache {
public static String TYPE_NAME = "TQ"; public static final String TYPE_NAME = "TQ";
private static final int MAIN = 1, IN = 2, OUT = 3; private static final int MAIN = 1, IN = 2, OUT = 3;
private int maxSize; private int maxSize;
......
...@@ -17,7 +17,7 @@ import org.h2.message.Message; ...@@ -17,7 +17,7 @@ import org.h2.message.Message;
*/ */
public class CacheLRU implements Cache { public class CacheLRU implements Cache {
public static String TYPE_NAME = "LRU"; public static final String TYPE_NAME = "LRU";
private int len; private int len;
private int maxSize; private int maxSize;
......
...@@ -99,11 +99,11 @@ public class DateTimeUtils { ...@@ -99,11 +99,11 @@ public class DateTimeUtils {
} }
public static Date convertDateToCalendar(Date x, Calendar calendar) throws SQLException { public static Date convertDateToCalendar(Date x, Calendar calendar) throws SQLException {
return x == null ? x : new Date(getLocalTime(x, calendar)); return x == null ? null : new Date(getLocalTime(x, calendar));
} }
public static Time convertTimeToCalendar(Time x, Calendar calendar) throws SQLException { public static Time convertTimeToCalendar(Time x, Calendar calendar) throws SQLException {
return x == null ? x : new Time(getLocalTime(x, calendar)); return x == null ? null : new Time(getLocalTime(x, calendar));
} }
public static java.util.Date parseDateTime(String s, int type, int errorCode) throws SQLException { public static java.util.Date parseDateTime(String s, int type, int errorCode) throws SQLException {
......
...@@ -25,7 +25,7 @@ import org.h2.message.TraceSystem; ...@@ -25,7 +25,7 @@ import org.h2.message.TraceSystem;
public class FileUtils { public class FileUtils {
public static HashMap memoryFiles = new HashMap(); public static final HashMap memoryFiles = new HashMap();
private static final String MEMORY_PREFIX = "inmemory:"; private static final String MEMORY_PREFIX = "inmemory:";
private static final String MEMORY_PREFIX_2 = "mem:"; private static final String MEMORY_PREFIX_2 = "mem:";
// TODO detection of 'case in sensitive filesystem' could maybe implemented using some other means // TODO detection of 'case in sensitive filesystem' could maybe implemented using some other means
......
...@@ -101,6 +101,9 @@ public class IntArray { ...@@ -101,6 +101,9 @@ public class IntArray {
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {
if(!(obj instanceof IntArray)) {
return false;
}
IntArray other = (IntArray) obj; IntArray other = (IntArray) obj;
if(hashCode() != other.hashCode() || size != other.size) { if(hashCode() != other.hashCode() || size != other.size) {
return false; return false;
......
package org.h2.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcUtils {
public static void closeSilently(Statement stat) {
if(stat != null) {
try {
stat.close();
} catch(SQLException e) {
// ignore
}
}
}
public static void closeSilently(Connection conn) {
if(conn != null) {
try {
conn.close();
} catch(SQLException e) {
// ignore
}
}
}
}
...@@ -6,157 +6,63 @@ package org.h2.util; ...@@ -6,157 +6,63 @@ package org.h2.util;
import org.h2.message.Message; import org.h2.message.Message;
// code originally from http://www.koders.com/java/fidD3445CD11B1DC687F6B8911075E7F01E23171553.aspx
// http://www.koders.com/java/fidD3445CD11B1DC687F6B8911075E7F01E23171553.aspx
/** /**
* The Permutations class provides an enumeration of all permutations of an * A class to iterate over all permutations of an array.
* array of objects. Each permutation is simply an ordered list of the group. * The algorithm is from Applied Combinatorics, by Alan Tucker as implemented in
* <p> * http://www.koders.com/java/fidD3445CD11B1DC687F6B8911075E7F01E23171553.aspx
* For example, to see all of the ways we can select a school representative and
* an alternate from a list of 4 children, begin with an array of names::
* <blockquote>
*
* <pre>
* Object[] children = { Leonardo, Monica, Nathan, Olivia };
* </pre>
*
* </blockquote> To see all 2-permutations of these 4 names, create and use a
* Permutations enumeration: <blockquote>
*
* <pre>
*
* Permutations c = new Permutations(children, 2);
* while (c.hasMoreElements()) {
* Object[] perm = (Object[])c.nextElement();
* for (int i = 0; i &lt; perm.length; i++) {
* System.out.print(perm[i] + );
* }
* System.out.println();
* }
*
* </pre>
*
* </blockquote> This will print out: <blockquote>
*
* <pre>
*
* Leonardo Monica
* Leonardo Nathan
* Leonardo Olivia
* Monica Leonardo
* Monica Nathan
* Monica Olivia
* Nathan Leonardo
* Nathan Monica
* Nathan Olivia
* Olivia Leonardo
* Olivia Monica
* Olivia Nathan
*
* </pre>
*
* </blockquote>
*
*/ */
public class Permutations implements java.util.Enumeration { public class Permutations {
private Object[] inArray;
private Object[] in;
private Object[] out;
private int n, m; private int n, m;
private int[] index; private int[] index;
private boolean hasNext = true;
private boolean hasMore = true; public Permutations(Object[] in, Object[] out) {
this(in, out, in.length);
/**
* Create a Permutation to enumerate through all possible lineups of the
* supplied array of Objects.
*
* @param inArray
* the group to line up
* @exception CombinatoricException
* Should never happen with this interface
*
*/
public Permutations(Object[] inArray) {
this(inArray, inArray.length);
} }
/** public Permutations(Object[] in, Object[] out, int m) {
* Create a Permutation to enumerate through all possible lineups of the this.n = in.length;
* supplied array of Objects.
*
* @param inArray
* the group to line up
* @param m
* the number of objects to use
* @exception CombinatoricException
* if m is greater than the length of inArray, or less than
* 0.
*/
public Permutations(Object[] inArray, int m) {
this.inArray = inArray;
this.n = inArray.length;
this.m = m; this.m = m;
// throw exception unless n >= m >= 0
if (n < m || m < 0) { if (n < m || m < 0) {
throw Message.getInternalError("n < m or m < 0"); throw Message.getInternalError("n < m or m < 0");
} }
this.in = in;
/** this.out = out;
* index is an array of ints that keep track of the next permutation to
* return. For example, an index on a permutation of 3 things might
* contain {1 2 0}. This index will be followed by {2 0 1} and {2 1 0}.
* Initially, the index is {0 ... n - 1}.
*/
index = new int[n]; index = new int[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
index[i] = i; index[i] = i;
} }
/** // The elements from m to n are always kept ascending right to left.
* The elements from m to n are always kept ascending right to left. // This keeps the dip in the interesting region.
* This keeps the dip in the interesting region.
*/
reverseAfter(m - 1); reverseAfter(m - 1);
} }
/**
* @return true, unless we have already returned the last permutation.
*/
public boolean hasMoreElements() {
return hasMore;
}
/** /**
* Move the index forward a notch. The algorithm first finds the rightmost * Move the index forward a notch. The algorithm first finds the rightmost
* index that is less than its neighbor to the right. This is the dip point. * index that is less than its neighbor to the right. This is the dip point.
* The algorithm next finds the least element to the right of the dip that * The algorithm next finds the least element to the right of the dip that
* is greater than the dip. That element is switched with the dip. Finally, * is greater than the dip. That element is switched with the dip. Finally,
* the list of elements to the right of the dip is reversed. * the list of elements to the right of the dip is reversed.
* <p>
* For example, in a permutation of 5 items, the index may be {1, 2, 4, 3, * For example, in a permutation of 5 items, the index may be {1, 2, 4, 3,
* 0}. The dip is 2 the rightmost element less than its neighbor on its * 0}. The dip is 2 the rightmost element less than its neighbor on its
* right. The least element to the right of 2 that is greater than 2 is 3. * right. The least element to the right of 2 that is greater than 2 is 3.
* These elements are swapped, yielding {1, 3, 4, 2, 0}, and the list right * These elements are swapped, yielding {1, 3, 4, 2, 0}, and the list right
* of the dip point is reversed, yielding {1, 3, 0, 2, 4}. * of the dip point is reversed, yielding {1, 3, 0, 2, 4}.
* <p>
* The algorithm is from Applied Combinatorics, by Alan Tucker.
*
*/ */
private void moveIndex() { private void moveIndex() {
// find the index of the first element that dips // find the index of the first element that dips
int i = rightmostDip(); int i = rightmostDip();
if (i < 0) { if (i < 0) {
hasMore = false; hasNext = false;
return; return;
} }
// find the least greater element to the right of the dip // find the least greater element to the right of the dip
int leastToRightIndex = i + 1; int leastToRightIndex = i + 1;
for (int j = i + 2; j < n; j++) { for (int j = i + 2; j < n; j++) {
if (index[j] < index[leastToRightIndex] && index[j] > index[i]) { if (index[j] < index[leastToRightIndex] && index[j] > index[i]) {
...@@ -165,46 +71,34 @@ public class Permutations implements java.util.Enumeration { ...@@ -165,46 +71,34 @@ public class Permutations implements java.util.Enumeration {
} }
// switch dip element with least greater element to its right // switch dip element with least greater element to its right
int t = index[i]; int t = index[i];
index[i] = index[leastToRightIndex]; index[i] = index[leastToRightIndex];
index[leastToRightIndex] = t; index[leastToRightIndex] = t;
if (m - 1 > i) { if (m - 1 > i) {
// reverse the elements to the right of the dip // reverse the elements to the right of the dip
reverseAfter(i); reverseAfter(i);
// reverse the elements to the right of m - 1 // reverse the elements to the right of m - 1
reverseAfter(m - 1); reverseAfter(m - 1);
} }
} }
/** /**
* @return java.lang.Object, the next permutation of the original Object * Get the index of the first element from the right that is less
* array. * than its neighbor on the right.
* <p>
* Actually, an array of Objects is returned. The declaration must
* say just Object, because the Permutations class implements
* Enumeration, which declares that the nextElement() returns a
* plain Object. Users must cast the returned object to (Object[]).
*/ */
public Object nextElement() { private int rightmostDip() {
if (!hasMore) { for (int i = n - 2; i >= 0; i--) {
return null; if (index[i] < index[i + 1]) {
} return i;
Object[] out = new Object[m]; }
for (int i = 0; i < m; i++) {
out[i] = inArray[index[i]];
} }
return -1;
moveIndex();
return out;
} }
/** /**
* Reverse the index elements to the right of the specified index. * Reverse the elements to the right of the specified index.
*/ */
private void reverseAfter(int i) { private void reverseAfter(int i) {
int start = i + 1; int start = i + 1;
...@@ -216,19 +110,22 @@ public class Permutations implements java.util.Enumeration { ...@@ -216,19 +110,22 @@ public class Permutations implements java.util.Enumeration {
start++; start++;
end--; end--;
} }
} }
/** /**
* @return int the index of the first element from the right that is less * Go to the next lineup, and if available, fill the target array.
* than its neighbor on the right. *
* @return if a new lineup is available
*/ */
private int rightmostDip() { public boolean next() {
for (int i = n - 2; i >= 0; i--) { if (!hasNext) {
if (index[i] < index[i + 1]) { return false;
return i;
}
} }
return -1; for (int i = 0; i < m; i++) {
out[i] = in[index[i]];
}
moveIndex();
return true;
} }
} }
...@@ -48,7 +48,7 @@ public class Transfer { ...@@ -48,7 +48,7 @@ public class Transfer {
this.session = session; this.session = session;
} }
public void finalize() { protected void finalize() {
if (!Constants.RUN_FINALIZERS) { if (!Constants.RUN_FINALIZERS) {
return; return;
} }
......
...@@ -77,7 +77,7 @@ public class ValueBoolean extends Value { ...@@ -77,7 +77,7 @@ public class ValueBoolean extends Value {
} }
protected boolean isEqual(Value v) { protected boolean isEqual(Value v) {
return v instanceof ValueBoolean && value == ((ValueBoolean)v).value; return v instanceof ValueBoolean && value.booleanValue() == ((ValueBoolean)v).value.booleanValue();
} }
} }
...@@ -87,9 +87,82 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -87,9 +87,82 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
TestAll test = new TestAll(); TestAll test = new TestAll();
test.printSystem(); test.printSystem();
// TODO check that xml is well formed, and html is more or less. // java.lang.Exception: query was too quick; result: 0 time:1192
// at org.h2.test.TestBase.logError(TestBase.java:219)
// at org.h2.test.db.TestCases$1.run(TestCases.java:158)
// at java.lang.Thread.run(Unknown Source)
// java.lang.Exception: query was too quick; result: 0 time:2203
// at org.h2.test.TestBase.logError(TestBase.java:219)
// at org.h2.test.db.TestCases$1.run(TestCases.java:158)
// at java.lang.Thread.run(Unknown Source)
// java.lang.Error: Results don't match: original (0):
// success
// other:
// exception: 90020: Database may be already open: Concurrent update [90020-36]
// org.h2.jdbc.JdbcSQLException: Database may be already open: Concurrent update [90020-36]
// at org.h2.message.Message.getSQLException(Message.java:67)
// at org.h2.message.Message.getSQLException(Message.java:49)
// at org.h2.store.FileLock.error(FileLock.java:310)
// at org.h2.store.FileLock.lockFile(FileLock.java:182)
// at org.h2.store.FileLock.lock(FileLock.java:65)
// at org.h2.engine.Database.open(Database.java:424)
// at org.h2.engine.Database.<init>(Database.java:382)
// at org.h2.engine.Engine.openSession(Engine.java:44)
// at org.h2.engine.Engine.getSession(Engine.java:85)
// at org.h2.engine.Session.createSession(Session.java:140)
// at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:944)
// at org.h2.Driver.connect(Driver.java:52)
// at java.sql.DriverManager.getConnection(Unknown Source)
// at java.sql.DriverManager.getConnection(Unknown Source)
// at org.h2.test.synth.DbConnection.getConnection(DbConnection.java:83)
// at org.h2.test.synth.DbConnection.connect(DbConnection.java:74)
// at org.h2.test.synth.Command.run(Command.java:229)
// at org.h2.test.synth.TestSynth.process(TestSynth.java:158)
// at org.h2.test.synth.TestSynth.testRun(TestSynth.java:145)
// at org.h2.test.synth.TestSynth.testCase(TestSynth.java:263)
// at org.h2.test.synth.TestSynth.test(TestSynth.java:274)
// at org.h2.test.TestBase.runTest(TestBase.java:59)
// at org.h2.test.TestAll.main(TestAll.java:159)
//
// at org.h2.test.synth.TestSynth.compareResults(TestSynth.java:185)
// at org.h2.test.synth.TestSynth.process(TestSynth.java:164)
// at org.h2.test.synth.TestSynth.testRun(TestSynth.java:145)
// at org.h2.test.synth.TestSynth.testCase(TestSynth.java:263)
// at org.h2.test.synth.TestSynth.test(TestSynth.java:274)
// at org.h2.test.TestBase.runTest(TestBase.java:59)
// at org.h2.test.TestAll.main(TestAll.java:159)
// java.lang.Exception: query was too quick; result: 0 time:1512
// at org.h2.test.TestBase.logError(TestBase.java:219)
// at org.h2.test.db.TestCases$1.run(TestCases.java:158)
// at java.lang.Thread.run(Unknown Source)
// Add FindBugs to Release Checklist
// Hot backup (incremental backup, online backup): backup data, log, index? files
// analyze hibernate read committed tests that fail
// Hibernate: when?
// when? server only? special test with TestAll (only this)
// java.lang.Exception: query was too quick; result: 0 time:1002
// at org.h2.test.TestBase.logError(TestBase.java:219)
// at org.h2.test.db.TestCases$1.run(TestCases.java:158)
// at java.lang.Thread.run(Unknown Source)
// PayPal donate - aaa.html/main.html // DROP TABLE TEST;
// CREATE TABLE TEST(C CHAR(10));
// INSERT INTO TEST VALUES('1');
// SELECT COUNT(*) FROM TEST WHERE C='1 ';
// -- PostgreSQL, HSQLDB, MySQL, Derby, MS SQL Server, Oracle: 1
// -- H2: 0
// SELECT LENGTH(C), LENGTH(C || 'x') FROM TEST;
// -- MySQL: 1, 1 (??)
// -- MS SQL Server: 1, 11 (SELECT LEN(C), LEN(C + 'x') FROM TEST)
// -- Oracle, Derby: 10, 11
// -- PostgreSQL, H2, HSQLDB: 1, 2
// maybe use system property for base directory (h2.baseDir) // maybe use system property for base directory (h2.baseDir)
...@@ -98,8 +171,6 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -98,8 +171,6 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
// auto-upgrade application: // auto-upgrade application:
// check if new version is available // check if new version is available
// (option: digital signature) // (option: digital signature)
// (option: RSS / atom newsfeed)
// (option: small XML parser)
// if yes download new version // if yes download new version
// (option: http, https, ftp, network) // (option: http, https, ftp, network)
// backup database to SQL script // backup database to SQL script
...@@ -127,7 +198,6 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -127,7 +198,6 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
// test LIKE: compare against other databases // test LIKE: compare against other databases
// TestRandomSQL is too random; most statements fails // TestRandomSQL is too random; most statements fails
// extend the random join test that compared the result against PostgreSQL // extend the random join test that compared the result against PostgreSQL
// Donate a translation: I am looking for people who would help translating the H2 Console into other languages. Please tell me if you think you can help
// long running test with the same database // long running test with the same database
// repeatable test with a very big database (making backups of the database files) // repeatable test with a very big database (making backups of the database files)
......
...@@ -35,15 +35,16 @@ public class MergeDocs { ...@@ -35,15 +35,16 @@ public class MergeDocs {
"faq.html", "faq.html",
"license.html" "license.html"
}; };
String finalText=""; StringBuffer buff = new StringBuffer();
for(int i=0; i<pages.length; i++) { for(int i=0; i<pages.length; i++) {
String text = getContent(pages[i]); String text = getContent(pages[i]);
for(int j=0; j<pages.length; j++) { for(int j=0; j<pages.length; j++) {
text = StringUtils.replaceAll(text, pages[j] + "#", "#"); text = StringUtils.replaceAll(text, pages[j] + "#", "#");
} }
text = removeHeaderFooter(text); text = removeHeaderFooter(text);
finalText += text; buff.append(text);
} }
String finalText= buff.toString();
File output = new File(baseDir, "onePage.html"); File output = new File(baseDir, "onePage.html");
PrintWriter writer = new PrintWriter(new FileWriter(output)); PrintWriter writer = new PrintWriter(new FileWriter(output));
writer.println("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"><title>"); writer.println("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"><title>");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论