Class Database
- java.lang.Object
-
- org.apache.manifoldcf.core.database.Database
-
- Direct Known Subclasses:
DBInterfaceHSQLDB,DBInterfaceMySQL,DBInterfacePostgreSQL
public abstract class Database extends java.lang.ObjectThis class implements jskw.interfaces.IDatabase, and provides basic cached database services. The actual cache keys are determined by layers above this. It is expected that there is ONE of these objects per thread per database! If there are more, then the transaction management will get screwed up (i.e. nobody will know what happened to the connection handles...)
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected classDatabase.ExecuteQueryThreadThread used to execute queries.protected static classDatabase.ModificationsClass to keep track of modifications while we're in a transaction.static classDatabase.QueryCacheExecutorThis object is meant to execute within a cache manager call.
-
Field Summary
Fields Modifier and Type Field Description static java.lang.String_rcsidprotected static java.lang.String_TRANSACTION_protected ICacheManagercacheManagerprotected booleancommitDoneprotected WrappedConnectionconnectionprotected IThreadContextcontextprotected java.lang.StringdatabaseNameprotected booleandebugprotected intdelayedTransactionDepthprotected booleandoRollbackprotected java.lang.StringjdbcDriverClassprotected java.lang.StringjdbcUrlprotected intmaxDBConnectionsprotected longmaxQueryTimeprotected java.util.Map<java.lang.String,Database.Modifications>modificationsSetprotected java.lang.Stringpasswordprotected static java.util.Randomrandomprotected TransactionHandlethprotected java.lang.StringuserName
-
Constructor Summary
Constructors Constructor Description Database(IThreadContext context, java.lang.String jdbcUrl, java.lang.String jdbcDriverClass, java.lang.String databaseName, java.lang.String userName, java.lang.String password)
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description voidbeginTransaction(int transactionType)Begin a database transaction.java.lang.StringbuildConjunctionClause(java.util.List outputParameters, ClauseDescription[] clauseDescriptions)protected static voidcleanupParameters(java.util.List data)Clean up parameters after query has been triggered.protected voidcommitCurrentTransaction()Abstract method to commit a transactionjava.lang.StringconstructIndexHintClause(java.lang.String tableName, IndexDescription description)Construct index hint clause.java.lang.StringconstructIndexOrderByClause(java.lang.String[] fieldNames, boolean direction)Construct ORDER-BY clause meant for reading from an index.java.lang.StringconstructOffsetLimitClause(int offset, int limit)Construct an offset/limit clause.abstract java.lang.StringconstructOffsetLimitClause(int offset, int limit, boolean afterOrderBy)Construct an offset/limit clause.voidendTransaction()End a database transaction, either performing a commit or a rollback (depending on whether signalRollback() was called within the transaction).protected IResultSetexecute(java.sql.Connection connection, java.lang.String query, java.util.List params, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit)Run a query.IResultSetexecuteQuery(java.lang.String query, java.util.List params, StringSet cacheKeys, StringSet invalidateKeys, java.lang.String queryClass, boolean needResult, int maxReturn, ResultSpecification spec, ILimitChecker returnLimits)Execute arbitrary database query, and optionally cache the result.protected IResultSetexecuteUncachedQuery(java.lang.String query, java.util.List params, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit)This method does NOT appear in any interface; it is here to service the cache object.protected IResultSetexecuteViaThread(java.sql.Connection connection, java.lang.String query, java.util.List params, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit)Do query execution via a subthread, so the primary thread can be interruptedprotected voidexplainQuery(java.lang.String query, java.util.List params)Abstract method for explaining a queryprotected intfindColumn(java.sql.ResultSet rs, java.lang.String name)intfindConjunctionClauseMax(ClauseDescription[] otherClauseDescriptions)protected java.sql.BlobgetBLOB(java.sql.ResultSet rs, int col)intgetCurrentTransactionType()Get the current transaction type.protected IResultSetgetData(java.sql.ResultSet rs, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit)java.lang.StringgetDatabaseName()Get the database name.abstract intgetMaxInClause()Obtain the maximum number of individual items that should be present in an IN clause.protected java.lang.ObjectgetObject(java.sql.ResultSet rs, java.sql.ResultSetMetaData rsmd, int col, int desiredForm)longgetSleepAmt()Sleep a random amount of time after a transaction abort.java.lang.StringgetTransactionID()Get the current transaction id.protected voidinitializeConnection(java.sql.Connection connection)Initialize the connection (for HSQLDB).protected voidinternalTransactionBegin()Perform actual transaction begin.protected voidinterruptCleanup(java.sql.Connection connection)This method must clean up after a execute query thread has been forcibly interrupted.protected booleanisBinary(java.sql.ResultSetMetaData rsmd, int col)protected booleanisBLOB(java.sql.ResultSetMetaData rsmd, int col)protected static voidloadPS(java.sql.PreparedStatement ps, java.util.List data)protected java.lang.StringmapLabelName(java.lang.String rawLabelName)Abstract method for mapping a label name from resultsetprotected java.lang.StringmapLookupName(java.lang.String rawColumnName, java.lang.String rawLabelName)Abstract method for mapping a column lookup name from resultsetvoidnoteModifications(java.lang.String tableName, int insertCount, int modifyCount, int deleteCount)Note a number of inserts, modifications, or deletions to a specific table.protected voidnoteModificationsNoTransactions(java.lang.String tableName, int insertCount, int modifyCount, int deleteCount)Protected method for receiving information about inserts, modifications, or deletions OUTSIDE of all transactions.voidperformCommit()Perform the transaction commit.voidprepareForDatabaseCreate()Prepare database for database creation step.protected voidrollbackCurrentTransaction()Abstract method to roll back a transactionvoidsignalRollback()Signal that a rollback should occur on the next endTransaction().voidsleepFor(long amt)Sleep, as part of recovery from deadlock.protected voidstartATransaction()Abstract method to start a transactionprotected voidsynchronizeTransactions()Synchronize internal transactions.
-
-
-
Field Detail
-
_rcsid
public static final java.lang.String _rcsid
- See Also:
- Constant Field Values
-
cacheManager
protected final ICacheManager cacheManager
-
context
protected final IThreadContext context
-
jdbcUrl
protected final java.lang.String jdbcUrl
-
jdbcDriverClass
protected final java.lang.String jdbcDriverClass
-
databaseName
protected final java.lang.String databaseName
-
userName
protected java.lang.String userName
-
password
protected java.lang.String password
-
th
protected TransactionHandle th
-
connection
protected WrappedConnection connection
-
doRollback
protected boolean doRollback
-
commitDone
protected boolean commitDone
-
delayedTransactionDepth
protected int delayedTransactionDepth
-
modificationsSet
protected java.util.Map<java.lang.String,Database.Modifications> modificationsSet
-
maxQueryTime
protected final long maxQueryTime
-
debug
protected final boolean debug
-
maxDBConnections
protected final int maxDBConnections
-
random
protected static java.util.Random random
-
_TRANSACTION_
protected static final java.lang.String _TRANSACTION_
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
Database
public Database(IThreadContext context, java.lang.String jdbcUrl, java.lang.String jdbcDriverClass, java.lang.String databaseName, java.lang.String userName, java.lang.String password) throws ManifoldCFException
- Throws:
ManifoldCFException
-
-
Method Detail
-
getDatabaseName
public java.lang.String getDatabaseName()
Get the database name. This is often used as a cache key qualifier.- Returns:
- the database name.
-
getTransactionID
public java.lang.String getTransactionID()
Get the current transaction id.- Returns:
- the current transaction identifier, or null if no transaction.
-
startATransaction
protected void startATransaction() throws ManifoldCFExceptionAbstract method to start a transaction- Throws:
ManifoldCFException
-
commitCurrentTransaction
protected void commitCurrentTransaction() throws ManifoldCFExceptionAbstract method to commit a transaction- Throws:
ManifoldCFException
-
rollbackCurrentTransaction
protected void rollbackCurrentTransaction() throws ManifoldCFExceptionAbstract method to roll back a transaction- Throws:
ManifoldCFException
-
explainQuery
protected void explainQuery(java.lang.String query, java.util.List params) throws ManifoldCFExceptionAbstract method for explaining a query- Throws:
ManifoldCFException
-
mapLookupName
protected java.lang.String mapLookupName(java.lang.String rawColumnName, java.lang.String rawLabelName)Abstract method for mapping a column lookup name from resultset
-
mapLabelName
protected java.lang.String mapLabelName(java.lang.String rawLabelName)
Abstract method for mapping a label name from resultset
-
prepareForDatabaseCreate
public void prepareForDatabaseCreate() throws ManifoldCFExceptionPrepare database for database creation step. In order to do this, all connections to the back end must be closed. Since we have a pool, and a local connection, these all need to be cleaned up.- Throws:
ManifoldCFException
-
executeQuery
public IResultSet executeQuery(java.lang.String query, java.util.List params, StringSet cacheKeys, StringSet invalidateKeys, java.lang.String queryClass, boolean needResult, int maxReturn, ResultSpecification spec, ILimitChecker returnLimits) throws ManifoldCFException
Execute arbitrary database query, and optionally cache the result. Cached results are returned for this operation if they are valid and appropriate. Note that any cached results returned were only guaranteed to be pertinent at the time the cached result was obtained; the actual data may become invalid due to other threads writing to the database. This is NOT true, however, if a transaction is started. If a transaction was started for this database within this thread context, then the query will be executed within the transaction, and since the transaction is owned by the current thread, no others will be able to disrupt its processing.- Parameters:
query- is the actual query string.params- if not null, are prepared statement parameters.cacheKeys- is the set of cache keys that the query result will be cached against. If the value for this parameter is null, then the query will not be cached.invalidateKeys- is the set of cache keys that the query will invalidate when the query occurs. If this is null, then no keys will be invalidated. Note that if this is in a transaction, the cache invalidation will only occur for queries that are part of the transaction, at least until the transaction is committed.queryClass- describes the class of the query, for the purposes of LRU and expiration time. The queryClass groups queries together, so that they are managed with a common set of timeouts and maximum sizes. If null, then no expiration or LRU behavior will take place.needResult- is true if the result is needed.maxReturn- is the maximum number of rows to return. Use -1 for infinite.spec- is the result specification object, or null for standard.returnLimits- is a description of how to limit return results (in addition to the maxReturn value). Pass null if no limits are desired.- Returns:
- the resultset
- Throws:
ManifoldCFException
-
getCurrentTransactionType
public int getCurrentTransactionType()
Get the current transaction type. Returns "READCOMMITTED" outside of a transaction.
-
beginTransaction
public void beginTransaction(int transactionType) throws ManifoldCFExceptionBegin a database transaction. This method call MUST be paired with an endTransaction() call, or database handles will be lost. If the transaction should be rolled back, then signalRollback() should be called before the transaction is ended. It is strongly recommended that the code that uses transactions be structured so that a try block starts immediately after this method call. The body of the try block will contain all direct or indirect calls to executeQuery(). After this should be a catch for every exception type, including Error, which should call the signalRollback() method, and rethrow the exception. Then, after that a finally{} block which calls endTransaction().- Parameters:
transactionType- describes the type of the transaction.- Throws:
ManifoldCFException
-
synchronizeTransactions
protected void synchronizeTransactions() throws ManifoldCFExceptionSynchronize internal transactions.- Throws:
ManifoldCFException
-
internalTransactionBegin
protected void internalTransactionBegin() throws ManifoldCFExceptionPerform actual transaction begin.- Throws:
ManifoldCFException
-
performCommit
public void performCommit() throws ManifoldCFExceptionPerform the transaction commit. Calling this method does not relieve the coder of the responsibility of calling endTransaction(), as listed below. The purpose of a separate commit operation is to allow handling of situations where the commit generates a TRANSACTION_ABORT signal.- Throws:
ManifoldCFException
-
signalRollback
public void signalRollback()
Signal that a rollback should occur on the next endTransaction().
-
endTransaction
public void endTransaction() throws ManifoldCFExceptionEnd a database transaction, either performing a commit or a rollback (depending on whether signalRollback() was called within the transaction).- Throws:
ManifoldCFException
-
noteModifications
public void noteModifications(java.lang.String tableName, int insertCount, int modifyCount, int deleteCount) throws ManifoldCFExceptionNote a number of inserts, modifications, or deletions to a specific table. This is so we can decide when to do appropriate maintenance.- Parameters:
tableName- is the name of the table being modified.insertCount- is the number of inserts.modifyCount- is the number of updates.deleteCount- is the number of deletions.- Throws:
ManifoldCFException
-
noteModificationsNoTransactions
protected void noteModificationsNoTransactions(java.lang.String tableName, int insertCount, int modifyCount, int deleteCount) throws ManifoldCFExceptionProtected method for receiving information about inserts, modifications, or deletions OUTSIDE of all transactions.- Throws:
ManifoldCFException
-
getSleepAmt
public long getSleepAmt()
Sleep a random amount of time after a transaction abort.
-
sleepFor
public void sleepFor(long amt) throws ManifoldCFExceptionSleep, as part of recovery from deadlock.- Throws:
ManifoldCFException
-
constructIndexHintClause
public java.lang.String constructIndexHintClause(java.lang.String tableName, IndexDescription description) throws ManifoldCFExceptionConstruct index hint clause. On most databases this returns an empty string, but on MySQL this returns a USE INDEX hint. It requires the name of an index.- Parameters:
tableName- is the table the index is from.description- is the description of an index, which is expected to exist.- Returns:
- the query chunk that should go between the table names and the WHERE clause.
- Throws:
ManifoldCFException
-
constructIndexOrderByClause
public java.lang.String constructIndexOrderByClause(java.lang.String[] fieldNames, boolean direction)Construct ORDER-BY clause meant for reading from an index. Supply the field names belonging to the index, in order. Also supply a corresponding boolean array, where TRUE means "ASC", and FALSE means "DESC".- Parameters:
fieldNames- are the names of the fields in the index that is to be used.direction- is a boolean describing the sorting order of the first term.- Returns:
- a query chunk, including "ORDER BY" text, which is appropriate for at least ordering by the FIRST column supplied.
-
constructOffsetLimitClause
public java.lang.String constructOffsetLimitClause(int offset, int limit)Construct an offset/limit clause. This method constructs an offset/limit clause in the proper manner for the database in question.- Parameters:
offset- is the starting offset number.limit- is the limit of result rows to return.- Returns:
- the proper clause, with no padding spaces on either side.
-
constructOffsetLimitClause
public abstract java.lang.String constructOffsetLimitClause(int offset, int limit, boolean afterOrderBy)Construct an offset/limit clause. This method constructs an offset/limit clause in the proper manner for the database in question.- Parameters:
offset- is the starting offset number.limit- is the limit of result rows to return.afterOrderBy- is true if this offset/limit comes after an ORDER BY.- Returns:
- the proper clause, with no padding spaces on either side.
-
findConjunctionClauseMax
public int findConjunctionClauseMax(ClauseDescription[] otherClauseDescriptions)
-
getMaxInClause
public abstract int getMaxInClause()
Obtain the maximum number of individual items that should be present in an IN clause. Exceeding this amount will potentially cause the query performance to drop.- Returns:
- the maximum number of IN clause members.
-
buildConjunctionClause
public java.lang.String buildConjunctionClause(java.util.List outputParameters, ClauseDescription[] clauseDescriptions)
-
executeViaThread
protected IResultSet executeViaThread(java.sql.Connection connection, java.lang.String query, java.util.List params, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit) throws ManifoldCFException
Do query execution via a subthread, so the primary thread can be interrupted- Throws:
ManifoldCFException
-
interruptCleanup
protected void interruptCleanup(java.sql.Connection connection)
This method must clean up after a execute query thread has been forcibly interrupted. It has been separated because some JDBC drivers don't handle forcible interrupts appropriately.
-
executeUncachedQuery
protected IResultSet executeUncachedQuery(java.lang.String query, java.util.List params, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit) throws ManifoldCFException
This method does NOT appear in any interface; it is here to service the cache object.- Throws:
ManifoldCFException
-
initializeConnection
protected void initializeConnection(java.sql.Connection connection) throws ManifoldCFExceptionInitialize the connection (for HSQLDB). HSQLDB has a great deal of session state, and no way to pool individual connections based on it. So, every time we pull a connection off the pool we have to execute a number of statements on it before it can work reliably for us. This is the abstraction that permits that to happen.- Parameters:
connection- is the JDBC connection.- Throws:
ManifoldCFException
-
execute
protected IResultSet execute(java.sql.Connection connection, java.lang.String query, java.util.List params, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit) throws ManifoldCFException
Run a query. No caching is involved at all at this level.- Parameters:
query- String the query stringbResults- boolean whether to load the resultset or notmaxResults- is the maximum number of results to load: -1 if allparams- List if params !=null, use preparedStatement- Throws:
ManifoldCFException
-
getData
protected IResultSet getData(java.sql.ResultSet rs, boolean bResults, int maxResults, ResultSpecification spec, ILimitChecker returnLimit) throws ManifoldCFException
- Throws:
ManifoldCFException
-
loadPS
protected static void loadPS(java.sql.PreparedStatement ps, java.util.List data) throws java.sql.SQLException, ManifoldCFException- Throws:
java.sql.SQLExceptionManifoldCFException
-
cleanupParameters
protected static void cleanupParameters(java.util.List data) throws ManifoldCFExceptionClean up parameters after query has been triggered.- Throws:
ManifoldCFException
-
findColumn
protected int findColumn(java.sql.ResultSet rs, java.lang.String name) throws ManifoldCFException- Throws:
ManifoldCFException
-
getBLOB
protected java.sql.Blob getBLOB(java.sql.ResultSet rs, int col) throws ManifoldCFException- Throws:
ManifoldCFException
-
isBLOB
protected boolean isBLOB(java.sql.ResultSetMetaData rsmd, int col) throws ManifoldCFException- Throws:
ManifoldCFException
-
isBinary
protected boolean isBinary(java.sql.ResultSetMetaData rsmd, int col) throws ManifoldCFException- Throws:
ManifoldCFException
-
getObject
protected java.lang.Object getObject(java.sql.ResultSet rs, java.sql.ResultSetMetaData rsmd, int col, int desiredForm) throws ManifoldCFException- Throws:
ManifoldCFException
-
-