提交 2c2e30e7 authored 作者: Thomas Mueller's avatar Thomas Mueller

javadocs

上级 8e2e57e5
......@@ -17,7 +17,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Deadlocks are now detected. One transaction is rolled back automatically.
<li>RunScript tool: new options to show and check the results of queries.
</li><li>Deadlocks are now detected. One transaction is rolled back automatically.
</li><li>The Lucene fulltext index was always re-created when opening a
database with fulltext index enabled.
</li><li>Support for overloaded Java methods. A user defined function can
......
......@@ -238,6 +238,15 @@ by the user; require a license to Oracle; lack advanced
query/retrieval; and the ability to handle chemical structures.
</p>
<p><a href="http://www.ontologyworks.com/">
Ontology Works</a><br />
This company provides semantic technologies including deductive
information repositories (the Ontology Works Knowledge Servers),
semantic information fusion and semantic federation of legacy
databases, ontology-based domain modeling, and management of the
distributed enterprise.
</p>
<p><a href="http://www.orionserver.com/">
Orion</a><br />
J2EE Application Server.
......
......@@ -3069,7 +3069,7 @@ public class Parser {
getSyntaxError();
}
Expression expr = readExpression();
column.setComputed(true, expr);
column.setComputedExpression(expr);
} else if (readIf("DEFAULT")) {
Expression defaultExpression = readExpression();
column.setDefaultExpression(session, defaultExpression);
......
......@@ -13,11 +13,11 @@ import java.io.Reader;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.constant.SysProperties;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.LocalResult;
import org.h2.util.ScriptReader;
import org.h2.util.StringUtils;
/**
* This class represents the statement
......@@ -25,7 +25,7 @@ import org.h2.util.StringUtils;
*/
public class RunScriptCommand extends ScriptBase {
private String charset = StringUtils.getDefaultCharset();
private String charset = SysProperties.FILE_ENCODING;
public RunScriptCommand(Session session) {
super(session);
......
......@@ -195,7 +195,7 @@ public class Constants {
* The number of milliseconds after which to check for a deadlock if locking
* is not successful.
*/
public static final int DEADLOCK_CHECK = 500;
public static final int DEADLOCK_CHECK = 100;
/**
* The default value of the ALLOW_LITERALS setting
......
......@@ -563,33 +563,9 @@ public class Database implements DataHandler {
false, false), Index.EMPTY_HEAD, null);
objectIds.set(0);
// there could be views on system tables, so they must be added first
addMetaData(MetaTable.TABLES);
addMetaData(MetaTable.COLUMNS);
addMetaData(MetaTable.INDEXES);
addMetaData(MetaTable.TABLE_TYPES);
addMetaData(MetaTable.TYPE_INFO);
addMetaData(MetaTable.CATALOGS);
addMetaData(MetaTable.SETTINGS);
addMetaData(MetaTable.HELP);
addMetaData(MetaTable.SEQUENCES);
addMetaData(MetaTable.USERS);
addMetaData(MetaTable.ROLES);
addMetaData(MetaTable.RIGHTS);
addMetaData(MetaTable.FUNCTION_ALIASES);
addMetaData(MetaTable.SCHEMATA);
addMetaData(MetaTable.TABLE_PRIVILEGES);
addMetaData(MetaTable.COLUMN_PRIVILEGES);
addMetaData(MetaTable.COLLATIONS);
addMetaData(MetaTable.VIEWS);
addMetaData(MetaTable.IN_DOUBT);
addMetaData(MetaTable.CROSS_REFERENCES);
addMetaData(MetaTable.CONSTRAINTS);
addMetaData(MetaTable.FUNCTION_COLUMNS);
addMetaData(MetaTable.CONSTANTS);
addMetaData(MetaTable.DOMAINS);
addMetaData(MetaTable.TRIGGERS);
addMetaData(MetaTable.SESSIONS);
addMetaData(MetaTable.LOCKS);
for (int i = 0; i < MetaTable.getMetaTableTypeCount(); i++) {
addMetaData(i);
}
starting = true;
Cursor cursor = metaIdIndex.find(systemSession, null, null);
// first, create all function aliases and sequences because
......
......@@ -148,8 +148,14 @@ public class Column {
}
}
public void setComputed(boolean computed, Expression expression) {
this.isComputed = computed;
/**
* Set the default value in the form of a computed expression of other
* columns.
*
* @param expression the computed expression
*/
public void setComputedExpression(Expression expression) {
this.isComputed = true;
this.defaultExpression = expression;
}
......@@ -162,6 +168,12 @@ public class Column {
return table;
}
/**
* Set the default expression.
*
* @param session the session
* @param defaultExpression the default expression
*/
public void setDefaultExpression(Session session, Expression defaultExpression) throws SQLException {
// also to test that no column names are used
if (defaultExpression != null) {
......@@ -205,6 +217,14 @@ public class Column {
nullable = b;
}
/**
* Validate the value, convert it if required, and update the sequence value
* if required. If the value is null, the default value (NULL if no default
* is set) is returned. Check constraints are validated as well.
*
* @param session the session
* @param value the value or null
*/
public Value validateConvertUpdateSequence(Session session, Value value) throws SQLException {
if (value == null) {
if (defaultExpression == null) {
......@@ -325,6 +345,11 @@ public class Column {
setSequence(sequence);
}
/**
* Prepare all expressions of this column.
*
* @param session the session
*/
public void prepareExpression(Session session) throws SQLException {
if (defaultExpression != null) {
computeTableFilter = new TableFilter(session, table, null, false, null);
......@@ -421,6 +446,13 @@ public class Column {
return autoIncrement;
}
/**
* Set the autoincrement flag and related properties of this column.
*
* @param autoInc the new autoincrement flag
* @param start the sequence start value
* @param increment the sequence increment
*/
public void setAutoIncrement(boolean autoInc, long start, long increment) {
this.autoIncrement = autoInc;
this.start = start;
......@@ -435,6 +467,12 @@ public class Column {
this.convertNullToDefault = convert;
}
/**
* Rename the column. This method will only set the column name to the new
* value.
*
* @param newName the new column name
*/
public void rename(String newName) {
this.name = newName;
}
......@@ -467,6 +505,13 @@ public class Column {
this.selectivity = selectivity;
}
/**
* Add a check constraint expression to this column. An existing check
* constraint constraint is added using AND.
*
* @param session the session
* @param expr the (additional) constraint
*/
public void addCheckConstraint(Session session, Expression expr) throws SQLException {
resolver = new SingleColumnResolver(this);
synchronized (this) {
......@@ -491,6 +536,13 @@ public class Column {
checkConstraintSQL = getCheckConstraintSQL(session, name);
}
/**
* Get the check constraint expression for this column if set.
*
* @param session the session
* @param asColumnName the column name to use
* @return the constraint expression
*/
public Expression getCheckConstraint(Session session, String asColumnName) throws SQLException {
if (checkConstraint == null) {
return null;
......
......@@ -137,6 +137,12 @@ public class FunctionTable extends Table {
throw Message.getUnsupportedException();
}
/**
* Read the result set from the function.
*
* @param session the session
* @return the result set
*/
public LocalResult getResult(Session session) throws SQLException {
function.optimize(session);
Value v = function.getValue(session);
......
......@@ -15,10 +15,28 @@ import org.h2.result.SortOrder;
* indexes support descending sorted columns.
*/
public class IndexColumn {
/**
* The column name.
*/
public String columnName;
/**
* The column, or null if not set.
*/
public Column column;
/**
* The sort type. Ascending (the default) and descending are supported;
* nulls can be sorted first or last.
*/
public int sortType = SortOrder.ASCENDING;
/**
* Get the SQL snippet for this index column.
*
* @return the SQL snippet
*/
public String getSQL() {
StringBuffer buff = new StringBuffer(column.getSQL());
if ((sortType & SortOrder.DESCENDING) != 0) {
......@@ -32,6 +50,13 @@ public class IndexColumn {
return buff.toString();
}
/**
* Create an array of index columns from a list of columns. The default sort
* type is used.
*
* @param columns the column list
* @return the index column array
*/
public static IndexColumn[] wrap(Column[] columns) {
IndexColumn[] list = new IndexColumn[columns.length];
for (int i = 0; i < list.length; i++) {
......@@ -41,6 +66,12 @@ public class IndexColumn {
return list;
}
/**
* Map the columns using the column names and the specified table.
*
* @param indexColumns the column list with column names set
* @param table the table from where to map the column names to columns
*/
public static void mapColumns(IndexColumn[] indexColumns, Table table) throws SQLException {
for (int i = 0; i < indexColumns.length; i++) {
IndexColumn col = indexColumns[i];
......
......@@ -67,16 +67,46 @@ public class MetaTable extends Table {
// TODO INFORMATION_SCHEMA.tables: select table_name
// from INFORMATION_SCHEMA.tables where TABLE_TYPE = 'BASE TABLE'
public static final int TABLES = 0, COLUMNS = 1, INDEXES = 2, TABLE_TYPES = 3, TYPE_INFO = 4, CATALOGS = 5,
SETTINGS = 6, HELP = 7, SEQUENCES = 8, USERS = 9, ROLES = 10, RIGHTS = 11, FUNCTION_ALIASES = 12,
SCHEMATA = 13, TABLE_PRIVILEGES = 14, COLUMN_PRIVILEGES = 15, COLLATIONS = 16, VIEWS = 17, IN_DOUBT = 18,
CROSS_REFERENCES = 19, CONSTRAINTS = 20, FUNCTION_COLUMNS = 21, CONSTANTS = 22, DOMAINS = 23,
TRIGGERS = 24, SESSIONS = 25, LOCKS = 26;
private static final int TABLES = 0;
private static final int COLUMNS = 1;
private static final int INDEXES = 2;
private static final int TABLE_TYPES = 3;
private static final int TYPE_INFO = 4;
private static final int CATALOGS = 5;
private static final int SETTINGS = 6;
private static final int HELP = 7;
private static final int SEQUENCES = 8;
private static final int USERS = 9;
private static final int ROLES = 10;
private static final int RIGHTS = 11;
private static final int FUNCTION_ALIASES = 12;
private static final int SCHEMATA = 13;
private static final int TABLE_PRIVILEGES = 14;
private static final int COLUMN_PRIVILEGES = 15;
private static final int COLLATIONS = 16;
private static final int VIEWS = 17;
private static final int IN_DOUBT = 18;
private static final int CROSS_REFERENCES = 19;
private static final int CONSTRAINTS = 20;
private static final int FUNCTION_COLUMNS = 21;
private static final int CONSTANTS = 22;
private static final int DOMAINS = 23;
private static final int TRIGGERS = 24;
private static final int SESSIONS = 25;
private static final int LOCKS = 26;
private static final int META_TABLE_TYPE_COUNT = LOCKS + 1;
private final int type;
private final int indexColumn;
private MetaIndex index;
/**
* Create a new metadata table.
*
* @param schema the schema
* @param id the object id
* @param type the meta table type
*/
public MetaTable(Schema schema, int id, int type) throws SQLException {
// tableName will be set later
super(schema, id, null, true);
......@@ -543,6 +573,15 @@ public class MetaTable extends Table {
return s == null ? "" : s;
}
/**
* Generate the data for the given metadata table using the given first and
* last row filters.
*
* @param session the session
* @param first the first row to return
* @param last the last row to return
* @return the generated rows
*/
public ObjectArray generateRows(Session session, SearchRow first, SearchRow last) throws SQLException {
Value indexFrom = null, indexTo = null;
......@@ -1664,4 +1703,14 @@ public class MetaTable extends Table {
return null;
}
/**
* Get the number of meta table types. Supported meta table
* types are 0 .. this value - 1.
*
* @return the number of meta table types
*/
public static int getMetaTableTypeCount() {
return META_TABLE_TYPE_COUNT;
}
}
......@@ -24,6 +24,13 @@ public class Plan {
private final Expression[] allConditions;
private final TableFilter[] allFilters;
/**
* Create a query plan with the given order.
*
* @param filters the tables of the query
* @param count the number of table items
* @param condition the condition in the WHERE clause
*/
public Plan(TableFilter[] filters, int count, Expression condition) {
this.filters = new TableFilter[count];
System.arraycopy(filters, 0, this.filters, 0, count);
......@@ -48,14 +55,28 @@ public class Plan {
all.toArray(allFilters);
}
/**
* Get the plan item for the given table.
*
* @param filter the table
* @return the plan item
*/
public PlanItem getItem(TableFilter filter) {
return (PlanItem) planItems.get(filter);
}
/**
* The the list of tables.
*
* @return the list of tables
*/
public TableFilter[] getFilters() {
return filters;
}
/**
* Remove all index conditions that can not be used.
*/
public void removeUnusableIndexConditions() {
for (int i = 0; i < allFilters.length; i++) {
TableFilter f = allFilters[i];
......@@ -74,6 +95,12 @@ public class Plan {
}
}
/**
* Calculate the cost of this query plan.
*
* @param session the session
* @return the cost
*/
public double calculateCost(Session session) throws SQLException {
double cost = 1;
boolean invalidPlan = false;
......
......@@ -25,10 +25,21 @@ import org.h2.value.Value;
*/
public class RangeTable extends Table {
/**
* The name of the range table.
*/
public static final String NAME = "SYSTEM_RANGE";
private Expression min, max;
private boolean optimized;
/**
* Create a new range with the given start and end expressions.
*
* @param schema the schema (always the main schema)
* @param min the start expression
* @param max the end expression
*/
public RangeTable(Schema schema, Expression min, Expression max) throws SQLException {
super(schema, 0, NAME, true);
Column[] cols = new Column[]{
......@@ -107,14 +118,26 @@ public class RangeTable extends Table {
return new RangeIndex(this, IndexColumn.wrap(columns));
}
public long getMin(Session s) throws SQLException {
optimize(s);
return min.getValue(s).getLong();
/**
* Calculate and get the start value of this range.
*
* @param session the session
* @return the start value
*/
public long getMin(Session session) throws SQLException {
optimize(session);
return min.getValue(session).getLong();
}
public long getMax(Session s) throws SQLException {
optimize(s);
return max.getValue(s).getLong();
/**
* Calculate and get the end value of this range.
*
* @param session the session
* @return the end value
*/
public long getMax(Session session) throws SQLException {
optimize(session);
return max.getValue(session).getLong();
}
private void optimize(Session s) throws SQLException {
......
......@@ -419,7 +419,7 @@ public class TableData extends Table implements RecordReader {
}
}
// don't wait too long so that deadlocks are detected early
long sleep = Math.min(Constants.DEADLOCK_CHECK, (max - now) / 4);
long sleep = Math.min(Constants.DEADLOCK_CHECK, max - now);
if (sleep == 0) {
sleep = 1;
}
......
......@@ -32,7 +32,6 @@ import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringCache;
import org.h2.util.StringUtils;
/**
* A facility to read from and write to CSV (comma separated values) files.
......@@ -41,7 +40,7 @@ import org.h2.util.StringUtils;
*/
public class Csv implements SimpleRowSource {
private String streamCharset = StringUtils.getDefaultCharset();
private String streamCharset = SysProperties.FILE_ENCODING;
private int bufferSize = 8 * 1024;
private String[] columnNames;
private char fieldSeparatorRead = ',';
......
......@@ -40,6 +40,9 @@ import org.h2.util.Tool;
*/
public class RunScript extends Tool {
private boolean showResults;
private boolean checkResults;
private void showUsage() {
out.println("Runs a SQL script.");
out.println("java "+getClass().getName() + "\n" +
......@@ -49,6 +52,8 @@ public class RunScript extends Tool {
" [-script <file>] The script file to run (default: backup.sql)\n" +
" [-driver <class>] The JDBC driver class to use (not required in most cases)\n" +
" [-quiet] Do not print progress information\n" +
" [-showResults] Show the statements and the results of queries\n" +
" [-checkResults] Check if the query results match the expected results\n" +
" [-options ...] The list of options (only for H2 embedded mode)");
out.println("See also http://h2database.com/javadoc/" + getClass().getName().replace('.', '/') + ".html");
}
......@@ -63,9 +68,13 @@ public class RunScript extends Tool {
* <li>-user username </li>
* <li>-password password </li>
* <li>-script filename (default file name is backup.sql) </li>
* <li>-driver driver the JDBC driver class name (not required for most
* <li>-driver driver (the JDBC driver class name; not required for most
* databases) </li>
* <li>-options to specify a list of options (only for H2 and only when
* <li>-quiet (do not print progress information) </li>
* <li>-showResults (show the statements and the results of queries)</li>
* <li>-checkResults (check if the query results match the expected results</li>
* <li>-quiet (do not print progress information)</li>
* <li>-options (to specify a list of options ;only for H2 and only when
* using the embedded mode) </li>
* </ul>
* To include local files when using remote databases, use the special
......@@ -103,6 +112,10 @@ public class RunScript extends Tool {
password = args[++i];
} else if (arg.equals("-continueOnError")) {
continueOnError = true;
} else if (arg.equals("-checkResults")) {
checkResults = true;
} else if (arg.equals("-showResults")) {
showResults = true;
} else if (arg.equals("-script")) {
script = args[++i];
} else if (arg.equals("-time")) {
......@@ -196,8 +209,9 @@ public class RunScript extends Tool {
if (sql == null) {
break;
}
sql = sql.trim();
if (sql.startsWith("@") && StringUtils.toUpperEnglish(sql).startsWith("@INCLUDE")) {
String trim = sql.trim();
if (trim.startsWith("@") && StringUtils.toUpperEnglish(trim).startsWith("@INCLUDE")) {
sql = trim;
sql = sql.substring("@INCLUDE".length()).trim();
if (!FileUtils.isAbsolute(sql)) {
sql = path + File.separator + sql;
......@@ -205,9 +219,46 @@ public class RunScript extends Tool {
process(conn, sql, continueOnError, charsetName);
} else {
try {
if (sql.trim().length() > 0) {
if (trim.length() > 0) {
if (showResults && !trim.startsWith("-->")) {
out.print(sql + ";");
}
if (showResults || checkResults) {
boolean query = stat.execute(sql);
if (query) {
ResultSet rs = stat.getResultSet();
int columns = rs.getMetaData().getColumnCount();
StringBuffer buff = new StringBuffer();
while (rs.next()) {
buff.append("\n-->");
for (int i = 0; i < columns; i++) {
String s = rs.getString(i + 1);
if (s != null) {
s = StringUtils.replaceAll(s, "\r\n", "\n");
s = StringUtils.replaceAll(s, "\n", "\n--> ");
s = StringUtils.replaceAll(s, "\r", "\r--> ");
}
buff.append(' ');
buff.append(s);
}
}
buff.append("\n;");
String result = buff.toString();
if (showResults) {
out.print(result);
}
if (checkResults) {
String expected = r.readStatement() + ";";
if (!expected.equals(result)) {
throw new SQLException("Unexpected output, got:\n" + result + "\nExpected:\n" + expected);
}
}
}
} else {
stat.execute(sql);
}
}
} catch (SQLException e) {
if (continueOnError) {
e.printStackTrace(out);
......@@ -266,4 +317,23 @@ public class RunScript extends Tool {
}
}
/**
* If the statements as well as the results should be printed to the output.
*
* @param show true if yes
*/
public void setShowResults(boolean show) {
this.showResults = show;
}
/**
* If results of statements should be cross-checked with the expected
* output. The expected result is the next line(s) of the script, commented.
*
* @param check true if yes
*/
public void setCheckResults(boolean check) {
this.checkResults = check;
}
}
......@@ -58,6 +58,11 @@ public abstract class HashBase {
*/
protected abstract void rehash(int newLevel) throws SQLException;
/**
* Get the size of the map.
*
* @return the size
*/
public int size() {
return size + (zeroKey ? 1 : 0);
}
......
......@@ -36,6 +36,11 @@ public class IOUtils {
// utility class
}
/**
* Close an output stream without throwing an exception.
*
* @param out the output stream or null
*/
public static void closeSilently(OutputStream out) {
if (out != null) {
try {
......@@ -47,6 +52,15 @@ public class IOUtils {
}
}
/**
* Skip a number of bytes in an input stream.
*
* @param in the input stream
* @param skip the number of bytes to skip
* @throws EOFException if the end of file has been reached before all bytes
* could be skipped
* @throws IOException if an IO exception occured while skipping
*/
public static void skipFully(InputStream in, long skip) throws IOException {
while (skip > 0) {
long skipped = in.skip(skip);
......@@ -57,6 +71,15 @@ public class IOUtils {
}
}
/**
* Skip a number of characters in a reader.
*
* @param reader the reader
* @param skip the number of characters to skip
* @throws EOFException if the end of file has been reached before all
* characters could be skipped
* @throws IOException if an IO exception occured while skipping
*/
public static void skipFully(Reader reader, long skip) throws IOException {
while (skip > 0) {
long skipped = reader.skip(skip);
......@@ -67,6 +90,14 @@ public class IOUtils {
}
}
/**
* Copy all data from the input stream to the output stream and close both
* streams. Exceptions while closing are ignored.
*
* @param in the input stream
* @param out the output stream
* @return the number of bytes copied
*/
public static long copyAndClose(InputStream in, OutputStream out) throws IOException {
try {
long len = copyAndCloseInput(in, out);
......@@ -77,6 +108,14 @@ public class IOUtils {
}
}
/**
* Copy all data from the input stream to the output stream and close the
* input stream. Exceptions while closing are ignored.
*
* @param in the input stream
* @param out the output stream
* @return the number of bytes copied
*/
public static long copyAndCloseInput(InputStream in, OutputStream out) throws IOException {
try {
return copy(in, out);
......@@ -85,6 +124,14 @@ public class IOUtils {
}
}
/**
* Copy all data from the input stream to the output stream. Both streams
* are kept open.
*
* @param in the input stream
* @param out the output stream
* @return the number of bytes copied
*/
public static long copy(InputStream in, OutputStream out) throws IOException {
long written = 0;
byte[] buffer = new byte[4 * 1024];
......@@ -99,6 +146,14 @@ public class IOUtils {
return written;
}
/**
* Copy all data from the reader to the writer and close the reader.
* Exceptions while closing are ignored.
*
* @param in the reader
* @param out the writer
* @return the number of characters copied
*/
public static long copyAndCloseInput(Reader in, Writer out) throws IOException {
long written = 0;
try {
......@@ -117,6 +172,11 @@ public class IOUtils {
return written;
}
/**
* Close an input stream without throwing an exception.
*
* @param in the input stream or null
*/
public static void closeSilently(InputStream in) {
if (in != null) {
try {
......@@ -128,6 +188,11 @@ public class IOUtils {
}
}
/**
* Close a reader without throwing an exception.
*
* @param reader the reader or null
*/
public static void closeSilently(Reader reader) {
if (reader != null) {
try {
......@@ -138,6 +203,11 @@ public class IOUtils {
}
}
/**
* Close a writer without throwing an exception.
*
* @param writer the writer or null
*/
public static void closeSilently(Writer writer) {
if (writer != null) {
try {
......@@ -149,6 +219,14 @@ public class IOUtils {
}
}
/**
* Read a number of bytes from an input stream and close the stream.
*
* @param in the input stream
* @param length the maximum number of bytes to read, or -1 to read until
* the end of file
* @return the bytes read
*/
public static byte[] readBytesAndClose(InputStream in, int length) throws IOException {
try {
if (length <= 0) {
......@@ -172,6 +250,14 @@ public class IOUtils {
}
}
/**
* Read a number of characters from a reader and close it.
*
* @param in the reader
* @param length the maximum number of characters to read, or -1 to read
* until the end of file
* @return the string read
*/
public static String readStringAndClose(Reader in, int length) throws IOException {
try {
if (length <= 0) {
......@@ -196,7 +282,9 @@ public class IOUtils {
}
/**
* Read the given number of bytes to the buffer.
* Try to read the given number of bytes to the buffer. This method reads
* until the maximum number of bytes have been read or until the end of
* file.
*
* @param in the input stream
* @param buffer the output buffer
......@@ -219,6 +307,16 @@ public class IOUtils {
return result;
}
/**
* Try to read the given number of characters to the buffer. This method
* reads until the maximum number of characters have been read or until the
* end of file.
*
* @param in the reader
* @param buffer the output buffer
* @param max the number of characters to read at most
* @return the number of characters read
*/
public static int readFully(Reader in, char[] buffer, int max) throws IOException {
int off = 0, len = Math.min(max, buffer.length);
if (len == 0) {
......@@ -238,6 +336,13 @@ public class IOUtils {
return off <= 0 ? -1 : off;
}
/**
* Create a reader to read from an input stream using the UTF-8 format. If
* the input stream is null, this method returns null.
*
* @param in the input stream or null
* @return the reader
*/
public static Reader getReader(InputStream in) throws SQLException {
try {
// InputStreamReader may read some more bytes
......@@ -247,6 +352,14 @@ public class IOUtils {
}
}
/**
* Create an input stream to read from a string. The string is converted to
* a byte array using UTF-8 encoding.
* If the string is null, this method returns null.
*
* @param s the string
* @return the input stream
*/
public static InputStream getInputStream(String s) throws SQLException {
if (s == null) {
return null;
......@@ -254,13 +367,27 @@ public class IOUtils {
return new ByteArrayInputStream(StringUtils.utf8Encode(s));
}
/**
* Create a reader to read from a string.
* If the string is null, this method returns null.
*
* @param s the string or null
* @return the reader
*/
public static Reader getReader(String s) {
return s == null ? null : new StringReader(s);
}
public static Reader getAsciiReader(InputStream x) throws SQLException {
/**
* Wrap an input stream in a reader. The bytes are converted to characters
* using the US-ASCII character set.
*
* @param in the input stream
* @return the reader
*/
public static Reader getAsciiReader(InputStream in) throws SQLException {
try {
return x == null ? null : new InputStreamReader(x, "US-ASCII");
return in == null ? null : new InputStreamReader(in, "US-ASCII");
} catch (UnsupportedEncodingException e) {
throw Message.convert(e);
}
......
......@@ -18,35 +18,55 @@ public class IntArray {
private int size;
private int hash;
/**
* Create an int array with the default initial capacity.
*/
public IntArray() {
data = new int[10];
}
/**
* Create an int array with the given values and size.
*/
public IntArray(int[] data) {
this.data = data;
size = data.length;
}
/**
* Append a value.
*
* @param value the value to append
*/
public void add(int value) {
checkCapacity();
data[size++] = value;
}
public int get(int i) {
if (SysProperties.CHECK && i >= size) {
throw new ArrayIndexOutOfBoundsException("i=" + i + " size=" + size);
/**
* Get the value at the given index.
*
* @param index the index
* @return the value
*/
public int get(int index) {
if (SysProperties.CHECK && index >= size) {
throw new ArrayIndexOutOfBoundsException("i=" + index + " size=" + size);
}
return data[i];
return data[index];
}
public int remove(int i) {
if (SysProperties.CHECK && i >= size) {
throw new ArrayIndexOutOfBoundsException("i=" + i + " size=" + size);
/**
* Remove the value at the given index.
*
* @param index the index
*/
public void remove(int index) {
if (SysProperties.CHECK && index >= size) {
throw new ArrayIndexOutOfBoundsException("i=" + index + " size=" + size);
}
int value = data[i];
System.arraycopy(data, i + 1, data, i, size - i - 1);
System.arraycopy(data, index + 1, data, index, size - index - 1);
size--;
return value;
}
private void checkCapacity() {
......@@ -57,25 +77,38 @@ public class IntArray {
}
}
public void add(int i, int value) {
if (SysProperties.CHECK && i > size) {
throw new ArrayIndexOutOfBoundsException("i=" + i + " size=" + size);
/**
* Insert an element at the given position. The element at this position and
* all elements with a higher index move one element.
*
* @param index the index where to insert the value
* @param value the value to insert
*/
public void add(int index, int value) {
if (SysProperties.CHECK && index > size) {
throw new ArrayIndexOutOfBoundsException("i=" + index + " size=" + size);
}
checkCapacity();
if (i == size) {
if (index == size) {
add(value);
} else {
System.arraycopy(data, i, data, i + 1, size - i);
data[i] = value;
System.arraycopy(data, index, data, index + 1, size - index);
data[index] = value;
size++;
}
}
public void set(int i, int value) {
if (SysProperties.CHECK && i >= size) {
throw new ArrayIndexOutOfBoundsException("i=" + i + " size=" + size);
/**
* Update the value at the given index.
*
* @param index the index
* @param value the new value
*/
public void set(int index, int value) {
if (SysProperties.CHECK && index >= size) {
throw new ArrayIndexOutOfBoundsException("i=" + index + " size=" + size);
}
data[i] = value;
data[index] = value;
}
public boolean equals(Object obj) {
......@@ -106,10 +139,21 @@ public class IntArray {
return h;
}
/**
* Get the size of the list.
*
* @return the size
*/
public int size() {
return size;
}
/**
* Insert an element at the correct position in a sorted list.
* If the list is not sorted, the result of this operation is undefined.
*
* @param value the value to insert
*/
public void addValueSorted(int value) {
int l = 0, r = size;
while (l < r) {
......@@ -142,6 +186,11 @@ public class IntArray {
// add(l, value);
// }
/**
* Remove the first element of this list that matches this value.
*
* @param value the value to be remove
*/
public void removeValue(int value) {
for (int i = 0; i < size; i++) {
if (data[i] == value) {
......@@ -152,6 +201,13 @@ public class IntArray {
throw Message.getInternalError();
}
/**
* Return the next index with a value larger than this one.
* If the list is not sorted, the result of this operation is undefined.
*
* @param value the value to find
* @return the index
*/
public int findNextValueIndex(int value) {
int l = 0, r = size;
while (l < r) {
......@@ -173,6 +229,9 @@ public class IntArray {
// return size;
}
/**
* Sort the array by value.
*/
public void sort() {
// insertion sort
for (int i = 1, j; i < size(); i++) {
......@@ -184,6 +243,11 @@ public class IntArray {
}
}
/**
* Convert this list to an array. The target array must be big enough.
*
* @param array the target array
*/
public void toArray(int[] array) {
System.arraycopy(data, 0, array, 0, size);
}
......
......@@ -15,26 +15,48 @@ import java.util.HashMap;
public class IntHashMap {
private final HashMap map = new HashMap();
/**
* Get the value for the given key. This method returns null if the
* entry has not been found.
*
* @param key the key
* @return the value or null
*/
public Object get(int key) {
return map.get(ObjectUtils.getInteger(key));
}
/**
* Store the given key-value pair. The value is overwritten or added.
*
* @param key the key
* @param value the value
*/
public void put(int key, Object value) {
map.put(ObjectUtils.getInteger(key), value);
}
/**
* Remove the key-value pair with the given key.
*
* @param key the key
*/
public void remove(int key) {
map.remove(ObjectUtils.getInteger(key));
}
public int size() {
return map.size();
}
/**
* Remove all entries from the map.
*/
public void clear() {
map.clear();
}
/**
* Get all values from the map.
*
* @return the values
*/
public Collection values() {
return map.values();
}
......
......@@ -17,7 +17,12 @@ import org.h2.message.Message;
* A deleted record has key=0 and value=DELETED
*/
public class IntIntHashMap extends HashBase {
/**
* The value indicating that the entry has not been found.
*/
public static final int NOT_FOUND = -1;
private static final int DELETED = 1;
private int[] keys;
private int[] values;
......@@ -29,6 +34,12 @@ public class IntIntHashMap extends HashBase {
values = new int[len];
}
/**
* Store the given key-value pair. The value is overwritten or added.
*
* @param key the key
* @param value the value (-1 is not supported)
*/
public void put(int key, int value) {
if (key == 0) {
zeroKey = true;
......@@ -72,6 +83,11 @@ public class IntIntHashMap extends HashBase {
throw Message.getInternalError("hashmap is full");
}
/**
* Remove the key-value pair with the given key.
*
* @param key the key
*/
public void remove(int key) {
if (key == 0) {
zeroKey = false;
......@@ -115,6 +131,13 @@ public class IntIntHashMap extends HashBase {
}
}
/**
* Get the value for the given key. This method returns NOT_FOUND if the
* entry has not been found.
*
* @param key the key
* @return the value or NOT_FOUND
*/
public int get(int key) {
if (key == 0) {
return zeroKey ? zeroValue : NOT_FOUND;
......
......@@ -46,6 +46,13 @@ public class JdbcDriverUtils {
// utility class
}
/**
* Get the driver class name for the given URL, or null if the URL is
* unknown.
*
* @param url the database URL
* @return the driver class name
*/
public static String getDriver(String url) {
for (int i = 0; i < DRIVERS.length; i += 2) {
String prefix = DRIVERS[i];
......@@ -56,6 +63,11 @@ public class JdbcDriverUtils {
return null;
}
/**
* Load the driver class for the given URL, if the database URL is known.
*
* @param url the database URL
*/
public static void load(String url) throws SQLException {
String driver = getDriver(url);
if (driver != null) {
......
......@@ -29,6 +29,11 @@ public class JdbcUtils {
// utility class
}
/**
* Close a statement without throwing an exception.
*
* @param stat the statement or null
*/
public static void closeSilently(Statement stat) {
if (stat != null) {
try {
......@@ -39,6 +44,11 @@ public class JdbcUtils {
}
}
/**
* Close a connection without throwing an exception.
*
* @param conn the connection or null
*/
public static void closeSilently(Connection conn) {
if (conn != null) {
try {
......@@ -49,6 +59,11 @@ public class JdbcUtils {
}
}
/**
* Close a result set without throwing an exception.
*
* @param rs the result set or null
*/
public static void closeSilently(ResultSet rs) {
if (rs != null) {
try {
......@@ -59,6 +74,13 @@ public class JdbcUtils {
}
}
/**
* Get the result set containing the generated keys from the given
* statement. This method returns null for Java versions older than 1.4.
*
* @param stat the statement
* @return the result set or null
*/
public static ResultSet getGeneratedKeys(Statement stat) throws SQLException {
ResultSet rs = null;
//## Java 1.4 begin ##
......@@ -67,6 +89,11 @@ public class JdbcUtils {
return rs;
}
/**
* Close an XA connection set without throwing an exception.
*
* @param conn the XA connection or null
*/
//## Java 1.4 begin ##
public static void closeSilently(XAConnection conn) {
if (conn != null) {
......@@ -80,7 +107,7 @@ public class JdbcUtils {
//## Java 1.4 end ##
/**
* Create a new database connection with the given settings.
* Open a new database connection with the given settings.
*
* @param driver the driver class name
* @param url the database URL
......@@ -99,6 +126,14 @@ public class JdbcUtils {
return getConnection(driver, url, prop);
}
/**
* Open a new database connection with the given settings.
*
* @param driver the driver class name
* @param url the database URL
* @param prop the properties containing at least the user name and password
* @return the database connection
*/
public static Connection getConnection(String driver, String url, Properties prop) throws SQLException {
if (StringUtils.isNullOrEmpty(driver)) {
JdbcDriverUtils.load(url);
......
......@@ -57,14 +57,12 @@ public class Resources {
}
}
static void add(String name, String[] data) {
StringBuffer buff = new StringBuffer();
for (int i = 0; i < data.length; i++) {
buff.append(data[i]);
}
FILES.put(name, ByteUtils.convertBinStringToBytes(buff.toString()));
}
/**
* Get a resource from the resource map.
*
* @param name the name of the resource
* @return the resource data
*/
public static byte[] get(String name) throws IOException {
byte[] data;
if (FILES.size() == 0) {
......
......@@ -25,10 +25,18 @@ public class ScriptReader {
private boolean blockRemark;
private boolean skipRemarks;
/**
* Create a new SQL script reader from the given reader
*
* @param reader the reader
*/
public ScriptReader(Reader reader) {
this.reader = reader;
}
/**
* Close the underlying reader.
*/
public void close() throws SQLException {
try {
reader.close();
......@@ -45,6 +53,12 @@ public class ScriptReader {
}
}
/**
* Read a statement from the reader. This method returns null if the end has
* been reached.
*
* @return the SQL statement or null
*/
public String readStatement() throws SQLException {
if (end) {
return null;
......@@ -224,15 +238,33 @@ public class ScriptReader {
return buff.toString();
}
/**
* Check if this is the last statement, and if the single line or block
* comment is not finished yet.
*
* @return true if the current position is inside a remark
*/
public boolean isInsideRemark() {
return insideRemark;
}
/**
* If currently inside a remark, this method tells if it is a block comment
* (true) or single line comment (false)
*
* @return true if inside a block comment
*/
public boolean isBlockRemark() {
return blockRemark;
}
/**
* If comments should be skipped completely by this reader.
*
* @param skipRemarks true if comments should be skipped
*/
public void setSkipRemarks(boolean skipRemarks) {
this.skipRemarks = skipRemarks;
}
}
差异被折叠。
......@@ -517,4 +517,6 @@ hides heterogeneous construction rutema prepending rowscn overrides jconsole
mbean explicit directs leaves printing holds covariant redirector piped alarm
indicate timezone unmounting beep ignoring gary tong extending respective
overloaded decide clash involve verification dining recursively originating
philosophers
\ No newline at end of file
philosophers technologies modeling federation enterprise semantic deductive
fusion legacy decoded commented trimmed reaches indicating marks scaled tells
monitor
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论