提交 1dee768f authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 3ac7cad3
无相关合并请求
......@@ -17,23 +17,29 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Infinite numbers in SQL script are listed as POWER(0, -1)), negative
infinite as (-POWER(0, -1)), and NaN (not a number) as SQRT(-1).
</li><li>The special double and float values 'NaN' (not a number) did not work
correctly when sorting or comparing.
<li>ParameterMetaData now also returns the right data type for most
conditions, as in WHERE ID=?.
</li><li>The table SYSTEM_RANGE now supports expressions and parameters.
</li><li>New column INFORMATION_SCHEMA.CONSTRAINTS.UNIQUE_INDEX_NAME
that contains the name of the unique index used to enforce this
constraint, if there is such an index.
</li><li>SET QUERY_TIMEOUT and Statement.setQueryTimeout no longer commits
a transaction. The same applies to SET @VARIABLE, SET LOCK_TIMEOUT,
SET TRACE_LEVEL_*, SET THROTTLE, and SET PATH.
</li><li>ParameterMetaData now also returns the right data type for most
conditions, as in WHERE ID=?.
</li><li>Negative scale values for DECIMAL or NUMBER columns are now supported
in regular tables and in linked tables.
</li><li>The SCRIPT command does now emit IF NOT EXISTS for CREATE ROLE.
</li><li>MySQL compatibility: auto_increment column are no longer automatically
converted to primary key columns.
</li><li>PostgreSQL compatibility: support for BOOL_OR and BOOL_AND
aggregate functions.
</li><li>The fulltext search did not support CLOB data types. Fixed.
</li><li>The table SYSTEM_RANGE now supports expressions and parameters.
</li><li>Negative scale values for DECIMAL or NUMBER columns are now supported
in regular tables and in linked tables.
</li><li>A role or right can now be granted or revoked multiple times without
getting an exception.
</li><li>Infinite numbers in SQL script are listed as POWER(0, -1)), negative
infinite as (-POWER(0, -1)), and NaN (not a number) as SQRT(-1).
</li><li>The special double and float values 'NaN' (not a number) did not work
correctly when sorting or comparing.
</li><li>The fulltext search did not support CLOB data types.
</li><li>If the drive with the database files was disconnected or unmounted
while writing, sometimes a stack overflow exception was thrown
instead of a IO exception.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -47,7 +47,8 @@ public interface Trigger {
* @param type
* the operation type: INSERT, UPDATE, or DELETE
*/
void init(Connection conn, String schemaName, String triggerName, String tableName, boolean before, int type) throws SQLException;
void init(Connection conn, String schemaName, String triggerName, String tableName, boolean before, int type)
throws SQLException;
/**
* This method is called for each triggered action.
......
......@@ -8,9 +8,11 @@ package org.h2.bnf;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
......@@ -53,7 +55,7 @@ public class Bnf {
* @param csv if not specified, the help.csv is used
* @return a new instance
*/
public static Bnf getInstance(Reader csv) throws Exception {
public static Bnf getInstance(Reader csv) throws SQLException, IOException {
Bnf bnf = new Bnf();
if (csv == null) {
byte[] data = Resources.get("/org/h2/res/help.csv");
......@@ -81,7 +83,7 @@ public class Bnf {
return random;
}
private void parse(Reader csv) throws Exception {
private void parse(Reader csv) throws SQLException, IOException {
csv = new BufferedReader(csv);
Rule functions = null;
statements = new ArrayList();
......@@ -137,11 +139,10 @@ public class Bnf {
/**
* Get the HTML documentation for a given syntax.
*
* @param rule the rule (topic)
* @param bnf the BNF syntax
* @return the HTML formatted text
*/
public String getSyntaxHtml(String rule, String bnf) {
public String getSyntaxHtml(String bnf) {
StringTokenizer tokenizer = new StringTokenizer(bnf, SEPARATORS, true);
StringBuffer buff = new StringBuffer();
while (tokenizer.hasMoreTokens()) {
......
......@@ -10,9 +10,9 @@ package org.h2.bnf;
* Represents the head of a BNF rule.
*/
public class RuleHead {
String section;
final String section;
Rule rule;
private String topic;
private final String topic;
RuleHead(String section, String topic, Rule rule) {
this.section = section;
......
......@@ -138,7 +138,7 @@ public abstract class Command implements CommandInterface {
database.checkPowerOff();
session.setCurrentCommand(this, startTime);
return query(maxrows);
} catch (Throwable e) {
} catch (Exception e) {
SQLException s = Message.convert(e);
database.exceptionThrown(s, sql);
throw s;
......
......@@ -445,7 +445,6 @@ public class Parser {
Expression expr = readExpression();
expr = expr.optimize(session);
p.setValue(expr.getValue(session));
index++;
} while (readIf(","));
read("}");
int len = parameters.size();
......@@ -1758,20 +1757,20 @@ public class Parser {
Expression r;
if (aggregateType == Aggregate.COUNT) {
if (readIf("*")) {
r = new Aggregate(database, Aggregate.COUNT_ALL, null, currentSelect, false);
r = new Aggregate(Aggregate.COUNT_ALL, null, currentSelect, false);
} else {
boolean distinct = readIf("DISTINCT");
Expression on = readExpression();
if (on instanceof Wildcard && !distinct) {
// PostgreSQL compatibility: count(t.*)
r = new Aggregate(database, Aggregate.COUNT_ALL, null, currentSelect, false);
r = new Aggregate(Aggregate.COUNT_ALL, null, currentSelect, false);
} else {
r = new Aggregate(database, Aggregate.COUNT, on, currentSelect, distinct);
r = new Aggregate(Aggregate.COUNT, on, currentSelect, distinct);
}
}
} else if (aggregateType == Aggregate.GROUP_CONCAT) {
boolean distinct = readIf("DISTINCT");
Aggregate agg = new Aggregate(database, Aggregate.GROUP_CONCAT, readExpression(), currentSelect, distinct);
Aggregate agg = new Aggregate(Aggregate.GROUP_CONCAT, readExpression(), currentSelect, distinct);
if (readIf("ORDER")) {
read("BY");
agg.setOrder(parseSimpleOrderList());
......@@ -1782,7 +1781,7 @@ public class Parser {
r = agg;
} else {
boolean distinct = readIf("DISTINCT");
r = new Aggregate(database, aggregateType, readExpression(), currentSelect, distinct);
r = new Aggregate(aggregateType, readExpression(), currentSelect, distinct);
}
read(")");
return r;
......@@ -2440,7 +2439,6 @@ public class Parser {
while (true) {
type = types[i];
if (type != CHAR_NAME && type != CHAR_VALUE) {
c = chars[i];
break;
}
i++;
......@@ -2925,7 +2923,6 @@ public class Parser {
return STRING_CONCAT;
}
break;
default:
}
}
throw getSyntaxError();
......
......@@ -33,7 +33,7 @@ public abstract class Prepared {
/**
* The SQL string.
*/
protected String sql;
protected String sqlStatement;
/**
* The position of the head record (used for indexes).
......@@ -202,7 +202,7 @@ public abstract class Prepared {
* @param sql the SQL statement
*/
public void setSQL(String sql) {
this.sql = sql;
this.sqlStatement = sql;
}
/**
......@@ -211,7 +211,7 @@ public abstract class Prepared {
* @return the SQL statement
*/
public String getSQL() {
return sql;
return sqlStatement;
}
protected int getCurrentObjectId() {
......@@ -305,7 +305,7 @@ public abstract class Prepared {
} else {
params = "";
}
session.getTrace().infoSQL(sql, params, count, time);
session.getTrace().infoSQL(sqlStatement, params, count, time);
}
}
......@@ -343,7 +343,7 @@ public abstract class Prepared {
* @return the SQL statement
*/
public String toString() {
return sql;
return sqlStatement;
}
}
......@@ -234,8 +234,8 @@ public class AlterTableAddConstraint extends SchemaCommand {
}
constraint = ref;
refTable.addConstraint(constraint);
ref.setDeleteAction(session, deleteAction);
ref.setUpdateAction(session, updateAction);
ref.setDeleteAction(deleteAction);
ref.setUpdateAction(updateAction);
break;
}
default:
......@@ -263,13 +263,11 @@ public class AlterTableAddConstraint extends SchemaCommand {
indexType.setBelongsToConstraint(true);
String prefix = constraintName == null ? "CONSTRAINT" : constraintName;
String indexName = t.getSchema().getUniqueIndexName(t, prefix + "_INDEX_");
Index idx;
try {
idx = t.addIndex(session, indexName, indexId, cols, indexType, Index.EMPTY_HEAD, null);
return t.addIndex(session, indexName, indexId, cols, indexType, Index.EMPTY_HEAD, null);
} finally {
getSchema().freeUniqueName(indexName);
}
return idx;
}
public void setDeleteAction(int action) {
......@@ -283,9 +281,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
private Index getUniqueIndex(Table t, IndexColumn[] cols) {
ObjectArray list = t.getIndexes();
for (int i = 0; i < list.size(); i++) {
Index index = (Index) list.get(i);
if (canUseUniqueIndex(index, t, cols)) {
return index;
Index idx = (Index) list.get(i);
if (canUseUniqueIndex(idx, t, cols)) {
return idx;
}
}
return null;
......@@ -294,19 +292,19 @@ public class AlterTableAddConstraint extends SchemaCommand {
private Index getIndex(Table t, IndexColumn[] cols) {
ObjectArray list = t.getIndexes();
for (int i = 0; i < list.size(); i++) {
Index index = (Index) list.get(i);
if (canUseIndex(index, t, cols)) {
return index;
Index idx = (Index) list.get(i);
if (canUseIndex(idx, t, cols)) {
return idx;
}
}
return null;
}
private boolean canUseUniqueIndex(Index index, Table table, IndexColumn[] cols) {
if (index.getTable() != table || !index.getIndexType().isUnique()) {
private boolean canUseUniqueIndex(Index idx, Table table, IndexColumn[] cols) {
if (idx.getTable() != table || !idx.getIndexType().isUnique()) {
return false;
}
Column[] indexCols = index.getColumns();
Column[] indexCols = idx.getColumns();
if (indexCols.length > cols.length) {
return false;
}
......
......@@ -9,9 +9,9 @@ package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.UserAggregate;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.UserAggregate;
import org.h2.message.Message;
/**
......
......@@ -9,9 +9,9 @@ package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.UserAggregate;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.UserAggregate;
import org.h2.message.Message;
/**
......
......@@ -145,7 +145,7 @@ public class GrantRevoke extends DefineCommand {
int id = getObjectId(true, true);
Right right = new Right(db, id, grantee, grantedRole);
db.addDatabaseObject(session, right);
grantee.grantRole(session, grantedRole, right);
grantee.grantRole(grantedRole, right);
}
private void revokeRight() throws SQLException {
......
......@@ -25,6 +25,7 @@ import org.h2.result.SortOrder;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueNull;
......@@ -284,14 +285,8 @@ public abstract class Query extends Prepared {
String tb = c2.getSQL();
// getTableAlias();
found = col.equals(c2.getColumnName());
if (ta == null || tb == null) {
if (ta != tb) {
found = false;
}
} else {
if (!ta.equals(tb)) {
found = false;
}
if (!StringUtils.equals(ta, tb)) {
found = false;
}
}
}
......
......@@ -154,7 +154,7 @@ public class ScriptCommand extends ScriptBase {
ObjectArray roles = db.getAllRoles();
for (int i = 0; i < roles.size(); i++) {
Role role = (Role) roles.get(i);
add(role.getCreateSQL(), false);
add(role.getCreateSQL(true), false);
}
ObjectArray schemas = db.getAllSchemas();
for (int i = 0; i < schemas.size(); i++) {
......
......@@ -812,7 +812,7 @@ public class Select extends Query {
public String getPlanSQL() {
if (topTableFilter == null) {
return sql;
return sqlStatement;
}
StringBuffer buff = new StringBuffer();
Expression[] exprList = new Expression[expressions.size()];
......
......@@ -76,7 +76,7 @@ public class SelectUnion extends Query {
}
public void setSQL(String sql) {
this.sql = sql;
this.sqlStatement = sql;
}
public void setOrder(ObjectArray order) {
......
......@@ -119,7 +119,8 @@ public abstract class Constraint extends SchemaObjectBase implements Comparable
public abstract void checkExistingData(Session session) throws SQLException;
/**
* Get the unique index used to enforce this constraint, or null if no index is used.
* Get the unique index used to enforce this constraint, or null if no index
* is used.
*
* @return the index
*/
......
......@@ -476,10 +476,9 @@ public class ConstraintReferential extends Constraint {
/**
* Set the action to apply (restrict, cascade,...) on a delete.
*
* @param session the session
* @param action the action
*/
public void setDeleteAction(Session session, int action) throws SQLException {
public void setDeleteAction(int action) throws SQLException {
if (action == deleteAction) {
return;
}
......@@ -513,10 +512,9 @@ public class ConstraintReferential extends Constraint {
/**
* Set the action to apply (restrict, cascade,...) on an update.
*
* @param session the session
* @param action the action
*/
public void setUpdateAction(Session session, int action) throws SQLException {
public void setUpdateAction(int action) throws SQLException {
if (action == updateAction) {
return;
}
......
......@@ -214,7 +214,7 @@ public class Database implements DataHandler {
// applets may not do that - ignore
}
}
} catch (Throwable e) {
} catch (Exception e) {
if (traceSystem != null) {
traceSystem.getTrace(Trace.DATABASE).error("opening " + databaseName, e);
traceSystem.close();
......@@ -518,7 +518,7 @@ public class Database implements DataHandler {
fileData.init();
try {
fileIndex.init();
} catch (Throwable e) {
} catch (Exception e) {
if (recovery) {
traceSystem.getTrace(Trace.DATABASE).error("opening index", e);
ArrayList list = new ArrayList(storageMap.values());
......@@ -637,7 +637,7 @@ public class Database implements DataHandler {
if (view.getInvalid()) {
try {
view.recompile(session);
} catch (Throwable e) {
} catch (SQLException e) {
// ignore
}
if (!view.getInvalid()) {
......
......@@ -76,7 +76,7 @@ public class MetaRecord {
command.setObjectId(id);
command.setHeadPos(headPos);
command.update();
} catch (Throwable e) {
} catch (Exception e) {
SQLException s = Message.addSQL(Message.convert(e), sql);
db.getTrace(Trace.DATABASE).error(sql, s);
if (listener != null) {
......
......@@ -131,7 +131,7 @@ public class Right extends DbObjectBase {
if (grantedTable != null) {
grantee.revokeRight(grantedTable);
} else {
grantee.revokeRole(session, grantedRole);
grantee.revokeRole(grantedRole);
}
database.removeMeta(session, getId());
grantedRole = null;
......
......@@ -6,7 +6,6 @@
*/
package org.h2.engine;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
......@@ -114,11 +113,10 @@ public abstract class RightOwner extends DbObjectBase {
/**
* Grant a role to this object.
*
* @param session the session
* @param role the role
* @param right the right to grant
*/
public void grantRole(Session session, Role role, Right right) {
public void grantRole(Role role, Right right) {
if (grantedRoles == null) {
grantedRoles = new HashMap();
}
......@@ -128,11 +126,10 @@ public abstract class RightOwner extends DbObjectBase {
/**
* Remove the right for the given role.
*
* @param session the session
* @param role the role to revoke
* @throws SQLException if the right has not been granted
*/
public void revokeRole(Session session, Role role) throws SQLException {
public void revokeRole(Role role) {
if (grantedRoles == null) {
return;
}
......
......@@ -33,11 +33,26 @@ public class Role extends RightOwner {
return null;
}
public String getCreateSQL() {
/**
* Get the CREATE SQL statement for this object.
*
* @param ifNotExists true if IF NOT EXISTS should be used
* @return the SQL statement
*/
public String getCreateSQL(boolean ifNotExists) {
if (system) {
return null;
}
return "CREATE ROLE " + getSQL();
StringBuffer buff = new StringBuffer("CREATE ROLE ");
if (ifNotExists) {
buff.append("IF NOT EXISTS ");
}
buff.append(getSQL());
return buff.toString();
}
public String getCreateSQL() {
return getCreateSQL(false);
}
public int getType() {
......
......@@ -466,7 +466,7 @@ public class Session implements SessionInterface {
if (SysProperties.CHECK) {
int lockMode = database.getLockMode();
if (lockMode != Constants.LOCK_MODE_OFF && !database.isMultiVersion()) {
if (locks.indexOf(log.getTable()) < 0 && log.getTable().getTableType() != Table.TABLE_LINK) {
if (locks.indexOf(log.getTable()) < 0 && !Table.TABLE_LINK.equals(log.getTable().getTableType())) {
throw Message.getInternalError();
}
}
......
......@@ -14,7 +14,6 @@ import org.h2.command.dml.Select;
import org.h2.command.dml.SelectOrderBy;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.Cursor;
import org.h2.index.Index;
......@@ -25,8 +24,8 @@ import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.ObjectUtils;
import org.h2.util.ObjectArray;
import org.h2.util.ObjectUtils;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
......@@ -115,7 +114,6 @@ public class Aggregate extends Expression {
private static final HashMap AGGREGATES = new HashMap();
private final Database database;
private final int type;
private final Select select;
private final boolean distinct;
......@@ -131,14 +129,12 @@ public class Aggregate extends Expression {
/**
* Create a new aggregate object.
*
* @param database the database
* @param type the aggregate type
* @param on the aggregated expression
* @param select the select statement
* @param distinct if distinct is used
*/
public Aggregate(Database database, int type, Expression on, Select select, boolean distinct) {
this.database = database;
public Aggregate(int type, Expression on, Select select, boolean distinct) {
this.type = type;
this.on = on;
this.select = select;
......@@ -210,8 +206,8 @@ public class Aggregate extends Expression {
for (int i = 0; i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
index[i] = i + 1;
int type = o.descending ? SortOrder.DESCENDING : SortOrder.ASCENDING;
sortType[i] = type;
int order = o.descending ? SortOrder.DESCENDING : SortOrder.ASCENDING;
sortType[i] = order;
}
return new SortOrder(session.getDatabase(), index, sortType);
}
......@@ -246,7 +242,7 @@ public class Aggregate extends Expression {
}
}
}
data.add(database, distinct, v);
data.add(session.getDatabase(), distinct, v);
}
public Value getValue(Session session) throws SQLException {
......@@ -284,7 +280,7 @@ public class Aggregate extends Expression {
if (data == null) {
data = new AggregateData(type);
}
Value v = data.getValue(database, distinct);
Value v = data.getValue(session.getDatabase(), distinct);
if (type == GROUP_CONCAT) {
ObjectArray list = data.getList();
if (list == null || list.size() == 0) {
......@@ -304,7 +300,7 @@ public class Aggregate extends Expression {
}
}
});
} catch (Error e) {
} catch (Exception e) {
throw Message.convert(e);
}
}
......@@ -445,34 +441,37 @@ public class Aggregate extends Expression {
public int getDisplaySize() {
return displaySize;
}
private String getSQLGroupConcat() {
StringBuffer buff = new StringBuffer();
buff.append("GROUP_CONCAT(");
buff.append(on.getSQL());
if (orderList != null) {
buff.append(" ORDER BY ");
for (int i = 0; i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
if (i > 0) {
buff.append(", ");
}
buff.append(o.expression.getSQL());
if (o.descending) {
buff.append(" DESC");
}
}
}
if (separator != null) {
buff.append(" SEPARATOR ");
buff.append(separator.getSQL());
}
buff.append(")");
return buff.toString();
}
public String getSQL() {
String text;
switch (type) {
case GROUP_CONCAT: {
StringBuffer buff = new StringBuffer();
buff.append("GROUP_CONCAT(");
buff.append(on.getSQL());
if (orderList != null) {
buff.append(" ORDER BY ");
for (int i = 0; i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
if (i > 0) {
buff.append(", ");
}
buff.append(o.expression.getSQL());
if (o.descending) {
buff.append(" DESC");
}
}
}
if (separator != null) {
buff.append(" SEPARATOR ");
buff.append(separator.getSQL());
}
buff.append(")");
return buff.toString();
}
case GROUP_CONCAT:
return getSQLGroupConcat();
case COUNT_ALL:
return "COUNT(*)";
case COUNT:
......
......@@ -23,7 +23,7 @@ import org.h2.value.ValueNull;
/**
* Data stored while calculating an aggregate.
*/
public class AggregateData {
class AggregateData {
private final int aggregateType;
private long count;
private ValueHashMap distinctValues;
......@@ -34,7 +34,7 @@ public class AggregateData {
AggregateData(int aggregateType) {
this.aggregateType = aggregateType;
}
void add(Database database, boolean distinct, Value v) throws SQLException {
if (aggregateType == Aggregate.SELECTIVITY) {
count++;
......
......@@ -95,9 +95,9 @@ public class CompareLike extends Condition {
if (e == ValueNull.INSTANCE) {
return ValueExpression.NULL;
}
String pattern = r.getString();
initPattern(pattern, getEscapeChar(e));
if ("%".equals(pattern)) {
String p = r.getString();
initPattern(p, getEscapeChar(e));
if ("%".equals(p)) {
// optimization for X LIKE '%': convert to X IS NOT NULL
return new Comparison(session, Comparison.IS_NOT_NULL, left, null).optimize(session);
}
......@@ -206,12 +206,12 @@ public class CompareLike extends Condition {
if (r == ValueNull.INSTANCE) {
return r;
}
String pattern = r.getString();
String p = r.getString();
Value e = escape == null ? null : escape.getValue(session);
if (e == ValueNull.INSTANCE) {
return ValueNull.INSTANCE;
}
initPattern(pattern, getEscapeChar(e));
initPattern(p, getEscapeChar(e));
}
String value = l.getString();
boolean result;
......
......@@ -340,6 +340,7 @@ public class Function extends Expression implements FunctionCall {
* such function.
*
* @param name the function name
* @return the function info
*/
public static FunctionInfo getFunctionInfo(String name) {
return (FunctionInfo) FUNCTIONS.get(name);
......
......@@ -35,8 +35,8 @@ import org.h2.message.Message;
import org.h2.tools.SimpleResultSet;
import org.h2.util.ByteUtils;
import org.h2.util.IOUtils;
import org.h2.util.ObjectUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.ObjectUtils;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
......
......@@ -19,7 +19,7 @@ import org.h2.util.ObjectUtils;
/**
* The global settings of a full text search.
*/
public class FullTextSettings {
class FullTextSettings {
private static HashMap settings = new HashMap();
......
......@@ -9,7 +9,7 @@ package org.h2.fulltext;
/**
* The settings of one full text search index.
*/
public class IndexInfo {
class IndexInfo {
int id;
String schemaName;
String tableName;
......
......@@ -83,6 +83,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
* @param session the session
* @param first the first row to return (null if no limit)
* @param last the last row to return (null if no limit)
* @return the cursor to iterate over the results
*/
public abstract Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException;
......@@ -91,6 +92,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
*
* @param session the session
* @param masks the condition mask
* @return the cost
*/
public abstract double getCost(Session session, int[] masks) throws SQLException;
......
......@@ -200,11 +200,10 @@ public class LinkedIndex extends BaseIndex {
* Update a row using a UPDATE statement. This method is to be called if the
* emit updates option is enabled.
*
* @param session the session
* @param oldRow the old data
* @param newRow the new data
*/
public void update(Session session, Row oldRow, Row newRow) throws SQLException {
public void update(Row oldRow, Row newRow) throws SQLException {
StringBuffer buff = new StringBuffer("UPDATE ");
buff.append(targetTableName).append(" SET ");
for (int i = 0; i < newRow.getColumnCount(); i++) {
......
......@@ -201,8 +201,8 @@ public class MultiVersionIndex implements Index {
return base.getCreateSQL();
}
public String getCreateSQLForCopy(Table table, String quotedName) {
return base.getCreateSQLForCopy(table, quotedName);
public String getCreateSQLForCopy(Table forTable, String quotedName) {
return base.getCreateSQLForCopy(forTable, quotedName);
}
public String getDropSQL() {
......
......@@ -11,7 +11,7 @@ import org.h2.result.Row;
/**
* Represents a index node of a tree index.
*/
public class TreeNode {
class TreeNode {
int balance;
TreeNode left, right, parent;
Row row;
......
......@@ -9,7 +9,7 @@ package org.h2.log;
/**
* Represents a record in the transaction log.
*/
public class LogRecord {
class LogRecord {
LogFile log;
int logRecordId;
int sessionId;
......
......@@ -173,10 +173,10 @@ public class Message {
* Gets an internal error.
*
* @param s the message
* @return the error object
* @return the RuntimeException object
*/
public static Error getInternalError(String s) {
Error e = new Error(s);
public static RuntimeException getInternalError(String s) {
RuntimeException e = new RuntimeException(s);
TraceSystem.traceThrowable(e);
return e;
}
......@@ -259,9 +259,9 @@ public class Message {
/**
* Gets an internal error.
*
* @return the error object
* @return the RuntimeException object
*/
public static Error getInternalError() {
public static RuntimeException getInternalError() {
return getInternalError("Unexpected code path");
}
......
......@@ -46,7 +46,10 @@ public class TraceObject {
this.id = id;
}
protected int getTraceId() {
/**
* INTERNAL
*/
public int getTraceId() {
return id;
}
......@@ -171,7 +174,7 @@ public class TraceObject {
return buff.toString();
}
protected SQLException logAndConvert(Throwable e) {
protected SQLException logAndConvert(Exception e) {
if (SysProperties.LOG_ALL_ERRORS) {
synchronized (TraceObject.class) {
// e.printStackTrace();
......
......@@ -42,7 +42,7 @@ class ResultDiskBuffer implements ResultExternal {
ObjectArray buffer = new ObjectArray();
}
public ResultDiskBuffer(Session session, SortOrder sort, int columnCount) throws SQLException {
ResultDiskBuffer(Session session, SortOrder sort, int columnCount) throws SQLException {
this.sort = sort;
this.columnCount = columnCount;
Database db = session.getDatabase();
......
......@@ -118,7 +118,7 @@ public class AES implements BlockCipher {
decKey[d++] = encKey[e++];
decKey[d++] = encKey[e++];
decKey[d++] = encKey[e++];
decKey[d++] = encKey[e++];
decKey[d] = encKey[e];
}
public void encrypt(byte[] bytes, int off, int len) {
......
......@@ -136,7 +136,7 @@ public class TcpServer implements Service {
}
}
public void init(String[] args) throws Exception {
public void init(String[] args) {
port = DEFAULT_PORT;
for (int i = 0; i < args.length; i++) {
String a = args[i];
......
......@@ -349,8 +349,6 @@ public class FtpControl extends Thread {
processRemoveDir(param);
}
break;
default:
break;
}
}
......
......@@ -102,8 +102,7 @@ public class FtpServer implements Service {
}
ServerSocket createDataSocket() throws SQLException {
ServerSocket dataSocket = NetUtils.createServerSocket(0, false);
return dataSocket;
return NetUtils.createServerSocket(0, false);
}
void appendFile(StringBuffer buff, String fileName) throws SQLException {
......@@ -178,7 +177,7 @@ public class FtpServer implements Service {
return userName.equals(this.readUserName);
}
public void init(String[] args) throws Exception {
public void init(String[] args) throws SQLException {
for (int i = 0; args != null && i < args.length; i++) {
String a = args[i];
if ("-ftpPort".equals(a)) {
......@@ -230,7 +229,7 @@ public class FtpServer implements Service {
Socket s = NetUtils.createLoopbackSocket(port, false);
s.close();
return true;
} catch (Exception e) {
} catch (IOException e) {
if (traceError) {
traceError(e);
}
......@@ -305,7 +304,7 @@ public class FtpServer implements Service {
if (outFile != null) {
try {
this.out = FileUtils.openFileOutputStream(outFile, false);
} catch (Exception e) {
} catch (SQLException e) {
// ignore
}
outFile = null;
......
......@@ -47,7 +47,7 @@ public class PgServer implements Service {
private boolean allowOthers;
private boolean ifExists;
public void init(String[] args) throws Exception {
public void init(String[] args) {
port = DEFAULT_PORT;
for (int i = 0; i < args.length; i++) {
String a = args[i];
......
......@@ -264,13 +264,11 @@ public class PgServerThread implements Runnable {
char type = (char) readByte();
String name = readString();
server.trace("Describe");
PreparedStatement prep;
if (type == 'S') {
Prepared p = (Prepared) prepared.get(name);
if (p == null) {
sendErrorResponse("Prepared not found: " + name);
} else {
prep = p.prep;
sendParameterDescription(p);
}
} else if (type == 'P') {
......@@ -278,7 +276,7 @@ public class PgServerThread implements Runnable {
if (p == null) {
sendErrorResponse("Portal not found: " + name);
} else {
prep = p.prep;
PreparedStatement prep = p.prep;
try {
ResultSetMetaData meta = prep.getMetaData();
sendRowDescription(meta);
......
......@@ -14,7 +14,7 @@ import java.sql.SQLException;
* Keeps the meta data information of a column.
* This class is used by the H2 Console.
*/
public class DbColumn {
class DbColumn {
String name;
String dataType;
......
......@@ -6,6 +6,7 @@
*/
package org.h2.server.web;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
......@@ -47,11 +48,11 @@ public class PageParser {
result = new StringBuffer(s);
}
private String parseBlockUntil(String end) throws Exception {
private String parseBlockUntil(String end) throws ParseException {
PageParser block = new PageParser(page, settings, pos);
block.parseAll();
if (!block.readIf(end)) {
throw new Exception();
throw new ParseException(page, block.pos);
}
pos = block.pos;
return block.result.toString();
......@@ -63,14 +64,14 @@ public class PageParser {
if (pos != len) {
setError(pos);
}
} catch (Exception e) {
} catch (ParseException e) {
// TODO log error
setError(pos);
}
return result.toString();
}
private void parseAll() throws Exception {
private void parseAll() throws ParseException {
StringBuffer buff = result;
String p = page;
int i = pos;
......@@ -78,22 +79,6 @@ public class PageParser {
char c = p.charAt(i);
switch (c) {
case '<': {
// if (p.charAt(i + 1) == '%') {
// // TODO <%@include %>: never used
// if (p.charAt(i + 2) == '@') {
// i += 3;
// pos = i;
// read("include");
// String file = readParam("file");
// read("%>");
// String s = server.getTextFile(file);
// append(s);
// i = pos;
// } else {
// buff.append(c);
// }
// break;
// } else
if (p.charAt(i + 3) == ':' && p.charAt(i + 1) == '/') {
// end tag
pos = i;
......@@ -163,6 +148,7 @@ public class PageParser {
break;
default:
buff.append(c);
break;
}
}
pos = i;
......@@ -188,7 +174,7 @@ public class PageParser {
}
}
private String readParam(String name) throws Exception {
private String readParam(String name) throws ParseException {
read(name);
read("=");
read("\"");
......@@ -208,9 +194,9 @@ public class PageParser {
}
}
private void read(String s) throws Exception {
private void read(String s) throws ParseException {
if (!readIf(s)) {
throw new Exception();
throw new ParseException(s, pos);
}
}
......@@ -303,6 +289,7 @@ public class PageParser {
} else {
buff.append(c);
}
break;
}
}
return buff.toString();
......@@ -339,6 +326,7 @@ public class PageParser {
break;
default:
buff.append(c);
break;
}
}
return buff.toString();
......
......@@ -189,7 +189,7 @@ public class WebServer implements Service {
return startDateTime;
}
public void init(String[] args) throws Exception {
public void init(String[] args) {
// TODO web: support using a different properties file
Properties prop = loadProperties();
driverList = prop.getProperty("drivers");
......@@ -516,7 +516,7 @@ public class WebServer implements Service {
}
}
Connection getConnection(String driver, String url, String user, String password, DatabaseEventListener listener) throws Exception {
Connection getConnection(String driver, String url, String user, String password, DatabaseEventListener listener) throws SQLException {
driver = driver.trim();
url = url.trim();
org.h2.Driver.load();
......
......@@ -50,15 +50,7 @@ public class WebServlet extends HttpServlet {
String[] args = new String[list.size()];
list.toArray(args);
server = new WebServer();
try {
server.init(args);
} catch (Exception e) {
throw new ServletException("Init failed", e);
}
}
public void destroy() {
// nothing to do
server.init(args);
}
private boolean allow(HttpServletRequest req) {
......@@ -66,13 +58,12 @@ public class WebServlet extends HttpServlet {
return true;
}
String addr = req.getRemoteAddr();
InetAddress address;
try {
address = InetAddress.getByName(addr);
InetAddress address = InetAddress.getByName(addr);
return address.isLoopbackAddress();
} catch (UnknownHostException e) {
return false;
}
return address.isLoopbackAddress();
}
private String getAllowedFile(HttpServletRequest req, String requestedFile) {
......
......@@ -23,7 +23,7 @@ import org.h2.message.TraceSystem;
* The web session keeps all data of a user session.
* This class is used by the H2 Console.
*/
public class WebSession {
class WebSession {
private static final int MAX_HISTORY = 1000;
......
......@@ -1630,7 +1630,6 @@ class WebThread extends Thread implements DatabaseEventListener {
generatedKeys = true;
sql = sql.substring("@GENERATED".length()).trim();
} else if (sql.startsWith("@LOOP")) {
metadata = true;
sql = sql.substring("@LOOP".length()).trim();
int idx = sql.indexOf(' ');
int count = MathUtils.decodeInt(sql.substring(0, idx));
......
......@@ -232,7 +232,7 @@ public class Storage {
} else {
if (isFreeAndMine(px, blockCount)) {
int pos = px;
freeList.remove(i--);
freeList.remove(i);
file.setUsed(pos, blockCount);
return pos;
}
......
......@@ -46,7 +46,7 @@ public class FileObjectMemory implements FileObject {
private static final long serialVersionUID = 5549197956072850355L;
private int size;
public Cache(int size) {
Cache(int size) {
this.size = size;
}
......
......@@ -6,6 +6,7 @@
*/
package org.h2.table;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
......@@ -41,9 +42,20 @@ import org.h2.value.ValueUuid;
*/
public class Column {
// must be equal to ResultSetMetaData columnNoNulls, columnNullable,
// columnNullableUnknown
public static final int NOT_NULLABLE = 0, NULLABLE = 1, NULLABLE_UNKNOWN = 2;
/**
* This column is not nullable.
*/
public static final int NOT_NULLABLE = ResultSetMetaData.columnNoNulls;
/**
* This column is nullable.
*/
public static final int NULLABLE = ResultSetMetaData.columnNullable;
/**
* It is not know whether this column is nullable.
*/
public static final int NULLABLE_UNKNOWN = ResultSetMetaData.columnNullableUnknown;
private final int type;
private final long precision;
......
......@@ -427,7 +427,9 @@ public abstract class Table extends SchemaObjectBase {
/**
* Get the best plan for the given search mask.
*
* @param masks - null means 'always false'
* @param session the session
* @param masks null means 'always false'
* @return the plan item
*/
public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException {
PlanItem item = new PlanItem();
......
......@@ -377,7 +377,7 @@ public class TableLink extends Table {
prepared.checkCancelled();
Row oldRow = rows.next();
Row newRow = rows.next();
linkedIndex.update(session, oldRow, newRow);
linkedIndex.update(oldRow, newRow);
session.log(this, UndoLogRecord.DELETE, oldRow);
session.log(this, UndoLogRecord.INSERT, newRow);
}
......
......@@ -114,7 +114,7 @@ public class CompressTool {
byte[] buff = new byte[len];
compress.expand(in, start, in.length - start, buff, 0, len);
return buff;
} catch (Throwable e) {
} catch (Exception e) {
throw Message.getSQLException(ErrorCode.COMPRESSION_ERROR, null, e);
}
}
......@@ -129,7 +129,7 @@ public class CompressTool {
int len = readInt(in, 1);
int start = 1 + getLength(len);
compress.expand(in, start, in.length - start, out, outPos, len);
} catch (Throwable e) {
} catch (Exception e) {
throw Message.getSQLException(ErrorCode.COMPRESSION_ERROR, null, e);
}
}
......@@ -140,17 +140,17 @@ public class CompressTool {
return x;
}
if (x < 0xc0) {
return ((x & 0x3f) << 8) + (buff[pos++] & 0xff);
return ((x & 0x3f) << 8) + (buff[pos] & 0xff);
}
if (x < 0xe0) {
return ((x & 0x1f) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
return ((x & 0x1f) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos] & 0xff);
}
if (x < 0xf0) {
return ((x & 0xf) << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8)
+ (buff[pos++] & 0xff);
+ (buff[pos] & 0xff);
}
return ((buff[pos++] & 0xff) << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8)
+ (buff[pos++] & 0xff);
+ (buff[pos] & 0xff);
}
private int writeInt(byte[] buff, int pos, int x) {
......@@ -159,32 +159,32 @@ public class CompressTool {
buff[pos++] = (byte) (x >> 24);
buff[pos++] = (byte) (x >> 16);
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) x;
buff[pos] = (byte) x;
return 5;
} else if (x < 0x80) {
buff[pos++] = (byte) x;
buff[pos] = (byte) x;
return 1;
} else if (x < 0x4000) {
buff[pos++] = (byte) (0x80 | (x >> 8));
buff[pos++] = (byte) x;
buff[pos] = (byte) x;
return 2;
} else if (x < 0x200000) {
buff[pos++] = (byte) (0xc0 | (x >> 16));
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) x;
buff[pos] = (byte) x;
return 3;
} else if (x < 0x10000000) {
buff[pos++] = (byte) (0xe0 | (x >> 24));
buff[pos++] = (byte) (x >> 16);
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) x;
buff[pos] = (byte) x;
return 4;
} else {
buff[pos++] = (byte) 0xf0;
buff[pos++] = (byte) (x >> 24);
buff[pos++] = (byte) (x >> 16);
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) x;
buff[pos] = (byte) x;
return 5;
}
}
......
......@@ -70,9 +70,8 @@ ShutdownHandler {
* Options are case sensitive.
*
* @param args the command line arguments
* @throws Exception
*/
public static void main(String[] args) throws Exception {
public static void main(String[] args) {
int exitCode = new Console().run(args);
if (exitCode != 0) {
System.exit(exitCode);
......@@ -87,31 +86,19 @@ ShutdownHandler {
web.setShutdownHandler(this);
web.start();
} catch (SQLException e) {
if (web == null) {
e.printStackTrace();
} else {
System.out.println(web.getStatus());
}
printProblem(e, web);
}
try {
tcp = Server.createTcpServer(args);
tcp.start();
} catch (SQLException e) {
if (tcp == null) {
e.printStackTrace();
} else {
System.out.println(tcp.getStatus());
}
printProblem(e, tcp);
}
try {
pg = Server.createPgServer(args);
pg.start();
} catch (SQLException e) {
if (pg == null) {
e.printStackTrace();
} else {
System.out.println(pg.getStatus());
}
printProblem(e, pg);
}
//## AWT begin ##
if (!GraphicsEnvironment.isHeadless()) {
......@@ -141,6 +128,14 @@ ShutdownHandler {
}
return exitCode;
}
private void printProblem(SQLException e, Server server) {
if (server == null) {
e.printStackTrace();
} else {
System.out.println(server.getStatus());
}
}
private Image loadImage(String name) throws IOException {
byte[] imageData = Resources.get(name);
......@@ -234,7 +229,7 @@ ShutdownHandler {
tray.getClass().
getMethod("add", new Class[] { Class.forName("java.awt.TrayIcon") }).
invoke(tray, new Object[] { trayIcon });
return true;
} catch (Exception e) {
return false;
......
......@@ -41,7 +41,7 @@ import org.h2.util.StringUtils;
*/
public class Csv implements SimpleRowSource {
private String charset = StringUtils.getDefaultCharset();
private String streamCharset = StringUtils.getDefaultCharset();
private int bufferSize = 8 * 1024;
private String[] columnNames;
private char fieldSeparatorRead = ',';
......@@ -53,8 +53,8 @@ public class Csv implements SimpleRowSource {
private String lineSeparator = SysProperties.LINE_SEPARATOR;
private String nullString = "";
private String fileName;
private Reader reader;
private Writer writer;
private Reader input;
private Writer output;
private int back;
private boolean endOfLine, endOfFile;
......@@ -88,7 +88,7 @@ public class Csv implements SimpleRowSource {
writeRow(row);
rows++;
}
writer.close();
output.close();
return rows;
} catch (IOException e) {
throw Message.convertIOException(e, null);
......@@ -104,50 +104,46 @@ public class Csv implements SimpleRowSource {
* @param writer the writer
* @param rs the result set
* @return the number of rows written
* @throws IOException
* @throws SQLException
*/
public int write(Writer writer, ResultSet rs) throws SQLException {
this.writer = writer;
this.output = writer;
return writeResultSet(rs);
}
/**
* Writes the result set to a file in the CSV format.
*
* @param fileName the name of the csv file
* @param outputFileName the name of the csv file
* @param rs the result set
* @param charset the charset or null to use UTF-8
* @return the number of rows written
* @throws SQLException
*/
public int write(String fileName, ResultSet rs, String charset) throws SQLException {
init(fileName, charset);
public int write(String outputFileName, ResultSet rs, String charset) throws SQLException {
init(outputFileName, charset);
try {
initWrite();
return writeResultSet(rs);
} catch (IOException e) {
throw convertException("IOException writing " + fileName, e);
throw convertException("IOException writing " + outputFileName, e);
}
}
/**
* Writes the result set of a query to a file in the CSV format.
*
* @param conn
* the connection
* @param fileName
* the file name
* @param sql
* the query
* @param charset
* the charset or null to use UTF-8
* @param conn the connection
* @param outputFileName the file name
* @param sql the query
* @param charset the charset or null to use UTF-8
* @return the number of rows written
* @throws SQLException
*/
public int write(Connection conn, String fileName, String sql, String charset) throws SQLException {
public int write(Connection conn, String outputFileName, String sql, String charset) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
int rows = write(fileName, rs, charset);
int rows = write(outputFileName, rs, charset);
stat.close();
return rows;
}
......@@ -157,18 +153,18 @@ public class Csv implements SimpleRowSource {
* set are created on demand, that means the file is kept open until all
* rows are read or the result set is closed.
*
* @param fileName the file name
* @param inputFileName the file name
* @param colNames or null if the column names should be read from the CSV file
* @param charset the charset or null to use UTF-8
* @return the result set
* @throws SQLException
*/
public ResultSet read(String fileName, String[] colNames, String charset) throws SQLException {
init(fileName, charset);
public ResultSet read(String inputFileName, String[] colNames, String charset) throws SQLException {
init(inputFileName, charset);
try {
return readResultSet(colNames);
} catch (IOException e) {
throw convertException("IOException reading " + fileName, e);
throw convertException("IOException reading " + inputFileName, e);
}
}
......@@ -184,7 +180,7 @@ public class Csv implements SimpleRowSource {
*/
public ResultSet read(Reader reader, String[] colNames) throws SQLException, IOException {
init(null, null);
this.reader = reader;
this.input = reader;
return readResultSet(colNames);
}
......@@ -208,7 +204,7 @@ public class Csv implements SimpleRowSource {
for (int j = 0; j < i; j++) {
String y = columnNames[j];
if (x.equals(y)) {
x = x + "1";
x += "1";
j = -1;
}
}
......@@ -216,19 +212,19 @@ public class Csv implements SimpleRowSource {
}
}
private void init(String fileName, String charset) {
this.fileName = fileName;
private void init(String newFileName, String charset) {
this.fileName = newFileName;
if (charset != null) {
this.charset = charset;
this.streamCharset = charset;
}
}
private void initWrite() throws IOException {
if (writer == null) {
if (output == null) {
try {
OutputStream out = new FileOutputStream(fileName);
out = new BufferedOutputStream(out, bufferSize);
writer = new BufferedWriter(new OutputStreamWriter(out, charset));
output = new BufferedWriter(new OutputStreamWriter(out, streamCharset));
} catch (IOException e) {
close();
throw e;
......@@ -240,31 +236,31 @@ public class Csv implements SimpleRowSource {
for (int i = 0; i < values.length; i++) {
if (i > 0) {
if (fieldSeparatorWrite != null) {
writer.write(fieldSeparatorWrite);
output.write(fieldSeparatorWrite);
}
}
String s = values[i];
if (s != null) {
if (escapeCharacter != 0) {
if (fieldDelimiter != 0) {
writer.write(fieldDelimiter);
output.write(fieldDelimiter);
}
writer.write(escape(s));
output.write(escape(s));
if (fieldDelimiter != 0) {
writer.write(fieldDelimiter);
output.write(fieldDelimiter);
}
} else {
writer.write(s);
output.write(s);
}
} else if (nullString != null && nullString.length() > 0) {
writer.write(nullString);
output.write(nullString);
}
}
if (rowSeparatorWrite != null) {
writer.write(rowSeparatorWrite);
output.write(rowSeparatorWrite);
}
writer.write(lineSeparator);
output.write(lineSeparator);
}
private String escape(String data) {
......@@ -285,12 +281,12 @@ public class Csv implements SimpleRowSource {
}
private void initRead() throws IOException {
if (reader == null) {
if (input == null) {
try {
InputStream in = FileUtils.openFileInputStream(fileName);
in = new BufferedInputStream(in, bufferSize);
reader = new InputStreamReader(in, charset);
reader = new BufferedReader(reader);
input = new InputStreamReader(in, streamCharset);
input = new BufferedReader(input);
} catch (IOException e) {
close();
throw e;
......@@ -333,7 +329,7 @@ public class Csv implements SimpleRowSource {
} else if (endOfFile) {
return -1;
}
ch = reader.read();
ch = input.read();
if (ch < 0) {
endOfFile = true;
close();
......@@ -475,12 +471,13 @@ public class Csv implements SimpleRowSource {
* INTERNAL
*/
public Object[] readRow() throws SQLException {
if (reader == null) {
if (input == null) {
return null;
}
String[] row = new String[columnNames.length];
try {
for (int i = 0;; i++) {
int i = 0;
while (true) {
String v = readValue();
if (v == null) {
if (endOfFile && i == 0) {
......@@ -489,14 +486,13 @@ public class Csv implements SimpleRowSource {
if (endOfLine) {
if (i == 0) {
// empty line
i--;
continue;
}
break;
}
}
if (i < row.length) {
row[i] = v;
row[i++] = v;
}
}
} catch (IOException e) {
......@@ -517,10 +513,10 @@ public class Csv implements SimpleRowSource {
* INTERNAL
*/
public void close() {
IOUtils.closeSilently(reader);
reader = null;
IOUtils.closeSilently(writer);
writer = null;
IOUtils.closeSilently(input);
input = null;
IOUtils.closeSilently(output);
output = null;
}
/**
......
......@@ -55,7 +55,7 @@ public class MultiDimension {
for (int i = 0; i < dimensions; i++) {
long k = values[i];
if (k < 0 || k > max) {
throw new Error("value out of range; value=" + values[i] + " min=0 max=" + max);
throw new IllegalArgumentException("value out of range; value=" + values[i] + " min=0 max=" + max);
}
for (int b = 0; b < bitsPerValue; b++) {
x |= (k & (1L << b)) << (i + (dimensions - 1) * b);
......@@ -64,7 +64,7 @@ public class MultiDimension {
if (dimensions == 2) {
long xx = getMorton2(values[0], values[1]);
if (xx != x) {
throw new Error("test");
throw new IllegalArgumentException("test");
}
}
return x;
......@@ -192,10 +192,10 @@ public class MultiDimension {
* @param max the maximum value
* @return the list of ranges
*/
public long[][] getMortonRanges(int[] min, int[] max) {
private long[][] getMortonRanges(int[] min, int[] max) {
int len = min.length;
if (max.length != len) {
throw new Error("dimensions mismatch");
throw new IllegalArgumentException("dimensions mismatch");
}
for (int i = 0; i < len; i++) {
if (min[i] > max[i]) {
......@@ -239,8 +239,7 @@ public class MultiDimension {
return la[0] > lb[0] ? 1 : -1;
}
});
int minGap = 10;
for (;; minGap += minGap / 2) {
for (int minGap = 10;; minGap += minGap / 2) {
for (int i = 0; i < list.size() - 1; i++) {
long[] current = (long[]) list.get(i);
long[] next = (long[]) list.get(i + 1);
......@@ -263,18 +262,18 @@ public class MultiDimension {
private void addMortonRanges(ArrayList list, int[] min, int[] max, int len, int level) {
if (level > 100) {
throw new Error("Stop");
throw new IllegalArgumentException("Stop");
}
int largest = 0, largestDiff = 0;
long size = 1;
for (int i = 0; i < len; i++) {
int diff = max[i] - min[i];
if (diff < 0) {
throw new Error("Stop");
throw new IllegalArgumentException("Stop");
}
size *= diff + 1;
if (size < 0) {
throw new Error("Stop");
throw new IllegalArgumentException("Stop");
}
if (diff > largestDiff) {
largestDiff = diff;
......@@ -283,7 +282,7 @@ public class MultiDimension {
}
long low = interleave(min), high = interleave(max);
if (high < low) {
throw new Error("Stop");
throw new IllegalArgumentException("Stop");
}
long range = high - low + 1;
if (range == size) {
......@@ -321,7 +320,7 @@ public class MultiDimension {
scale--;
int m = roundUp(a + 2, 1 << scale) - 1;
if (m <= a || m >= b) {
throw new Error("stop");
throw new IllegalArgumentException("stop");
}
return m;
}
......
......@@ -622,7 +622,7 @@ public class Recover extends Tool implements DataHandler {
int blocks = (int) (length / blockSize);
blockCount = 1;
int[] pageOwners = new int[blocks / DiskFile.BLOCKS_PER_PAGE];
for (int block = 0; block < blocks; block += blockCount) {
for (block = 0; block < blocks; block += blockCount) {
store.seek(offset + (long) block * blockSize);
byte[] buff = new byte[blockSize];
DataPage s = DataPage.create(this, buff);
......@@ -678,7 +678,7 @@ public class Recover extends Tool implements DataHandler {
writer.close();
} catch (Throwable e) {
writeError(writer, e);
e.printStackTrace();
e.printStackTrace();
} finally {
IOUtils.closeSilently(writer);
closeSilently(store);
......@@ -718,7 +718,7 @@ e.printStackTrace();
int blocks = (int) (length / blockSize);
blockCount = 1;
int[] pageOwners = new int[blocks / DiskFile.BLOCKS_PER_PAGE];
for (int block = 0; block < blocks; block += blockCount) {
for (block = 0; block < blocks; block += blockCount) {
store.seek(offset + (long) block * blockSize);
byte[] buff = new byte[blockSize];
DataPage s = DataPage.create(this, buff);
......@@ -908,7 +908,6 @@ e.printStackTrace();
private void closeSilently(FileStore store) {
if (store != null) {
store.closeSilently();
store = null;
}
}
......
......@@ -58,7 +58,6 @@ public class Restore extends Tool {
String zipFileName = "backup.zip";
String dir = ".";
String db = null;
boolean quiet = false;
for (int i = 0; args != null && i < args.length; i++) {
String arg = args[i];
if (arg.equals("-dir")) {
......@@ -68,7 +67,7 @@ public class Restore extends Tool {
} else if (arg.equals("-db")) {
db = args[++i];
} else if (arg.equals("-quiet")) {
quiet = true;
// ignore
} else if (arg.equals("-help") || arg.equals("-?")) {
showUsage();
return;
......@@ -78,7 +77,7 @@ public class Restore extends Tool {
return;
}
}
process(zipFileName, dir, db, quiet);
process(zipFileName, dir, db);
}
private static String getOriginalDbName(String fileName, String db) throws IOException {
......@@ -131,7 +130,7 @@ public class Restore extends Tool {
* @throws SQLException
*/
public static void execute(String zipFileName, String directory, String db, boolean quiet) throws SQLException {
new Restore().process(zipFileName, directory, db, quiet);
new Restore().process(zipFileName, directory, db);
}
/**
......@@ -143,7 +142,7 @@ public class Restore extends Tool {
* @param quiet don't print progress information
* @throws SQLException
*/
private void process(String zipFileName, String directory, String db, boolean quiet) throws SQLException {
private void process(String zipFileName, String directory, String db) throws SQLException {
InputStream in = null;
try {
if (!FileUtils.exists(zipFileName)) {
......
......@@ -229,7 +229,7 @@ public class Shell {
upper = upper.substring("MAXWIDTH".length()).trim();
try {
maxColumnSize = Integer.parseInt(upper);
} catch (Exception e) {
} catch (NumberFormatException e) {
println("Usage: maxwidth <integer value>");
}
println("Maximum column width is now " + maxColumnSize);
......@@ -237,10 +237,10 @@ public class Shell {
if (statement == null) {
statement = line;
} else {
statement = statement + " " + line;
statement += " " + line;
}
if (end) {
execute(statement, listMode);
execute(statement);
statement = null;
}
}
......@@ -336,7 +336,7 @@ public class Shell {
print("Password ");
char[] password = (char[]) readPassword.invoke(console, (Object[]) null);
return password == null ? null : new String(password);
} catch (Throwable t) {
} catch (Exception e) {
// ignore, use the default solution
}
/**
......@@ -383,7 +383,7 @@ public class Shell {
return line;
}
private void execute(String sql, boolean listMode) {
private void execute(String sql) {
long time = System.currentTimeMillis();
boolean result;
try {
......
......@@ -23,7 +23,7 @@ public class ByteUtils {
}
public static int readInt(byte[] buff, int pos) {
return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos] & 0xff);
}
public static long readLong(byte[] buff, int pos) {
......
......@@ -29,9 +29,8 @@ public class CacheLRU implements Cache {
private CacheObject head = new CacheHead();
public CacheLRU(CacheWriter writer, int maxKb) {
int maxSize = maxKb * 1024 / 4;
this.maxSize = maxKb * 1024 / 4;
this.writer = writer;
this.maxSize = maxSize;
this.len = MathUtils.nextPowerOf2(maxSize / 64);
this.mask = len - 1;
MathUtils.checkPowerOf2(len);
......
......@@ -99,7 +99,6 @@ public class IntIntHashMap extends HashBase {
return;
}
index = (index + plus++) & mask;
k = keys[index];
} while(plus <= len);
// not found
}
......
......@@ -177,7 +177,8 @@ public class RandomUtils {
}
/**
* Get a cryptographically secure pseudo random int value between 0 (including and the given value (excluding).
* Get a cryptographically secure pseudo random int value between 0
* (including and the given value (excluding).
*
* @param lower the value returned will be lower than this value
* @return the random long value
......
......@@ -381,7 +381,13 @@ public class StringUtils {
}
/**
* Formats a date using a format string
* Formats a date using a format string.
*
* @param date the date to format
* @param format the format string
* @param locale the locale
* @param timeZone the timezone
* @return the formatted date
*/
public static String formatDateTime(Date date, String format, String locale, String timeZone) throws SQLException {
SimpleDateFormat dateFormat = getDateFormat(format, locale, timeZone);
......@@ -391,7 +397,13 @@ public class StringUtils {
}
/**
* Parses a date using a format string
* Parses a date using a format string.
*
* @param date the date to parse
* @param format the parsing format
* @param locale the locale
* @param timeZone the timeZone
* @return the parsed date
*/
public static Date parseDateTime(String date, String format, String locale, String timeZone) throws SQLException {
SimpleDateFormat dateFormat = getDateFormat(format, locale, timeZone);
......
......@@ -101,7 +101,6 @@ public class ValueHashMap extends HashBase {
return;
}
index = (index + plus++) & mask;
k = keys[index];
} while(plus <= len);
// not found
}
......
......@@ -24,7 +24,7 @@ public class SecurePassword {
*
* @param args the command line parameters
*/
public static void main(String[] argv) throws Exception {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
String url = "jdbc:h2:data/simple";
......
......@@ -167,10 +167,6 @@ java org.h2.test.TestAll timer
/*
grant select on test to sa;
C:\download\Data Concurrency and Consistency.pdf
detect deadlock alarm
......@@ -181,23 +177,9 @@ Procedure
DeallocateProcedure DEALLOCATE [PLAN] <name>
ExecuteProcedure EXECUTE <name>[([p[,...])]
> DROP TABLE IF EXISTS TEST;
> CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
> INSERT INTO TEST VALUES(1, 'Hello');
> INSERT INTO TEST VALUES(2, 'World');
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN;
> CREATE USER IF NOT EXISTS SERGEY PASSWORD '' ;
> CREATE ROLE IF NOT EXISTS MANAGER;
> GRANT MANAGER TO SERGEY;
> GRANT SELECT ON PUBLIC.TEST TO MANAGER;
>
> SCRIPT DROP TO 'SCRIPT_ERROR.SQL';
> RUNSCRIPT FROM 'SCRIPT_ERROR.SQL';
Ignore errors if role already granted? What do other dbs do?
Maybe add a REVOKE before the GRANT?
Concurrent update in table test: another transaction has updated or deleted the same row
when exactly does it occur in other databases (PostgreSQL, Oracle)?
Concurrent update in table test: another transaction has updated or
deleted the same row when exactly does it occur in other databases
(PostgreSQL, Oracle)?
create an mbean for each database? server? (jconsole)
......@@ -261,6 +243,7 @@ History:
constraint, if there is such an index.
It is now possible to grant or revoke a role to a user multiple times without
getting an exception.
The SCRIPT command does now emit IF NOT EXISTS for CREATE ROLE.
Roadmap:
......
......@@ -32,6 +32,7 @@ public class TestMetaData extends TestBase {
deleteDb("metaData");
conn = getConnection("metaData");
testColumnMetaData();
testColumnPrecision();
testColumnDefault();
testCrossReferences();
......@@ -195,6 +196,14 @@ public class TestMetaData extends TestBase {
}
private void testColumnMetaData() throws Exception {
String statement = "select substring('Hello',0,1)";
ResultSet rs = conn.prepareStatement(statement).executeQuery();
rs.next();
int type = rs.getMetaData().getColumnType(1);
check(Types.VARCHAR, type);
}
private void testColumnPrecision() throws Exception {
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE ONE(X NUMBER(12,2), Y FLOAT)");
......
......@@ -26,7 +26,7 @@ Corrupted database
I am sorry to say that, but it looks like a corruption problem. I am very interested in analyzing and solving this problem. Corruption problems have top priority for me. I have a few question:
- Could you send the full stack trace of the exception?
- Could you send the full stack trace of the exception including message text?
- What is your database URL?
- You can find out if the database is corrupted when running SCRIPT TO 'test.sql'
- What version H2 are you using?
......@@ -35,10 +35,11 @@ I am sorry to say that, but it looks like a corruption problem. I am very intere
- Did you use multiple connections?
- The first workarounds is: append ;RECOVER=1 to the database URL.
Does it work when you do this?
- The second workarounds is: delete the index.db file (it is re-created automatically)
and try again. Does it work when you do this?
- The third workarounds is: use the tool org.h2.tools.Recover to create the SQL script file,
and then re-create the database using this script. Does it work when you do this?
- The second workarounds is: delete the index.db file
(it is re-created automatically) and try again. Does it work when you do this?
- The third workarounds is: use the tool org.h2.tools.Recover to create
the SQL script file, and then re-create the database using this script.
Does it work when you do this?
- Do you use any settings or special features (for example, the setting LOG=0,
or two phase commit, linked tables, cache settings)?
- Is the application multi-threaded?
......@@ -46,7 +47,8 @@ I am sorry to say that, but it looks like a corruption problem. I am very intere
- How big is the database?
- Is the database usually closed normally, or is process terminated forcefully
or the computer switched off?
- Is it possible to reproduce this problem using a fresh database (sometimes, or always)?
- Is it possible to reproduce this problem using a fresh database
(sometimes, or always)?
- Are there any other exceptions (maybe in the .trace.db file)?
Could you send them to me please?
- Do you still have any .trace.db files, and if yes could you send them?
......
......@@ -129,6 +129,7 @@ public class Build extends BuildBase {
public void docs() {
javadoc();
copy("docs", getFiles("src/docsrc/index.html"), "src/docsrc");
java("org.h2.build.doc.XMLChecker", null);
java("org.h2.build.code.CheckJavadoc", null);
java("org.h2.build.code.CheckTextFiles", null);
java("org.h2.build.doc.GenerateDoc", null);
......
......@@ -125,7 +125,7 @@ public class GenerateDoc {
String syntax = rs.getString("SYNTAX");
syntax = PageParser.escapeHtml(syntax);
syntax = StringUtils.replaceAll(syntax, "<br />", "");
syntax = bnf.getSyntaxHtml(topic, syntax);
syntax = bnf.getSyntaxHtml(syntax);
map.put("syntax", syntax);
String link = topic.toLowerCase();
link = StringUtils.replaceAll(link, " ", "");
......
......@@ -514,5 +514,5 @@ derbynet ado happy derbyclient unspecified federated sysadmin lengths doing
gives clunky cooperative paged conflicts ontology freely regards standards
placing refer informational unlocks memo unlimited unmounted keeping hints
hides heterogeneous construction rutema prepending rowscn overrides jconsole
mbean explicit directs leaves printing holds covariant redirector piped
mbean explicit directs leaves printing holds covariant redirector piped alarm
indicate timezone
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论