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

--no commit message

--no commit message
上级 1e0d5542
...@@ -261,15 +261,20 @@ ...@@ -261,15 +261,20 @@
<mkdir dir="docs/javadocImpl"/> <mkdir dir="docs/javadocImpl"/>
<javadoc <javadoc
sourcepath="src/main;src/test;src/tools" sourcepath="src/main;src/test;src/tools"
classpath="${path.lucene.jar};${path.servlet.jar};${java.class.path}"
packagenames="org.h2.*"
doclet="org.h2.tools.doclet.Doclet"
docletpath="bin"
additionalparam="-J-Dh2.interfacesOnly=false -J-Dh2.destDir=docs/javadocImpl"
/>
<javadoc
sourcepath="src/main;src/test;src/tools"
noindex="true"
packagenames="org.h2.*" packagenames="org.h2.*"
excludepackagenames="org.h2.tools.doclet" excludepackagenames="org.h2.tools.doclet"
classpath="${path.lucene.jar};${path.servlet.jar}" classpath="${path.lucene.jar};${path.servlet.jar};${java.class.path}"
destDir="docs/javadocImpl" destDir="docs/javadocImpl"
/> />
<!--
doclet="org.h2.tools.doclet.Doclet" docletpath="bin"
additionalparam="-J-Dh2.interfacesOnly=true -J-Dh2.destDir=docs/javadocImpl"
-->
<copy todir="docs/javadoc"> <copy todir="docs/javadoc">
<fileset dir="src/docsrc/javadoc" includes="**/*"/> <fileset dir="src/docsrc/javadoc" includes="**/*"/>
</copy> </copy>
......
...@@ -21,7 +21,7 @@ Welcome to H2, the free SQL database. The main feature of H2 are: ...@@ -21,7 +21,7 @@ Welcome to H2, the free SQL database. The main feature of H2 are:
</p> </p>
<ul> <ul>
<li>Very fast, free for everybody, source code is included <li>Very fast, free for everybody, source code is included
</li><li>Written Java; can be compiled with GCJ (Linux) </li><li>Written in Java; can be compiled with GCJ (Linux)
</li><li>Embedded, Server and Cluster modes </li><li>Embedded, Server and Cluster modes
</li><li>JDBC and (partial) ODBC API; Web Client application </li><li>JDBC and (partial) ODBC API; Web Client application
</li></ul> </li></ul>
......
...@@ -4169,7 +4169,7 @@ Welcome to H2, the free SQL database. The main feature of H2 are: ...@@ -4169,7 +4169,7 @@ Welcome to H2, the free SQL database. The main feature of H2 are:
Very fast, free for everybody, source code is included Very fast, free for everybody, source code is included
@mainWeb_1003_li @mainWeb_1003_li
Written Java; can be compiled with GCJ (Linux) Written in Java; can be compiled with GCJ (Linux)
@mainWeb_1004_li @mainWeb_1004_li
Embedded, Server and Cluster modes Embedded, Server and Cluster modes
......
...@@ -1388,7 +1388,7 @@ links_1112_p=A database front end to register volunteers, partnership and donati ...@@ -1388,7 +1388,7 @@ links_1112_p=A database front end to register volunteers, partnership and donati
mainWeb_1000_h1=H2 Database Engine mainWeb_1000_h1=H2 Database Engine
mainWeb_1001_p=Welcome to H2, the free SQL database. The main feature of H2 are\: mainWeb_1001_p=Welcome to H2, the free SQL database. The main feature of H2 are\:
mainWeb_1002_li=Very fast, free for everybody, source code is included mainWeb_1002_li=Very fast, free for everybody, source code is included
mainWeb_1003_li=Written Java; can be compiled with GCJ (Linux) mainWeb_1003_li=Written in Java; can be compiled with GCJ (Linux)
mainWeb_1004_li=Embedded, Server and Cluster modes mainWeb_1004_li=Embedded, Server and Cluster modes
mainWeb_1005_li=JDBC and (partial) ODBC API; Web Client application mainWeb_1005_li=JDBC and (partial) ODBC API; Web Client application
mainWeb_1006_h3=Download mainWeb_1006_h3=Download
......
...@@ -134,7 +134,14 @@ public class Bnf { ...@@ -134,7 +134,14 @@ public class Bnf {
addFixedRule("@digit@", RuleFixed.DIGIT); addFixedRule("@digit@", RuleFixed.DIGIT);
} }
public String getSyntax(String rule, String syntax) { /**
* Get the HTML documentation for a given syntax.
*
* @param rule the rule (topic)
* @param syntax the BNF syntax
* @return the HTML formatted text
*/
public String getSyntaxHtml(String rule, String syntax) {
StringTokenizer tokenizer = new StringTokenizer(syntax, SEPARATORS, true); StringTokenizer tokenizer = new StringTokenizer(syntax, SEPARATORS, true);
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
while (tokenizer.hasMoreTokens()) { while (tokenizer.hasMoreTokens()) {
...@@ -269,6 +276,18 @@ public class Bnf { ...@@ -269,6 +276,18 @@ public class Bnf {
return (String[]) list.toArray(new String[0]); return (String[]) list.toArray(new String[0]);
} }
/**
* Get the list of tokens that can follow.
* This is the main autocomplete method.
* The returned map for the query 'S' may look like this:
* <pre>
* key: 1#SELECT, value: ELECT
* key: 1#SET, value: ET
* </pre>
*
* @param query the start of the statement
* @return the map of possible token types / tokens
*/
public HashMap getNextTokenList(String query) { public HashMap getNextTokenList(String query) {
HashMap next = new HashMap(); HashMap next = new HashMap();
Sentence sentence = new Sentence(); Sentence sentence = new Sentence();
...@@ -285,6 +304,10 @@ public class Bnf { ...@@ -285,6 +304,10 @@ public class Bnf {
return next; return next;
} }
/**
* Cross-link all statements with each other.
* This method is called after updating the topics.
*/
public void linkStatements() { public void linkStatements() {
for (Iterator it = ruleMap.values().iterator(); it.hasNext();) { for (Iterator it = ruleMap.values().iterator(); it.hasNext();) {
RuleHead r = (RuleHead) it.next(); RuleHead r = (RuleHead) it.next();
...@@ -292,6 +315,13 @@ public class Bnf { ...@@ -292,6 +315,13 @@ public class Bnf {
} }
} }
/**
* Update a topic with a context specific rule.
* This is used for autocomplete support.
*
* @param topic the topic
* @param rule the database context rule
*/
public void updateTopic(String topic, DbContextRule rule) { public void updateTopic(String topic, DbContextRule rule) {
topic = StringUtils.toLowerEnglish(topic); topic = StringUtils.toLowerEnglish(topic);
RuleHead head = (RuleHead) ruleMap.get(topic); RuleHead head = (RuleHead) ruleMap.get(topic);
...@@ -304,6 +334,11 @@ public class Bnf { ...@@ -304,6 +334,11 @@ public class Bnf {
} }
} }
/**
* Get the list of possible statements.
*
* @return the list of statements
*/
public ArrayList getStatements() { public ArrayList getStatements() {
return statements; return statements;
} }
......
...@@ -77,7 +77,7 @@ public class RuleList implements Rule { ...@@ -77,7 +77,7 @@ public class RuleList implements Rule {
public String name() { public String name() {
return null; return null;
} }
public Rule last() { public Rule last() {
return get(list.size() - 1); return get(list.size() - 1);
} }
......
...@@ -15,6 +15,11 @@ import org.h2.server.web.DbTableOrView; ...@@ -15,6 +15,11 @@ import org.h2.server.web.DbTableOrView;
* Used for autocomplete. * Used for autocomplete.
*/ */
public class Sentence { public class Sentence {
/**
* 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; public static final int CONTEXT = 0;
static final int KEYWORD = 1; static final int KEYWORD = 1;
static final int FUNCTION = 2; static final int FUNCTION = 2;
......
...@@ -87,10 +87,23 @@ public abstract class Command implements CommandInterface { ...@@ -87,10 +87,23 @@ public abstract class Command implements CommandInterface {
trace = session.getDatabase().getTrace(Trace.COMMAND); trace = session.getDatabase().getTrace(Trace.COMMAND);
} }
/**
* Execute an updating statement, if this is possible.
*
* @return the update count
* @throws SQLException if the command is not an updating statement
*/
public int update() throws SQLException { public int update() throws SQLException {
throw Message.getSQLException(ErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY); throw Message.getSQLException(ErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY);
} }
/**
* Execute a query statement, if this is possible.
*
* @param maxrows the maximum number of rows returned
* @return the local result set
* @throws SQLException if the command is not a query
*/
public LocalResult query(int maxrows) throws SQLException { public LocalResult query(int maxrows) throws SQLException {
throw Message.getSQLException(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY); throw Message.getSQLException(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
} }
...@@ -107,6 +120,13 @@ public abstract class Command implements CommandInterface { ...@@ -107,6 +120,13 @@ public abstract class Command implements CommandInterface {
return executeQueryLocal(maxrows); return executeQueryLocal(maxrows);
} }
/**
* Execute a query and return a local result set.
* This method prepares everything and calls {@link query} finally.
*
* @param maxrows the maximum number of rows to return
* @return the local result set
*/
public LocalResult executeQueryLocal(int maxrows) throws SQLException { public LocalResult executeQueryLocal(int maxrows) throws SQLException {
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
Database database = session.getDatabase(); Database database = session.getDatabase();
...@@ -131,6 +151,11 @@ public abstract class Command implements CommandInterface { ...@@ -131,6 +151,11 @@ public abstract class Command implements CommandInterface {
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
} }
/**
* Check if this command has been cancelled, and throw an exception if yes.
*
* @throws SQLException if the statement has been cancelled
*/
public void checkCancelled() throws SQLException { public void checkCancelled() throws SQLException {
if (cancel) { if (cancel) {
cancel = false; cancel = false;
......
...@@ -219,6 +219,10 @@ public class CommandRemote implements CommandInterface { ...@@ -219,6 +219,10 @@ public class CommandRemote implements CommandInterface {
} }
} }
/**
* Cancel this current statement.
* This method is not yet implemented for this class.
*/
public void cancel() { public void cancel() {
// TODO server: support cancel // TODO server: support cancel
} }
......
...@@ -188,6 +188,12 @@ public class Parser { ...@@ -188,6 +188,12 @@ public class Parser {
database = session.getDatabase(); database = session.getDatabase();
} }
/**
* Parse the statement and prepare it for execution.
*
* @param sql the SQL statement to parse
* @return the prepared object
*/
public Prepared prepare(String sql) throws SQLException { public Prepared prepare(String sql) throws SQLException {
try { try {
Prepared p = parse(sql); Prepared p = parse(sql);
...@@ -198,6 +204,12 @@ public class Parser { ...@@ -198,6 +204,12 @@ public class Parser {
} }
} }
/**
* Parse the statement, but don't prepare it for execution.
*
* @param sql the SQL statement to parse
* @return the prepared object
*/
public Prepared parseOnly(String sql) throws SQLException { public Prepared parseOnly(String sql) throws SQLException {
try { try {
return parse(sql); return parse(sql);
...@@ -206,6 +218,12 @@ public class Parser { ...@@ -206,6 +218,12 @@ public class Parser {
} }
} }
/**
* Parse a statement or a list of statements, and prepare it for execution.
*
* @param sql the SQL statement to parse
* @return the command object
*/
public Command prepareCommand(String sql) throws SQLException { public Command prepareCommand(String sql) throws SQLException {
try { try {
Prepared p = parse(sql); Prepared p = parse(sql);
...@@ -2883,6 +2901,12 @@ public class Parser { ...@@ -2883,6 +2901,12 @@ public class Parser {
return getSaveTokenType(s); return getSaveTokenType(s);
} }
/**
* Checks if this string is a SQL keyword.
*
* @param s the token to check
* @return true if it is a keyword
*/
public static boolean isKeyword(String s) { public static boolean isKeyword(String s) {
if (s == null || s.length() == 0) { if (s == null || s.length() == 0) {
return false; return false;
...@@ -4444,6 +4468,12 @@ public class Parser { ...@@ -4444,6 +4468,12 @@ public class Parser {
} }
} }
/**
* Add double quotes around an identifier if required.
*
* @param s the identifier
* @return the quoted identifier
*/
public static String quoteIdentifier(String s) { public static String quoteIdentifier(String s) {
if (s == null || s.length() == 0) { if (s == null || s.length() == 0) {
return "\"\""; return "\"\"";
...@@ -4469,6 +4499,13 @@ public class Parser { ...@@ -4469,6 +4499,13 @@ public class Parser {
this.rightsChecked = rightsChecked; this.rightsChecked = rightsChecked;
} }
/**
* Parse a SQL code snippet that represents an expression.
*
* @param sql the code snippet
* @return the expression object
* @throws SQLException if the code snipped could not be parsed
*/
public Expression parseExpression(String sql) throws SQLException { public Expression parseExpression(String sql) throws SQLException {
parameters = new ObjectArray(); parameters = new ObjectArray();
initialize(sql); initialize(sql);
......
...@@ -70,6 +70,11 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -70,6 +70,11 @@ public class AlterTableAddConstraint extends SchemaCommand {
} }
} }
/**
* Try to execute the statement.
*
* @return the update count
*/
public int tryUpdate() throws SQLException { public int tryUpdate() throws SQLException {
session.commit(true); session.commit(true);
Database db = session.getDatabase(); Database db = session.getDatabase();
...@@ -350,6 +355,12 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -350,6 +355,12 @@ public class AlterTableAddConstraint extends SchemaCommand {
return indexColumns; return indexColumns;
} }
/**
* Set the referenced table.
*
* @param refSchema the schema
* @param ref the table name
*/
public void setRefTableName(Schema refSchema, String ref) { public void setRefTableName(Schema refSchema, String ref) {
this.refSchema = refSchema; this.refSchema = refSchema;
this.refTableName = ref; this.refTableName = ref;
......
...@@ -59,6 +59,11 @@ public class CreateTable extends SchemaCommand { ...@@ -59,6 +59,11 @@ public class CreateTable extends SchemaCommand {
this.tableName = tableName; this.tableName = tableName;
} }
/**
* Add a column to this table.
*
* @param column the column to add
*/
public void addColumn(Column column) { public void addColumn(Column column) {
if (columns == null) { if (columns == null) {
columns = new ObjectArray(); columns = new ObjectArray();
...@@ -66,6 +71,12 @@ public class CreateTable extends SchemaCommand { ...@@ -66,6 +71,12 @@ public class CreateTable extends SchemaCommand {
columns.add(column); columns.add(column);
} }
/**
* Add a constraint statement to this statement.
* The primary key definition is one possible constraint statement.
*
* @param command the statement to add
*/
public void addConstraintCommand(Prepared command) throws SQLException { public void addConstraintCommand(Prepared command) throws SQLException {
if (command instanceof CreateIndex) { if (command instanceof CreateIndex) {
constraintCommands.add(command); constraintCommands.add(command);
...@@ -236,10 +247,16 @@ public class CreateTable extends SchemaCommand { ...@@ -236,10 +247,16 @@ public class CreateTable extends SchemaCommand {
this.globalTemporary = globalTemporary; this.globalTemporary = globalTemporary;
} }
/**
* This temporary table is dropped on commit.
*/
public void setOnCommitDrop() { public void setOnCommitDrop() {
this.onCommitDrop = true; this.onCommitDrop = true;
} }
/**
* This temporary table is truncated on commit.
*/
public void setOnCommitTruncate() { public void setOnCommitTruncate() {
this.onCommitTruncate = true; this.onCommitTruncate = true;
} }
......
...@@ -24,23 +24,14 @@ public abstract class DefineCommand extends Prepared { ...@@ -24,23 +24,14 @@ public abstract class DefineCommand extends Prepared {
super(session); super(session);
} }
/**
* {@inheritDoc}
*/
public boolean isTransactional() { public boolean isTransactional() {
return false; return false;
} }
/**
* {@inheritDoc}
*/
public boolean isReadOnly() { public boolean isReadOnly() {
return false; return false;
} }
/**
* {@inheritDoc}
*/
public LocalResult queryMeta() { public LocalResult queryMeta() {
return null; return null;
} }
......
...@@ -30,6 +30,11 @@ public class DropTable extends SchemaCommand { ...@@ -30,6 +30,11 @@ public class DropTable extends SchemaCommand {
super(session, schema); super(session, schema);
} }
/**
* Chain another drop table statement to this statement.
*
* @param next the statement to add
*/
public void addNextDropTable(DropTable next) { public void addNextDropTable(DropTable next) {
if (this.next == null) { if (this.next == null) {
this.next = next; this.next = next;
......
...@@ -41,10 +41,20 @@ public class GrantRevoke extends DefineCommand { ...@@ -41,10 +41,20 @@ public class GrantRevoke extends DefineCommand {
this.operationType = operationType; this.operationType = operationType;
} }
/**
* Add the specified right bit to the rights bitmap.
*
* @param right the right bit
*/
public void addRight(int right) { public void addRight(int right) {
this.rightMask |= right; this.rightMask |= right;
} }
/**
* Add the specified role to the list of roles.
*
* @param roleName the role
*/
public void addRoleName(String roleName) { public void addRoleName(String roleName) {
if (roleNames == null) { if (roleNames == null) {
roleNames = new ObjectArray(); roleNames = new ObjectArray();
...@@ -163,6 +173,11 @@ public class GrantRevoke extends DefineCommand { ...@@ -163,6 +173,11 @@ public class GrantRevoke extends DefineCommand {
return false; return false;
} }
/**
* Add the specified table to the list of tables.
*
* @param table the table
*/
public void addTable(Table table) { public void addTable(Table table) {
tables.add(table); tables.add(table);
} }
......
...@@ -53,8 +53,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -53,8 +53,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
private String cipher; private String cipher;
private byte[] key; private byte[] key;
private FileStore store; private FileStore store;
private OutputStream outStream;
private InputStream inStream;
private String compressionAlgorithm; private String compressionAlgorithm;
public ScriptBase(Session session) { public ScriptBase(Session session) {
...@@ -110,8 +108,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -110,8 +108,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
// always use a big buffer, otherwise end-of-block is written a lot // always use a big buffer, otherwise end-of-block is written a lot
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS); out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS);
} else { } else {
outStream = FileUtils.openFileOutputStream(fileName, false); OutputStream o = FileUtils.openFileOutputStream(fileName, false);
out = new BufferedOutputStream(outStream, Constants.IO_BUFFER_SIZE); out = new BufferedOutputStream(o, Constants.IO_BUFFER_SIZE);
out = CompressTool.wrapOutputStream(out, compressionAlgorithm, Constants.SCRIPT_SQL); out = CompressTool.wrapOutputStream(out, compressionAlgorithm, Constants.SCRIPT_SQL);
} }
} }
...@@ -124,6 +122,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -124,6 +122,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
initStore(); initStore();
in = new FileStoreInputStream(store, this, compressionAlgorithm != null, false); in = new FileStoreInputStream(store, this, compressionAlgorithm != null, false);
} else { } else {
InputStream inStream;
try { try {
inStream = FileUtils.openFileInputStream(fileName); inStream = FileUtils.openFileInputStream(fileName);
} catch (IOException e) { } catch (IOException e) {
...@@ -146,10 +145,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -146,10 +145,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
store.closeSilently(); store.closeSilently();
store = null; store = null;
} }
IOUtils.closeSilently(inStream);
inStream = null;
IOUtils.closeSilently(outStream);
outStream = null;
} }
public boolean needRecompile() { public boolean needRecompile() {
......
...@@ -336,7 +336,9 @@ public class ScriptCommand extends ScriptBase { ...@@ -336,7 +336,9 @@ public class ScriptCommand extends ScriptBase {
Comment comment = (Comment) comments.get(i); Comment comment = (Comment) comments.get(i);
add(comment.getCreateSQL(), false); add(comment.getCreateSQL(), false);
} }
closeIO(); if (out != null) {
out.close();
}
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, fileName); throw Message.convertIOException(e, fileName);
} finally { } finally {
......
...@@ -78,6 +78,12 @@ public class SelectUnion extends Query { ...@@ -78,6 +78,12 @@ public class SelectUnion extends Query {
return result; return result;
} }
/**
* Execute the query without using the cache.
*
* @param maxrows the maximum number of rows to return
* @return the result
*/
public LocalResult queryWithoutCache(int maxrows) throws SQLException { public LocalResult queryWithoutCache(int maxrows) throws SQLException {
if (maxrows != 0) { if (maxrows != 0) {
if (limit != null) { if (limit != null) {
......
...@@ -72,6 +72,12 @@ public class SetTypes { ...@@ -72,6 +72,12 @@ public class SetTypes {
types.set(type, name); types.set(type, name);
} }
/**
* Get the set type number.
*
* @param name the set type name
* @return the number
*/
public static int getType(String name) { public static int getType(String name) {
for (int i = 0; i < types.size(); i++) { for (int i = 0; i < types.size(); i++) {
if (name.equals(types.get(i))) { if (name.equals(types.get(i))) {
...@@ -85,6 +91,12 @@ public class SetTypes { ...@@ -85,6 +91,12 @@ public class SetTypes {
return types; return types;
} }
/**
* Get the set type name.
*
* @param type the type number
* @return the name
*/
public static String getTypeName(int type) { public static String getTypeName(int type) {
return (String) types.get(type); return (String) types.get(type);
} }
......
...@@ -48,6 +48,12 @@ public class Update extends Prepared { ...@@ -48,6 +48,12 @@ public class Update extends Prepared {
this.condition = condition; this.condition = condition;
} }
/**
* Add an assignment of the form column = expression.
*
* @param column the column
* @param expression the expression
*/
public void setAssignment(Column column, Expression expression) public void setAssignment(Column column, Expression expression)
throws SQLException { throws SQLException {
int id = column.getColumnId(); int id = column.getColumnId();
......
...@@ -82,7 +82,7 @@ implements Xid ...@@ -82,7 +82,7 @@ implements Xid
return branchQualifier; return branchQualifier;
} }
/** /**
* The global transaction identifier. * The global transaction identifier.
* *
* @return the transaction id * @return the transaction id
......
...@@ -259,6 +259,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -259,6 +259,7 @@ public class FileSystemDisk extends FileSystem {
} }
out.write(buffer, 0, len); out.write(buffer, 0, len);
} }
out.close();
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, "original: " + original + " copy: " + copy); throw Message.convertIOException(e, "original: " + original + " copy: " + copy);
} finally { } finally {
......
...@@ -83,6 +83,7 @@ public class Csv implements SimpleRowSource { ...@@ -83,6 +83,7 @@ public class Csv implements SimpleRowSource {
writeRow(row); writeRow(row);
rows++; rows++;
} }
writer.close();
return rows; return rows;
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, null); throw Message.convertIOException(e, null);
......
...@@ -352,6 +352,7 @@ public class Recover implements DataHandler { ...@@ -352,6 +352,7 @@ public class Recover implements DataHandler {
out.write(buffer, 0, l); out.write(buffer, 0, l);
size += l; size += l;
} }
out.close();
} catch (Throwable e) { } catch (Throwable e) {
// this is usually not a problem, because we try both compressed and // this is usually not a problem, because we try both compressed and
// uncompressed // uncompressed
...@@ -544,6 +545,7 @@ public class Recover implements DataHandler { ...@@ -544,6 +545,7 @@ public class Recover implements DataHandler {
} }
} }
} }
writer.close();
} catch (Throwable e) { } catch (Throwable e) {
writeError(writer, e); writeError(writer, e);
} finally { } finally {
...@@ -663,6 +665,7 @@ public class Recover implements DataHandler { ...@@ -663,6 +665,7 @@ public class Recover implements DataHandler {
} }
writer.println("// [" + block + "] page:" + page + " blocks:" + blockCount + " storage:" + storageId); writer.println("// [" + block + "] page:" + page + " blocks:" + blockCount + " storage:" + storageId);
} }
writer.close();
} catch (Throwable e) { } catch (Throwable e) {
writeError(writer, e); writeError(writer, e);
} finally { } finally {
...@@ -833,6 +836,7 @@ public class Recover implements DataHandler { ...@@ -833,6 +836,7 @@ public class Recover implements DataHandler {
} }
writer.println("DROP ALIAS READ_CLOB;"); writer.println("DROP ALIAS READ_CLOB;");
writer.println("DROP ALIAS READ_BLOB;"); writer.println("DROP ALIAS READ_BLOB;");
writer.close();
} catch (Throwable e) { } catch (Throwable e) {
writeError(writer, e); writeError(writer, e);
} finally { } finally {
......
...@@ -161,6 +161,7 @@ public class Restore { ...@@ -161,6 +161,7 @@ public class Restore {
try { try {
out = FileUtils.openFileOutputStream(directory + File.separator + fileName, false); out = FileUtils.openFileOutputStream(directory + File.separator + fileName, false);
IOUtils.copy(zipIn, out); IOUtils.copy(zipIn, out);
out.close();
} finally { } finally {
IOUtils.closeSilently(out); IOUtils.closeSilently(out);
} }
......
...@@ -64,9 +64,11 @@ public class IOUtils { ...@@ -64,9 +64,11 @@ public class IOUtils {
public static long copyAndClose(InputStream in, OutputStream out) throws IOException { public static long copyAndClose(InputStream in, OutputStream out) throws IOException {
try { try {
return copyAndCloseInput(in, out); long len = copyAndCloseInput(in, out);
} finally {
out.close(); out.close();
return len;
} finally {
closeSilently(out);
} }
} }
...@@ -74,7 +76,7 @@ public class IOUtils { ...@@ -74,7 +76,7 @@ public class IOUtils {
try { try {
return copy(in, out); return copy(in, out);
} finally { } finally {
in.close(); closeSilently(in);
} }
} }
......
...@@ -115,13 +115,10 @@ public class CompareMode { ...@@ -115,13 +115,10 @@ public class CompareMode {
} }
/** /**
* Get the collation name * Get the collation name.
* *
* @param a the first string * @param l the locale
* @param b the second string * @return the name of the collation
* @param ignoreCase true if a case-insensitive comparison should be made
* @return -1 if the first string is 'smaller', 1 if the second string is
* smaller, and 0 if they are equal
*/ */
public static String getName(Locale l) { public static String getName(Locale l) {
Locale english = Locale.ENGLISH; Locale english = Locale.ENGLISH;
......
...@@ -166,8 +166,10 @@ create index idx_type on test(type); ...@@ -166,8 +166,10 @@ create index idx_type on test(type);
explain SELECT type, max(name) FROM TEST group by type; explain SELECT type, max(name) FROM TEST group by type;
SELECT type, max(name) FROM TEST group by type; SELECT type, max(name) FROM TEST group by type;
read uncommitted and multi-threaded mode at the same time is dangerous read uncommitted and multi-threaded mode at the same time is dangerous
add @author
CREATE TABLE in a before trigger results in an internal error. CREATE TABLE in a before trigger results in an internal error.
...@@ -212,6 +214,7 @@ New experimental optimization for GROUP BY queries if an index can be used ...@@ -212,6 +214,7 @@ New experimental optimization for GROUP BY queries if an index can be used
Roadmap: Roadmap:
Use ant 'get' to download dependencies Use ant 'get' to download dependencies
Index usage for UPDATE ... WHERE .. IN (SELECT...)
*/ */
......
...@@ -24,6 +24,10 @@ import org.h2.util.StringUtils; ...@@ -24,6 +24,10 @@ import org.h2.util.StringUtils;
/** /**
* CSVREAD and CSVWRITE tests. * CSVREAD and CSVWRITE tests.
*
* @author Thomas Mueller
* @author Sylvain Cuaz (testNull)
*
*/ */
public class TestCsv extends TestBase { public class TestCsv extends TestBase {
...@@ -40,8 +44,6 @@ public class TestCsv extends TestBase { ...@@ -40,8 +44,6 @@ public class TestCsv extends TestBase {
/** /**
* Test custom NULL string. * Test custom NULL string.
*
* @author Sylvain Cuaz, Thomas Mueller
*/ */
public void testNull() throws Exception { public void testNull() throws Exception {
deleteDb("csv"); deleteDb("csv");
......
...@@ -103,7 +103,7 @@ public class GenerateDoc { ...@@ -103,7 +103,7 @@ public class GenerateDoc {
String syntax = rs.getString("SYNTAX"); String syntax = rs.getString("SYNTAX");
syntax = PageParser.escapeHtml(syntax); syntax = PageParser.escapeHtml(syntax);
syntax = StringUtils.replaceAll(syntax, "<br />", ""); syntax = StringUtils.replaceAll(syntax, "<br />", "");
syntax = bnf.getSyntax(topic, syntax); syntax = bnf.getSyntaxHtml(topic, syntax);
map.put("syntax", syntax); map.put("syntax", syntax);
String link = topic.toLowerCase(); String link = topic.toLowerCase();
link = StringUtils.replaceAll(link, " ", ""); link = StringUtils.replaceAll(link, " ", "");
......
...@@ -32,8 +32,13 @@ import com.sun.javadoc.Type; ...@@ -32,8 +32,13 @@ import com.sun.javadoc.Type;
public class Doclet { public class Doclet {
private static final boolean INTERFACES_ONLY = Boolean.getBoolean("h2.interfacesOnly"); private static final boolean INTERFACES_ONLY = Boolean.getBoolean("h2.interfacesOnly");
private int errorCount;
public static boolean start(RootDoc root) throws IOException { public static boolean start(RootDoc root) throws IOException {
return new Doclet().startDoc(root);
}
public boolean startDoc(RootDoc root) throws IOException {
ClassDoc[] classes = root.classes(); ClassDoc[] classes = root.classes();
String[][] options = root.options(); String[][] options = root.options();
String destDir = System.getProperty("h2.destDir", "docs/javadoc"); String destDir = System.getProperty("h2.destDir", "docs/javadoc");
...@@ -46,6 +51,9 @@ public class Doclet { ...@@ -46,6 +51,9 @@ public class Doclet {
ClassDoc clazz = classes[i]; ClassDoc clazz = classes[i];
processClass(destDir, clazz); processClass(destDir, clazz);
} }
if (errorCount > 0) {
throw new IOException("FAILED: " + errorCount + " errors found");
}
return true; return true;
} }
...@@ -56,7 +64,7 @@ public class Doclet { ...@@ -56,7 +64,7 @@ public class Doclet {
return name; return name;
} }
private static void processClass(String destDir, ClassDoc clazz) throws IOException { private void processClass(String destDir, ClassDoc clazz) throws IOException {
String packageName = clazz.containingPackage().name(); String packageName = clazz.containingPackage().name();
String dir = destDir + "/" + packageName.replace('.', '/'); String dir = destDir + "/" + packageName.replace('.', '/');
(new File(dir)).mkdirs(); (new File(dir)).mkdirs();
...@@ -141,7 +149,8 @@ public class Doclet { ...@@ -141,7 +149,8 @@ public class Doclet {
String name = field.name(); String name = field.name();
String text = field.commentText(); String text = field.commentText();
if (text == null || text.trim().length() == 0) { if (text == null || text.trim().length() == 0) {
throw new Error("undocumented field? " + clazz.name() + "." + name + " " + field); System.out.println("Undocumented field? " + clazz.name() + "." + name + " " + field);
errorCount++;
} }
if (text.startsWith("INTERNAL")) { if (text.startsWith("INTERNAL")) {
continue; continue;
...@@ -290,15 +299,16 @@ public class Doclet { ...@@ -290,15 +299,16 @@ public class Doclet {
out.close(); out.close();
} }
private static String getFieldLink(String text, String constant, ClassDoc clazz, String name) { private String getFieldLink(String text, String constant, ClassDoc clazz, String name) {
String link = constant != null ? constant : name.toLowerCase(); String link = constant != null ? constant : name.toLowerCase();
int linkStart = text.indexOf("<code>"); int linkStart = text.indexOf("<code>");
if (linkStart >= 0) { if (linkStart >= 0) {
int linkEnd = text.indexOf("</code>", linkStart); int linkEnd = text.indexOf("</code>", linkStart);
link = text.substring(linkStart + "<code>".length(), linkEnd); link = text.substring(linkStart + "<code>".length(), linkEnd);
if (constant != null && !constant.equals(link)) { if (constant != null && !constant.equals(link)) {
throw new Error("wrong code tag? " + clazz.name() + "." + name + System.out.println("Wrong code tag? " + clazz.name() + "." + name +
" code: " + link + " constant: " + constant); " code: " + link + " constant: " + constant);
errorCount++;
} }
} }
if (Character.isDigit(link.charAt(0))) { if (Character.isDigit(link.charAt(0))) {
...@@ -322,26 +332,67 @@ public class Doclet { ...@@ -322,26 +332,67 @@ public class Doclet {
return false; return false;
} }
private static boolean skipMethod(MethodDoc method) { private boolean skipMethod(MethodDoc method) {
ClassDoc clazz = method.containingClass(); ClassDoc clazz = method.containingClass();
if (INTERFACES_ONLY && (!clazz.isAbstract() || !method.isAbstract()) && !clazz.isInterface()) { boolean isInterface = clazz.isInterface() || (clazz.isAbstract() && method.isAbstract());
if (INTERFACES_ONLY && !isInterface) {
return true; return true;
} }
String name = method.name(); String name = method.name();
if (!method.isPublic() || name.equals("finalize")) { if (!method.isPublic() || name.equals("finalize")) {
return true; return true;
} }
if (method.getRawCommentText().startsWith("@deprecated INTERNAL")) { if (method.getRawCommentText().trim().startsWith("@deprecated INTERNAL")) {
return true; return true;
} }
String firstSentence = getFirstSentence(method.firstSentenceTags()); String firstSentence = getFirstSentence(method.firstSentenceTags());
if (firstSentence == null || firstSentence.trim().length() == 0) { String raw = method.getRawCommentText();
throw new Error("undocumented method? " + clazz.name() + "." + name + " " if (firstSentence != null && firstSentence.startsWith("INTERNAL")) {
+ method.getRawCommentText());
}
if (firstSentence.startsWith("INTERNAL")) {
return true; return true;
}
if ((firstSentence == null || firstSentence.trim().length() == 0) && raw.indexOf("{@inheritDoc}") < 0) {
if (!doesOverride(method)) {
boolean setterOrGetter = name.startsWith("set") && method.parameters().length == 1;
setterOrGetter |= name.startsWith("get") && method.parameters().length == 0;
if (isInterface || !setterOrGetter) {
System.out.println("Undocumented method? " + " (" + clazz.name() + ".java:" + method.position().line() +") " + name + " " + raw);
errorCount++;
return true;
}
}
}
return false;
}
private boolean doesOverride(MethodDoc method) {
ClassDoc clazz = method.containingClass();
int test;
//System.out.println(clazz.name() + ". " + method.name());
ClassDoc[] ifs = clazz.interfaces();
int pc = method.parameters().length;
String name = method.name();
for (int i = 0;; i++) {
ClassDoc c;
if (i < ifs.length) {
c = ifs[i];
} else {
clazz = clazz.superclass();
if (clazz == null) {
break;
}
c = clazz;
}
MethodDoc[] ms = c.methods();
for (int j = 0; j < ms.length; j++) {
MethodDoc m = ms[j];
//System.out.println(" " + c.name() + ". " + m);
if (m.name().equals(name) && m.parameters().length == pc) {
//System.out.println(" true");
return true;
}
}
} }
//System.out.println(" false");
return false; return false;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论