提交 41a063a1 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 8ab34eda
......@@ -256,14 +256,18 @@
</copy>
</target>
<target name="javadocImpl">
<target name="javadocImpl" depends="javadoc">
<mkdir dir="docs/javadocImpl"/>
<javadoc
sourcepath="src/main"
packagenames="org.h2.*"
destDir="docs/javadocImpl"
classpath="${path.lucene.jar};${path.servlet.jar}"
/> <!-- doclet="org.h2.tools.doclet.Doclet" docletpath="bin"-->
destDir="docs/javadocImpl"
/>
<!--
doclet="org.h2.tools.doclet.Doclet" docletpath="bin"
additionalparam="-J-Dh2.interfacesOnly=true -J-Dh2.destDir=docs/javadocImpl"
-->
<copy todir="docs/javadoc">
<fileset dir="src/docsrc/javadoc" includes="**/*"/>
</copy>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -28,10 +28,23 @@ public class Sentence {
return System.currentTimeMillis() > max;
}
/**
* Add a word to the set of next tokens.
*
* @param n the token name
* @param string an example text
* @param type the type
*/
public void add(String n, String string, int type) {
next.put(type+"#"+n, string);
}
/**
* Add an alias name and object
*
* @param alias the alias name
* @param table the alias table
*/
public void addAlias(String alias, DbTableOrView table) {
if (aliases == null) {
aliases = new HashMap();
......@@ -39,6 +52,11 @@ public class Sentence {
aliases.put(alias, table);
}
/**
* Add a table.
*
* @param table the table
*/
public void addTable(DbTableOrView table) {
lastTable = table;
if (tables == null) {
......@@ -47,14 +65,29 @@ public class Sentence {
tables.add(table);
}
/**
* Get the set of tables.
*
* @return the set of tables
*/
public HashSet getTables() {
return tables;
}
/**
* Get the alias map.
*
* @return the alias map
*/
public HashMap getAliases() {
return aliases;
}
/**
* Get the last added table.
*
* @return the last table
*/
public DbTableOrView getLastTable() {
return lastTable;
}
......
......@@ -21,17 +21,65 @@ import org.h2.util.ObjectArray;
* Represents a SQL statement. This object is only used on the server side.
*/
public abstract class Command implements CommandInterface {
private final String sql;
/**
* The session.
*/
protected final Session session;
/**
* The trace module.
*/
protected final Trace trace;
/**
* The last start time.
*/
protected long startTime;
/**
* If this query was cancelled.
*/
private volatile boolean cancel;
private final String sql;
/**
* Check if this command is transactional.
* If it is not, then it forces the current transaction to commit.
*
* @return true if it is
*/
public abstract boolean isTransactional();
/**
* Check if this command is a query.
*
* @return true if it is
*/
public abstract boolean isQuery();
/**
* Get the list of parameters.
*
* @return the list of parameters
*/
public abstract ObjectArray getParameters();
/**
* Check if this command is read only.
*
* @return true if it is
*/
public abstract boolean isReadOnly();
/**
* Get an empty result set containing the meta data.
*
* @return an empty result set
*/
public abstract LocalResult queryMeta() throws SQLException;
public Command(Parser parser, String sql) {
this.session = parser.getSession();
this.sql = sql;
......@@ -46,8 +94,6 @@ public abstract class Command implements CommandInterface {
throw Message.getSQLException(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
}
public abstract LocalResult queryMeta() throws SQLException;
public final LocalResult getMetaDataLocal() throws SQLException {
return queryMeta();
}
......
......@@ -41,13 +41,13 @@ public class CommandContainer extends Command {
private void recompileIfRequired() throws SQLException {
if (prepared.needRecompile()) {
// TODO test with 'always recompile'
prepared.setModificationId(0);
prepared.setModificationMetaId(0);
String sql = prepared.getSQL();
ObjectArray oldValues = prepared.getParameters();
Parser parser = new Parser(session);
prepared = parser.parseOnly(sql);
long mod = prepared.getModificationId();
prepared.setModificationId(0);
long mod = prepared.getModificationMetaId();
prepared.setModificationMetaId(0);
ObjectArray newParams = prepared.getParameters();
for (int i = 0; i < newParams.size(); i++) {
Value v = ((Expression) oldValues.get(i)).getValue(session);
......@@ -55,7 +55,7 @@ public class CommandContainer extends Command {
p.setValue(v);
}
prepared.prepare();
prepared.setModificationId(mod);
prepared.setModificationMetaId(mod);
}
}
......
......@@ -21,21 +21,76 @@ import org.h2.util.ObjectArray;
*/
public abstract class Prepared {
/**
* The session.
*/
protected Session session;
/**
* The SQL string.
*/
protected String sql;
/**
* The position of the head record (used for indexes).
*/
protected int headPos = -1;
/**
* The list of parameters.
*/
protected ObjectArray parameters;
private long modificationId;
/**
* If the query should be prepared before each execution.
* This is set for queries with LIKE ?, because the query plan depends on the parameter value.
*/
protected boolean prepareAlways;
private long modificationMetaId;
private Command command;
private int objectId;
protected boolean prepareAlways;
private int currentRowNumber;
/**
* Check if this command is transactional.
* If it is not, then it forces the current transaction to commit.
*
* @return true if it is
*/
public abstract boolean isTransactional();
/**
* Get an empty result set containing the meta data.
*
* @return an empty result set
*/
public abstract LocalResult queryMeta() throws SQLException;
/**
* Check if this command is read only.
*
* @return true if it is
*/
public boolean isReadOnly() {
return false;
}
/**
* Create a new object.
*
* @param session the session
*/
public Prepared(Session session) {
this.session = session;
modificationId = session.getDatabase().getModificationMetaId();
modificationMetaId = session.getDatabase().getModificationMetaId();
}
/**
* Check if the statement needs to be re-compiled.
*
* @return true if it must
*/
public boolean needRecompile() throws SQLException {
Database db = session.getDatabase();
if (db == null) {
......@@ -43,27 +98,41 @@ public abstract class Prepared {
}
// TODO parser: currently, compiling every create/drop/... twice!
// because needRecompile return true even for the first execution
return SysProperties.RECOMPILE_ALWAYS || prepareAlways || modificationId < db.getModificationMetaId();
return SysProperties.RECOMPILE_ALWAYS || prepareAlways || modificationMetaId < db.getModificationMetaId();
}
public abstract boolean isTransactional();
public boolean isReadOnly() {
return false;
}
long getModificationId() {
return modificationId;
/**
* Get the meta data modification id of the database when this statement was compiled.
*
* @return the meta data modification id
*/
long getModificationMetaId() {
return modificationMetaId;
}
void setModificationId(long id) {
this.modificationId = id;
/**
* Set the meta data modification id of this statement.
*
* @param id the new id
*/
void setModificationMetaId(long id) {
this.modificationMetaId = id;
}
/**
* Set the parameter list of this statement.
*
* @param parameters the parameter list
*/
public void setParameterList(ObjectArray parameters) {
this.parameters = parameters;
}
/**
* Get the parameter list.
*
* @return the parameter list
*/
public ObjectArray getParameters() {
return parameters;
}
......@@ -75,32 +144,66 @@ public abstract class Prepared {
}
}
/**
* Set the command.
*
* @param command the new command
*/
public void setCommand(Command command) {
this.command = command;
}
/**
* Check if this object is a query.
*
* @return true if it is
*/
public boolean isQuery() {
return false;
}
/**
* Prepare this statement.
*/
public void prepare() throws SQLException {
// nothing to do
}
/**
* Execute the statement.
*
* @return the update count
* @throws SQLException if it is a query
*/
public int update() throws SQLException {
throw Message.getSQLException(ErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY);
}
/**
* Execute the query.
*
* @param maxrows the maximum number of rows to return
* @return the result set
* @throws SQLException if it is not a query
*/
public LocalResult query(int maxrows) throws SQLException {
throw Message.getSQLException(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
}
public abstract LocalResult queryMeta() throws SQLException;
/**
* Set the SQL statement.
*
* @param sql the SQL statement
*/
public void setSQL(String sql) {
this.sql = sql;
}
/**
* Get the SQL statement.
*
* @return the SQL statement
*/
public String getSQL() {
return sql;
}
......@@ -115,10 +218,20 @@ public abstract class Prepared {
return id;
}
/**
* Get the SQL statement with the execution plan.
*
* @return the execution plan
*/
public String getPlanSQL() {
return null;
}
/**
* Check if this statement was cancelled.
*
* @throws SQLException if it was cancelled
*/
public void checkCancelled() throws SQLException {
// TODO strange code: probably checkCancelled should always be called on the session. fix & test after release 1.0
if (command != null) {
......@@ -128,14 +241,29 @@ public abstract class Prepared {
}
}
/**
* Set the object id for this statement.
*
* @param i the object id
*/
public void setObjectId(int i) {
this.objectId = i;
}
/**
* Set the head position.
*
* @param headPos the head position
*/
public void setHeadPos(int headPos) {
this.headPos = headPos;
}
/**
* Set the session for this statement.
*
* @param currentSession the new session
*/
public void setSession(Session currentSession) {
this.session = currentSession;
}
......@@ -163,18 +291,39 @@ public abstract class Prepared {
}
}
/**
* Set the prepare always flag.
* If set, the statement is re-compiled whenever it is executed.
*
* @param prepareAlways the new value
*/
public void setPrepareAlways(boolean prepareAlways) {
this.prepareAlways = prepareAlways;
}
/**
* Set the current row number.
*
* @param rowNumber the row number
*/
protected void setCurrentRowNumber(int rowNumber) {
this.currentRowNumber = rowNumber;
}
/**
* Get the current row number.
*
* @return the row number
*/
public int getCurrentRowNumber() {
return currentRowNumber;
}
/**
* Convert the statement to a String.
*
* @return the SQL statement
*/
public String toString() {
return sql;
}
......
......@@ -13,18 +13,32 @@ import org.h2.result.LocalResult;
*/
public abstract class DefineCommand extends Prepared {
/**
* Create a new command for the given session.
*
* @param session the session
*/
public DefineCommand(Session session) {
super(session);
}
/**
* {@inheritDoc}
*/
public boolean isTransactional() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isReadOnly() {
return false;
}
/**
* {@inheritDoc}
*/
public LocalResult queryMeta() {
return null;
}
......
......@@ -16,11 +16,22 @@ public abstract class SchemaCommand extends DefineCommand {
private final Schema schema;
/**
* Create a new command.
*
* @param session the session
* @param schema the schema
*/
public SchemaCommand(Session session, Schema schema) {
super(session);
this.schema = schema;
}
/**
* Get the schema
*
* @return the schema
*/
protected Schema getSchema() throws SQLException {
return schema;
}
......
......@@ -32,7 +32,19 @@ import org.h2.value.ValueNull;
*/
public abstract class Query extends Prepared {
protected Expression limit, offset;
/**
* The limit expression as specified in the LIMIT or TOP clause.
*/
protected Expression limit;
/**
* The offset expression as specified in the LIMIT .. OFFSET clause.
*/
protected Expression offset;
/**
* The sample size
*/
protected int sampleSize;
private int lastLimit;
......@@ -40,8 +52,119 @@ public abstract class Query extends Prepared {
private LocalResult lastResult;
private Value[] lastParameters;
/**
* Execute the query without checking the cache.
*
* @param limit the limit as specified in the JDBC method call
* @return the result
*/
abstract LocalResult queryWithoutCache(int limit) throws SQLException;
/**
* Initialize the query.
*/
public abstract void init() throws SQLException;
/**
* The the list of select expressions.
* This may include invisible expressions such as order by expressions.
*
* @return the list of expressions
*/
public abstract ObjectArray getExpressions();
/**
* Calculate the cost to execute this query.
*
* @return the cost
*/
public abstract double getCost();
/**
* Get all tables that are involved in this query.
*
* @return the set of tables
*/
public abstract HashSet getTables();
/**
* Set the order by list.
*
* @param order the order by list
*/
public abstract void setOrder(ObjectArray order);
/**
* Set the 'for update' flag.
*
* @param forUpdate the new setting
*/
public abstract void setForUpdate(boolean forUpdate);
/**
* Get the column count of this query.
*
* @return the column count
*/
public abstract int getColumnCount();
/**
* Map the columns to the given column resolver.
*
* @param resolver the resolver
* @param level the subquery level (0 is the top level query, 1 is the first subquery level)
*/
public abstract void mapColumns(ColumnResolver resolver, int level) throws SQLException;
/**
* Change the evaluatable flag. This is used when building the execution plan.
*
* @param tableFilter the table filter
* @param b the new value
*/
public abstract void setEvaluatable(TableFilter tableFilter, boolean b);
/**
* Add a condition to the query. This is used for views.
*
* @param param the parameter
* @param columnId the column index (0 meaning the first column)
* @param comparisonType the comparison type
*/
public abstract void addGlobalCondition(Parameter param, int columnId, int comparisonType) throws SQLException;
/**
* Set the distinct flag.
*
* @param b the new value
*/
public abstract void setDistinct(boolean b);
/**
* Get the alias (or column name) of the first column.
* This is used to convert IN(SELECT ...) queries to inner joins.
*
* @param session the session
* @return the alias or column name
*/
public abstract String getFirstColumnAlias(Session session);
/**
* Check if this expression and all sub-expressions can fulfill a criteria.
* If any part returns false, the result is false.
*
* @param visitor the visitor
* @return if the criteria can be fulfilled
*/
public abstract boolean isEverything(ExpressionVisitor visitor);
/**
* Update all aggregate function values.
*
* @param session the session
*/
public abstract void updateAggregate(Session session) throws SQLException;
public Query(Session session) {
super(session);
}
......@@ -237,19 +360,6 @@ public abstract class Query extends Prepared {
this.limit = limit;
}
public abstract void init() throws SQLException;
public abstract ObjectArray getExpressions();
public abstract double getCost();
public abstract HashSet getTables();
public abstract void setOrder(ObjectArray order);
public abstract void setForUpdate(boolean forUpdate);
public abstract int getColumnCount();
public abstract void mapColumns(ColumnResolver resolver, int level) throws SQLException;
public abstract void setEvaluatable(TableFilter tableFilter, boolean b);
public abstract void addGlobalCondition(Parameter param, int columnId, int comparisonType) throws SQLException;
public abstract void setDistinct(boolean b);
public abstract String getFirstColumnAlias(Session session);
void addParameter(Parameter param) {
if (parameters == null) {
parameters = new ObjectArray();
......@@ -267,13 +377,9 @@ public abstract class Query extends Prepared {
return visitor.getMaxDataModificationId();
}
public abstract boolean isEverything(ExpressionVisitor visitor);
public final boolean isEverything(int expressionVisitorType) {
ExpressionVisitor visitor = ExpressionVisitor.get(expressionVisitorType);
return isEverything(visitor);
}
public abstract void updateAggregate(Session session) throws SQLException;
}
......@@ -33,14 +33,26 @@ import org.h2.value.Value;
*/
public abstract class ScriptBase extends Prepared implements DataHandler {
/**
* The output stream.
*/
protected OutputStream out;
/**
* The input stream.
*/
protected InputStream in;
/**
* The file name (if set).
*/
protected String fileName;
private String cipher;
private byte[] key;
private FileStore store;
private OutputStream outStream;
private InputStream inStream;
protected OutputStream out;
protected InputStream in;
protected String fileName;
private String compressionAlgorithm;
public ScriptBase(Session session) {
......@@ -76,7 +88,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
FileUtils.delete(fileName);
}
}
private void initStore() throws SQLException {
byte[] magic = Database.getMagic(true);
Database db = session.getDatabase();
......@@ -85,7 +97,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
store.setCheckedWriting(false);
store.init();
}
protected void openOutput() throws SQLException {
if (fileName == null) {
return;
......@@ -194,7 +206,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
public String getLobCompressionAlgorithm(int type) {
return session.getDatabase().getLobCompressionAlgorithm(type);
}
public void setCompressionAlgorithm(String algorithm) {
this.compressionAlgorithm = algorithm;
}
......
......@@ -573,8 +573,6 @@ public class Select extends Query {
if (!type.isHash() && (!type.isUnique() || columnIndex.getColumns().length > 1)) {
topTableFilter.setIndex(columnIndex);
isDistinctQuery = true;
int test;
System.out.println("##distinct: " + this.sql);
}
}
}
......
......@@ -46,6 +46,7 @@ public interface Compressor {
/**
* Expand a number of compressed bytes.
*
* @param in the compressed data
* @param inPos the offset at the input array
* @param inLen the number of bytes to read
......@@ -54,5 +55,12 @@ public interface Compressor {
* @param outLen the size of the uncompressed data
*/
void expand(byte[] in, int inPos, int inLen, byte[] out, int outPos, int outLen) throws SQLException;
/**
* Set the compression options. This may include settings for
* higher performance but less compression.
*
* @param options the options
*/
void setOptions(String options) throws SQLException;
}
......@@ -21,9 +21,90 @@ import org.h2.table.Table;
*/
public abstract class Constraint extends SchemaObjectBase {
public static final String CHECK = "CHECK", REFERENTIAL = "REFERENTIAL", UNIQUE = "UNIQUE";
/**
* The constraint type name for check constraints.
*/
public static final String CHECK = "CHECK";
/**
* The constraint type name for referential constraints.
*/
public static final String REFERENTIAL = "REFERENTIAL";
/**
* The constraint type name for unique constraints.
*/
public static final String UNIQUE = "UNIQUE";
/**
* The table for which this constraint is defined.
*/
protected Table table;
/**
* The constraint type name
*
* @return the name
*/
public abstract String getConstraintType();
/**
* Check if this row fulfils the constraint.
* This method throws an exception if not.
*
* @param session the session
* @param t the table
* @param oldRow the old row
* @param newRow the new row
*/
public abstract void checkRow(Session session, Table t, Row oldRow, Row newRow) throws SQLException;
/**
* Check if this constraint needs the specified index.
*
* @param index the index
* @return true if the index is used
*/
public abstract boolean usesIndex(Index index);
/**
* Check if this constraint contains the given column.
*
* @param col the column
* @return true if it does
*/
public abstract boolean containsColumn(Column col);
/**
* Get the SQL statement to create this constraint.
*
* @return the SQL statement
*/
public abstract String getCreateSQLWithoutIndexes();
/**
* Check if this constraint needs to be checked before updating the data.
*
* @return true if it must be checked before updating
*/
public abstract boolean isBefore();
/**
* Get a short description of the constraint. This includes the constraint name (if set),
* and the constraint expression.
*
* @return the description
*/
public abstract String getShortDescription();
/**
* Check the existing data. This method is called if the constraint is added after
* data has been inserted into the table.
*
* @param session the session
*/
public abstract void checkExistingData(Session session) throws SQLException;
public Constraint(Schema schema, int id, String name, Table table) {
super(schema, id, name, Trace.CONSTRAINT);
this.table = table;
......@@ -38,15 +119,6 @@ public abstract class Constraint extends SchemaObjectBase {
return DbObject.CONSTRAINT;
}
public abstract String getConstraintType();
public abstract void checkRow(Session session, Table t, Row oldRow, Row newRow) throws SQLException;
public abstract boolean usesIndex(Index index);
public abstract boolean containsColumn(Column col);
public abstract String getCreateSQLWithoutIndexes();
public abstract boolean isBefore();
public abstract String getShortDescription();
public abstract void checkExistingData(Session session) throws SQLException;
public Table getTable() {
return table;
}
......
......@@ -32,9 +32,6 @@ import org.h2.value.ValueNull;
public class ConstraintReferential extends Constraint {
public static final int RESTRICT = 0, CASCADE = 1, SET_DEFAULT = 2, SET_NULL = 3;
// TODO referential constraints: maybe use a own class for self referencing
// constraints
private int deleteAction;
private int updateAction;
private Table refTable;
......
......@@ -12,20 +12,80 @@ import org.h2.util.ObjectArray;
* A database object such as a table, an index, or a user.
*/
public interface DbObject {
/**
* The object is of the type table or view.
*/
int TABLE_OR_VIEW = 0;
/**
* This object is an index.
*/
int INDEX = 1;
/**
* This object is a user.
*/
int USER = 2;
/**
* This object is a sequence.
*/
int SEQUENCE = 3;
/**
* This object is a trigger.
*/
int TRIGGER = 4;
/**
* This object is a constraint (check constraint, unique constraint, or referential constraint).
*/
int CONSTRAINT = 5;
/**
* This object is a setting.
*/
int SETTING = 6;
/**
* This object is a role.
*/
int ROLE = 7;
/**
* This object is a right.
*/
int RIGHT = 8;
/**
* This object is an alias for a Java function.
*/
int FUNCTION_ALIAS = 9;
/**
* This object is a schema.
*/
int SCHEMA = 10;
/**
* This object is a constant.
*/
int CONSTANT = 11;
/**
* This object is a user data type (domain).
*/
int USER_DATATYPE = 12;
/**
* This object is a comment.
*/
int COMMENT = 13;
/**
* This object is a user defined aggregate function.
*/
int AGGREGATE = 14;
/**
......
......@@ -17,13 +17,68 @@ import org.h2.util.ObjectArray;
*/
public abstract class DbObjectBase implements DbObject {
private int id;
/**
* The database.
*/
protected Database database;
/**
* The trace module.
*/
protected Trace trace;
/**
* The comment (if set).
*/
protected String comment;
private int id;
private String objectName;
private long modificationId;
private boolean temporary;
protected String comment;
/**
* Build a SQL statement to re-create the object, or to create a copy of the object
* with a different name or referencing a different table
*
* @param table the new table name
* @param quotedName the new quoted name
* @return the SQL statement
*/
public abstract String getCreateSQLForCopy(Table table, String quotedName);
/**
* Build a SQL statement to re-create this object.
*
* @return the SQL statement
*/
public abstract String getCreateSQL();
/**
* Build a SQL statement to drop this object.
*
* @return the SQL statement
*/
public abstract String getDropSQL();
/**
* Get the object type.
*
* @return the object type
*/
public abstract int getType();
/**
* Remove all dependent objects and free all resources (files, blocks in files) of this object.
*
* @param session the session
*/
public abstract void removeChildrenAndResources(Session session) throws SQLException;
/**
* Check if this object can be renamed. System objects may not be renamed.
*/
public abstract void checkRename() throws SQLException;
protected DbObjectBase(Database database, int id, String name, String traceModule) {
this.database = database;
......@@ -65,18 +120,6 @@ public abstract class DbObjectBase implements DbObject {
return objectName;
}
public abstract String getCreateSQLForCopy(Table table, String quotedName);
public abstract String getCreateSQL();
public abstract String getDropSQL();
public abstract int getType();
public abstract void removeChildrenAndResources(Session session) throws SQLException;
public abstract void checkRename() throws SQLException;
protected void invalidate() {
setModified();
id = -1;
......
......@@ -17,9 +17,18 @@ import org.h2.table.Table;
*/
public abstract class RightOwner extends DbObjectBase {
// key: role; value: right
/**
* The map of granted roles.
* The key is the role,
* and the value is the right.
*/
private HashMap grantedRoles;
// key: table; value: right
/**
* The map of granted rights.
* The key is the table,
* and the value is the right.
*/
private HashMap grantedRights;
protected RightOwner(Database database, int id, String name, String traceModule) {
......
......@@ -76,20 +76,4 @@ public interface FunctionCall {
*/
String getSQL();
/**
* Check if the function can return the row count
* (if the function returns a number of rows).
*
* @return true if the function can return the row count
*/
// boolean canGetRowCount();
/**
* Get the number of rows
* (if the function returns a number of rows).
*
* @return the row count
*/
// int getRowCount(Session session);
}
......@@ -36,6 +36,82 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
protected IndexType indexType;
protected long rowCount;
/**
* Close this index.
*
* @param session the session
*/
public abstract void close(Session session) throws SQLException;
/**
* Add a row to this index.
*
* @param session the session
* @param row the row to add
*/
public abstract void add(Session session, Row row) throws SQLException;
/**
* Remove a row from the index.
*
* @param session the session
* @param row the row
*/
public abstract void remove(Session session, Row row) throws SQLException;
/**
* Create a cursor to iterate over a number of rows.
*
* @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)
*/
public abstract Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException;
/**
* Calculate the cost to find rows.
*
* @param session the session
* @param masks the condition mask
*/
public abstract double getCost(Session session, int[] masks) throws SQLException;
/**
* Remove the index.
*
* @param session the session
*/
public abstract void remove(Session session) throws SQLException;
/**
* Truncate the index.
*
* @param session the session
*/
public abstract void truncate(Session session) throws SQLException;
/**
* Check if this index can quickly find the first or last value.
*
* @return true if it can
*/
public abstract boolean canGetFirstOrLast();
/**
* Find the first (or last) value of this index.
*
* @param session the session
* @param first true for the first value, false for the last
*/
public abstract SearchRow findFirstOrLast(Session session, boolean first) throws SQLException;
/**
* Check if this index needs to be re-built.
*
* @return true if it must be re-built.
*/
public abstract boolean needRebuild();
public BaseIndex(Table table, int id, String name, IndexColumn[] indexColumns, IndexType indexType) {
super(table.getSchema(), id, name, Trace.INDEX);
this.indexType = indexType;
......@@ -77,14 +153,6 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
remove(session);
}
public abstract void close(Session session) throws SQLException;
public abstract void add(Session session, Row row) throws SQLException;
public abstract void remove(Session session, Row row) throws SQLException;
public abstract Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException;
public boolean canFindNext() {
return false;
}
......@@ -93,18 +161,6 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
throw Message.getInternalError();
}
public abstract double getCost(Session session, int[] masks) throws SQLException;
public abstract void remove(Session session) throws SQLException;
public abstract void truncate(Session session) throws SQLException;
public abstract boolean canGetFirstOrLast();
public abstract SearchRow findFirstOrLast(Session session, boolean first) throws SQLException;
public abstract boolean needRebuild();
public long getRowCount(Session session) {
return rowCount;
}
......
......@@ -180,7 +180,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
truncate(session);
} else {
BtreePage root = getRoot(session);
root.remove(session, row, 0);
root.remove(session, row);
rowCount--;
}
}
......
......@@ -84,7 +84,7 @@ public class BtreeLeaf extends BtreePage {
return splitPoint;
}
public SearchRow remove(Session session, Row oldRow, int level) throws SQLException {
public SearchRow remove(Session session, Row oldRow) throws SQLException {
int l = 0, r = pageData.size();
if (r == 0) {
if (!Constants.ALLOW_EMPTY_BTREE_PAGES && !root) {
......
......@@ -112,7 +112,7 @@ public class BtreeNode extends BtreePage {
return 0;
}
public SearchRow remove(Session session, Row oldRow, int level) throws SQLException {
public SearchRow remove(Session session, Row oldRow) throws SQLException {
int l = 0, r = pageData.size();
if (!Constants.ALLOW_EMPTY_BTREE_PAGES && pageChildren.size() == 0) {
throw Message.getInternalError("Empty btree page");
......@@ -134,7 +134,7 @@ public class BtreeNode extends BtreePage {
int at = l;
// merge is not implemented to allow concurrent usage of btrees
BtreePage page = index.getPage(session, pageChildren.get(at));
SearchRow first = page.remove(session, oldRow, level + 1);
SearchRow first = page.remove(session, oldRow);
if (first == null) {
// the first row didn't change - nothing to do here
return null;
......
......@@ -30,14 +30,24 @@ public abstract class BtreePage extends Record {
protected ObjectArray pageData;
protected boolean root;
BtreePage(BtreeIndex index) {
this.index = index;
}
/**
* Add a row to the index.
*
* @param row the row
* @param session the session
* @return the split point of this page, or 0 if no split is required
*/
abstract int add(Row row, Session session) throws SQLException;
// Returns the new first row in the list; null if no change; the deleted row if not empty
abstract SearchRow remove(Session session, Row row, int level) throws SQLException;
/**
* Remove a row from the page.
*
* @param session the session
* @param row the row
* @return the new first row in the list; null if no change; the deleted row if not empty
*/
abstract SearchRow remove(Session session, Row row) throws SQLException;
abstract BtreePage split(Session session, int splitPoint) throws SQLException;
abstract boolean findFirst(BtreeCursor cursor, SearchRow row, boolean bigger) throws SQLException;
abstract SearchRow getFirst(Session session) throws SQLException;
......@@ -46,6 +56,10 @@ public abstract class BtreePage extends Record {
abstract void first(BtreeCursor cursor) throws SQLException;
abstract int getRealByteCount() throws SQLException;
BtreePage(BtreeIndex index) {
this.index = index;
}
SearchRow getData(int i) throws SQLException {
return (SearchRow) pageData.get(i);
}
......
......@@ -34,7 +34,7 @@ public class JdbcStatement extends TraceObject implements Statement {
protected int queryTimeout;
protected boolean queryTimeoutSet;
protected int fetchSize = SysProperties.SERVER_RESULT_SET_FETCH_SIZE;
; protected int updateCount;
protected int updateCount;
private CommandInterface executingCommand;
private ObjectArray batchCommands;
protected int resultSetType;
......
......@@ -42,10 +42,115 @@ import org.h2.value.ValueUuid;
public abstract class DataPage {
static final boolean CHECKSUM = true;
/**
* The data handler responsible for lob objects.
*/
protected DataHandler handler;
/**
* The data itself.
*/
protected byte[] data;
/**
* The current write or read position.
*/
protected int pos;
/**
* Calculate the checksum and write.
*
*/
public abstract void updateChecksum();
/**
* Test if the checksum is correct.
*
* @param len the number of bytes
* @throws SQLException if the checksum does not match
*/
public abstract void check(int len) throws SQLException;
/**
* The space required for the checksum and additional fillers.
*
* @return the size
*/
public abstract int getFillerLength();
/**
* Update an integer at the given position.
* The current position is not change.
*
* @param pos the position
* @param x the value
*/
public abstract void setInt(int pos, int x);
/**
* Write an integer at the current position.
* The current position is incremented.
*
* @param x the value
*/
public abstract void writeInt(int x);
/**
* Read an integer at the current position.
* The current position is incremented.
*
* @return the value
*/
public abstract int readInt();
/**
* Get the length of an integer value.
*
* @return the length
*/
public abstract int getIntLen();
/**
* Get the length of a long value.
*
* @param x the value
* @return the length
*/
public abstract int getLongLen(long x);
/**
* Get the length of a String value.
*
* @param s the value
* @return the length
*/
public abstract int getStringLen(String s);
/**
* Read a String value.
* The current position is incremented.
*
* @return the value
*/
public abstract String readString();
/**
* Write a String value.
* The current position is incremented.
*
* @param s the value
*/
public abstract void writeString(String s);
/**
* Increase the size to the given length.
* The current position is set to the given value.
*
* @param len the new length
*/
public abstract void fill(int len);
public static DataPage create(DataHandler handler, int capacity) {
if (handler.getTextStorage()) {
return new DataPageText(handler, new byte[capacity]);
......@@ -77,14 +182,6 @@ public abstract class DataPage {
}
}
public abstract void updateChecksum();
public abstract void check(int len) throws SQLException;
public abstract int getFillerLength();
public abstract void setInt(int pos, int x);
public int length() {
return pos;
}
......@@ -132,20 +229,6 @@ public abstract class DataPage {
return data[pos++];
}
public abstract void writeInt(int x);
public abstract int readInt();
public abstract int getIntLen();
public abstract int getLongLen(long x);
public abstract int getStringLen(String s);
public abstract String readString();
public abstract void writeString(String s);
public long readLong() {
return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
}
......@@ -418,8 +501,6 @@ public abstract class DataPage {
}
}
public abstract void fill(int len);
public void fillAligned() {
// TODO datapage: fillAligned should not use a fixed constant '2'
// 0..6 > 8, 7..14 > 16, 15..22 > 24, ...
......
......@@ -20,8 +20,21 @@ public abstract class Record extends CacheObject {
private int lastLog = LogSystem.LOG_WRITTEN;
private int lastPos = LogSystem.LOG_WRITTEN;
/**
* Get the number of bytes required for the data if the given data page would be used.
*
* @param dummy the template data page
* @return the number of bytes
*/
public abstract int getByteCount(DataPage dummy) throws SQLException;
/**
* Write the record to the data page.
*
* @param buff the data page
*/
public abstract void write(DataPage buff) throws SQLException;
/**
* This method is called just before the page is written.
* If a read operation is required before writing, this needs to be done here.
......@@ -31,8 +44,6 @@ public abstract class Record extends CacheObject {
public void prepareWrite() throws SQLException {
}
public abstract void write(DataPage buff) throws SQLException;
public boolean isEmpty() {
return false;
}
......@@ -40,18 +51,18 @@ public abstract class Record extends CacheObject {
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public void setSessionId(int sessionId) {
this.sessionId = sessionId;
}
public int getSessionId() {
return sessionId;
}
public void commit() {
this.sessionId = 0;
}
}
public boolean getDeleted() {
return deleted;
......
......@@ -47,7 +47,16 @@ public abstract class Table extends SchemaObjectBase {
public static final String TABLE = "TABLE";
public static final String VIEW = "VIEW";
/**
* The columns of this table.
*/
protected Column[] columns;
/**
* The amount of memory required for a row if all values would be very small.
*/
protected int memoryPerRow;
private final HashMap columnMap = new HashMap();
private final boolean persistent;
private ObjectArray triggers;
......@@ -56,7 +65,142 @@ public abstract class Table extends SchemaObjectBase {
private ObjectArray views;
private boolean checkForeignKeyConstraints = true;
private boolean onCommitDrop, onCommitTruncate;
protected int memoryPerRow;
/**
* Lock the table for the given session.
* This method waits until the lock is granted.
*
* @param session the session
* @param exclusive true for write locks, false for read locks
* @param force lock even in the MVCC mode
* @throws SQLException if a lock timeout occured
*/
public abstract void lock(Session session, boolean exclusive, boolean force) throws SQLException;
/**
* Close the table object and flush changes.
*
* @param session the session
*/
public abstract void close(Session session) throws SQLException;
/**
* Release the lock for this session.
*
* @param s the session
*/
public abstract void unlock(Session s);
/**
* Create an index for this table
*
* @param session the session
* @param indexName the name of the index
* @param indexId the id
* @param cols the index columns
* @param indexType the index type
* @param headPos the position of the head (if the index already exists)
* @param comment the comment
* @return the index
*/
public abstract Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType,
int headPos, String comment) throws SQLException;
/**
* Remove a row from the table and all indexes.
*
* @param session the session
* @param row the row
*/
public abstract void removeRow(Session session, Row row) throws SQLException;
/**
* Remove all rows from the table and indexes.
*
* @param session the session
*/
public abstract void truncate(Session session) throws SQLException;
/**
* Add a row to the table and all indexes.
*
* @param session the session
* @param row the row
* @throws SQLException if a constraint was violated
*/
public abstract void addRow(Session session, Row row) throws SQLException;
/**
* Check if this table supports ALTER TABLE.
*
* @throws SQLException if it is not supported
*/
public abstract void checkSupportAlter() throws SQLException;
/**
* Get the table type name
*
* @return the table type name
*/
public abstract String getTableType();
/**
* Get the scan index to iterate through all rows.
*
* @param session the session
* @return the index
*/
public abstract Index getScanIndex(Session session) throws SQLException;
/**
* Get any unique index for this table if one exists.
*
* @return a unique index
*/
public abstract Index getUniqueIndex();
/**
* Get all indexes for this table.
*
* @return the list of indexes
*/
public abstract ObjectArray getIndexes();
/**
* Check if this table is locked exclusively.
*
* @return true if it is.
*/
public abstract boolean isLockedExclusively();
/**
* Get the last data modification id.
*
* @return the modification id
*/
public abstract long getMaxDataModificationId();
/**
* Check if the row count can be retrieved quickly.
*
* @return true if it can
*/
public abstract boolean canGetRowCount();
/**
* Check if this table can be dropped.
*
* @return true if it can
*/
public abstract boolean canDrop();
/**
* Get the row count for this table.
*
* @param session the session
* @return the row count
*/
public abstract long getRowCount(Session session) throws SQLException;
public Table(Schema schema, int id, String name, boolean persistent) {
super(schema, id, name, Trace.TABLE);
......@@ -133,39 +277,10 @@ public abstract class Table extends SchemaObjectBase {
columnMap.put(newName, column);
}
public abstract void lock(Session session, boolean exclusive, boolean force) throws SQLException;
public boolean isLockExclusive(Session s) {
return false;
}
public abstract void close(Session session) throws SQLException;
public abstract void unlock(Session s);
public abstract Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType,
int headPos, String comment) throws SQLException;
public abstract void removeRow(Session session, Row row) throws SQLException;
public abstract void truncate(Session session) throws SQLException;
public abstract void addRow(Session session, Row row) throws SQLException;
public abstract void checkSupportAlter() throws SQLException;
public abstract String getTableType();
public abstract Index getScanIndex(Session session) throws SQLException;
public abstract Index getUniqueIndex();
public abstract ObjectArray getIndexes();
public abstract boolean isLockedExclusively();
public abstract long getMaxDataModificationId();
public void updateRows(Prepared prepared, Session session, RowList rows)
throws SQLException {
// remove the old rows
......@@ -474,12 +589,6 @@ public abstract class Table extends SchemaObjectBase {
return cols;
}
public abstract boolean canGetRowCount();
public abstract boolean canDrop();
public abstract long getRowCount(Session session) throws SQLException;
public boolean getGlobalTemporary() {
return false;
}
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.io.IOException;
......
......@@ -14,11 +14,23 @@ import org.h2.store.DiskFile;
* The base object for all cached objects.
*/
public abstract class CacheObject {
private boolean changed;
/**
* The number of blocks occupied by this object.
*/
protected int blockCount;
public CacheObject previous, next, chained;
public int cacheQueue;
protected int blockCount;
private int pos;
private boolean changed;
/**
* Check if the object can be removed from the cache.
* For example pinned objects can not be removed.
*
* @return true if it can be removed
*/
public abstract boolean canRemove();
public static void sort(ObjectArray recordList) {
recordList.sort(new Comparator() {
......@@ -61,10 +73,9 @@ public abstract class CacheObject {
return false;
}
public abstract boolean canRemove();
/*
/**
* Get the estimated memory size.
*
* @return number of double words (4 bytes)
*/
public int getMemorySize() {
......
......@@ -10,11 +10,47 @@ import java.sql.SQLException;
* The base for other hash classes.
*/
public abstract class HashBase {
protected int mask, len, size, deletedCount, level;
/**
* The bit mask to get the index from the hash code.
*/
protected int mask;
/**
* The number of slots in the table.
*/
protected int len;
/**
* The number of occupied slots, excluding the zero key (if any).
*/
protected int size;
/**
* The number of deleted slots.
*/
protected int deletedCount;
/**
* The level. The number of slots is 2 ^ level.
*/
protected int level;
/**
* Whether the zero key is used.
*/
protected boolean zeroKey;
private int maxSize, minSize, maxDeleted;
private static final int MAX_LOAD = 90;
/**
* Increase the size of the underlying table and re-distribute the elements.
*
* @param newLevel the new level
*/
protected abstract void rehash(int newLevel) throws SQLException;
public HashBase() {
reset(2);
}
......@@ -40,8 +76,6 @@ public abstract class HashBase {
}
}
protected abstract void rehash(int newLevel) throws SQLException;
protected void reset(int newLevel) {
minSize = size * 3 / 4;
size = 0;
......
......@@ -33,9 +33,9 @@ import org.h2.util.StringUtils;
*/
public abstract class Value {
// TODO value: float is missing
// remember to keep the order
/**
* The data type is unknown at this time.
*/
public static final int UNKNOWN = -1;
public static final int NULL = 0, BOOLEAN = 1, BYTE = 2, SHORT = 3, INT = 4, LONG = 5, DECIMAL = 6;
public static final int DOUBLE = 7, FLOAT = 8, TIME = 9, DATE = 10, TIMESTAMP = 11, BYTES = 12;
......@@ -45,14 +45,76 @@ public abstract class Value {
public static final int TYPE_COUNT = STRING_FIXED + 1;
private static WeakReference weakCache = new WeakReference(null);
// private static int cacheCleaner = 0;
// testing: cacheHit / miss are public!
// public static int cacheHit = 0, cacheMiss = 0;
// private static Value[] cache = new Value[Constants.OBJECT_CACHE_SIZE];
private static final BigDecimal MAX_LONG_DECIMAL = new BigDecimal("" + Long.MAX_VALUE);
private static final BigDecimal MIN_LONG_DECIMAL = new BigDecimal("" + Long.MIN_VALUE);
/**
* Get the SQL expression for this value.
*
* @return the SQL expression
*/
public abstract String getSQL();
/**
* Get the value type.
*
* @return the type
*/
public abstract int getType();
/**
* Get the precision.
*
* @return the precision
*/
public abstract long getPrecision();
/**
* Get the display size in characters.
*
* @return the display size
*/
public abstract int getDisplaySize();
/**
* Get the value as a string.
*
* @return the string
*/
public abstract String getString() throws SQLException;
/**
* Get the value as an object.
*
* @return the object
*/
public abstract Object getObject() throws SQLException;
/**
* Set the value as a parameter in a prepared statement.
*
* @param prep the prepared statement
* @param parameterIndex the parameter index
*/
public abstract void set(PreparedStatement prep, int parameterIndex) throws SQLException;
/**
* Compare the value with another value of the same type.
*
* @param v the other value
* @param mode the compare mode
* @return 0 if both values are equal, -1 if the other value is smaller, and 1 otherwise
*/
protected abstract int compareSecure(Value v, CompareMode mode) throws SQLException;
/**
* Check if the two values are equal.
*
* @param v the other value
* @return true if they are equal
*/
protected abstract boolean isEqual(Value v);
public static int getOrder(int type) {
switch(type) {
case UNKNOWN:
......@@ -142,17 +204,6 @@ public abstract class Value {
return v;
}
public abstract String getSQL();
public abstract int getType();
public abstract long getPrecision();
public abstract int getDisplaySize();
public abstract String getString() throws SQLException;
protected abstract int compareSecure(Value v, CompareMode mode) throws SQLException;
protected abstract boolean isEqual(Value v);
public abstract Object getObject() throws SQLException;
public abstract void set(PreparedStatement prep, int parameterIndex) throws SQLException;
public Boolean getBoolean() throws SQLException {
return ((ValueBoolean) convertTo(Value.BOOLEAN)).getBoolean();
}
......
......@@ -14,6 +14,10 @@ import org.h2.util.StringUtils;
* The base class for all ValueString* classes.
*/
abstract class ValueStringBase extends Value {
/**
* The string data.
*/
protected final String value;
protected ValueStringBase(String value) {
......
......@@ -154,6 +154,8 @@ java org.h2.test.TestAll timer
/*
Javadocs: abstract class (Table)
add tests with select distinct type (code coverage)
documentation: package.html
......
......@@ -22,6 +22,14 @@ PostgreSQL
--------------------------------------------------------------------------------------------------------
HSQLDB
--------------------------------------------------------------------------------------------------------
To use the same default settings as H2, use:
jdbc:hsqldb:data/test;hsqldb.default_table_type=cached;sql.enforce_size=true
Also, you need to execute the following statement:
SET WRITE_DELAY 1
Derby
--------------------------------------------------------------------------------------------------------
To call getFD().sync() (which results in the OS call fsync()),
......
......@@ -518,4 +518,6 @@ llc computing oliver road inaccessible android velasques duplicates eduardo chu
encapsulates negating igor midnight fulfill prefixes communicates nesting convenience negated resides optimizing principal applets dobrovolskyi
involves ukrainian chile machines restricting summer aliased backus naur multiples avl operates grow normalized rijndael
countdown paused javac analyzing accesses solving forcefully urgent originally defect coordinates
camel council merges spelled adaptive pull controller abstractions workarounds driven
\ No newline at end of file
camel council merges spelled adaptive pull controller abstractions workarounds driven
thousands ridvan incremented slots debugging inherit agar fulvio invisible biondi hundreds occupied remap retrieved involved
turkish fulfils iapi filesync
\ No newline at end of file
......@@ -27,10 +27,13 @@ import com.sun.javadoc.Type;
* Javadoc for this product.
*/
public class Doclet {
private static final boolean INTERFACES_ONLY = Boolean.getBoolean("h2.interfacesOnly");
public static boolean start(RootDoc root) throws IOException {
ClassDoc[] classes = root.classes();
String[][] options = root.options();
String destDir = "docs/javadoc";
String destDir = System.getProperty("h2.destDir", "docs/javadoc");
for (int i = 0; i < options.length; i++) {
if (options[i][0].equals("destdir")) {
destDir = options[i][1];
......@@ -227,6 +230,10 @@ public class Doclet {
}
private static boolean skipMethod(MethodDoc method) {
ClassDoc clazz = method.containingClass();
if (INTERFACES_ONLY && (!clazz.isAbstract() || !method.isAbstract()) && !clazz.isInterface()) {
return true;
}
String name = method.name();
if (!method.isPublic() || name.equals("finalize")) {
return true;
......@@ -236,7 +243,7 @@ public class Doclet {
}
String firstSentence = getFirstSentence(method.firstSentenceTags());
if (firstSentence == null || firstSentence.trim().length() == 0) {
throw new Error("undocumented method? " + name + " " + method.containingClass().name() + " "
throw new Error("undocumented method? " + clazz.name() + "." + name + " "
+ method.getRawCommentText());
}
if (firstSentence.startsWith("INTERNAL")) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论