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

javadocs

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