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

--no commit message

--no commit message
上级 476b0169
...@@ -35,6 +35,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -35,6 +35,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3> <h3>Version 1.0 (Current)</h3>
<h3>Version 1.0 / TODO</h3><ul> <h3>Version 1.0 / TODO</h3><ul>
<li>Selecting a column using the syntax schemaName.tableName.columName did not work in all cases.
<li>Can now parse timestamps with timezone information (Z or +/-hh:mm) and dates before year 1. <li>Can now parse timestamps with timezone information (Z or +/-hh:mm) and dates before year 1.
However dates before year 1 are not formatted correctly (this is a Java problem). However dates before year 1 are not formatted correctly (this is a Java problem).
<li>When stopping the TCP server from an application and immediately afterwards staring it again <li>When stopping the TCP server from an application and immediately afterwards staring it again
......
...@@ -11,23 +11,24 @@ package org.h2.engine; ...@@ -11,23 +11,24 @@ package org.h2.engine;
* - System.out > trace messages * - System.out > trace messages
* *
* Release checklist * Release checklist
* - Run FindBugs
* - Update latest version in build.html: http://mirrors.ibiblio.org/pub/mirrors/maven2/com/h2database/h2/ * - Update latest version in build.html: http://mirrors.ibiblio.org/pub/mirrors/maven2/com/h2database/h2/
* - ant jarClient, check jar file size * - ant jarClient, check jar file size
* - try compiling with JDK 1.3, 1.4, 1.5 and 1.6 * - Compiling with JDK 1.3, 1.4, 1.5 and 1.6
* set path=C:\Programme\Java\jdk1.6.0\bin;%PATH% * set path=C:\Programme\Java\jdk1.6.0\bin;%PATH%
* - change FAQ (next release planned, known bugs) * - Change FAQ (next release planned, known bugs)
* - check version, change build number in Constants.java and build.xml * - Check version, change build number in Constants.java and build.xml
* - check code coverage * - Check code coverage
* - No " Message.getInternalError" (must be "throw Message.getInternalError") * - No " Message.getInternalError" (must be "throw Message.getInternalError")
* - No TODO in the docs * - No TODO in the docs
* - Run regression test with JDK 1.4 and 1.5 * - Run regression test with JDK 1.4 and 1.5
* - Change version(s) in performance.html; use latest versions of other databases * - Change version(s) in performance.html; use latest versions of other databases
* - Run 'ant benchmark' (with JDK 1.4 currently) * - Run 'ant benchmark' (with JDK 1.4 currently)
* - copy the benchmark results and update the performance page and diagram * - Copy the benchmark results and update the performance page and diagram
* (remove rows 2*open/close, 2*executed statement) * (remove rows 2*open/close, 2*executed statement)
* *
* - documentation: if there are new files, add them to MergeDocs * - Documentation: if there are new files, add them to MergeDocs
* - documentation: check if all javadoc files are in the index * - Documentation: check if all javadoc files are in the index
* - ant docs * - ant docs
* - PDF (15 min) * - PDF (15 min)
* - footer * - footer
...@@ -35,18 +36,18 @@ package org.h2.engine; ...@@ -35,18 +36,18 @@ package org.h2.engine;
* - tables (optimal size) * - tables (optimal size)
* - orphan control, page breaks * - orphan control, page breaks
* - table of contents * - table of contents
* - switch off auto-build * - Switch off auto-build
* - ant all * - ant all
* - make sure odbc files are the * - Make sure odbc files are the
* - make sure the pdf file is there * - Make sure the pdf file is there
* - make sure the build files are removed * - Make sure the build files are removed
* - ant zip * - ant zip
* - windows installer (nsis) * - Windows installer (nsis)
* - test * - Test
* - test the windows service * - Test the windows service
* - TestSystemExit * - TestSystemExit
* - test with hibernate * - Test with hibernate
* - scan for viruses * - Scan for viruses
* *
* - Send a mail to Google Groups * - Send a mail to Google Groups
* - newsletter: prepare, send (always send to BCC!!) * - newsletter: prepare, send (always send to BCC!!)
...@@ -185,7 +186,7 @@ public class Constants { ...@@ -185,7 +186,7 @@ public class Constants {
public static final int ALLOW_LITERALS_ALL = 2; public static final int ALLOW_LITERALS_ALL = 2;
public static final int DEFAULT_ALLOW_LITERALS = ALLOW_LITERALS_ALL; public static final int DEFAULT_ALLOW_LITERALS = ALLOW_LITERALS_ALL;
public static boolean AUTO_CONVERT_LOB_TO_FILES = true; public static final boolean AUTO_CONVERT_LOB_TO_FILES = true;
public static final boolean ALLOW_EMTPY_BTREE_PAGES = true; public static final boolean ALLOW_EMTPY_BTREE_PAGES = true;
public static final String CONN_URL_INTERNAL = "jdbc:default:connection"; public static final String CONN_URL_INTERNAL = "jdbc:default:connection";
public static final String CONN_URL_COLUMNLIST = "jdbc:columnlist:connection"; public static final String CONN_URL_COLUMNLIST = "jdbc:columnlist:connection";
...@@ -205,28 +206,28 @@ public class Constants { ...@@ -205,28 +206,28 @@ public class Constants {
// for testing only // for testing only
public static int CACHE_MIN_RECORDS = 16; public static int CACHE_MIN_RECORDS = 16;
public static int MIN_WRITE_DELAY = getIntSetting("h2.minWriteDelay", 5); public static final int MIN_WRITE_DELAY = getIntSetting("h2.minWriteDelay", 5);
public static boolean CHECK = getBooleanSetting("h2.check", true); public static boolean CHECK = getBooleanSetting("h2.check", true);
public static boolean CHECK2 = getBooleanSetting("h2.check2", false); public static final boolean CHECK2 = getBooleanSetting("h2.check2", false);
// TODO: also remove DataHandler.allocateObjectId, createTempFile when setting this to true and removing it // TODO: also remove DataHandler.allocateObjectId, createTempFile when setting this to true and removing it
public static boolean LOB_FILES_IN_DIRECTORIES = getBooleanSetting("h2.lobFilesInDirectories", false); public static final boolean LOB_FILES_IN_DIRECTORIES = getBooleanSetting("h2.lobFilesInDirectories", false);
public static int LOB_FILES_PER_DIRECTORY = getIntSetting("h2.lobFilesPerDirectory", 256); public static final int LOB_FILES_PER_DIRECTORY = getIntSetting("h2.lobFilesPerDirectory", 256);
public static boolean MULTI_THREADED_KERNEL = getBooleanSetting("h2.multiThreadedKernel", false); public static boolean MULTI_THREADED_KERNEL = getBooleanSetting("h2.multiThreadedKernel", false);
public static boolean RUN_FINALIZERS = getBooleanSetting("h2.runFinalizers", true); public static boolean RUN_FINALIZERS = getBooleanSetting("h2.runFinalizers", true);
public static boolean OPTIMIZE_MIN_MAX = getBooleanSetting("h2.optimizeMinMax", true); public static final boolean OPTIMIZE_MIN_MAX = getBooleanSetting("h2.optimizeMinMax", true);
public static boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true); public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true);
public static int REDO_BUFFER_SIZE = getIntSetting("h2.redoBufferSize", 256 * 1024); public static final int REDO_BUFFER_SIZE = getIntSetting("h2.redoBufferSize", 256 * 1024);
public static boolean RECOMPILE_ALWAYS = getBooleanSetting("h2.recompileAlways", false); public static final boolean RECOMPILE_ALWAYS = getBooleanSetting("h2.recompileAlways", false);
public static boolean OPTIMIZE_SUBQUERY_CACHE = getBooleanSetting("h2.optimizeSubqueryCache", true); public static final boolean OPTIMIZE_SUBQUERY_CACHE = getBooleanSetting("h2.optimizeSubqueryCache", true);
public static boolean OVERFLOW_EXCEPTIONS = getBooleanSetting("h2.overflowExceptions", true); public static final boolean OVERFLOW_EXCEPTIONS = getBooleanSetting("h2.overflowExceptions", true);
public static boolean LOG_ALL_ERRORS = getBooleanSetting("h2.logAllErrors", false); public static final boolean LOG_ALL_ERRORS = getBooleanSetting("h2.logAllErrors", false);
public static String LOG_ALL_ERRORS_FILE = getStringSetting("h2.logAllErrorsFile", "h2errors.txt"); public static final String LOG_ALL_ERRORS_FILE = getStringSetting("h2.logAllErrorsFile", "h2errors.txt");
public static int SERVER_CACHED_OBJECTS = getIntSetting("h2.serverCachedObjects", 64); public static final int SERVER_CACHED_OBJECTS = getIntSetting("h2.serverCachedObjects", 64);
public static final int SERVER_SMALL_RESULTSET_SIZE = getIntSetting("h2.serverSmallResultSetSize", 100); public static final int SERVER_SMALL_RESULTSET_SIZE = getIntSetting("h2.serverSmallResultSetSize", 100);
public static final int EMERGENCY_SPACE_INITIAL = getIntSetting("h2.emergencySpaceInitial", 1 * 1024 * 1024); public static final int EMERGENCY_SPACE_INITIAL = getIntSetting("h2.emergencySpaceInitial", 1 * 1024 * 1024);
public static final int EMERGENCY_SPACE_MIN = getIntSetting("h2.emergencySpaceMin", 128 * 1024); public static final int EMERGENCY_SPACE_MIN = getIntSetting("h2.emergencySpaceMin", 128 * 1024);
......
...@@ -1314,7 +1314,7 @@ public class Database implements DataHandler { ...@@ -1314,7 +1314,7 @@ public class Database implements DataHandler {
return lockMode; return lockMode;
} }
public void setCloseDelay(int value) { public synchronized void setCloseDelay(int value) {
this.closeDelay = value; this.closeDelay = value;
} }
...@@ -1416,7 +1416,7 @@ public class Database implements DataHandler { ...@@ -1416,7 +1416,7 @@ public class Database implements DataHandler {
return ignoreCase; return ignoreCase;
} }
public void setDeleteFilesOnDisconnect(boolean b) { public synchronized void setDeleteFilesOnDisconnect(boolean b) {
this.deleteFilesOnDisconnect = b; this.deleteFilesOnDisconnect = b;
} }
......
...@@ -9,6 +9,7 @@ import java.util.HashMap; ...@@ -9,6 +9,7 @@ import java.util.HashMap;
import org.h2.command.Parser; import org.h2.command.Parser;
import org.h2.command.dml.Select; import org.h2.command.dml.Select;
import org.h2.engine.Constants;
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;
...@@ -44,6 +45,7 @@ public class ExpressionColumn extends Expression { ...@@ -44,6 +45,7 @@ public class ExpressionColumn extends Expression {
public ExpressionColumn(Database database, Select select, String schemaName, String tableAlias, String columnName) { public ExpressionColumn(Database database, Select select, String schemaName, String tableAlias, String columnName) {
this.database = database; this.database = database;
this.select = select; this.select = select;
this.schemaName = schemaName;
this.tableAlias = tableAlias; this.tableAlias = tableAlias;
this.columnName = columnName; this.columnName = columnName;
} }
...@@ -58,7 +60,8 @@ public class ExpressionColumn extends Expression { ...@@ -58,7 +60,8 @@ public class ExpressionColumn extends Expression {
if(tableAlias != null) { if(tableAlias != null) {
sql = Parser.quoteIdentifier(tableAlias) + "." + sql; sql = Parser.quoteIdentifier(tableAlias) + "." + sql;
} }
if(schemaName != null) { if(schemaName != null && !schemaName.equals(Constants.SCHEMA_MAIN)) {
int todoTempSolution;
sql = Parser.quoteIdentifier(schemaName) + "." + sql; sql = Parser.quoteIdentifier(schemaName) + "." + sql;
} }
return sql; return sql;
......
...@@ -38,7 +38,7 @@ public class JdbcDataSource extends TraceObject implements XADataSource, DataSou ...@@ -38,7 +38,7 @@ public class JdbcDataSource extends TraceObject implements XADataSource, DataSou
private static final long serialVersionUID = 1288136338451857771L; private static final long serialVersionUID = 1288136338451857771L;
private transient JdbcDataSourceFactory factory; private transient JdbcDataSourceFactory factory = new JdbcDataSourceFactory();
private transient PrintWriter logWriter; private transient PrintWriter logWriter;
private int timeout; private int timeout;
private String user; private String user;
...@@ -46,7 +46,6 @@ public class JdbcDataSource extends TraceObject implements XADataSource, DataSou ...@@ -46,7 +46,6 @@ public class JdbcDataSource extends TraceObject implements XADataSource, DataSou
private String url; private String url;
public JdbcDataSource() { public JdbcDataSource() {
this.factory = new JdbcDataSourceFactory();
int id = getNextId(TraceObject.DATASOURCE); int id = getNextId(TraceObject.DATASOURCE);
setTrace(factory.getTrace(), TraceObject.DATASOURCE, id); setTrace(factory.getTrace(), TraceObject.DATASOURCE, id);
} }
......
...@@ -109,7 +109,7 @@ public class Sequence extends SchemaObject { ...@@ -109,7 +109,7 @@ public class Sequence extends SchemaObject {
// nothing to do // nothing to do
} }
public long getCurrentValue() { public synchronized long getCurrentValue() {
return value - increment; return value - increment;
} }
......
...@@ -18,6 +18,8 @@ import java.util.ArrayList; ...@@ -18,6 +18,8 @@ import java.util.ArrayList;
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.command.Parser; import org.h2.command.Parser;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -303,13 +305,14 @@ public class Recover implements DataHandler { ...@@ -303,13 +305,14 @@ public class Recover implements DataHandler {
FileStore store = null; FileStore store = null;
int size = 0; int size = 0;
String n = fileName + (lobCompression ? ".comp" : "") + ".txt"; String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
InputStream in = null;
try { try {
out = new FileOutputStream(n); out = new FileOutputStream(n);
textStorage = Database.isTextStorage(fileName, false); textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage); byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, magic); store = FileStore.open(null, fileName, magic);
store.init(); store.init();
InputStream in = new BufferedInputStream(new FileStoreInputStream(store, this, lobCompression)); in = new BufferedInputStream(new FileStoreInputStream(store, this, lobCompression));
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE]; byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while(true) { while(true) {
int l = in.read(buffer); int l = in.read(buffer);
...@@ -326,6 +329,7 @@ public class Recover implements DataHandler { ...@@ -326,6 +329,7 @@ public class Recover implements DataHandler {
} }
} finally { } finally {
IOUtils.closeSilently(out); IOUtils.closeSilently(out);
IOUtils.closeSilently(in);
closeSilently(store); closeSilently(store);
} }
if(size == 0) { if(size == 0) {
...@@ -714,8 +718,9 @@ public class Recover implements DataHandler { ...@@ -714,8 +718,9 @@ public class Recover implements DataHandler {
writer.println(m.getSQL() + ";"); writer.println(m.getSQL() + ";");
} }
for(Iterator it = tableMap.keySet().iterator(); it.hasNext(); ) { for(Iterator it = tableMap.keySet().iterator(); it.hasNext(); ) {
Integer objectId = (Integer) it.next(); Map.Entry entry = (Entry) it.next();
String name = (String) tableMap.get(objectId); Integer objectId = (Integer) entry.getKey();
String name = (String) entry.getValue();
writer.println("INSERT INTO " + name +" SELECT * FROM O_" + objectId + ";"); writer.println("INSERT INTO " + name +" SELECT * FROM O_" + objectId + ";");
} }
for(Iterator it = objectIdSet.iterator(); it.hasNext(); ) { for(Iterator it = objectIdSet.iterator(); it.hasNext(); ) {
......
...@@ -21,6 +21,7 @@ import java.util.Iterator; ...@@ -21,6 +21,7 @@ import java.util.Iterator;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.JdbcUtils;
import org.h2.util.ScriptReader; import org.h2.util.ScriptReader;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -215,18 +216,19 @@ public class RunScript { ...@@ -215,18 +216,19 @@ public class RunScript {
} }
private static void executeRunscript(String url, String user, String password, String fileName, String options) throws SQLException { private static void executeRunscript(String url, String user, String password, String fileName, String options) 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 = "RUNSCRIPT FROM '" + fileName + "' " + options; String sql = "RUNSCRIPT FROM '" + fileName + "' " + options;
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);
} }
} }
......
...@@ -17,6 +17,7 @@ import org.h2.server.Service; ...@@ -17,6 +17,7 @@ import org.h2.server.Service;
import org.h2.server.TcpServer; import org.h2.server.TcpServer;
import org.h2.server.ftp.FtpServer; import org.h2.server.ftp.FtpServer;
import org.h2.server.web.WebServer; import org.h2.server.web.WebServer;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.StartBrowser; import org.h2.util.StartBrowser;
...@@ -230,9 +231,11 @@ public class Server implements Runnable { ...@@ -230,9 +231,11 @@ public class Server implements Runnable {
throw Message.convert(e); throw Message.convert(e);
} }
for(int i=0; i<2; i++) { for(int i=0; i<2; i++) {
Connection conn = null;
PreparedStatement prep = null;
try { try {
Connection conn = DriverManager.getConnection("jdbc:h2:" + url + "/" + db, "sa", password); conn = DriverManager.getConnection("jdbc:h2:" + url + "/" + db, "sa", password);
PreparedStatement prep = conn.prepareStatement("CALL STOP_SERVER(?, ?, ?)"); prep = conn.prepareStatement("CALL STOP_SERVER(?, ?, ?)");
prep.setInt(1, port); prep.setInt(1, port);
prep.setString(2, password); prep.setString(2, password);
prep.setInt(3, force ? TcpServer.SHUTDOWN_FORCE : TcpServer.SHUTDOWN_NORMAL); prep.setInt(3, force ? TcpServer.SHUTDOWN_FORCE : TcpServer.SHUTDOWN_NORMAL);
...@@ -244,18 +247,15 @@ public class Server implements Runnable { ...@@ -244,18 +247,15 @@ public class Server implements Runnable {
} else { } else {
throw e; throw e;
} }
} finally {
try {
conn.close();
} catch(SQLException e) {
// ignore
}
} }
break; break;
} catch(SQLException e) { } catch(SQLException e) {
if(i == 1) { if(i == 1) {
throw e; throw e;
} }
} finally {
JdbcUtils.closeSilently(prep);
JdbcUtils.closeSilently(conn);
} }
} }
} }
...@@ -338,7 +338,8 @@ public class Server implements Runnable { ...@@ -338,7 +338,8 @@ public class Server implements Runnable {
private static void wait(int i) { private static void wait(int i) {
try { try {
// sleep at most 4096 ms // sleep at most 4096 ms
Thread.sleep(i * i); long sleep = (long)i * (long)i;
Thread.sleep(sleep);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore // ignore
} }
......
...@@ -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 < 0 || len % 2 == 1) { if (len % 2 != 0) {
throw Message.getSQLException(Message.HEX_STRING_ODD_1, s); throw Message.getSQLException(Message.HEX_STRING_ODD_1, s);
} }
len /= 2; len /= 2;
......
...@@ -233,7 +233,8 @@ public class FileUtils { ...@@ -233,7 +233,8 @@ public class FileUtils {
} }
try { try {
// sleep at most 256 ms // sleep at most 256 ms
Thread.sleep(i * i); long sleep = (long)i * (long)i;
Thread.sleep(sleep);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore // ignore
} }
......
package org.h2.util; package org.h2.util;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
...@@ -26,4 +27,14 @@ public class JdbcUtils { ...@@ -26,4 +27,14 @@ public class JdbcUtils {
} }
} }
public static void closeSilently(ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch(SQLException e) {
// ignore
}
}
}
} }
...@@ -87,65 +87,101 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -87,65 +87,101 @@ 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();
// java.lang.Exception: query was too quick; result: 0 time:1192 // > Of course performance is relative. There are situations where a tractor is faster than a car.
// at org.h2.test.TestBase.logError(TestBase.java:219) // > It would be good to have a test case where Derby is faster, tell me if you have one.
// 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) // I gave a specific database server stress test scenario case when I mentioned TPC-B (this is just 1 particular case) - A tractor does not compete in some F1 race and that is where your analogy is flawed because Derby actually performs more than decently in that context - Like I said, embedded applications is one particular facet of today's applications but that does not represent all of the applications out there - Everything is relevant to the particular tests one is defining and running (yours in that case) but that does not represent how a database performs in some other contexts (embedded or not).
// at org.h2.test.synth.TestSynth.process(TestSynth.java:164) // > Currently H2 doesn't support row locks. But I don't think that most embedded applications need it.
// at org.h2.test.synth.TestSynth.testRun(TestSynth.java:145) // > Anyway, the trend is towards multi version concurrency control (MVCC), and that's the next big
// at org.h2.test.synth.TestSynth.testCase(TestSynth.java:263) // > thing that will be implemented in H2 (however this will take some time).
// 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) // Good to hear this - Row-lock in Derby has been implemented since the first incarnation of Cloudscape in 96' - MVCC is good but not for applications which are doing intense updates and writes - The reason is pretty obvious versus a lock concurrency scheme and that is why "some" database(s) are supporting both approaches.
// java.lang.Exception: query was too quick; result: 0 time:1512 //
// at org.h2.test.TestBase.logError(TestBase.java:219) // > Durability: The default isolation level of Derby is read committed, right?
// at org.h2.test.db.TestCases$1.run(TestCases.java:158) // > As far as I understand it, for fully-ACID compliant the isolation level should
// at java.lang.Thread.run(Unknown Source) // > be serialized (see Isolation in Wikipedia). I'm not sure if supporting 'full ACID'
// > compliance by default would make sense. I have implemented and run a durability test
// > with various databases and the file system (a simple power-off test using two computers),
// > and things don't look good. The problem is, even if the database tries to flush to disk
// > for each commit, the operating system and/or hard disk does not always do that.
// > For details see ACID. If you really want to enforce flushing to disk, you need to wait
// > at least 0.1 seconds per transaction, and even Derby doesn't do that by default.
// > That means, even Derby does *not* guarantee that all committed transactions will survive
// > a power failure or an application crash. If you have other results using common
// > hardware / default settings and this test, or if you find a way that is faster,
// > please tell me! Hopefully the next generation hard drives (with integrated flash memory)
// > will be better... But if you need 'no single point of failure' then you anyway need
// > clustering / mirroring. H2 support clustering, Derby does not.
// >
//
// The golden rule is that you should not rely on the file system for write operations unless you have some means to force-flush & check I/O completions - that is why Unix Raw Devices were made available almost 20 years ago so that one could bypass the FS and use Async I/O's at the kernel level to retrieve status on a particular I/O (completion) and made sure it made it to disk(s) - there are technics such as write through-case where you don't rely on I/O write operations to be handled at all by the FS buffer (as it is bypassed) but rather expect a write I/O to be written to disks everytime you request it - it is a binary operation, either it works or not and you'd get an I/O error if an I/O has not complete to disk. Relying on the FS and some UPS hardware device is ok _but_ that is NOT what you usually find in every embedded devices or client desktop - You can't expect everyone to have a UPS to alleviate some issues due to a database system loosing committed rtansaction and therefore not handling ACID durability as it should and it is expected. I've worked at many database companies and dealing with critical-level type of applications and if I had told the customers that could loose committed transactions due to an application or system crash, then I don't think these database companies would have been as successful as they have been. Some things such as not loosing committed transactions have to be handled at the database level and that is what durability is all about. Today, Derby will not loose transactions that have been committed whether you have some UPS or not.
//
// > Download size: I think David was talking about size of product download (16 MB for
// > Derby versus 3 MB for H2) not about the jar file size (2.2 MB for Derby versus 1 MB
// > for H2). By the way, the H2 jar also contains the Console web application and web server,
// > and other tools. And debugging info (line numbers) is switched on in H2, and switched off
// > in Derby. But I agree the jar file size is not the most important factor.
// >
//
// Download size is irrelevant in today's world except for web applications and in this case, one does NOT have to download the whole product - for embedded applications, it is only 1 JAR file basically and whether it is H2 or Derby, the size is not really an issue (as I mentioned in some earlier thread)
//
// > Community: Yes, Derby has more developers (4, according to Ohloh, not sure if
// > this is correct), but that doesn't necessarily mean a better product.
// > Development of Derby started in 1996 or earlier, while H2 started in 2004
// > (it is now one year online). H2 is a very young product, and currently doesn't
// > have professional support from a bigger company. This will be available in the
// > future when there is demand. You could also say Derby has a liability (big, old,
// > slow code base). Anyway, H2 also has quite a big community, given how young it is.
// > But of course Derby has the advantage the Apache name ('branding'), but this doesn't
// > mean it's better (there are many failed Apache projects).
// >
//
// Derby has more than 30+ contributors - what you saw in Ohloh are the top committers for 2007 (new year eh) and this is why it is 4 - last year 23 committers checked-in code, so I'll let you do the stats as far as how many contributors there could be - not every contributor is a committer to the project - that's how Apache works and a lot of other open source projects. Derby has developers from Sun (Java DB), IBM (Cloudscape) as well as other independent contributors or companies. Derby is _not_ big - The footprint is not big (2MB) for the engine compared to some other databases out there and is more than adequate for a lot of today's embedded applications. Apache is not just about branding - it has and continue to be a set of communities for many successful projects with defined rules and guidelines. At the end of the day, it is all about Open Source projects and quite a few of them have made lots of noise in the past many years and still continue to do so.
//
// > But only time can tell which database is more successful.
// >
//
//
// Again, I was not bashing H2 if this is the way you felt - I clearly mentioned that one has to know what type of database(s) one is dealing with before claiming it is faster for *all* use case scenarios out there.
//
// test big:false net:false cipher:null memory:false log:0 diskResult:false
// ERROR: query was too quick; result: 0 time:1532 java.lang.Exception: query was too quick; result: 0 time:1532 ------------------------------
// test big:false net:false cipher:null memory:false log:1 diskResult:false
// ERROR: query was too quick; result: 0 time:1853 java.lang.Exception: query was too quick; result: 0 time:1853 ------------------------------
// test big:false net:false cipher:null memory:false log:2 diskResult:false
// ERROR: query was too quick; result: 0 time:1152 java.lang.Exception: query was too quick; result: 0 time:1152 ------------------------------
// test big:false net:false cipher:null memory:false log:0 diskResult:false
// ERROR: query was too quick; result: 0 time:1462 java.lang.Exception: query was too quick; result: 0 time:1462 ------------------------------
// test big:false net:false cipher:null memory:false log:2 diskResult:false
// ERROR: query was too quick; result: 0 time:1692 java.lang.Exception: query was too quick; result: 0 time:1692 ------------------------------
// test big:true net:false cipher:null memory:false log:0 diskResult:false
// ERROR: query was too quick; result: 0 time:952 java.lang.Exception: query was too quick; result: 0 time:952 ------------------------------
// test big:true net:false cipher:null memory:false log:1 diskResult:false
// ERROR: query was too quick; result: 0 time:1171 java.lang.Exception: query was too quick; result: 0 time:1171 ------------------------------
// test big:true net:false cipher:null memory:false log:2 diskResult:false
// ERROR: query was too quick; result: 0 time:1502 java.lang.Exception: query was too quick; result: 0 time:1502 ------------------------------
// test big:true net:false cipher:null memory:false log:0 diskResult:false
// ERROR: query was too quick; result: 0 time:1372 java.lang.Exception: query was too quick; result: 0 time:1372 ------------------------------
// Hot backup (incremental backup, online backup): backup data, log, index? files
// delay reading the row if data is not required
// document compensations
// eliminate undo log records if stored on disk (just one pointer per block, not per record)
// Add FindBugs to Release Checklist // release checklist:
// add to freshmeat
// add to http://code.google.com/p/h2database/downloads/list
// Hot backup (incremental backup, online backup): backup data, log, index? files // SELECT ... FROM TA, TB, TC WHERE TC.COL3 = TA.COL1 AND TC.COL3=TB.COL2 AND TC.COL4 = 1
// ...
// The query implies TA.COL1 = TB.COL2 but does not explicitly set this condition.
// analyze hibernate read committed tests that fail // analyze hibernate read committed tests that fail
// Hibernate: when?
// when? server only? special test with TestAll (only this) // when? server only? special test with TestAll (only this)
// java.lang.Exception: query was too quick; result: 0 time:1002 // java.lang.Exception: query was too quick; result: 0 time:1002
// at org.h2.test.TestBase.logError(TestBase.java:219) // at org.h2.test.TestBase.logError(TestBase.java:219)
......
...@@ -286,7 +286,7 @@ public abstract class TestBase { ...@@ -286,7 +286,7 @@ public abstract class TestBase {
for(int i=0; i<a.length(); i++) { for(int i=0; i<a.length(); i++) {
String s = a.substring(0, i); String s = a.substring(0, i);
if(!b.startsWith(s)) { if(!b.startsWith(s)) {
s = s.substring(0, i) + "<*>" + s.substring(i); a = a.substring(0, i) + "<*>" + a.substring(i);
break; break;
} }
} }
......
...@@ -16,8 +16,8 @@ public class BenchA implements Bench { ...@@ -16,8 +16,8 @@ public class BenchA implements Bench {
private Database db; private Database db;
private int branches; private int branches;
private int tellers = branches * 20; private int tellers;
private int accounts = branches * 100; private int accounts;
private int size; private int size;
private static final String FILLER = "abcdefghijklmnopqrstuvwxyz"; private static final String FILLER = "abcdefghijklmnopqrstuvwxyz";
......
...@@ -371,7 +371,7 @@ public class BenchCThread { ...@@ -371,7 +371,7 @@ public class BenchCThread {
rs.next(); rs.next();
rs.getString(1); // c_first rs.getString(1); // c_first
rs.getString(2); // c_middle rs.getString(2); // c_middle
c_last = rs.getString(3); rs.getString(3); // c_last
rs.getString(4); // c_street_1 rs.getString(4); // c_street_1
rs.getString(5); // c_street_2 rs.getString(5); // c_street_2
rs.getString(6); // c_city rs.getString(6); // c_city
...@@ -499,7 +499,7 @@ public class BenchCThread { ...@@ -499,7 +499,7 @@ public class BenchCThread {
rs.getBigDecimal(1); // c_balance rs.getBigDecimal(1); // c_balance
rs.getString(2); // c_first rs.getString(2); // c_first
rs.getString(3); // c_middle rs.getString(3); // c_middle
c_last = rs.getString(4); rs.getString(4); // c_last
rs.close(); rs.close();
} }
prep = prepare("SELECT MAX(O_ID) " prep = prepare("SELECT MAX(O_ID) "
......
...@@ -20,6 +20,7 @@ import java.util.StringTokenizer; ...@@ -20,6 +20,7 @@ import java.util.StringTokenizer;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.Server; import org.h2.tools.Server;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
class Database { class Database {
...@@ -129,7 +130,13 @@ class Database { ...@@ -129,7 +130,13 @@ class Database {
Connection conn = DriverManager.getConnection(url, user, password); Connection conn = DriverManager.getConnection(url, user, password);
if(url.startsWith("jdbc:derby:")) { if(url.startsWith("jdbc:derby:")) {
// Derby: use higher cache size // Derby: use higher cache size
conn.createStatement().execute("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.storage.pageSize', '8192')"); Statement stat = null;
try {
stat = conn.createStatement();
stat.execute("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.storage.pageSize', '8192')");
} finally {
JdbcUtils.closeSilently(stat);
}
} }
return conn; return conn;
} }
......
...@@ -10,10 +10,13 @@ import java.sql.Connection; ...@@ -10,10 +10,13 @@ import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Properties; import java.util.Properties;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
public class TestPerformance { public class TestPerformance {
...@@ -29,13 +32,20 @@ public class TestPerformance { ...@@ -29,13 +32,20 @@ public class TestPerformance {
} }
private void openResults(boolean init) throws Exception { private void openResults(boolean init) throws Exception {
Connection conn = getResultConnection(); Connection conn = null;
Statement stat = null;
try {
conn = getResultConnection();
stat = conn.createStatement();
if(init) { if(init) {
conn.createStatement().execute("DROP TABLE IF EXISTS RESULTS"); stat.execute("DROP TABLE IF EXISTS RESULTS");
} }
conn.createStatement().execute("CREATE TABLE IF NOT EXISTS RESULTS(TESTID INT, TEST VARCHAR, " stat.execute("CREATE TABLE IF NOT EXISTS RESULTS(TESTID INT, TEST VARCHAR, "
+ "UNIT VARCHAR, DBID INT, DB VARCHAR, RESULT VARCHAR)"); + "UNIT VARCHAR, DBID INT, DB VARCHAR, RESULT VARCHAR)");
conn.close(); } finally {
JdbcUtils.closeSilently(stat);
JdbcUtils.closeSilently(conn);
}
} }
private void test(String[] args) throws Exception { private void test(String[] args) throws Exception {
...@@ -84,8 +94,14 @@ public class TestPerformance { ...@@ -84,8 +94,14 @@ public class TestPerformance {
return; return;
} }
ArrayList results = ((Database)dbs.get(0)).getResults(); ArrayList results = ((Database)dbs.get(0)).getResults();
Connection conn = getResultConnection(); Connection conn = null;
PreparedStatement prep = conn.prepareStatement( PreparedStatement prep = null;
Statement stat = null;
PrintWriter writer = null;
try {
conn = getResultConnection();
stat = conn.createStatement();
prep = conn.prepareStatement(
"INSERT INTO RESULTS(TESTID, TEST, UNIT, DBID, DB, RESULT) VALUES(?, ?, ?, ?, ?, ?)"); "INSERT INTO RESULTS(TESTID, TEST, UNIT, DBID, DB, RESULT) VALUES(?, ?, ?, ?, ?, ?)");
for(int i=0; i<results.size(); i++) { for(int i=0; i<results.size(); i++) {
Object[] res = (Object[])results.get(i); Object[] res = (Object[])results.get(i);
...@@ -103,8 +119,8 @@ public class TestPerformance { ...@@ -103,8 +119,8 @@ public class TestPerformance {
} }
} }
PrintWriter writer = new PrintWriter(new FileWriter(out)); writer = new PrintWriter(new FileWriter(out));
ResultSet rs = conn.createStatement().executeQuery( ResultSet rs = stat.executeQuery(
"CALL '<table><tr><th>Test Case</th><th>Unit</th>' " "CALL '<table><tr><th>Test Case</th><th>Unit</th>' "
+"|| SELECT GROUP_CONCAT('<th>' || DB || '</th>' ORDER BY DBID SEPARATOR '') FROM " +"|| SELECT GROUP_CONCAT('<th>' || DB || '</th>' ORDER BY DBID SEPARATOR '') FROM "
+"(SELECT DISTINCT DBID, DB FROM RESULTS)" +"(SELECT DISTINCT DBID, DB FROM RESULTS)"
...@@ -118,7 +134,12 @@ public class TestPerformance { ...@@ -118,7 +134,12 @@ public class TestPerformance {
rs.next(); rs.next();
String result = rs.getString(1); String result = rs.getString(1);
writer.println(result); writer.println(result);
conn.close(); } finally {
JdbcUtils.closeSilently(prep);
JdbcUtils.closeSilently(stat);
JdbcUtils.closeSilently(conn);
IOUtils.closeSilently(writer);
}
// ResultSet rsDbs = conn.createStatement().executeQuery("SELECT DB RESULTS GROUP BY DBID, DB ORDER BY DBID"); // ResultSet rsDbs = conn.createStatement().executeQuery("SELECT DB RESULTS GROUP BY DBID, DB ORDER BY DBID");
// while(rsDbs.next()) { // while(rsDbs.next()) {
...@@ -154,7 +175,6 @@ public class TestPerformance { ...@@ -154,7 +175,6 @@ public class TestPerformance {
// } // }
// writer.println("</table>"); // writer.println("</table>");
writer.close();
System.out.println("Test finished"); System.out.println("Test finished");
System.exit(0); System.exit(0);
} }
......
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.cases;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.h2.tools.Csv;
public class TestCloseAtShutdown extends Thread {
Connection conn;
TestCloseAtShutdown() {
Csv csv = null;
csv.setFieldSeparatorWrite(";");
}
public void run() {
try {
Thread.sleep(100);
} catch(Exception e) {
// ignore
}
System.out.println("hook app");
try {
conn.getAutoCommit();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
TestCloseAtShutdown closer = new TestCloseAtShutdown();
Runtime.getRuntime().addShutdownHook(closer);
Connection conn = DriverManager.getConnection("jdbc:h2:test2;TRACE_LEVEL_FILE=3;DB_CLOSE_ON_EXIT=FALSE", "sa", "sa");
closer.conn = conn;
conn.getAutoCommit();
}
}
...@@ -87,6 +87,7 @@ public class Coverage { ...@@ -87,6 +87,7 @@ public class Coverage {
c.processAll(); c.processAll();
c.data.close(); c.data.close();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
} }
} }
...@@ -154,8 +155,6 @@ public class Coverage { ...@@ -154,8 +155,6 @@ public class Coverage {
} }
File f = new File(name); File f = new File(name);
File fnew = new File(name + ".new"); File fnew = new File(name + ".new");
String key = name;
key = key.replace('\\', '.');
try { try {
writer = new BufferedWriter(new FileWriter(fnew)); writer = new BufferedWriter(new FileWriter(fnew));
Reader r = new BufferedReader(new FileReader(f)); Reader r = new BufferedReader(new FileReader(f));
......
...@@ -9,6 +9,8 @@ import java.io.FileReader; ...@@ -9,6 +9,8 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import org.h2.util.IOUtils;
/** /**
* The class used at runtime to measure the code usage and performance. * The class used at runtime to measure the code usage and performance.
*/ */
...@@ -16,8 +18,8 @@ public class Profile extends Thread { ...@@ -16,8 +18,8 @@ public class Profile extends Thread {
public static final boolean LIST_UNVISITED = true; public static final boolean LIST_UNVISITED = true;
public static final boolean FAST = false; public static final boolean FAST = false;
public static final boolean TRACE = false; public static final boolean TRACE = false;
public static final Profile main = new Profile();
public static int current; public static int current;
public static Profile main = new Profile();
private BufferedWriter trace; private BufferedWriter trace;
public int[] count; public int[] count;
public int[] time; public int[] time;
...@@ -74,11 +76,12 @@ public class Profile extends Thread { ...@@ -74,11 +76,12 @@ public class Profile extends Thread {
} }
Profile() { Profile() {
FileReader reader = null;
try { try {
LineNumberReader r = new LineNumberReader(new FileReader( reader = new FileReader("profile.txt");
"profile.txt")); LineNumberReader r = new LineNumberReader(reader);
while (r.readLine() != null) { while (r.readLine() != null) {
// nothing // nothing - just count lines
} }
maxIndex = r.getLineNumber(); maxIndex = r.getLineNumber();
count = new int[maxIndex]; count = new int[maxIndex];
...@@ -88,6 +91,8 @@ public class Profile extends Thread { ...@@ -88,6 +91,8 @@ public class Profile extends Thread {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
System.exit(1); System.exit(1);
} finally {
IOUtils.closeSilently(reader);
} }
} }
...@@ -115,8 +120,13 @@ public class Profile extends Thread { ...@@ -115,8 +120,13 @@ public class Profile extends Thread {
printLine('='); printLine('=');
print("NOT COVERED"); print("NOT COVERED");
printLine('-'); printLine('-');
LineNumberReader r = new LineNumberReader(new FileReader("profile.txt")); FileReader reader = null;
BufferedWriter writer = new BufferedWriter(new FileWriter("notcovered.txt")); FileWriter fwriter = null;
try {
reader = new FileReader("profile.txt");
LineNumberReader r = new LineNumberReader(reader);
fwriter = new FileWriter("notcovered.txt");
BufferedWriter writer = new BufferedWriter(fwriter);
int unvisited = 0; int unvisited = 0;
int unvisitedthrow = 0; int unvisitedthrow = 0;
for (int i = 0; i < maxIndex; i++) { for (int i = 0; i < maxIndex; i++) {
...@@ -133,10 +143,13 @@ public class Profile extends Thread { ...@@ -133,10 +143,13 @@ public class Profile extends Thread {
} }
} }
} }
writer.close();
int percent = (100 * unvisited / maxIndex); int percent = (100 * unvisited / maxIndex);
print("Not covered: " + percent + " % " + " (" + unvisited + " of " print("Not covered: " + percent + " % " + " (" + unvisited + " of "
+ maxIndex + "; throw=" + unvisitedthrow + ")"); + maxIndex + "; throw=" + unvisitedthrow + ")");
} finally {
IOUtils.closeSilently(fwriter);
IOUtils.closeSilently(reader);
}
} }
void listTop(String title, int[] list, int max) throws Exception { void listTop(String title, int[] list, int max) throws Exception {
...@@ -171,7 +184,10 @@ public class Profile extends Thread { ...@@ -171,7 +184,10 @@ public class Profile extends Thread {
list[bigIndex] = -(big + 1); list[bigIndex] = -(big + 1);
index[i] = bigIndex; index[i] = bigIndex;
} }
LineNumberReader r = new LineNumberReader(new FileReader("profile.txt")); FileReader reader = null;
try {
reader = new FileReader("profile.txt");
LineNumberReader r = new LineNumberReader(reader);
for (int i = 0; i < maxIndex; i++) { for (int i = 0; i < maxIndex; i++) {
String line = r.readLine(); String line = r.readLine();
int k = list[i]; int k = list[i];
...@@ -189,6 +205,9 @@ public class Profile extends Thread { ...@@ -189,6 +205,9 @@ public class Profile extends Thread {
for (int i = 0; i < max; i++) { for (int i = 0; i < max; i++) {
print(text[i]); print(text[i]);
} }
} finally {
IOUtils.closeSilently(reader);
}
} }
void print(String s) { void print(String s) {
......
...@@ -1725,15 +1725,13 @@ select "PUBLIC".test."ID" from test; ...@@ -1725,15 +1725,13 @@ select "PUBLIC".test."ID" from test;
> -- > --
> rows: 0 > rows: 0
select "PUBLIC"."TEST"."ID" from test; select public."TEST"."ID" from test;
> ID > ID
> -- > --
> rows: 0 > rows: 0
select "public"."TEST"."ID" from test; select "public"."TEST"."ID" from test;
> ID > exception
> --
> rows: 0
drop table test; drop table test;
> ok > ok
......
create schema a;
create table a.test(id int);
insert into a.test values(1);
create schema b;
create table b.test(id int);
insert into b.test values(2);
select a.test.id + b.test.id from a.test, b.test;
> 3;
drop schema a;
drop schema b;
select date '+0011-01-01'; select date '+0011-01-01';
> 0011-01-01; > 0011-01-01;
select date'-0010-01-01'; select date'-0010-01-01';
......
...@@ -18,6 +18,7 @@ import org.h2.bnf.Bnf; ...@@ -18,6 +18,7 @@ import org.h2.bnf.Bnf;
import org.h2.server.web.PageParser; import org.h2.server.web.PageParser;
import org.h2.tools.indexer.Indexer; import org.h2.tools.indexer.Indexer;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
public class GenerateDoc { public class GenerateDoc {
...@@ -80,7 +81,9 @@ public class GenerateDoc { ...@@ -80,7 +81,9 @@ public class GenerateDoc {
} }
void map(String key, String sql) throws Exception { void map(String key, String sql) throws Exception {
ResultSet rs = conn.createStatement().executeQuery(sql); ResultSet rs = null;
try {
rs = conn.createStatement().executeQuery(sql);
ArrayList list = new ArrayList(); ArrayList list = new ArrayList();
while(rs.next()) { while(rs.next()) {
HashMap map = new HashMap(); HashMap map = new HashMap();
...@@ -97,5 +100,8 @@ public class GenerateDoc { ...@@ -97,5 +100,8 @@ public class GenerateDoc {
list.add(map); list.add(map);
} }
session.put(key, list); session.put(key, list);
} finally {
JdbcUtils.closeSilently(rs);
}
} }
} }
...@@ -168,7 +168,7 @@ public class Indexer { ...@@ -168,7 +168,7 @@ public class Indexer {
return; return;
} }
if(!noIndex.contains(fileName)) { if(!noIndex.contains(fileName)) {
page = new Page(pages.size(), fileName, name); page = new Page(pages.size(), fileName);
pages.add(page); pages.add(page);
readPage(file); readPage(file);
} }
......
...@@ -8,16 +8,14 @@ package org.h2.tools.indexer; ...@@ -8,16 +8,14 @@ package org.h2.tools.indexer;
public class Page { public class Page {
int id; int id;
String fileName; String fileName;
String name;
String title; String title;
// TODO page.totalWeight is currently not used // TODO page.totalWeight is currently not used
int totalWeight; int totalWeight;
int relations; int relations;
Page(int id, String fileName, String name) { Page(int id, String fileName) {
this.id = id; this.id = id;
this.fileName = fileName; this.fileName = fileName;
this.name = name;
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论