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

--no commit message

--no commit message
上级 1e0d5542
......@@ -261,15 +261,20 @@
<mkdir dir="docs/javadocImpl"/>
<javadoc
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.*"
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"
/>
<!--
doclet="org.h2.tools.doclet.Doclet" docletpath="bin"
additionalparam="-J-Dh2.interfacesOnly=true -J-Dh2.destDir=docs/javadocImpl"
-->
<copy todir="docs/javadoc">
<fileset dir="src/docsrc/javadoc" includes="**/*"/>
</copy>
......
......@@ -21,7 +21,7 @@ Welcome to H2, the free SQL database. The main feature of H2 are:
</p>
<ul>
<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>JDBC and (partial) ODBC API; Web Client application
</li></ul>
......
......@@ -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
@mainWeb_1003_li
Written Java; can be compiled with GCJ (Linux)
Written in Java; can be compiled with GCJ (Linux)
@mainWeb_1004_li
Embedded, Server and Cluster modes
......
......@@ -1388,7 +1388,7 @@ links_1112_p=A database front end to register volunteers, partnership and donati
mainWeb_1000_h1=H2 Database Engine
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_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_1005_li=JDBC and (partial) ODBC API; Web Client application
mainWeb_1006_h3=Download
......
......@@ -134,7 +134,14 @@ public class Bnf {
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);
StringBuffer buff = new StringBuffer();
while (tokenizer.hasMoreTokens()) {
......@@ -269,6 +276,18 @@ public class Bnf {
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) {
HashMap next = new HashMap();
Sentence sentence = new Sentence();
......@@ -285,6 +304,10 @@ public class Bnf {
return next;
}
/**
* Cross-link all statements with each other.
* This method is called after updating the topics.
*/
public void linkStatements() {
for (Iterator it = ruleMap.values().iterator(); it.hasNext();) {
RuleHead r = (RuleHead) it.next();
......@@ -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) {
topic = StringUtils.toLowerEnglish(topic);
RuleHead head = (RuleHead) ruleMap.get(topic);
......@@ -304,6 +334,11 @@ public class Bnf {
}
}
/**
* Get the list of possible statements.
*
* @return the list of statements
*/
public ArrayList getStatements() {
return statements;
}
......
......@@ -77,7 +77,7 @@ public class RuleList implements Rule {
public String name() {
return null;
}
public Rule last() {
return get(list.size() - 1);
}
......
......@@ -15,6 +15,11 @@ import org.h2.server.web.DbTableOrView;
* Used for autocomplete.
*/
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;
static final int KEYWORD = 1;
static final int FUNCTION = 2;
......
......@@ -87,10 +87,23 @@ public abstract class Command implements CommandInterface {
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 {
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 {
throw Message.getSQLException(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
}
......@@ -107,6 +120,13 @@ public abstract class Command implements CommandInterface {
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 {
startTime = System.currentTimeMillis();
Database database = session.getDatabase();
......@@ -131,6 +151,11 @@ public abstract class Command implements CommandInterface {
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 {
if (cancel) {
cancel = false;
......
......@@ -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() {
// TODO server: support cancel
}
......
......@@ -188,6 +188,12 @@ public class Parser {
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 {
try {
Prepared p = parse(sql);
......@@ -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 {
try {
return parse(sql);
......@@ -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 {
try {
Prepared p = parse(sql);
......@@ -2883,6 +2901,12 @@ public class Parser {
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) {
if (s == null || s.length() == 0) {
return false;
......@@ -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) {
if (s == null || s.length() == 0) {
return "\"\"";
......@@ -4469,6 +4499,13 @@ public class Parser {
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 {
parameters = new ObjectArray();
initialize(sql);
......
......@@ -70,6 +70,11 @@ public class AlterTableAddConstraint extends SchemaCommand {
}
}
/**
* Try to execute the statement.
*
* @return the update count
*/
public int tryUpdate() throws SQLException {
session.commit(true);
Database db = session.getDatabase();
......@@ -350,6 +355,12 @@ public class AlterTableAddConstraint extends SchemaCommand {
return indexColumns;
}
/**
* Set the referenced table.
*
* @param refSchema the schema
* @param ref the table name
*/
public void setRefTableName(Schema refSchema, String ref) {
this.refSchema = refSchema;
this.refTableName = ref;
......
......@@ -59,6 +59,11 @@ public class CreateTable extends SchemaCommand {
this.tableName = tableName;
}
/**
* Add a column to this table.
*
* @param column the column to add
*/
public void addColumn(Column column) {
if (columns == null) {
columns = new ObjectArray();
......@@ -66,6 +71,12 @@ public class CreateTable extends SchemaCommand {
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 {
if (command instanceof CreateIndex) {
constraintCommands.add(command);
......@@ -236,10 +247,16 @@ public class CreateTable extends SchemaCommand {
this.globalTemporary = globalTemporary;
}
/**
* This temporary table is dropped on commit.
*/
public void setOnCommitDrop() {
this.onCommitDrop = true;
}
/**
* This temporary table is truncated on commit.
*/
public void setOnCommitTruncate() {
this.onCommitTruncate = true;
}
......
......@@ -24,23 +24,14 @@ public abstract class DefineCommand extends Prepared {
super(session);
}
/**
* {@inheritDoc}
*/
public boolean isTransactional() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isReadOnly() {
return false;
}
/**
* {@inheritDoc}
*/
public LocalResult queryMeta() {
return null;
}
......
......@@ -30,6 +30,11 @@ public class DropTable extends SchemaCommand {
super(session, schema);
}
/**
* Chain another drop table statement to this statement.
*
* @param next the statement to add
*/
public void addNextDropTable(DropTable next) {
if (this.next == null) {
this.next = next;
......
......@@ -41,10 +41,20 @@ public class GrantRevoke extends DefineCommand {
this.operationType = operationType;
}
/**
* Add the specified right bit to the rights bitmap.
*
* @param right the right bit
*/
public void addRight(int right) {
this.rightMask |= right;
}
/**
* Add the specified role to the list of roles.
*
* @param roleName the role
*/
public void addRoleName(String roleName) {
if (roleNames == null) {
roleNames = new ObjectArray();
......@@ -163,6 +173,11 @@ public class GrantRevoke extends DefineCommand {
return false;
}
/**
* Add the specified table to the list of tables.
*
* @param table the table
*/
public void addTable(Table table) {
tables.add(table);
}
......
......@@ -53,8 +53,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
private String cipher;
private byte[] key;
private FileStore store;
private OutputStream outStream;
private InputStream inStream;
private String compressionAlgorithm;
public ScriptBase(Session session) {
......@@ -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
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS);
} else {
outStream = FileUtils.openFileOutputStream(fileName, false);
out = new BufferedOutputStream(outStream, Constants.IO_BUFFER_SIZE);
OutputStream o = FileUtils.openFileOutputStream(fileName, false);
out = new BufferedOutputStream(o, Constants.IO_BUFFER_SIZE);
out = CompressTool.wrapOutputStream(out, compressionAlgorithm, Constants.SCRIPT_SQL);
}
}
......@@ -124,6 +122,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
initStore();
in = new FileStoreInputStream(store, this, compressionAlgorithm != null, false);
} else {
InputStream inStream;
try {
inStream = FileUtils.openFileInputStream(fileName);
} catch (IOException e) {
......@@ -146,10 +145,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
store.closeSilently();
store = null;
}
IOUtils.closeSilently(inStream);
inStream = null;
IOUtils.closeSilently(outStream);
outStream = null;
}
public boolean needRecompile() {
......
......@@ -336,7 +336,9 @@ public class ScriptCommand extends ScriptBase {
Comment comment = (Comment) comments.get(i);
add(comment.getCreateSQL(), false);
}
closeIO();
if (out != null) {
out.close();
}
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
} finally {
......
......@@ -78,6 +78,12 @@ public class SelectUnion extends Query {
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 {
if (maxrows != 0) {
if (limit != null) {
......
......@@ -72,6 +72,12 @@ public class SetTypes {
types.set(type, name);
}
/**
* Get the set type number.
*
* @param name the set type name
* @return the number
*/
public static int getType(String name) {
for (int i = 0; i < types.size(); i++) {
if (name.equals(types.get(i))) {
......@@ -85,6 +91,12 @@ public class SetTypes {
return types;
}
/**
* Get the set type name.
*
* @param type the type number
* @return the name
*/
public static String getTypeName(int type) {
return (String) types.get(type);
}
......
......@@ -48,6 +48,12 @@ public class Update extends Prepared {
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)
throws SQLException {
int id = column.getColumnId();
......
......@@ -82,7 +82,7 @@ implements Xid
return branchQualifier;
}
/**
/**
* The global transaction identifier.
*
* @return the transaction id
......
......@@ -259,6 +259,7 @@ public class FileSystemDisk extends FileSystem {
}
out.write(buffer, 0, len);
}
out.close();
} catch (IOException e) {
throw Message.convertIOException(e, "original: " + original + " copy: " + copy);
} finally {
......
......@@ -83,6 +83,7 @@ public class Csv implements SimpleRowSource {
writeRow(row);
rows++;
}
writer.close();
return rows;
} catch (IOException e) {
throw Message.convertIOException(e, null);
......
......@@ -352,6 +352,7 @@ public class Recover implements DataHandler {
out.write(buffer, 0, l);
size += l;
}
out.close();
} catch (Throwable e) {
// this is usually not a problem, because we try both compressed and
// uncompressed
......@@ -544,6 +545,7 @@ public class Recover implements DataHandler {
}
}
}
writer.close();
} catch (Throwable e) {
writeError(writer, e);
} finally {
......@@ -663,6 +665,7 @@ public class Recover implements DataHandler {
}
writer.println("// [" + block + "] page:" + page + " blocks:" + blockCount + " storage:" + storageId);
}
writer.close();
} catch (Throwable e) {
writeError(writer, e);
} finally {
......@@ -833,6 +836,7 @@ public class Recover implements DataHandler {
}
writer.println("DROP ALIAS READ_CLOB;");
writer.println("DROP ALIAS READ_BLOB;");
writer.close();
} catch (Throwable e) {
writeError(writer, e);
} finally {
......
......@@ -161,6 +161,7 @@ public class Restore {
try {
out = FileUtils.openFileOutputStream(directory + File.separator + fileName, false);
IOUtils.copy(zipIn, out);
out.close();
} finally {
IOUtils.closeSilently(out);
}
......
......@@ -64,9 +64,11 @@ public class IOUtils {
public static long copyAndClose(InputStream in, OutputStream out) throws IOException {
try {
return copyAndCloseInput(in, out);
} finally {
long len = copyAndCloseInput(in, out);
out.close();
return len;
} finally {
closeSilently(out);
}
}
......@@ -74,7 +76,7 @@ public class IOUtils {
try {
return copy(in, out);
} finally {
in.close();
closeSilently(in);
}
}
......
......@@ -115,13 +115,10 @@ public class CompareMode {
}
/**
* Get the collation name
* Get the collation name.
*
* @param a the first string
* @param b the second string
* @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
* @param l the locale
* @return the name of the collation
*/
public static String getName(Locale l) {
Locale english = Locale.ENGLISH;
......
......@@ -166,8 +166,10 @@ create index idx_type on test(type);
explain 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
add @author
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
Roadmap:
Use ant 'get' to download dependencies
Index usage for UPDATE ... WHERE .. IN (SELECT...)
*/
......
......@@ -24,6 +24,10 @@ import org.h2.util.StringUtils;
/**
* CSVREAD and CSVWRITE tests.
*
* @author Thomas Mueller
* @author Sylvain Cuaz (testNull)
*
*/
public class TestCsv extends TestBase {
......@@ -40,8 +44,6 @@ public class TestCsv extends TestBase {
/**
* Test custom NULL string.
*
* @author Sylvain Cuaz, Thomas Mueller
*/
public void testNull() throws Exception {
deleteDb("csv");
......
......@@ -103,7 +103,7 @@ public class GenerateDoc {
String syntax = rs.getString("SYNTAX");
syntax = PageParser.escapeHtml(syntax);
syntax = StringUtils.replaceAll(syntax, "<br />", "");
syntax = bnf.getSyntax(topic, syntax);
syntax = bnf.getSyntaxHtml(topic, syntax);
map.put("syntax", syntax);
String link = topic.toLowerCase();
link = StringUtils.replaceAll(link, " ", "");
......
......@@ -32,8 +32,13 @@ import com.sun.javadoc.Type;
public class Doclet {
private static final boolean INTERFACES_ONLY = Boolean.getBoolean("h2.interfacesOnly");
private int errorCount;
public static boolean start(RootDoc root) throws IOException {
return new Doclet().startDoc(root);
}
public boolean startDoc(RootDoc root) throws IOException {
ClassDoc[] classes = root.classes();
String[][] options = root.options();
String destDir = System.getProperty("h2.destDir", "docs/javadoc");
......@@ -46,6 +51,9 @@ public class Doclet {
ClassDoc clazz = classes[i];
processClass(destDir, clazz);
}
if (errorCount > 0) {
throw new IOException("FAILED: " + errorCount + " errors found");
}
return true;
}
......@@ -56,7 +64,7 @@ public class Doclet {
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 dir = destDir + "/" + packageName.replace('.', '/');
(new File(dir)).mkdirs();
......@@ -141,7 +149,8 @@ public class Doclet {
String name = field.name();
String text = field.commentText();
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")) {
continue;
......@@ -290,15 +299,16 @@ public class Doclet {
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();
int linkStart = text.indexOf("<code>");
if (linkStart >= 0) {
int linkEnd = text.indexOf("</code>", linkStart);
link = text.substring(linkStart + "<code>".length(), linkEnd);
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);
errorCount++;
}
}
if (Character.isDigit(link.charAt(0))) {
......@@ -322,26 +332,67 @@ public class Doclet {
return false;
}
private static boolean skipMethod(MethodDoc method) {
private boolean skipMethod(MethodDoc method) {
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;
}
String name = method.name();
if (!method.isPublic() || name.equals("finalize")) {
return true;
}
if (method.getRawCommentText().startsWith("@deprecated INTERNAL")) {
if (method.getRawCommentText().trim().startsWith("@deprecated INTERNAL")) {
return true;
}
String firstSentence = getFirstSentence(method.firstSentenceTags());
if (firstSentence == null || firstSentence.trim().length() == 0) {
throw new Error("undocumented method? " + clazz.name() + "." + name + " "
+ method.getRawCommentText());
}
if (firstSentence.startsWith("INTERNAL")) {
String raw = method.getRawCommentText();
if (firstSentence != null && firstSentence.startsWith("INTERNAL")) {
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;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论