提交 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();
}
public long getMax(Session s) throws SQLException {
optimize(s);
return max.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();
}
/**
* 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 = ',';
......
......@@ -39,6 +39,9 @@ import org.h2.util.Tool;
* </pre>
*/
public class RunScript extends Tool {
private boolean showResults;
private boolean checkResults;
private void showUsage() {
out.println("Runs a SQL script.");
......@@ -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,8 +219,45 @@ public class RunScript extends Tool {
process(conn, sql, continueOnError, charsetName);
} else {
try {
if (sql.trim().length() > 0) {
stat.execute(sql);
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) {
......@@ -265,5 +316,24 @@ public class RunScript extends Tool {
throw Message.convertIOException(e, fileName);
}
}
/**
* 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) {
......@@ -151,7 +200,14 @@ 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 {
......@@ -48,7 +58,12 @@ 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) {
......
......@@ -23,10 +23,23 @@ public class SmallMap {
private int lastId;
private int maxElements;
/**
* Create a map with the given maximum number of entries.
*
* @param maxElements the maximum number of entries
*/
public SmallMap(int maxElements) {
this.maxElements = maxElements;
}
/**
* Add an object to the map. If the size of the map is larger than twice the
* maximum size, objects with a low id are removed.
*
* @param id the object id
* @param o the object
* @return the id
*/
public int addObject(int id, Object o) {
if (map.size() > maxElements * 2) {
Iterator it = map.keySet().iterator();
......@@ -46,6 +59,11 @@ public class SmallMap {
return id;
}
/**
* Remove an object from the map.
*
* @param id the id of the object to remove
*/
public void freeObject(int id) {
if (cacheId == id) {
cacheId = -1;
......@@ -54,6 +72,15 @@ public class SmallMap {
map.remove(ObjectUtils.getInteger(id));
}
/**
* Get an object from the map if it is stored.
*
* @param id the id of the object
* @param ifAvailable only return it if available, otherwise return null
* @return the object or null
* @throws SQLException if isAvailable is false and the object has not been
* found
*/
public Object getObject(int id, boolean ifAvailable) throws SQLException {
if (id == cacheId) {
return cache;
......
......@@ -19,6 +19,11 @@ public class StartBrowser {
// utility class
}
/**
* Open a new browser tab or window with the given URL.
*
* @param url the URL to open
*/
public static void openURL(String url) {
String osName = SysProperties.getStringSetting("os.name", "linux").toLowerCase();
Runtime rt = Runtime.getRuntime();
......
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论