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

javadocs

上级 1865ce3d
...@@ -17,7 +17,11 @@ Change Log ...@@ -17,7 +17,11 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Linked tables: To view the statements that are executed against the target table, set the trace level to 3. <li>
</li><li>Improved compatibility. New compatibility modes for Oracle and Derby.
New compatibility flag uniqueIndexNullDistinct to only allow one row with 'NULL' in a unique
index. This flag is enabled for Derby, Oracle, MSSQLServer, and HSQLDB.
</li><li>Linked tables: To view the statements that are executed against the target table, set the trace level to 3.
</li><li>RunScript tool: new options to show and check the results of queries. </li><li>RunScript tool: new options to show and check the results of queries.
</li><li>Deadlocks are now detected. One transaction is rolled back automatically. </li><li>Deadlocks are now detected. One transaction is rolled back automatically.
</li><li>The Lucene fulltext index was always re-created when opening a </li><li>The Lucene fulltext index was always re-created when opening a
...@@ -100,7 +104,7 @@ Change Log ...@@ -100,7 +104,7 @@ Change Log
<li>H2 is now dual-licensed under the Eclipse Public License (EPL) and the <li>H2 is now dual-licensed under the Eclipse Public License (EPL) and the
old 'H2 License' (which is basically MPL). old 'H2 License' (which is basically MPL).
</li><li>Sometimes an exception 'File ID mismatch' or 'try to add a record twice' </li><li>Sometimes an exception 'File ID mismatch' or 'try to add a record twice'
occured after large records (8 KB or larger) are updated or deleted. occurred after large records (8 KB or larger) are updated or deleted.
See also http://code.google.com/p/h2database/issues/detail?id=22 See also http://code.google.com/p/h2database/issues/detail?id=22
</li><li>H2 Console: The tools can now be translated </li><li>H2 Console: The tools can now be translated
(it didn't work in the last release). (it didn't work in the last release).
...@@ -194,10 +198,10 @@ Change Log ...@@ -194,10 +198,10 @@ Change Log
</li><li>For years below 1, the YEAR method didn't return the correct value, </li><li>For years below 1, the YEAR method didn't return the correct value,
and the conversion from date and timestamp to varchar was incorrect. and the conversion from date and timestamp to varchar was incorrect.
</li><li>CSVWRITE caused a NullPointerException when not specifying a nullString. </li><li>CSVWRITE caused a NullPointerException when not specifying a nullString.
</li><li>When a log file switch occured just after a truncate table or drop table </li><li>When a log file switch occurred just after a truncate table or drop table
statement, the database could not be started normally (RECOVER=1 statement, the database could not be started normally (RECOVER=1
was required). Fixed. was required). Fixed.
</li><li>When a log file switch occured in the middle of a sequence flush </li><li>When a log file switch occurred in the middle of a sequence flush
(sequences are only flushed every 32 values by default), the sequence (sequences are only flushed every 32 values by default), the sequence
value was lost. Fixed. value was lost. Fixed.
</li><li>Altering a sequence didn't unlock the system table </li><li>Altering a sequence didn't unlock the system table
......
...@@ -99,7 +99,6 @@ via PayPal: ...@@ -99,7 +99,6 @@ via PayPal:
</p> </p>
<ul> <ul>
<li>Florent Ramiere, France <li>Florent Ramiere, France
</li><li>Pete Haidinyak, USA
</li><li>Jun Iyama, Japan </li><li>Jun Iyama, Japan
</li><li>Antonio Casqueiro, Portugal </li><li>Antonio Casqueiro, Portugal
</li><li>Oliver Computing LLC, USA </li><li>Oliver Computing LLC, USA
...@@ -109,6 +108,7 @@ via PayPal: ...@@ -109,6 +108,7 @@ via PayPal:
</li><li>Antonio Dieguez, Chile </li><li>Antonio Dieguez, Chile
</li><li><a href="http://ontologyworks.com/">Ontology Works, USA</a> </li><li><a href="http://ontologyworks.com/">Ontology Works, USA</a>
</li><li>lumber-mill.co.jp, Japan </li><li>lumber-mill.co.jp, Japan
</li><li>Pete Haidinyak, USA
</li></ul> </li></ul>
</div></td></tr></table><!-- analytics --></body></html> </div></td></tr></table><!-- analytics --></body></html>
...@@ -272,11 +272,27 @@ PolePosition</a><br /> ...@@ -272,11 +272,27 @@ PolePosition</a><br />
Open source database benchmark. Open source database benchmark.
</p> </p>
<p><a href="http://poormans.sourceforge.net/index.html">
Poormans</a><br />
Very basic CMS running as a SWT application and generating static html pages.
</p>
<p><a href="http://www.railo-technologies.com">
Railo</a><br />
Railo is an alternative engine for the Cold Fusion Markup Language, that compiles code
programmed in CFML into Java bytecode and executes it on a servlet engine.
</p>
<p><a href="http://patir.rubyforge.org/rutema/index.html"> <p><a href="http://patir.rubyforge.org/rutema/index.html">
Rutema</a><br /> Rutema</a><br />
Rutema is a test execution and management tool for heterogeneous development environments written in Ruby. Rutema is a test execution and management tool for heterogeneous development environments written in Ruby.
</p> </p>
<p><a href="http://scriptella.javaforge.com">
Sava</a><br />
Open-source web-based content management system.
</p>
<p><a href="http://scriptella.javaforge.com"> <p><a href="http://scriptella.javaforge.com">
Scriptella</a><br /> Scriptella</a><br />
ETL (Extract-Transform-Load) and script execution tool. ETL (Extract-Transform-Load) and script execution tool.
......
...@@ -79,7 +79,7 @@ Roadmap ...@@ -79,7 +79,7 @@ Roadmap
</li><li>Test performance again with SQL Server, Oracle, DB2 </li><li>Test performance again with SQL Server, Oracle, DB2
</li><li>Test with dbmonster (http://dbmonster.kernelpanic.pl/) </li><li>Test with dbmonster (http://dbmonster.kernelpanic.pl/)
</li><li>Test with dbcopy (http://dbcopyplugin.sourceforge.net) </li><li>Test with dbcopy (http://dbcopyplugin.sourceforge.net)
</li><li>Find a tool to view a text file >100 MB, with find, page up and down (like less) </li><li>Find a tool to view large text file >100 MB, with find, page up and down (like less), truncate before / after
</li><li>Implement, test, document XAConnection and so on </li><li>Implement, test, document XAConnection and so on
</li><li>Web site: get rid of frame set </li><li>Web site: get rid of frame set
</li><li>Pluggable data type (for compression, validation, conversion, encryption) </li><li>Pluggable data type (for compression, validation, conversion, encryption)
......
...@@ -179,8 +179,8 @@ public abstract class Command implements CommandInterface { ...@@ -179,8 +179,8 @@ public abstract class Command implements CommandInterface {
} }
if (trace.isInfoEnabled()) { if (trace.isInfoEnabled()) {
long time = System.currentTimeMillis() - startTime; long time = System.currentTimeMillis() - startTime;
if (time > Constants.LONG_QUERY_LIMIT_MS) { if (time > Constants.SLOW_QUERY_LIMIT_MS) {
trace.info("long query: " + time); trace.info("slow query: " + time);
} }
} }
} }
......
...@@ -170,7 +170,7 @@ public class ErrorCode { ...@@ -170,7 +170,7 @@ public class ErrorCode {
* to lock a table the first session has locked. As an example, session 1 * to lock a table the first session has locked. As an example, session 1
* has locked table A, while session 2 has locked table B. If session 1 now * has locked table A, while session 2 has locked table B. If session 1 now
* tries to lock table B and session 2 tries to lock table A, a deadlock has * tries to lock table B and session 2 tries to lock table A, a deadlock has
* occured. Deadlocks that involve more than two sessions are also possible. * occurred. Deadlocks that involve more than two sessions are also possible.
* To solve deadlock problems, an application should lock tables always in * To solve deadlock problems, an application should lock tables always in
* the same order, such as always lock table A before locking table B. For * the same order, such as always lock table A before locking table B. For
* details, see <a href="http://en.wikipedia.org/wiki/Deadlock">Wikipedia * details, see <a href="http://en.wikipedia.org/wiki/Deadlock">Wikipedia
...@@ -301,7 +301,7 @@ public class ErrorCode { ...@@ -301,7 +301,7 @@ public class ErrorCode {
/** /**
* The error with code <code>50200</code> is thrown when * The error with code <code>50200</code> is thrown when
* another connection locked an object longer than the lock timeout * another connection locked an object longer than the lock timeout
* set for this connection, or when a deadlock occured. * set for this connection, or when a deadlock occurred.
* Example: * Example:
* <pre> * <pre>
* CREATE TABLE TEST(ID INT); * CREATE TABLE TEST(ID INT);
...@@ -560,7 +560,7 @@ public class ErrorCode { ...@@ -560,7 +560,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90021</code> is thrown when * The error with code <code>90021</code> is thrown when
* trying to convert a value to a data type where the conversion is undefined, * trying to convert a value to a data type where the conversion is undefined,
* or when an error occured trying to convert. * or when an error occurred trying to convert.
* Example: * Example:
* <pre> * <pre>
* CALL CAST(DATE '2001-01-01' AS BOOLEAN); * CALL CAST(DATE '2001-01-01' AS BOOLEAN);
...@@ -599,7 +599,7 @@ public class ErrorCode { ...@@ -599,7 +599,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90025</code> is thrown when * The error with code <code>90025</code> is thrown when
* a file could not be deleted, because it is still in use * a file could not be deleted, because it is still in use
* (only in Windows), or because an error occured when deleting. * (only in Windows), or because an error occurred when deleting.
*/ */
public static final int FILE_DELETE_FAILED_1 = 90025; public static final int FILE_DELETE_FAILED_1 = 90025;
...@@ -617,7 +617,7 @@ public class ErrorCode { ...@@ -617,7 +617,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90028</code> is thrown when * The error with code <code>90028</code> is thrown when
* an input / output error occured. For more information, see the root * an input / output error occurred. For more information, see the root
* cause of the exception. * cause of the exception.
*/ */
public static final int IO_EXCEPTION_1 = 90028; public static final int IO_EXCEPTION_1 = 90028;
...@@ -645,7 +645,7 @@ public class ErrorCode { ...@@ -645,7 +645,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90031</code> is thrown when * The error with code <code>90031</code> is thrown when
* an input / output error occured. For more information, see the root * an input / output error occurred. For more information, see the root
* cause of the exception. * cause of the exception.
*/ */
public static final int IO_EXCEPTION_2 = 90031; public static final int IO_EXCEPTION_2 = 90031;
...@@ -780,7 +780,7 @@ public class ErrorCode { ...@@ -780,7 +780,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90044</code> is thrown when * The error with code <code>90044</code> is thrown when
* an exception or error occured while calling the triggers fire method. * an exception or error occurred while calling the triggers fire method.
* See the root cause for details. * See the root cause for details.
*/ */
public static final int ERROR_EXECUTING_TRIGGER_3 = 90044; public static final int ERROR_EXECUTING_TRIGGER_3 = 90044;
...@@ -1398,7 +1398,7 @@ public class ErrorCode { ...@@ -1398,7 +1398,7 @@ public class ErrorCode {
public static final int SIMULATED_POWER_OFF = 90098; public static final int SIMULATED_POWER_OFF = 90098;
/** /**
* The error with code <code>90099</code> is thrown when an error occured * The error with code <code>90099</code> is thrown when an error occurred
* trying to initialize the database event listener. Example: * trying to initialize the database event listener. Example:
* <pre> * <pre>
* jdbc:h2:&tilde;/test;DATABASE_EVENT_LISTENER='java.lang.String' * jdbc:h2:&tilde;/test;DATABASE_EVENT_LISTENER='java.lang.String'
...@@ -1457,7 +1457,7 @@ public class ErrorCode { ...@@ -1457,7 +1457,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90105</code> is thrown when * The error with code <code>90105</code> is thrown when
* an exception occured in a user-defined method. * an exception occurred in a user-defined method.
* Example: * Example:
* <pre> * <pre>
* CREATE ALIAS SYS_PROP FOR "java.lang.System.getProperty"; * CREATE ALIAS SYS_PROP FOR "java.lang.System.getProperty";
...@@ -1513,7 +1513,7 @@ public class ErrorCode { ...@@ -1513,7 +1513,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90111</code> is thrown when * The error with code <code>90111</code> is thrown when
* an exception occured while accessing a linked table. * an exception occurred while accessing a linked table.
*/ */
public static final int ERROR_ACCESSING_LINKED_TABLE_2 = 90111; public static final int ERROR_ACCESSING_LINKED_TABLE_2 = 90111;
......
...@@ -358,12 +358,6 @@ public class Constants { ...@@ -358,12 +358,6 @@ public class Constants {
* the largest file (data file or index file). * the largest file (data file or index file).
*/ */
public static final long LOG_SIZE_DIVIDER = 10; public static final long LOG_SIZE_DIVIDER = 10;
/**
* Queries that take longer than this number of milliseconds are written to
* the trace file with the level info.
*/
public static final long LONG_QUERY_LIMIT_MS = 100;
/** /**
* The file header used for binary files. * The file header used for binary files.
...@@ -468,6 +462,12 @@ public class Constants { ...@@ -468,6 +462,12 @@ public class Constants {
*/ */
public static final String SERVER_PROPERTIES_TITLE = "H2 Server Properties"; public static final String SERVER_PROPERTIES_TITLE = "H2 Server Properties";
/**
* Queries that take longer than this number of milliseconds are written to
* the trace file with the level info.
*/
public static final long SLOW_QUERY_LIMIT_MS = 100;
/** /**
* The file name suffix of data files. * The file name suffix of data files.
*/ */
......
...@@ -1687,7 +1687,7 @@ public class Database implements DataHandler { ...@@ -1687,7 +1687,7 @@ public class Database implements DataHandler {
} }
/** /**
* This method is called after an exception occured, to inform the database * This method is called after an exception occurred, to inform the database
* event listener (if one is set). * event listener (if one is set).
* *
* @param e the exception * @param e the exception
......
...@@ -31,6 +31,13 @@ public class Mode { ...@@ -31,6 +31,13 @@ public class Mode {
public boolean indexDefinitionInCreateTable; public boolean indexDefinitionInCreateTable;
public boolean systemColumns; public boolean systemColumns;
public boolean squareBracketQuotedNames; public boolean squareBracketQuotedNames;
/**
* When using unique indexes, multiple rows with NULL in one of the columns
* are allowed by default. However many databases view NULL as distinct in
* this regard and only allow one row with NULL.
*/
public boolean uniqueIndexSingleNull;
private String name; private String name;
...@@ -54,10 +61,20 @@ public class Mode { ...@@ -54,10 +61,20 @@ public class Mode {
mode = new Mode("HSQLDB"); mode = new Mode("HSQLDB");
mode.nullConcatIsNull = true; mode.nullConcatIsNull = true;
mode.convertOnlyToSmallerScale = true; mode.convertOnlyToSmallerScale = true;
mode.uniqueIndexSingleNull = true;
add(mode); add(mode);
mode = new Mode("MSSQLServer"); mode = new Mode("MSSQLServer");
mode.squareBracketQuotedNames = true; mode.squareBracketQuotedNames = true;
mode.uniqueIndexSingleNull = true;
add(mode);
mode = new Mode("Derby");
mode.uniqueIndexSingleNull = true;
add(mode);
mode = new Mode("Oracle");
mode.uniqueIndexSingleNull = true;
add(mode); add(mode);
} }
......
...@@ -237,7 +237,10 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -237,7 +237,10 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
return 0; return 0;
} }
public boolean isNull(Row newRow) { public boolean containsNullAndAllowMultipleNull(Session session, Row newRow) {
if (session.getDatabase().getMode().uniqueIndexSingleNull) {
return false;
}
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
int index = columnIds[i]; int index = columnIds[i];
Value v = newRow.getValue(index); Value v = newRow.getValue(index);
......
...@@ -63,7 +63,7 @@ public class BtreeLeaf extends BtreePage { ...@@ -63,7 +63,7 @@ public class BtreeLeaf extends BtreePage {
int comp = index.compareRows(row, newRow); int comp = index.compareRows(row, newRow);
if (comp == 0) { if (comp == 0) {
if (index.indexType.getUnique()) { if (index.indexType.getUnique()) {
if (!index.isNull(newRow)) { if (!index.containsNullAndAllowMultipleNull(session, newRow)) {
throw index.getDuplicateKeyException(); throw index.getDuplicateKeyException();
} }
} }
......
...@@ -83,7 +83,7 @@ public class BtreeNode extends BtreePage { ...@@ -83,7 +83,7 @@ public class BtreeNode extends BtreePage {
int comp = index.compareRows(row, newRow); int comp = index.compareRows(row, newRow);
if (comp == 0) { if (comp == 0) {
if (index.indexType.getUnique()) { if (index.indexType.getUnique()) {
if (!index.isNull(newRow)) { if (!index.containsNullAndAllowMultipleNull(session, newRow)) {
throw index.getDuplicateKeyException(); throw index.getDuplicateKeyException();
} }
} }
......
...@@ -179,12 +179,15 @@ public interface Index extends SchemaObject { ...@@ -179,12 +179,15 @@ public interface Index extends SchemaObject {
int compareRows(SearchRow rowData, SearchRow compare) throws SQLException; int compareRows(SearchRow rowData, SearchRow compare) throws SQLException;
/** /**
* Check if a row is NULL. * Check if one of the columns is NULL and multiple rows with NULL are
* * allowed using the current compatibility mode for unique indexes. Note:
* NULL behavior is complicated in SQL.
*
* @param newRow * @param newRow
* @return if it is null * @return true if one of the columns is null and multiple nulls in unique
* indexes are allowed
*/ */
boolean isNull(Row newRow); boolean containsNullAndAllowMultipleNull(Session session, Row newRow);
/** /**
* Compare the positions of two rows. * Compare the positions of two rows.
......
...@@ -237,8 +237,8 @@ public class MultiVersionIndex implements Index { ...@@ -237,8 +237,8 @@ public class MultiVersionIndex implements Index {
return base.getType(); return base.getType();
} }
public boolean isNull(Row newRow) { public boolean containsNullAndAllowMultipleNull(Session session, Row newRow) {
return base.isNull(newRow); return base.containsNullAndAllowMultipleNull(session, newRow);
} }
public void removeChildrenAndResources(Session session) throws SQLException { public void removeChildrenAndResources(Session session) throws SQLException {
......
...@@ -53,7 +53,7 @@ public class TreeIndex extends BaseIndex { ...@@ -53,7 +53,7 @@ public class TreeIndex extends BaseIndex {
int compare = compareRows(row, r); int compare = compareRows(row, r);
if (compare == 0) { if (compare == 0) {
if (indexType.getUnique()) { if (indexType.getUnique()) {
if (!isNull(row)) { if (!containsNullAndAllowMultipleNull(session, row)) {
throw getDuplicateKeyException(); throw getDuplicateKeyException();
} }
} }
......
...@@ -170,7 +170,7 @@ public class JdbcConnectionPool implements DataSource { ...@@ -170,7 +170,7 @@ public class JdbcConnectionPool implements DataSource {
* *
* @return a new Connection object. * @return a new Connection object.
* @throws SQLException when a new connection could not be established, * @throws SQLException when a new connection could not be established,
* or a timeout occured * or a timeout occurred
*/ */
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
for (int i = 0;; i++) { for (int i = 0;; i++) {
......
...@@ -52,10 +52,10 @@ public interface DataHandler { ...@@ -52,10 +52,10 @@ public interface DataHandler {
int getChecksum(byte[] data, int start, int end); int getChecksum(byte[] data, int start, int end);
/** /**
* Check if the simulated power failure occured. * Check if the simulated power failure occurred.
* This call will decrement the countdown. * This call will decrement the countdown.
* *
* @throws SQLException if the simulated power failure occured * @throws SQLException if the simulated power failure occurred
*/ */
void checkPowerOff() throws SQLException; void checkPowerOff() throws SQLException;
......
...@@ -105,7 +105,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -105,7 +105,7 @@ public abstract class Table extends SchemaObjectBase {
* @param session the session * @param session the session
* @param exclusive true for write locks, false for read locks * @param exclusive true for write locks, false for read locks
* @param force lock even in the MVCC mode * @param force lock even in the MVCC mode
* @throws SQLException if a lock timeout occured * @throws SQLException if a lock timeout occurred
*/ */
public abstract void lock(Session session, boolean exclusive, boolean force) throws SQLException; public abstract void lock(Session session, boolean exclusive, boolean force) throws SQLException;
...@@ -871,7 +871,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -871,7 +871,7 @@ public abstract class Table extends SchemaObjectBase {
} }
/** /**
* Check if a deadlock occured. This method is called recursively. There is * Check if a deadlock occurred. This method is called recursively. There is
* a circle if the session to be tested for is the same as the originating * a circle if the session to be tested for is the same as the originating
* session (the 'clash session'). In this case the method must return an * session (the 'clash session'). In this case the method must return an
* empty object array. Once a deadlock has been detected, the methods must * empty object array. Once a deadlock has been detected, the methods must
......
...@@ -61,7 +61,7 @@ public class IOUtils { ...@@ -61,7 +61,7 @@ public class IOUtils {
* @param skip the number of bytes to skip * @param skip the number of bytes to skip
* @throws EOFException if the end of file has been reached before all bytes * @throws EOFException if the end of file has been reached before all bytes
* could be skipped * could be skipped
* @throws IOException if an IO exception occured while skipping * @throws IOException if an IO exception occurred while skipping
*/ */
public static void skipFully(InputStream in, long skip) throws IOException { public static void skipFully(InputStream in, long skip) throws IOException {
while (skip > 0) { while (skip > 0) {
...@@ -80,7 +80,7 @@ public class IOUtils { ...@@ -80,7 +80,7 @@ public class IOUtils {
* @param skip the number of characters to skip * @param skip the number of characters to skip
* @throws EOFException if the end of file has been reached before all * @throws EOFException if the end of file has been reached before all
* characters could be skipped * characters could be skipped
* @throws IOException if an IO exception occured while skipping * @throws IOException if an IO exception occurred while skipping
*/ */
public static void skipFully(Reader reader, long skip) throws IOException { public static void skipFully(Reader reader, long skip) throws IOException {
while (skip > 0) { while (skip > 0) {
......
...@@ -18,7 +18,7 @@ public interface JdbcConnectionListener { ...@@ -18,7 +18,7 @@ public interface JdbcConnectionListener {
// TODO pooled connection: make sure // TODO pooled connection: make sure
// fatalErrorOccurred is called in the right situations // fatalErrorOccurred is called in the right situations
/** /**
* A fatal error occured. * A fatal error occurred.
* *
* @param conn the connection * @param conn the connection
* @param e the exception * @param e the exception
......
...@@ -575,8 +575,8 @@ public class DataType { ...@@ -575,8 +575,8 @@ public class DataType {
/** /**
* Convert a SQL type to a value type. * Convert a SQL type to a value type.
* *
* @param the SQL type * @param sqlType the SQL type
* @return type the value type * @return the value type
*/ */
public static int convertSQLTypeToValueType(int sqlType) throws SQLException { public static int convertSQLTypeToValueType(int sqlType) throws SQLException {
switch(sqlType) { switch(sqlType) {
......
...@@ -133,8 +133,8 @@ public class Transfer { ...@@ -133,8 +133,8 @@ public class Transfer {
* @param x the value * @param x the value
* @return itself * @return itself
*/ */
public Transfer writeInt(int i) throws IOException { public Transfer writeInt(int x) throws IOException {
out.writeInt(i); out.writeInt(x);
return this; return this;
} }
...@@ -153,8 +153,8 @@ public class Transfer { ...@@ -153,8 +153,8 @@ public class Transfer {
* @param x the value * @param x the value
* @return itself * @return itself
*/ */
public Transfer writeLong(long i) throws IOException { public Transfer writeLong(long x) throws IOException {
out.writeLong(i); out.writeLong(x);
return this; return this;
} }
......
...@@ -102,7 +102,7 @@ INSERT INTO ITEM VALUES(41, ...@@ -102,7 +102,7 @@ INSERT INTO ITEM VALUES(41,
</li></ul> </li></ul>
<b>Bugfixes:</b> <b>Bugfixes:</b>
<ul><li>Sometimes an exception ''File ID mismatch'' or ''try to add a record twice'' <ul><li>Sometimes an exception ''File ID mismatch'' or ''try to add a record twice''
occured after large records (8 KB or larger) are updated or deleted. occurred after large records (8 KB or larger) are updated or deleted.
See also http://code.google.com/p/h2database/issues/detail?id=22 See also http://code.google.com/p/h2database/issues/detail?id=22
</li><li>H2 Console: The tools can now be translated </li><li>H2 Console: The tools can now be translated
(it didn''t work in the last release). (it didn''t work in the last release).
...@@ -186,7 +186,7 @@ INSERT INTO ITEM VALUES(39, ...@@ -186,7 +186,7 @@ INSERT INTO ITEM VALUES(39,
</li><li>TRACE_LEVEL_ settings are no longer persistent. </li><li>TRACE_LEVEL_ settings are no longer persistent.
</li></ul> </li></ul>
<b>Bugfixes:</b> <b>Bugfixes:</b>
<ul><li>When a log file switch occured in the middle of certain operations, <ul><li>When a log file switch occurred in the middle of certain operations,
the database could not be started normally (RECOVER=1 was required). the database could not be started normally (RECOVER=1 was required).
</li><li>Altering a sequence didn''t unlock the system table with autocommit disabled. </li><li>Altering a sequence didn''t unlock the system table with autocommit disabled.
</li><li>CSVWRITE caused a NullPointerException when not specifying a nullString. </li><li>CSVWRITE caused a NullPointerException when not specifying a nullString.
......
...@@ -593,7 +593,7 @@ Roadmap: ...@@ -593,7 +593,7 @@ Roadmap:
} }
} }
public void beforeTest() throws SQLException { void beforeTest() throws SQLException {
DeleteDbFiles.execute(TestBase.baseDir, null, true); DeleteDbFiles.execute(TestBase.baseDir, null, true);
FileSystemDisk.getInstance().deleteRecursive("trace.db"); FileSystemDisk.getInstance().deleteRecursive("trace.db");
if (networked) { if (networked) {
...@@ -609,7 +609,7 @@ Roadmap: ...@@ -609,7 +609,7 @@ Roadmap:
} }
} }
public void afterTest() throws SQLException { private void afterTest() throws SQLException {
FileSystemDisk.getInstance().deleteRecursive("trace.db"); FileSystemDisk.getInstance().deleteRecursive("trace.db");
if (networked && server != null) { if (networked && server != null) {
server.stop(); server.stop();
......
...@@ -37,8 +37,11 @@ public abstract class TestBase { ...@@ -37,8 +37,11 @@ public abstract class TestBase {
protected TestAll config; protected TestAll config;
private long start; private long start;
// private static final String BASE_TEST_DIR = /**
// System.getProperty("java.io.tmpdir") + "/h2"; * Get the test directory for this test.
*
* @param name the directory name suffix
*/
public static String getTestDir(String name) { public static String getTestDir(String name) {
return BASE_TEST_DIR + "/test" + name; return BASE_TEST_DIR + "/test" + name;
} }
...@@ -47,6 +50,12 @@ public abstract class TestBase { ...@@ -47,6 +50,12 @@ public abstract class TestBase {
config.beforeTest(); config.beforeTest();
} }
/**
* Initialize the test configuration.
*
* @param conf the configuration
* @return itself
*/
public TestBase init(TestAll conf) throws Exception { public TestBase init(TestAll conf) throws Exception {
baseDir = getTestDir(""); baseDir = getTestDir("");
this.config = conf; this.config = conf;
...@@ -62,6 +71,13 @@ public abstract class TestBase { ...@@ -62,6 +71,13 @@ public abstract class TestBase {
// do nothing // do nothing
} }
/**
* This method is initializes the test, runs the test by calling the test()
* method, and prints status information. It also catches exceptions so that
* the tests can continue.
*
* @param conf the test configuration
*/
public void runTest(TestAll conf) { public void runTest(TestAll conf) {
try { try {
init(conf); init(conf);
...@@ -77,10 +93,25 @@ public abstract class TestBase { ...@@ -77,10 +93,25 @@ public abstract class TestBase {
} }
} }
/**
* Open a database connection in admin mode. The default user name and
* password is used.
*
* @param name the database name
* @return the connection
*/
public Connection getConnection(String name) throws Exception { public Connection getConnection(String name) throws Exception {
return getConnectionInternal(getURL(name, true), getUser(), getPassword()); return getConnectionInternal(getURL(name, true), getUser(), getPassword());
} }
/**
* Open a database connection.
*
* @param name the database name
* @param user the user name to use
* @param password the password to use
* @return the connection
*/
protected Connection getConnection(String name, String user, String password) throws Exception { protected Connection getConnection(String name, String user, String password) throws Exception {
return getConnectionInternal(getURL(name, false), user, password); return getConnectionInternal(getURL(name, false), user, password);
} }
...@@ -194,6 +225,11 @@ public abstract class TestBase { ...@@ -194,6 +225,11 @@ public abstract class TestBase {
trace("" + x); trace("" + x);
} }
/**
* Write a message to system out if trace is enabled.
*
* @param s the message to write
*/
public void trace(String s) { public void trace(String s) {
if (config.traceTest) { if (config.traceTest) {
println(s); println(s);
...@@ -206,6 +242,13 @@ public abstract class TestBase { ...@@ -206,6 +242,13 @@ public abstract class TestBase {
} }
} }
/**
* Print the currently used memory, the message and the given time in
* milliseconds.
*
* @param s the message
* @param time the time in millis
*/
public void printTimeMemory(String s, long time) { public void printTimeMemory(String s, long time) {
if (config.big) { if (config.big) {
println(getMemoryUsed() + " MB: " + s + " ms: " + time); println(getMemoryUsed() + " MB: " + s + " ms: " + time);
...@@ -236,6 +279,12 @@ public abstract class TestBase { ...@@ -236,6 +279,12 @@ public abstract class TestBase {
throw new Exception(string); throw new Exception(string);
} }
/**
* Log an error message.
*
* @param s the message
* @param e the exception
*/
public static void logError(String s, Throwable e) { public static void logError(String s, Throwable e) {
if (e == null) { if (e == null) {
e = new Exception(s); e = new Exception(s);
...@@ -281,14 +330,34 @@ public abstract class TestBase { ...@@ -281,14 +330,34 @@ public abstract class TestBase {
DeleteDbFiles.execute(dir, name, true); DeleteDbFiles.execute(dir, name, true);
} }
/**
* This method will be called by the test framework.
*
* @throws Exception if an exception in the test occurs
*/
public abstract void test() throws Exception; public abstract void test() throws Exception;
/**
* Check if two values are equal, and if not throw an exception.
*
* @param message the message to print in case of error
* @param expected the expected value
* @param actual the actual value
* @throws Exception if the values are not equal
*/
public void assertEquals(String message, int expected, int actual) throws Exception { public void assertEquals(String message, int expected, int actual) throws Exception {
if (expected != actual) { if (expected != actual) {
fail("Expected: " + expected + " actual: " + actual + " message: " + message); fail("Expected: " + expected + " actual: " + actual + " message: " + message);
} }
} }
/**
* Check if two values are equal, and if not throw an exception.
*
* @param expected the expected value
* @param actual the actual value
* @throws Exception if the values are not equal
*/
public void assertEquals(int expected, int actual) throws Exception { public void assertEquals(int expected, int actual) throws Exception {
if (expected != actual) { if (expected != actual) {
fail("Expected: " + expected + " actual: " + actual); fail("Expected: " + expected + " actual: " + actual);
......
...@@ -55,19 +55,19 @@ public class Coverage { ...@@ -55,19 +55,19 @@ public class Coverage {
* *
* @param args the command line parameters * @param args the command line parameters
*/ */
public static void main(String[] arg) { public static void main(String[] args) {
new Coverage().run(arg); new Coverage().run(args);
} }
void run(String[] arg) { void run(String[] args) {
if (arg.length == 0 || arg[0].equals("-?")) { if (args.length == 0 || args[0].equals("-?")) {
printUsage(); printUsage();
return; return;
} }
Coverage c = new Coverage(); Coverage c = new Coverage();
int recurse = 1; int recurse = 1;
for (int i = 0; i < arg.length; i++) { for (int i = 0; i < args.length; i++) {
String s = arg[i]; String s = args[i];
if (s.equals("-r")) { if (s.equals("-r")) {
// maximum recurse is 100 subdirectories, that should be enough // maximum recurse is 100 subdirectories, that should be enough
recurse = 100; recurse = 100;
...@@ -76,7 +76,7 @@ public class Coverage { ...@@ -76,7 +76,7 @@ public class Coverage {
} else if (s.equals("-f")) { } else if (s.equals("-f")) {
c.perFunction = true; c.perFunction = true;
} else if (s.equals("-e")) { } else if (s.equals("-e")) {
c.addExclude(arg[++i]); c.addExclude(args[++i]);
} else { } else {
c.addDir(s, recurse); c.addDir(s, recurse);
} }
......
...@@ -39,6 +39,15 @@ public class Db { ...@@ -39,6 +39,15 @@ public class Db {
} }
} }
/**
* Open the database connection. For most databases, it is not required to
* load the driver before calling this method.
*
* @param url the database URL
* @param user the user name
* @param password the password
* @return the database
*/
public static Db open(String url, String user, String password) { public static Db open(String url, String user, String password) {
try { try {
JdbcDriverUtils.load(url); JdbcDriverUtils.load(url);
...@@ -48,6 +57,12 @@ public class Db { ...@@ -48,6 +57,12 @@ public class Db {
} }
} }
/**
* Prepare a SQL statement.
*
* @param sql the SQL statement
* @return the prepared statement
*/
public Prepared prepare(String sql) { public Prepared prepare(String sql) {
try { try {
PreparedStatement prep = (PreparedStatement) prepared.get(sql); PreparedStatement prep = (PreparedStatement) prepared.get(sql);
...@@ -61,6 +76,11 @@ public class Db { ...@@ -61,6 +76,11 @@ public class Db {
} }
} }
/**
* Execute a SQL statement.
*
* @param sql the SQL statement
*/
public void execute(String sql) { public void execute(String sql) {
try { try {
stat.execute(sql); stat.execute(sql);
...@@ -69,6 +89,9 @@ public class Db { ...@@ -69,6 +89,9 @@ public class Db {
} }
} }
/**
* Close the database connection.
*/
public void close() { public void close() {
try { try {
conn.close(); conn.close();
...@@ -88,6 +111,11 @@ public class Db { ...@@ -88,6 +111,11 @@ public class Db {
this.prep = prep; this.prep = prep;
} }
/**
* Set the value of the current parameter.
*
* @param x the value
*/
public Prepared set(int x) { public Prepared set(int x) {
try { try {
prep.setInt(++index, x); prep.setInt(++index, x);
...@@ -97,6 +125,11 @@ public class Db { ...@@ -97,6 +125,11 @@ public class Db {
} }
} }
/**
* Set the value of the current parameter.
*
* @param x the value
*/
public Prepared set(String x) { public Prepared set(String x) {
try { try {
prep.setString(++index, x); prep.setString(++index, x);
...@@ -106,6 +139,11 @@ public class Db { ...@@ -106,6 +139,11 @@ public class Db {
} }
} }
/**
* Set the value of the current parameter.
*
* @param x the value
*/
public Prepared set(byte[] x) { public Prepared set(byte[] x) {
try { try {
prep.setBytes(++index, x); prep.setBytes(++index, x);
...@@ -115,6 +153,11 @@ public class Db { ...@@ -115,6 +153,11 @@ public class Db {
} }
} }
/**
* Set the value of the current parameter.
*
* @param x the value
*/
public Prepared set(InputStream x) { public Prepared set(InputStream x) {
try { try {
prep.setBinaryStream(++index, x, -1); prep.setBinaryStream(++index, x, -1);
...@@ -124,6 +167,9 @@ public class Db { ...@@ -124,6 +167,9 @@ public class Db {
} }
} }
/**
* Execute the prepared statement.
*/
public void execute() { public void execute() {
try { try {
prep.execute(); prep.execute();
...@@ -145,6 +191,9 @@ public class Db { ...@@ -145,6 +191,9 @@ public class Db {
} }
} }
/**
* Commit a pending transaction.
*/
public void commit() { public void commit() {
try { try {
conn.commit(); conn.commit();
......
...@@ -8,6 +8,7 @@ package org.h2.test.db; ...@@ -8,6 +8,7 @@ package org.h2.test.db;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -23,12 +24,32 @@ public class TestCompatibility extends TestBase { ...@@ -23,12 +24,32 @@ public class TestCompatibility extends TestBase {
deleteDb("compatibility"); deleteDb("compatibility");
conn = getConnection("compatibility"); conn = getConnection("compatibility");
testUniqueIndexSingleNull();
testHsqlDb(); testHsqlDb();
testMySQL(); testMySQL();
conn.close(); conn.close();
} }
private void testUniqueIndexSingleNull() throws Exception {
Statement stat = conn.createStatement();
String[] modes = new String[] { "PostgreSQL", "MySQL", "HSQLDB", "MSSQLServer", "Derby", "Oracle", "Regular" };
String multiNull = "PostgreSQL,MySQL,Regular";
for (int i = 0; i < modes.length; i++) {
String mode = modes[i];
stat.execute("SET MODE " + mode);
stat.execute("CREATE TABLE TEST(ID INT)");
stat.execute("CREATE UNIQUE INDEX IDX_ID_U ON TEST(ID)");
try {
stat.execute("INSERT INTO TEST VALUES(1), (2), (NULL), (NULL)");
assertTrue(mode + " mode should not support multiple NULL", multiNull.indexOf(mode) >= 0);
} catch (SQLException e) {
assertTrue(mode + " mode should support multiple NULL", multiNull.indexOf(mode) < 0);
}
stat.execute("DROP TABLE TEST");
}
}
private void testHsqlDb() throws Exception { private void testHsqlDb() throws Exception {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
...@@ -120,31 +120,52 @@ public class TestFunctionOverload extends TestBase { ...@@ -120,31 +120,52 @@ public class TestFunctionOverload extends TestBase {
stat.close(); stat.close();
} }
/**
* This method is called via reflection from the database.
*/
public static int overload0() { public static int overload0() {
return 0; return 0;
} }
/**
* This method is called via reflection from the database.
*/
public static int overload1or2(int one) { public static int overload1or2(int one) {
return one; return one;
} }
/**
* This method is called via reflection from the database.
*/
public static int overload1or2(int one, int two) { public static int overload1or2(int one, int two) {
return one + two; return one + two;
} }
/**
* This method is called via reflection from the database.
*/
public static int overload1or2WithConn(Connection conn, int one) throws SQLException { public static int overload1or2WithConn(Connection conn, int one) throws SQLException {
conn.createStatement().executeQuery("select 1 from dual"); conn.createStatement().executeQuery("select 1 from dual");
return one; return one;
} }
/**
* This method is called via reflection from the database.
*/
public static int overload1or2WithConn(int one, int two) { public static int overload1or2WithConn(int one, int two) {
return one + two; return one + two;
} }
/**
* This method is called via reflection from the database.
*/
public static int overloadError(int one, int two) { public static int overloadError(int one, int two) {
return one + two; return one + two;
} }
/**
* This method is called via reflection from the database.
*/
public static int overloadError(double one, double two) { public static int overloadError(double one, double two) {
return (int) (one + two); return (int) (one + two);
} }
......
...@@ -269,6 +269,9 @@ public class TestFunctions extends TestBase { ...@@ -269,6 +269,9 @@ public class TestFunctions extends TestBase {
assertEquals(value, s); assertEquals(value, s);
} }
/**
* This method is called via reflection from the database.
*/
public static BufferedInputStream blob2stream(Blob value) throws SQLException { public static BufferedInputStream blob2stream(Blob value) throws SQLException {
if (value == null) { if (value == null) {
return null; return null;
...@@ -277,6 +280,9 @@ public class TestFunctions extends TestBase { ...@@ -277,6 +280,9 @@ public class TestFunctions extends TestBase {
return bufferedInStream; return bufferedInStream;
} }
/**
* This method is called via reflection from the database.
*/
public static BufferedInputStream stream2stream(InputStream value) { public static BufferedInputStream stream2stream(InputStream value) {
if (value == null) { if (value == null) {
return null; return null;
...@@ -285,6 +291,9 @@ public class TestFunctions extends TestBase { ...@@ -285,6 +291,9 @@ public class TestFunctions extends TestBase {
return bufferedInStream; return bufferedInStream;
} }
/**
* This method is called via reflection from the database.
*/
public static int addRow(Connection conn, int id, String name) throws SQLException { public static int addRow(Connection conn, int id, String name) throws SQLException {
conn.createStatement().execute("INSERT INTO TEST VALUES(" + id + ", '" + name + "')"); conn.createStatement().execute("INSERT INTO TEST VALUES(" + id + ", '" + name + "')");
ResultSet rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM TEST"); ResultSet rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM TEST");
...@@ -294,19 +303,31 @@ public class TestFunctions extends TestBase { ...@@ -294,19 +303,31 @@ public class TestFunctions extends TestBase {
return result; return result;
} }
/**
* This method is called via reflection from the database.
*/
public static ResultSet select(Connection conn, String sql) throws SQLException { public static ResultSet select(Connection conn, String sql) throws SQLException {
Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
return stat.executeQuery(sql); return stat.executeQuery(sql);
} }
/**
* This method is called via reflection from the database.
*/
public static ResultSet selectMaxId(Connection conn) throws SQLException { public static ResultSet selectMaxId(Connection conn) throws SQLException {
return conn.createStatement().executeQuery("SELECT MAX(ID) FROM TEST"); return conn.createStatement().executeQuery("SELECT MAX(ID) FROM TEST");
} }
/**
* This method is called via reflection from the database.
*/
public static Object[] getArray() { public static Object[] getArray() {
return new Object[] { new Integer(0), "Hello" }; return new Object[] { new Integer(0), "Hello" };
} }
/**
* This method is called via reflection from the database.
*/
public static ResultSet nullResultSet(Connection conn) throws SQLException { public static ResultSet nullResultSet(Connection conn) throws SQLException {
PreparedStatement statement = conn.prepareStatement("select null from system_range(1,1)"); PreparedStatement statement = conn.prepareStatement("select null from system_range(1,1)");
return statement.executeQuery(); return statement.executeQuery();
...@@ -349,6 +370,9 @@ public class TestFunctions extends TestBase { ...@@ -349,6 +370,9 @@ public class TestFunctions extends TestBase {
return rs; return rs;
} }
/**
* This method is called via reflection from the database.
*/
public static int root(int value) { public static int root(int value) {
if (value < 0) { if (value < 0) {
TestBase.logError("function called but should not", null); TestBase.logError("function called but should not", null);
......
...@@ -131,6 +131,14 @@ public class TestMultiDimension extends TestBase { ...@@ -131,6 +131,14 @@ public class TestMultiDimension extends TestBase {
conn.close(); conn.close();
} }
/**
* This method is called via reflection from the database.
*
* @param x the x value
* @param y the y value
* @param z the z value
* @return the bit-interleaved value
*/
public static long interleave(int x, int y, int z) { public static long interleave(int x, int y, int z) {
return MultiDimension.getInstance().interleave(new int[] { x, y, z }); return MultiDimension.getInstance().interleave(new int[] { x, y, z });
} }
......
...@@ -24,7 +24,13 @@ public class TestOpenClose extends TestBase implements DatabaseEventListener { ...@@ -24,7 +24,13 @@ public class TestOpenClose extends TestBase implements DatabaseEventListener {
int nextId = 10; int nextId = 10;
public static void main(String[] a) throws Exception { /**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception {
new TestOpenClose().test(); new TestOpenClose().test();
} }
......
...@@ -65,7 +65,7 @@ public class TestRights extends TestBase { ...@@ -65,7 +65,7 @@ public class TestRights extends TestBase {
conn.close(); conn.close();
} }
public void testSchemaRenameUser() throws Exception { void testSchemaRenameUser() throws Exception {
if (config.memory) { if (config.memory) {
return; return;
} }
...@@ -98,7 +98,7 @@ public class TestRights extends TestBase { ...@@ -98,7 +98,7 @@ public class TestRights extends TestBase {
conn.close(); conn.close();
} }
public void testAccessRights() throws Exception { void testAccessRights() throws Exception {
if (config.memory) { if (config.memory) {
return; return;
} }
...@@ -246,7 +246,7 @@ public class TestRights extends TestBase { ...@@ -246,7 +246,7 @@ public class TestRights extends TestBase {
executeSuccess("DROP TABLE TEST"); executeSuccess("DROP TABLE TEST");
} }
public void executeError(String sql) throws Exception { void executeError(String sql) throws Exception {
try { try {
stat.execute(sql); stat.execute(sql);
fail("not admin"); fail("not admin");
...@@ -255,7 +255,7 @@ public class TestRights extends TestBase { ...@@ -255,7 +255,7 @@ public class TestRights extends TestBase {
} }
} }
public void executeSuccess(String sql) throws Exception { void executeSuccess(String sql) throws Exception {
if (stat.execute(sql)) { if (stat.execute(sql)) {
ResultSet rs = stat.getResultSet(); ResultSet rs = stat.getResultSet();
......
...@@ -23,6 +23,12 @@ public class TestRunscript extends TestBase implements Trigger { ...@@ -23,6 +23,12 @@ public class TestRunscript extends TestBase implements Trigger {
test(true); test(true);
} }
/**
* This method is called via reflection from the database.
*
* @param a the value
* @return the absolute value
*/
public static int test(int a) { public static int test(int a) {
return Math.abs(a); return Math.abs(a);
} }
......
...@@ -153,6 +153,9 @@ public class TestCancel extends TestBase { ...@@ -153,6 +153,9 @@ public class TestCancel extends TestBase {
} }
} }
/**
* This method is called via reflection from the database.
*/
public static int visit(int x) { public static int visit(int x) {
lastVisited = x; lastVisited = x;
return x; return x;
......
...@@ -84,6 +84,11 @@ public class TestXid implements Xid { ...@@ -84,6 +84,11 @@ public class TestXid implements Xid {
} }
} }
/**
* This method is called when executing this application.
*
* @param args the command line parameters
*/
public static void main(String[] args) { public static void main(String[] args) {
new TestXid(); new TestXid();
} }
......
...@@ -19,6 +19,12 @@ public class Listener implements Runnable { ...@@ -19,6 +19,12 @@ public class Listener implements Runnable {
volatile int maxValue; volatile int maxValue;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new Listener().test(args); new Listener().test(args);
} }
......
...@@ -85,6 +85,12 @@ public class Test { ...@@ -85,6 +85,12 @@ public class Test {
} }
} }
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new Test().test(args); new Test().test(args);
} }
......
...@@ -56,6 +56,12 @@ public class TestRecover { ...@@ -56,6 +56,12 @@ public class TestRecover {
// System.getProperty("test.driver", // System.getProperty("test.driver",
// "org.apache.derby.jdbc.EmbeddedDriver"); // "org.apache.derby.jdbc.EmbeddedDriver");
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new TestRecover().runTest(); new TestRecover().runTest();
} }
......
...@@ -25,6 +25,12 @@ public class TestWrite { ...@@ -25,6 +25,12 @@ public class TestWrite {
// utility class // utility class
} }
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
testFile("rw", false); testFile("rw", false);
testFile("rwd", false); testFile("rwd", false);
......
...@@ -49,7 +49,7 @@ public class WebClient { ...@@ -49,7 +49,7 @@ public class WebClient {
this.sessionId = id; this.sessionId = id;
} }
public String get(String url, String page) throws IOException { String get(String url, String page) throws IOException {
if (sessionId != null) { if (sessionId != null) {
if (page.indexOf('?') < 0) { if (page.indexOf('?') < 0) {
page += "?"; page += "?";
......
...@@ -44,7 +44,7 @@ import org.h2.util.RandomUtils; ...@@ -44,7 +44,7 @@ import org.h2.util.RandomUtils;
*/ */
public class TestCrashAPI extends TestBase { public class TestCrashAPI extends TestBase {
public static final Class[] INTERFACES = { Connection.class, PreparedStatement.class, Statement.class, private static final Class[] INTERFACES = { Connection.class, PreparedStatement.class, Statement.class,
ResultSet.class, ResultSetMetaData.class, Savepoint.class, ResultSet.class, ResultSetMetaData.class, Savepoint.class,
ParameterMetaData.class, Clob.class, Blob.class, Array.class, CallableStatement.class }; ParameterMetaData.class, Clob.class, Blob.class, Array.class, CallableStatement.class };
......
...@@ -229,7 +229,7 @@ public abstract class TestHalt extends TestBase { ...@@ -229,7 +229,7 @@ public abstract class TestHalt extends TestBase {
} }
} }
public void disconnectHSQLDB() { void disconnectHSQLDB() {
try { try {
conn.createStatement().execute("SHUTDOWN"); conn.createStatement().execute("SHUTDOWN");
} catch (Exception e) { } catch (Exception e) {
...@@ -238,7 +238,7 @@ public abstract class TestHalt extends TestBase { ...@@ -238,7 +238,7 @@ public abstract class TestHalt extends TestBase {
// super.disconnect(); // super.disconnect();
} }
public void disconnectDerby() { void disconnectDerby() {
// super.disconnect(); // super.disconnect();
try { try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
......
...@@ -20,6 +20,12 @@ public class TestHaltApp extends TestHalt { ...@@ -20,6 +20,12 @@ public class TestHaltApp extends TestHalt {
private int rowCount; private int rowCount;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
SelfDestructor.startCountdown(60); SelfDestructor.startCountdown(60);
baseDir = TestHalt.DIR; baseDir = TestHalt.DIR;
......
...@@ -25,6 +25,11 @@ public class TestKillProcess { ...@@ -25,6 +25,11 @@ public class TestKillProcess {
// utility class // utility class
} }
/**
* This method is called when executing this application.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
SelfDestructor.startCountdown(60); SelfDestructor.startCountdown(60);
try { try {
......
...@@ -62,6 +62,12 @@ public class TestKillRestart extends TestBase { ...@@ -62,6 +62,12 @@ public class TestKillRestart extends TestBase {
} }
} }
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
SelfDestructor.startCountdown(60); SelfDestructor.startCountdown(60);
String driver = "org.h2.Driver"; String driver = "org.h2.Driver";
......
...@@ -113,6 +113,12 @@ public class TestKillRestartMulti extends TestBase { ...@@ -113,6 +113,12 @@ public class TestKillRestartMulti extends TestBase {
} }
} }
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
SelfDestructor.startCountdown(60); SelfDestructor.startCountdown(60);
new TestKillRestartMulti().test(args); new TestKillRestartMulti().test(args);
......
...@@ -13,26 +13,78 @@ import java.sql.SQLException; ...@@ -13,26 +13,78 @@ import java.sql.SQLException;
*/ */
public interface DbInterface { public interface DbInterface {
/**
* Drop all objects in the database.
*/
void reset() throws SQLException; void reset() throws SQLException;
/**
* Connect to the database.
*/
void connect() throws Exception; void connect() throws Exception;
/**
* Disconnect from the database.
*/
void disconnect() throws SQLException; void disconnect() throws SQLException;
/**
* Close the connection and the database.
*/
void end() throws SQLException; void end() throws SQLException;
/**
* Create the specified table.
*
* @param table the table to create
*/
void createTable(Table table) throws SQLException; void createTable(Table table) throws SQLException;
/**
* Drop the specified table.
*
* @param table the table to drop
*/
void dropTable(Table table) throws SQLException; void dropTable(Table table) throws SQLException;
/**
* Create an index.
*
* @param index the index to create
*/
void createIndex(Index index) throws SQLException; void createIndex(Index index) throws SQLException;
/**
* Drop an index.
*
* @param index the index to drop
*/
void dropIndex(Index index) throws SQLException; void dropIndex(Index index) throws SQLException;
/**
* Insert a row into a table.
*
* @param table the table
* @param c the column list
* @param v the values
* @return the result
*/
Result insert(Table table, Column[] c, Value[] v) throws SQLException; Result insert(Table table, Column[] c, Value[] v) throws SQLException;
/**
* Execute a query.
*
* @param sql the SQL statement
*/
Result select(String sql) throws SQLException; Result select(String sql) throws SQLException;
/**
* Delete a number of rows.
*
* @param table the table
* @param condition the condition
* @return the result
*/
Result delete(Table table, String condition) throws SQLException; Result delete(Table table, String condition) throws SQLException;
/** /**
...@@ -46,9 +98,20 @@ public interface DbInterface { ...@@ -46,9 +98,20 @@ public interface DbInterface {
*/ */
Result update(Table table, Column[] columns, Value[] values, String condition) throws SQLException; Result update(Table table, Column[] columns, Value[] values, String condition) throws SQLException;
/**
* Enable or disable autocommit.
*
* @param b the new value
*/
void setAutoCommit(boolean b) throws SQLException; void setAutoCommit(boolean b) throws SQLException;
/**
* Commit a pending transaction.
*/
void commit() throws SQLException; void commit() throws SQLException;
/**
* Roll back a pending transaction.
*/
void rollback() throws SQLException; void rollback() throws SQLException;
} }
...@@ -80,7 +80,7 @@ public class DbState implements DbInterface { ...@@ -80,7 +80,7 @@ public class DbState implements DbInterface {
// nothing to do // nothing to do
} }
public Table randomTable() { Table randomTable() {
if (tables.size() == 0) { if (tables.size() == 0) {
return null; return null;
} }
......
...@@ -32,15 +32,15 @@ public class TestSynth extends TestBase { ...@@ -32,15 +32,15 @@ public class TestSynth extends TestBase {
private boolean stopImmediately; private boolean stopImmediately;
private int mode; private int mode;
public boolean is(int isType) { boolean is(int isType) {
return mode == isType; return mode == isType;
} }
public RandomGen random() { RandomGen random() {
return random; return random;
} }
public String randomIdentifier() { String randomIdentifier() {
int len = random.getLog(8) + 2; int len = random.getLog(8) + 2;
while (true) { while (true) {
return random.randomString(len); return random.randomString(len);
...@@ -193,11 +193,11 @@ public class TestSynth extends TestBase { ...@@ -193,11 +193,11 @@ public class TestSynth extends TestBase {
} }
} }
public Table randomTable() { Table randomTable() {
return db.randomTable(); return db.randomTable();
} }
public void log(int id, String s) { void log(int id, String s) {
if (showLog && id == 0) { if (showLog && id == 0) {
System.out.println(s); System.out.println(s);
} }
......
...@@ -64,6 +64,12 @@ public class TestExit extends TestBase implements DatabaseEventListener { ...@@ -64,6 +64,12 @@ public class TestExit extends TestBase implements DatabaseEventListener {
} }
} }
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
SelfDestructor.startCountdown(60); SelfDestructor.startCountdown(60);
if (args.length == 0) { if (args.length == 0) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论