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

javadocs

上级 cf963b69
......@@ -17,7 +17,7 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>
<li>RUNSCRIPT could throw a NullPointerException if the script name was an expression.
</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.
......
......@@ -311,6 +311,20 @@ http://groups.google.com/group/h2-database/web/roadmap
<td class="compareY">Yes</td>
<td class="compareY">Yes</td>
</tr><tr>
<td>Computed Columns</td>
<td class="compareY">Yes</td>
<td class="compareN">No</td>
<td class="compareN">No</td>
<td class="compareN">No</td>
<td class="compareY">Yes *6</td>
</tr><tr>
<td>Case Insensitive Columns</td>
<td class="compareY">Yes</td>
<td class="compareN">No</td>
<td class="compareY">Yes</td>
<td class="compareY">Yes</td>
<td class="compareY">Yes *6</td>
</tr><tr>
<td>Custom Aggregate Functions</td>
<td class="compareY">Yes</td>
<td class="compareN">No</td>
......@@ -331,7 +345,8 @@ http://groups.google.com/group/h2-database/web/roadmap
*2 MySQL supports linked MySQL tables under the name 'federated tables'.<br />
*3 Derby support for roles based security and password checking as an option.<br />
*4 Derby only supports global temporary tables.<br />
*5 The default H2 jar file contains debug information.
*5 The default H2 jar file contains debug information, jar files for other databases do not.<br />
*6 PostgreSQL supports functional indexes.
</p>
<h3>Derby and HSQLDB</h3>
......@@ -973,38 +988,81 @@ IGNORECASE=TRUE to the database URL (example: jdbc:h2:~/test;IGNORECASE=TRUE).
<h3>Compatibility Modes</h3>
<p>
For certain features, this database can emulate the behavior of specific databases. Not all features or differences of those
databases are implemented. Currently, this feature is mainly used for randomized comparative testing
(where random statements are executed against multiple databases and the results are compared).
The mode can be changed by specifying the mode in the database URL, or using the SQL statement SET MODE.
To use the HSQLDB mode, you can use the database URL <code>jdbc:h2:~/test;MODE=HSQLDB</code>
or the SQL statement <code>SET MODE HSQLDB</code>.
For certain features, this database can emulate the behavior of specific databases.
Not all features or differences of those databases are implemented.
Here is the list of currently supported modes and the difference to the regular mode:
</p>
<table>
<tr><th>Mode</th><th>Differences</th></tr>
<tr><td>
PostgreSQL
</td><td>
Concatenation of a NULL with another value results in NULL.
Usually, the NULL is treated as an empty string if only one of the operators is NULL,
and NULL is only returned if both values are NULL.
</td></tr>
<tr><td>
MySQL
</td><td>
When inserting data, if a column is defined to be NOT NULL and NULL is inserted,
then a 0 (or empty string, or the current timestamp for timestamp columns) value is used.
Usually, this operation is not allowed and an exception is thrown.
</td></tr>
<tr><td>
HSQLDB
</td><td>
When converting the scale of decimal data, the number is only converted if the new scale is
smaller then current scale.
Usually, the scale is converted and 0s are added if required.
</td></tr>
</table>
<h3>PostgreSQL Compatibility Mode</h3>
<p>
To use the PostgreSQL mode, use the database URL <code>jdbc:h2:~/test;MODE=PostgreSQL</code>
or the SQL statement <code>SET MODE PostgreSQL</code>.
</p>
<ul><li>Concatenation of a NULL with another value results in NULL. Usually, the NULL is treated as an empty
string if only one of the operators is NULL, and NULL is only returned if both values are NULL.
</li><li>When converting a floating point number to a integer, the fractional
digits should not be truncated, but the value should be rounded.
</li><li>The system columns 'CTID' and 'OID' should be supported.
</li></ul>
<h3>MySQL Compatibility Mode</h3>
<p>
To use the MySQL mode, use the database URL <code>jdbc:h2:~/test;MODE=MySQL</code>
or the SQL statement <code>SET MODE MySQL</code>.
</p>
<ul><li>When inserting data, if a column is defined to be NOT NULL and NULL is inserted,
then a 0 (or empty string, or the current timestamp for timestamp columns) value is used.
Usually, this operation is not allowed and an exception is thrown.
</li><li>When converting a floating point number to a integer, the fractional
digits should not be truncated, but the value should be rounded.
</li><li>The identifiers should be returned in lower case.
</li><li>Creating indexes in the CREATE TABLE statement should be supported.
</li></ul>
<h3>HSQLDB Compatibility Mode</h3>
<p>
To use the HSQLDB mode, use the database URL <code>jdbc:h2:~/test;MODE=HSQLDB</code>
or the SQL statement <code>SET MODE HSQLDB</code>.
</p>
<ul><li>Concatenation of a NULL with another value results in NULL. Usually, the NULL is treated as an empty
string if only one of the operators is NULL, and NULL is only returned if both values are NULL.
</li><li>When converting the scale of decimal data, the number is only converted if the new scale is
smaller then current scale. Usually, the scale is converted and 0s are added if required.
</li><li>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.
</li></ul>
<h3>MS SQL Server Compatibility Mode</h3>
<p>
To use the MS SQL Server mode, use the database URL <code>jdbc:h2:~/test;MODE=MSSQLServer</code>
or the SQL statement <code>SET MODE MSSQLServer</code>.
</p>
<ul><li>Identifiers may be quoted using square brackets as in [Test].
</li><li>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.
</li></ul>
<h3>Derby Compatibility Mode</h3>
<p>
To use the Derby mode, use the database URL <code>jdbc:h2:~/test;MODE=Derby</code>
or the SQL statement <code>SET MODE Derby</code>.
</p>
<ul><li>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.
</li></ul>
<h3>Oracle Compatibility Mode</h3>
<p>
To use the Oracle mode, use the database URL <code>jdbc:h2:~/test;MODE=Oracle</code>
or the SQL statement <code>SET MODE Oracle</code>.
</p>
<ul><li>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.
</li></ul>
<br /><a name="trace_options"></a>
<h2>Using the Trace Options</h2>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -32,7 +32,6 @@ import org.h2.util.StringUtils;
public class Bnf {
private static final String SEPARATORS = " [](){}|.,\r\n<>:-+*/=<\">!'$";
private static final long MAX_PARSE_TIME = 100;
private final Random random = new Random();
private final HashMap ruleMap = new HashMap();
......@@ -286,20 +285,17 @@ public class Bnf {
* @return the map of possible token types / tokens
*/
public HashMap getNextTokenList(String query) {
HashMap next = new HashMap();
Sentence sentence = new Sentence();
sentence.next = next;
sentence.text = query;
sentence.setQuery(query);
for (int i = 0; i < statements.size(); i++) {
RuleHead head = (RuleHead) statements.get(i);
if (!head.section.startsWith("Commands")) {
continue;
}
sentence.max = System.currentTimeMillis() + MAX_PARSE_TIME;
sentence.setQuery(query);
sentence.start();
head.getRule().addNextTokenList(sentence);
}
return next;
return sentence.getNext();
}
/**
......
......@@ -78,15 +78,15 @@ public class RuleElement implements Rule {
}
public boolean matchRemove(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return false;
}
String query = sentence.query;
String query = sentence.getQuery();
if (query.length() == 0) {
return false;
}
if (keyword) {
String up = sentence.queryUpper;
String up = sentence.getQueryUpper();
if (up.startsWith(name)) {
query = query.substring(name.length());
while (!"_".equals(name) && query.length() > 0 && Character.isWhitespace(query.charAt(0))) {
......@@ -101,7 +101,7 @@ public class RuleElement implements Rule {
return false;
}
if (name != null && !name.startsWith("@") && (link.name() == null || !link.name().startsWith("@"))) {
query = sentence.query;
query = sentence.getQuery();
while (query.length() > 0 && Character.isWhitespace(query.charAt(0))) {
query = query.substring(1);
}
......@@ -111,13 +111,13 @@ public class RuleElement implements Rule {
}
public void addNextTokenList(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return;
}
if (keyword) {
String query = sentence.query;
String query = sentence.getQuery();
String q = query.trim();
String up = sentence.queryUpper.trim();
String up = sentence.getQueryUpper().trim();
if (q.length() == 0 || name.startsWith(up)) {
if (q.length() < name.length()) {
sentence.add(name, name.substring(q.length()), type);
......
......@@ -109,10 +109,10 @@ public class RuleFixed implements Rule {
}
public boolean matchRemove(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return false;
}
String query = sentence.query;
String query = sentence.getQuery();
if (query.length() == 0) {
return false;
}
......@@ -223,10 +223,10 @@ public class RuleFixed implements Rule {
}
public void addNextTokenList(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return;
}
String query = sentence.query;
String query = sentence.getQuery();
switch(type) {
case YMD:
if (query.length() == 0) {
......
......@@ -96,7 +96,7 @@ public class RuleList implements Rule {
}
public boolean matchRemove(Sentence sentence) {
String query = sentence.query;
String query = sentence.getQuery();
if (query.length() == 0) {
return false;
}
......@@ -118,7 +118,7 @@ public class RuleList implements Rule {
}
public void addNextTokenList(Sentence sentence) {
String old = sentence.query;
String old = sentence.getQuery();
if (or) {
for (int i = 0; i < list.size(); i++) {
sentence.setQuery(old);
......
......@@ -46,10 +46,10 @@ public class RuleOptional implements Rule {
}
public boolean matchRemove(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return false;
}
String query = sentence.query;
String query = sentence.getQuery();
if (query.length() == 0) {
return true;
}
......@@ -60,7 +60,7 @@ public class RuleOptional implements Rule {
}
public void addNextTokenList(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return;
}
rule.addNextTokenList(sentence);
......
......@@ -40,10 +40,10 @@ public class RuleRepeat implements Rule {
}
public boolean matchRemove(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return false;
}
String query = sentence.query;
String query = sentence.getQuery();
if (query.length() == 0) {
return false;
}
......@@ -51,20 +51,20 @@ public class RuleRepeat implements Rule {
if (!rule.matchRemove(sentence)) {
return true;
}
if (sentence.query.length() == 0) {
if (sentence.getQuery().length() == 0) {
return true;
}
}
}
public void addNextTokenList(Sentence sentence) {
if (sentence.stop()) {
if (sentence.shouldStop()) {
return;
}
String old = sentence.query;
String old = sentence.getQuery();
while (true) {
rule.addNextTokenList(sentence);
if (!rule.matchRemove(sentence) || old == sentence.query) {
if (!rule.matchRemove(sentence) || old == sentence.getQuery()) {
break;
}
}
......
......@@ -20,25 +20,60 @@ import org.h2.util.StringUtils;
public class Sentence {
/**
* The possible choices of the item depend on the context.
* This token type means the possible choices of the item depend on the context.
* For example the item represents a table name of the current database.
*/
public static final int CONTEXT = 0;
/**
* The token type for a keyword.
*/
static final int KEYWORD = 1;
/**
* The token type for a function name.
*/
static final int FUNCTION = 2;
public String text;
public String query;
public String queryUpper;
HashMap next;
long max;
private static final long MAX_PROCESSING_TIME = 100;
/**
* The map of next tokens in the form type#tokenName token.
*/
private HashMap next = new HashMap();
/**
* The complete query string.
*/
private String query;
/**
* The uppercase version of the query string.
*/
private String queryUpper;
private long stopAt;
private DbSchema lastMatchedSchema;
private DbTableOrView lastMatchedTable;
private DbTableOrView lastTable;
private HashSet tables;
private HashMap aliases;
/**
* Start the timer to make sure processing doesn't take too long.
*/
void start() {
stopAt = System.currentTimeMillis() + MAX_PROCESSING_TIME;
}
boolean stop() {
return System.currentTimeMillis() > max;
/**
* Check if it's time to stop processing.
* Processing auto-complete shouldn't take more than a few milliseconds.
*
* @return true if it's time to stop processing
*/
boolean shouldStop() {
return System.currentTimeMillis() > stopAt;
}
/**
......@@ -46,7 +81,7 @@ public class Sentence {
*
* @param n the token name
* @param string an example text
* @param type the type
* @param type the token type
*/
public void add(String n, String string, int type) {
next.put(type+"#"+n, string);
......@@ -142,6 +177,11 @@ public class Sentence {
return lastMatchedTable;
}
/**
* Set the query string.
*
* @param query the query string
*/
public void setQuery(String query) {
if (this.query != query) {
this.query = query;
......@@ -149,4 +189,31 @@ public class Sentence {
}
}
/**
* Get the query string.
*
* @return the query
*/
public String getQuery() {
return query;
}
/**
* Get the uppercase version of the query string.
*
* @return the uppercase query
*/
public String getQueryUpper() {
return queryUpper;
}
/**
* Get the map of next tokens.
*
* @return the next token map
*/
public HashMap getNext() {
return next;
}
}
......@@ -148,7 +148,7 @@ public abstract class Command implements CommandInterface {
}
}
protected void start() {
void start() {
startTime = System.currentTimeMillis();
}
......
......@@ -143,6 +143,11 @@ public abstract class Prepared {
return parameters;
}
/**
* Check if all parameters have been set.
*
* @throws SQLException if any parameter has not been set
*/
protected void checkParameters() throws SQLException {
for (int i = 0; parameters != null && i < parameters.size(); i++) {
Parameter param = (Parameter) parameters.get(i);
......@@ -214,10 +219,25 @@ public abstract class Prepared {
return sqlStatement;
}
/**
* Get the object id to use for the database object that is created in this
* statement. This id is only set when the object is persistent.
* If not set, this method returns 0.
*
* @return the object id or 0 if not set
*/
protected int getCurrentObjectId() {
return objectId;
}
/**
* Get the current object id, or get a new id from the database. The object
* id is used when creating new database object (CREATE statement).
*
* @param needFresh if a fresh id is required
* @param dataFile if the object id is used for the
* @return the object id
*/
protected int getObjectId(boolean needFresh, boolean dataFile) {
Database db = session.getDatabase();
int id = objectId;
......
......@@ -242,7 +242,7 @@ public abstract class Query extends Prepared {
}
}
protected void initOrder(ObjectArray expressions, ObjectArray expressionSQL, ObjectArray orderList, int visible,
void initOrder(ObjectArray expressions, ObjectArray expressionSQL, ObjectArray orderList, int visible,
boolean mustBeInResult) throws SQLException {
for (int i = 0; i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
......
......@@ -66,7 +66,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
cipher = c;
}
protected boolean isEncrypted() {
private boolean isEncrypted() {
return cipher != null;
}
......@@ -94,7 +94,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
return false;
}
protected void deleteStore() throws SQLException {
void deleteStore() throws SQLException {
String fileName = getFileName();
if (fileName != null) {
FileUtils.delete(fileName);
......@@ -111,7 +111,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
store.init();
}
protected void openOutput() throws SQLException {
void openOutput() throws SQLException {
String fileName = getFileName();
if (fileName == null) {
return;
......@@ -128,7 +128,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
}
}
protected void openInput() throws SQLException {
void openInput() throws SQLException {
String fileName = getFileName();
if (fileName == null) {
return;
......@@ -151,7 +151,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
}
}
protected void closeIO() {
void closeIO() {
IOUtils.closeSilently(out);
out = null;
IOUtils.closeSilently(in);
......
......@@ -9,12 +9,34 @@ package org.h2.command.dml;
import org.h2.expression.Expression;
/**
* Describes the ORDER BY clause of a query.
* Describes one element of the ORDER BY clause of a query.
*/
public class SelectOrderBy {
/**
* The order by expression.
*/
public Expression expression;
/**
* The column index expression. This can be a column index number (1 meaning
* the first column of the select list) or a parameter (the parameter is a
* number representing the column index number).
*/
public Expression columnIndexExpr;
/**
* If the column should be sorted descending.
*/
public boolean descending;
/**
* If NULL should be appear first.
*/
public boolean nullsFirst;
/**
* If NULL should be appear at the end.
*/
public boolean nullsLast;
}
......@@ -54,9 +54,8 @@ public class ConstraintReferential extends Constraint {
*/
public static final int SET_NULL = 3;
protected IndexColumn[] columns;
protected IndexColumn[] refColumns;
private IndexColumn[] columns;
private IndexColumn[] refColumns;
private int deleteAction;
private int updateAction;
private Table refTable;
......
......@@ -39,6 +39,14 @@ public abstract class DbObjectBase implements DbObject {
private long modificationId;
private boolean temporary;
/**
* Initialize some attributes of this object.
*
* @param database the database
* @param id the object id
* @param name the name
* @param traceModule the trace module name
*/
protected void initDbObjectBase(Database database, int id, String name, String traceModule) {
this.database = database;
this.trace = database.getTrace(traceModule);
......@@ -125,6 +133,10 @@ public abstract class DbObjectBase implements DbObject {
return objectName;
}
/**
* Set the main attributes to null to make sure the object is no longer
* used.
*/
protected void invalidate() {
setModified();
id = -1;
......
......@@ -23,13 +23,54 @@ public class Mode {
private static final HashMap MODES = new HashMap();
// Modes are also documented in the features section
/**
* Concatenation of a NULL with another value results in NULL. Usually, the
* NULL is treated as an empty string if only one of the operators is NULL,
* and NULL is only returned if both values are NULL.
*/
public boolean nullConcatIsNull;
/**
* When inserting data, if a column is defined to be NOT NULL and NULL is
* inserted, then a 0 (or empty string, or the current timestamp for
* timestamp columns) value is used. Usually, this operation is not allowed
* and an exception is thrown.
*/
public boolean convertInsertNullToZero;
/**
* When converting the scale of decimal data, the number is only converted
* if the new scale is smaller then current scale. Usually, the scale is
* converted and 0s are added if required.
*/
public boolean convertOnlyToSmallerScale;
/**
* When converting a floating point number to a integer, the fractional
* digits should not be truncated, but the value should be rounded.
*/
public boolean roundWhenConvertToLong;
/**
* The identifiers should be returned in lower case.
*/
public boolean lowerCaseIdentifiers;
/**
* Creating indexes in the CREATE TABLE statement should be supported.
*/
public boolean indexDefinitionInCreateTable;
/**
* The system columns 'CTID' and 'OID' should be supported.
*/
public boolean systemColumns;
/**
* Identifiers may be quoted using square brackets as in [Test].
*/
public boolean squareBracketQuotedNames;
/**
......
......@@ -59,7 +59,7 @@ public abstract class RightOwner extends DbObjectBase {
return false;
}
protected boolean isRightGrantedRecursive(Table table, int rightMask) {
boolean isRightGrantedRecursive(Table table, int rightMask) {
Right right;
if (grantedRights != null) {
right = (Right) grantedRights.get(table);
......
......@@ -1450,6 +1450,12 @@ public class Function extends Expression implements FunctionCall {
}
}
/**
* Check if the parameter count is correct.
*
* @param len the number of parameters set
* @throws SQLException if the parameter count is incorrect
*/
protected void checkParameterCount(int len) throws SQLException {
int min = 0, max = Integer.MAX_VALUE;
switch (info.type) {
......
......@@ -633,7 +633,14 @@ public class FullText implements Trigger {
return search(conn, text, limit, offset, false);
}
protected static SimpleResultSet createResultSet(boolean data) throws SQLException {
/**
* Create an empty search result and initialize the columns.
*
* @param data true if the result set should contain the primary key data as
* an array.
* @return the empty result set
*/
static SimpleResultSet createResultSet(boolean data) throws SQLException {
SimpleResultSet result = new SimpleResultSet();
if (data) {
result.addColumn(FullText.FIELD_SCHEMA, Types.VARCHAR, 0, 0);
......@@ -722,7 +729,14 @@ public class FullText implements Trigger {
return result;
}
protected static Object[][] parseKey(Connection conn, String key) throws SQLException {
/**
* Parse a primary key condition into the primary key columns.
*
* @param conn the database connection
* @param key the primary key condition as a string
* @return an array containing the column name list and the data list
*/
static Object[][] parseKey(Connection conn, String key) throws SQLException {
ArrayList columns = new ArrayList();
ArrayList data = new ArrayList();
JdbcConnection c = (JdbcConnection) conn;
......
......@@ -22,17 +22,28 @@ import org.h2.value.Value;
* An abstract b-tree page.
*/
public abstract class BtreePage extends Record {
// TODO btree: make sure the indexed data is at most half this size!
// (and find a solution to work around this problem!)
// TODO memory: the btree page needs a lot of memory (in the cache) -
// probably better not use ObjectArray but array;
// not Row but ValueList / Value (for single key index), int array for row
// pos
/**
* The maximum number of blocks occupied by a b-tree page.
*/
protected static final int BLOCKS_PER_PAGE = 1024 / DiskFile.BLOCK_SIZE;
/**
* The b-tree index object
*/
protected BtreeIndex index;
// TODO memory: the btree page needs a lot of memory (in the cache) -
// probably better not use ObjectArray but array
/**
* The list of data pages.
*/
protected ObjectArray pageData;
/**
* If this is the root page of the index.
*/
protected boolean root;
BtreePage(BtreeIndex index) {
......
......@@ -13,12 +13,38 @@ import org.h2.store.Storage;
* Such records are only used when recovering.
*/
public class RedoLogRecord {
/**
* The storage object to where this log record belongs to.
*/
public Storage storage;
/**
* The sequence id. This id is used to sort the records in the same order as
* they appear in the log file.
*/
public int sequenceId;
/**
* The position in the data file.
*/
public int recordId;
/**
* The offset in the data byte array.
*/
public int offset;
/**
* The data.
*/
public byte[] data;
/**
* Get the estimated memory size used by this object.
*
* @return the estimated memory size
*/
public int getSize() {
// estimated memory size in bytes ((5 variables+myself) * 4 bytes each)
if (data == null) {
......@@ -26,4 +52,5 @@ public class RedoLogRecord {
}
return 28 + data.length;
}
}
......@@ -15,6 +15,14 @@ public abstract class SchemaObjectBase extends DbObjectBase implements SchemaObj
private Schema schema;
/**
* Initialize some attributes of this object.
*
* @param schema the schema
* @param id the object id
* @param name the name
* @param traceModule the trace module name
*/
protected void initSchemaObjectBase(Schema schema, int id, String name, String traceModule) {
initDbObjectBase(schema.getDatabase(), id, name, traceModule);
this.schema = schema;
......
......@@ -14,7 +14,24 @@ import org.h2.util.StringUtils;
* This class is used by the H2 Console.
*/
public class ConnectionInfo {
public String driver, url, user;
/**
* The driver class name.
*/
public String driver;
/**
* The database URL.
*/
public String url;
/**
* The user name.
*/
public String user;
/**
* The connection display name.
*/
String name;
int lastAccess;
......
......@@ -98,7 +98,7 @@ public class DbContextRule implements Rule {
}
private void addTableAlias(Sentence sentence) {
String query = sentence.query;
String query = sentence.getQuery();
String q = StringUtils.toUpperEnglish(query.trim());
HashMap map = sentence.getAliases();
HashSet set = new HashSet();
......@@ -136,7 +136,7 @@ public class DbContextRule implements Rule {
}
private void addNewTableAlias(Sentence sentence) {
String query = sentence.query;
String query = sentence.getQuery();
if (SUGGEST_TABLE_ALIAS) {
// good when testing!
if (query.length() > 3) {
......@@ -181,7 +181,7 @@ public class DbContextRule implements Rule {
// }
private void addSchema(Sentence sentence) {
String query = sentence.query;
String query = sentence.getQuery();
String q = StringUtils.toUpperEnglish(query);
if (q.trim().length() == 0) {
q = q.trim();
......@@ -201,7 +201,7 @@ public class DbContextRule implements Rule {
}
private void addTable(Sentence sentence) {
String query = sentence.query;
String query = sentence.getQuery();
DbSchema schema = sentence.getLastMatchedSchema();
if (schema == null) {
schema = contents.defaultSchema;
......@@ -222,14 +222,11 @@ public class DbContextRule implements Rule {
}
private void addColumn(Sentence sentence) {
String query = sentence.query;
String query = sentence.getQuery();
String tableName = query;
String columnPattern = "";
if (query.trim().length() == 0) {
tableName = null;
if (sentence.text.trim().endsWith(".")) {
return;
}
} else {
tableName = StringUtils.toUpperEnglish(query.trim());
if (tableName.endsWith(".")) {
......@@ -286,7 +283,7 @@ public class DbContextRule implements Rule {
}
public boolean matchRemove(Sentence sentence) {
if (sentence.query.length() == 0) {
if (sentence.getQuery().length() == 0) {
return false;
}
String s;
......@@ -320,8 +317,8 @@ public class DbContextRule implements Rule {
}
private String matchSchema(Sentence sentence) {
String query = sentence.query;
String up = sentence.queryUpper;
String query = sentence.getQuery();
String up = sentence.getQueryUpper();
DbSchema[] schemas = contents.schemas;
String best = null;
DbSchema bestSchema = null;
......@@ -347,8 +344,8 @@ public class DbContextRule implements Rule {
}
private String matchTable(Sentence sentence) {
String query = sentence.query;
String up = sentence.queryUpper;
String query = sentence.getQuery();
String up = sentence.getQueryUpper();
DbSchema schema = sentence.getLastMatchedSchema();
if (schema == null) {
schema = contents.defaultSchema;
......@@ -378,8 +375,8 @@ public class DbContextRule implements Rule {
}
private String matchColumnAlias(Sentence sentence) {
String query = sentence.query;
String up = sentence.queryUpper;
String query = sentence.getQuery();
String up = sentence.getQueryUpper();
int i = 0;
if (query.indexOf(' ') < 0) {
return null;
......@@ -401,8 +398,8 @@ public class DbContextRule implements Rule {
}
private String matchTableAlias(Sentence sentence, boolean add) {
String query = sentence.query;
String up = sentence.queryUpper;
String query = sentence.getQuery();
String up = sentence.getQueryUpper();
int i = 0;
if (query.indexOf(' ') < 0) {
return null;
......@@ -455,8 +452,8 @@ public class DbContextRule implements Rule {
}
private String matchColumn(Sentence sentence) {
String query = sentence.query;
String up = sentence.queryUpper;
String query = sentence.getQuery();
String up = sentence.getQueryUpper();
HashSet set = sentence.getTables();
String best = null;
DbTableOrView last = sentence.getLastMatchedTable();
......
......@@ -139,6 +139,11 @@ public class FileStore {
return store;
}
/**
* Generate the random salt bytes if required.
*
* @return the random salt or the magic
*/
protected byte[] generateSalt() {
return magic;
}
......
......@@ -871,7 +871,7 @@ public class MetaTable extends Table {
// PARAMS
t.params,
// AUTO_INCREMENT
String.valueOf(t.autoInc),
String.valueOf(t.autoIncrement),
// MINIMUM_SCALE
String.valueOf(t.minScale),
// MAXIMUM_SCALE
......
......@@ -17,13 +17,34 @@ import org.h2.store.DiskFile;
*/
public abstract class CacheObject {
public CacheObject previous, next, chained;
/**
* The previous element in the LRU linked list. If the previous element is
* the head, then this element is the most recently used object.
*/
public CacheObject previous;
/**
* The next element in the LRU linked list. If the next element is the head,
* then this element is the least recently used object.
*/
public CacheObject next;
/**
* The next element in the hash chain.
*/
public CacheObject chained;
/**
* The cache queue identifier. This field is only used for the 2Q cache
* algorithm.
*/
public int cacheQueue;
/**
* The number of blocks occupied by this object.
*/
protected int blockCount;
private int pos;
private boolean changed;
......
......@@ -67,7 +67,11 @@ public abstract class HashBase {
return size + (zeroKey ? 1 : 0);
}
protected void checkSizePut() throws SQLException {
/**
* Check the size before adding an entry. This method resizes the map if
* required.
*/
void checkSizePut() throws SQLException {
if (deletedCount > size) {
rehash(level);
}
......@@ -76,6 +80,10 @@ public abstract class HashBase {
}
}
/**
* Check the size before removing an entry. This method resizes the map if
* required.
*/
protected void checkSizeRemove() throws SQLException {
if (size < minSize && level > 0) {
rehash(level - 1);
......@@ -84,6 +92,11 @@ public abstract class HashBase {
}
}
/**
* Clear the map and reset the level to the specified value.
*
* @param newLevel the new level
*/
protected void reset(int newLevel) {
minSize = size * 3 / 4;
size = 0;
......@@ -95,6 +108,12 @@ public abstract class HashBase {
maxDeleted = 20 + len / 2;
}
/**
* Calculate the index for this hash code.
*
* @param hash the hash code
* @return the index
*/
protected int getIndex(int hash) {
return hash & mask;
}
......
......@@ -15,6 +15,9 @@ import java.sql.SQLException;
*/
public abstract class Tool {
/**
* The output stream where this tool writes to.
*/
protected PrintStream out = System.out;
/**
......
......@@ -52,27 +52,111 @@ public class DataType {
private static ObjectArray types = new ObjectArray();
private static HashMap typesByName = new HashMap();
private static DataType[] typesByValueType = new DataType[Value.TYPE_COUNT];
/**
* The value type of this data type.
*/
public int type;
/**
* The data type name.
*/
public String name;
/**
* The SQL type.
*/
public int sqlType;
/**
* The SQL type name.
*/
public String jdbc;
// how closely the data type maps
// to the corresponding JDBC SQL type (low is best)
/**
* How closely the data type maps to the corresponding JDBC SQL type (low is
* best).
*/
public int sqlTypePos;
/**
* The maximum supported precision.
*/
public int maxPrecision;
public int minScale, maxScale;
/**
* The lowest possible scale.
*/
public int minScale;
/**
* The highest possible scale.
*/
public int maxScale;
/**
* If this is a numeric type.
*/
public boolean decimal;
public String prefix, suffix;
/**
* The prefix required for the SQL literal representation.
*/
public String prefix;
/**
* The suffix required for the SQL literal representation.
*/
public String suffix;
/**
* The list of parameters used in the column definition.
*/
public String params;
public boolean autoInc;
/**
* If this is an autoincrement type.
*/
public boolean autoIncrement;
/**
* If this data type is an autoincrement type.
*/
public boolean caseSensitive;
public boolean supportsPrecision, supportsScale;
/**
* If the precision parameter is supported.
*/
public boolean supportsPrecision;
/**
* If the scale parameter is supported.
*/
public boolean supportsScale;
/**
* The default precision.
*/
public long defaultPrecision;
/**
* The default scale.
*/
public int defaultScale;
/**
* The default display size.
*/
public int defaultDisplaySize;
/**
* If this data type should not be listed in the database meta data.
*/
public boolean hidden;
/**
* The number of bytes required for an object.
*/
public int memory;
static {
......@@ -250,7 +334,7 @@ public class DataType {
dt.sqlType = sqlType;
dt.jdbc = jdbc;
dt.name = names[i];
dt.autoInc = dataType.autoInc;
dt.autoIncrement = dataType.autoIncrement;
dt.decimal = dataType.decimal;
dt.maxPrecision = dataType.maxPrecision;
dt.maxScale = dataType.maxScale;
......@@ -292,7 +376,7 @@ public class DataType {
dataType.supportsScale = true;
}
dataType.decimal = true;
dataType.autoInc = autoInc;
dataType.autoIncrement = autoInc;
return dataType;
}
......
......@@ -144,14 +144,110 @@ java org.h2.test.TestAll timer
*/
public boolean smallLog, big, networked, memory, ssl, textStorage, diskUndo, diskResult, deleteIndex, traceSystemOut;
public boolean codeCoverage, mvcc, endless;
public int logMode = 1, traceLevelFile, throttle;
/**
* If the test should run with many rows.
*/
public boolean big;
/**
* If remote database connections should be used.
*/
public boolean networked;
/**
* If in-memory databases should be used.
*/
public boolean memory;
/**
* If index files should be deleted before re-opening the database.
*/
public boolean deleteIndex;
/**
* If code coverage is enabled.
*/
public boolean codeCoverage;
/**
* If the multi version concurrency control mode should be used.
*/
public boolean mvcc;
/**
* The log mode to use.
*/
public int logMode = 1;
/**
* The cipher to use (null for unencrypted).
*/
public String cipher;
public boolean traceTest, stopOnError;
/**
* If only JDK 1.4 methods should be tested.
*/
public boolean jdk14 = true;
public boolean cache2Q;
/**
* If the transaction log files should be kept small (that is, log files should be switched early).
*/
boolean smallLog;
/**
* If SSL should be used for remote connections.
*/
boolean ssl;
/**
* If MAX_MEMORY_UNDO=3 should be used.
*/
boolean diskUndo;
/**
* If the text storage mechanism should be used.
*/
boolean textStorage;
/**
* If a small cache and a low number for MAX_MEMORY_ROWS should be used.
*/
boolean diskResult;
/**
* If TRACE_LEVEL_SYSTEM_OUT should be set to 2 (for debugging only).
*/
boolean traceSystemOut;
/**
* If the tests should run forever.
*/
boolean endless;
/**
* The file trace level value to use.
*/
int traceLevelFile;
/**
* The THROTTLE value to use.
*/
int throttle;
/**
* If test trace information should be written (for debugging only).
*/
boolean traceTest;
/**
* If the test should stop when the first error occurs.
*/
boolean stopOnError;
/**
* If the Two-Queue cache algorithm should be used.
*/
boolean cache2Q;
private Server server;
......@@ -168,34 +264,17 @@ java org.h2.test.TestAll timer
System.setProperty("h2.maxMemoryRowsDistinct", "128");
/*
document bug
Caused by: java.lang.NullPointerException
at org.h2.expression.ExpressionColumn.getValue(ExpressionColumn.java:155)
at org.h2.expression.Operation.getValue(Operation.java:97)
at org.h2.command.dml.ScriptBase.getFileName(ScriptBase.java:84)
at org.h2.command.dml.ScriptBase.openInput(ScriptBase.java:132)
at org.h2.command.dml.RunScriptCommand.update(RunScriptCommand.java:38)
at org.h2.command.CommandContainer.update(CommandContainer.java:69)
at org.h2.command.Command.executeUpdate(Command.java:198)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:163)
... 6 more
add test case
> RUNSCRIPT FROM SCRIPT_DIRECTORY || 'Create_Users.sql';
> SCRIPT_DIRECTORY is a constant.
feature list:
computed columns: H2, HSQLDB (PostgreSQL: functional index)
case insensitive columns: H2, HSQLDB, MySQL (PostgreSQL: functional index)
jazoon
measure and improve performance of ObjectArray.toArray()
H2 Console should support Java Queries
convert test.in.sql to RunScript syntax
C:\download\Data Concurrency and Consistency.pdf
detect deadlock: alarm
not tested:
PreparedProcedure PREPARE <name>(column,...) AS ...
Procedure
......@@ -208,8 +287,6 @@ deleted the same row when exactly does it occur in other databases
create an mbean for each database? server? (jconsole)
jazoon
in help.csv, use complete examples for functions; add a test case
improve javadocs
......
......@@ -43,12 +43,12 @@ public class TestBackup extends TestBase {
stat1.execute("backup to '" + baseDir + "/backup.zip'");
conn2.rollback();
compareDatabases(stat1, stat2);
assertEqualDatabases(stat1, stat2);
Restore.execute(baseDir + "/backup.zip", baseDir, "restored", true);
conn3 = getConnection("restored");
stat3 = conn3.createStatement();
compareDatabases(stat1, stat3);
assertEqualDatabases(stat1, stat3);
conn1.close();
conn2.close();
......
......@@ -88,7 +88,7 @@ public class TestMemoryUsage extends TestBase {
System.gc();
System.gc();
int used = MemoryUtils.getMemoryUsed();
if ((used - start) > 4000) {
if ((used - start) > 5000) {
fail("Used: " + (used - start));
}
stat.execute("drop table test");
......
......@@ -85,7 +85,7 @@ public class TestRunscript extends TestBase implements Trigger {
stat2.execute(sql);
stat2.execute("script to '" + baseDir + "/backup.3.sql'");
compareDatabases(stat1, stat2);
assertEqualDatabases(stat1, stat2);
conn1.close();
conn2.close();
......
......@@ -621,7 +621,7 @@ public class TestPreparedStatement extends TestBase {
assertTrue(stat.execute("SELECT * FROM T_INT ORDER BY ID"));
rs = stat.getResultSet();
testResultSetOrdered(rs, new String[][] { { "1", "0" }, { "2", "-1" }, { "3", "3" }, { "4", null },
assertResultSetOrdered(rs, new String[][] { { "1", "0" }, { "2", "-1" }, { "3", "3" }, { "4", null },
{ "5", "0" }, { "6", "-1" }, { "7", "3" }, { "8", null }, { "9", "-4" }, { "10", "5" }, { "11", null },
{ "12", "1" }, { "13", "0" }, { "14", "-20" }, { "15", "100" }, { "16", "30000" }, { "17", "-30000" },
{ "18", "" + Integer.MAX_VALUE }, { "19", "" + Integer.MIN_VALUE }, });
......
......@@ -283,7 +283,7 @@ public class TestResultSet extends TestBase {
assertEquals(meta.getColumnClassName(3), null);
assertTrue(rs.getRow() == 0);
testResultSetMeta(rs, 3, new String[] { "ID", "VALUE", "N" }, new int[] { Types.INTEGER, Types.INTEGER,
assertResultSetMeta(rs, 3, new String[] { "ID", "VALUE", "N" }, new int[] { Types.INTEGER, Types.INTEGER,
Types.NULL }, new int[] { 10, 10, 1 }, new int[] { 0, 0, 0 });
rs.next();
assertEquals(rs.getConcurrency(), ResultSet.CONCUR_READ_ONLY);
......@@ -408,7 +408,7 @@ public class TestResultSet extends TestBase {
stat.execute("INSERT INTO TEST VALUES(10,'\\''')");
stat.execute("INSERT INTO TEST VALUES(11,'\\%')");
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.VARCHAR }, new int[] {
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.VARCHAR }, new int[] {
10, 255 }, new int[] { 0, 0 });
String value;
rs.next();
......@@ -488,7 +488,7 @@ public class TestResultSet extends TestBase {
stat.execute("INSERT INTO TEST VALUES(7,-99999998.99)");
stat.execute("INSERT INTO TEST VALUES(8,NULL)");
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.DECIMAL }, new int[] {
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.DECIMAL }, new int[] {
10, 10 }, new int[] { 0, 2 });
BigDecimal bd;
rs.next();
......@@ -539,7 +539,7 @@ public class TestResultSet extends TestBase {
stat.execute("INSERT INTO TEST VALUES(7, -99999999.99, -99999999.99)");
stat.execute("INSERT INTO TEST VALUES(8, NULL, NULL)");
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 3, new String[] { "ID", "D", "R" },
assertResultSetMeta(rs, 3, new String[] { "ID", "D", "R" },
new int[] { Types.INTEGER, Types.DOUBLE, Types.REAL }, new int[] { 10, 17, 7 }, new int[] { 0, 0, 0 });
BigDecimal bd;
rs.next();
......@@ -603,10 +603,10 @@ public class TestResultSet extends TestBase {
stat.execute("INSERT INTO TEST VALUES(4,TIMESTAMP '9999-12-31 23:59:59')");
stat.execute("INSERT INTO TEST VALUES(5,NULL)");
rs = stat.executeQuery("SELECT 0 ID, TIMESTAMP '9999-12-31 23:59:59' VALUE FROM TEST ORDER BY ID");
testResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.TIMESTAMP },
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.TIMESTAMP },
new int[] { 10, 23 }, new int[] { 0, 10 });
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.TIMESTAMP },
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.TIMESTAMP },
new int[] { 10, 23 }, new int[] { 0, 10 });
rs.next();
java.sql.Date date;
......@@ -723,7 +723,7 @@ public class TestResultSet extends TestBase {
prep.execute();
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 4, new String[] { "ID", "D", "T", "TS" }, new int[] { Types.INTEGER, Types.DATE,
assertResultSetMeta(rs, 4, new String[] { "ID", "D", "T", "TS" }, new int[] { Types.INTEGER, Types.DATE,
Types.TIME, Types.TIMESTAMP }, new int[] { 10, 8, 6, 23 }, new int[] { 0, 0, 0, 10 });
rs.next();
......@@ -777,7 +777,7 @@ public class TestResultSet extends TestBase {
stat.execute("INSERT INTO TEST VALUES(5,X'0bcec1')");
stat.execute("INSERT INTO TEST VALUES(6,NULL)");
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.BLOB }, new int[] {
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.BLOB }, new int[] {
10, Integer.MAX_VALUE }, new int[] { 0, 0 });
rs.next();
checkBytes(rs.getBytes(2), new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 });
......@@ -816,7 +816,7 @@ public class TestResultSet extends TestBase {
stat.execute("INSERT INTO TEST VALUES(6,NULL)");
stat.execute("INSERT INTO TEST VALUES(7,NULL)");
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
testResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.CLOB }, new int[] {
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, new int[] { Types.INTEGER, Types.CLOB }, new int[] {
10, Integer.MAX_VALUE }, new int[] { 0, 0 });
rs.next();
string = rs.getString(2);
......
......@@ -105,6 +105,7 @@ public class TestWeb extends TestBase {
result = client.get(url, "logout.do");
result = client.get(url, "settingRemove.do?name=_test_");
server.stop();
}
......
......@@ -30,14 +30,67 @@ import org.h2.util.IOUtils;
*/
public abstract class TestHalt extends TestBase {
protected static final int OP_INSERT = 1, OP_DELETE = 2, OP_UPDATE = 4, OP_SELECT = 8;
protected static final int FLAG_NO_DELAY = 1, FLAG_LOBS = 2;
/**
* This bit flag means insert operations should be performed.
*/
protected static final int OP_INSERT = 1;
/**
* This bit flag means delete operations should be performed.
*/
protected static final int OP_DELETE = 2;
/**
* This bit flag means update operations should be performed.
*/
protected static final int OP_UPDATE = 4;
/**
* This bit flag means select operations should be performed.
*/
protected static final int OP_SELECT = 8;
/**
* This bit flag means operations should be written to the log file immediately.
*/
protected static final int FLAG_NO_DELAY = 1;
/**
* This bit flag means the test should use LOB values.
*/
protected static final int FLAG_LOBS = 2;
/**
* The test directory.
*/
static final String DIR = TestBase.getTestDir("halt");
private static final String DATABASE_NAME = "halt";
private static final String TRACE_FILE_NAME = "haltTrace.trace.db";
protected int operations, flags, value;
/**
* The current operations bit mask.
*/
protected int operations;
/**
* The current flags bit mask.
*/
protected int flags;
/**
* The current test value, for example the number of rows.
*/
protected int value;
/**
* The database connection.
*/
protected Connection conn;
/**
* The pseudo random number generator used for this test.
*/
protected Random random = new Random();
private SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss ");
......@@ -73,6 +126,11 @@ public abstract class TestHalt extends TestBase {
return DriverManager.getConnection("jdbc:h2:" + baseDir + "/halt", "sa", "sa");
}
/**
* Start the program.
*
* @param args the command line arguments
*/
protected void start(String[] args) throws Exception {
if (args.length == 0) {
runTest();
......@@ -111,10 +169,21 @@ public abstract class TestHalt extends TestBase {
}
}
/**
* Print a trace message to the trace file.
*
* @param s the message
*/
protected void traceOperation(String s) {
trace(s, null);
}
/**
* Print a trace message to the trace file.
*
* @param s the message
* @param e the exception or null
*/
protected void trace(String s, Exception e) {
FileWriter writer = null;
try {
......@@ -191,6 +260,9 @@ public abstract class TestHalt extends TestBase {
}
}
/**
* Close the database connection normally.
*/
protected void disconnect() {
try {
traceOperation("disconnect");
......@@ -248,6 +320,12 @@ public abstract class TestHalt extends TestBase {
}
}
/**
* Create a random string with the specified length.
*
* @param len the number of characters
* @return the random string
*/
protected String getRandomString(int len) {
StringBuffer buff = new StringBuffer();
for (int i = 0; i < len; i++) {
......
......@@ -37,6 +37,9 @@ public class TestHaltApp extends TestHalt {
stat.execute(sql);
}
/**
* Initialize the database.
*/
protected void testInit() throws SQLException {
Statement stat = conn.createStatement();
// stat.execute("CREATE TABLE TEST(ID IDENTITY, NAME VARCHAR(255))");
......@@ -51,6 +54,9 @@ public class TestHaltApp extends TestHalt {
execute(stat, "CREATE TABLE TEST(ID BIGINT GENERATED BY DEFAULT AS IDENTITY, NAME VARCHAR(255), DATA CLOB)");
}
/**
* Wait after the application has been started.
*/
protected void testWaitAfterAppStart() throws Exception {
int sleep = 10 + random.nextInt(300);
if ((flags & FLAG_NO_DELAY) == 0) {
......@@ -59,6 +65,12 @@ public class TestHaltApp extends TestHalt {
Thread.sleep(sleep);
}
/**
* This method is called after a simulated crash. The method should check if
* the data is transactionally consistent and throw an exception if not.
*
* @throws Exception if the data is not consistent.
*/
protected void testCheckAfterCrash() throws Exception {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT COUNT(*) FROM TEST");
......@@ -71,6 +83,9 @@ public class TestHaltApp extends TestHalt {
}
}
/**
* Initialize the application.
*/
protected void appStart() throws SQLException {
Statement stat = conn.createStatement();
if ((flags & FLAG_NO_DELAY) != 0) {
......@@ -83,6 +98,9 @@ public class TestHaltApp extends TestHalt {
trace("rows: " + rowCount, null);
}
/**
* Run the application code.
*/
protected void appRun() throws Exception {
conn.setAutoCommit(false);
traceOperation("setAutoCommit false");
......
......@@ -17,6 +17,9 @@ import org.h2.test.TestBase;
*/
public class TestMulti extends TestBase {
/**
* If set, the test should stop.
*/
public volatile boolean stop;
public void test() throws Exception {
......
......@@ -521,4 +521,5 @@ philosophers technologies modeling federation enterprise semantic deductive
fusion legacy decoded commented trimmed reaches indicating marks scaled tells
monitor benefit performing conditional significant arithmetic instrumented
doclets extremes instructions printable skips sava sources cms bytecode cfml
cold compiles markup spellchecker interleaved poormans programmed swt railo
\ No newline at end of file
cold compiles markup spellchecker interleaved poormans programmed swt railo
clobs resizes precisions scales
\ No newline at end of file
......@@ -334,7 +334,7 @@ public class Doclet {
}
private static boolean skipField(ClassDoc clazz, FieldDoc field) {
if (!field.isFinal() || !field.isStatic() || !field.isPublic() || field.containingClass() != clazz) {
if (field.isPrivate() || field.containingClass() != clazz) {
return true;
}
return false;
......@@ -347,7 +347,7 @@ public class Doclet {
return true;
}
String name = method.name();
if (!method.isPublic() || name.equals("finalize")) {
if ((method.isPrivate() && !method.isPackagePrivate()) || name.equals("finalize")) {
return true;
}
if (method.getRawCommentText().trim().startsWith("@deprecated INTERNAL")) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论