Class Database

  • Direct Known Subclasses:
    DBInterfaceHSQLDB, DBInterfaceMySQL, DBInterfacePostgreSQL

    public abstract class Database
    extends java.lang.Object
    This 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...)
    • Field Detail

      • 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
      • doRollback

        protected boolean doRollback
      • commitDone

        protected boolean commitDone
      • delayedTransactionDepth

        protected int delayedTransactionDepth
      • maxQueryTime

        protected final long maxQueryTime
      • debug

        protected final boolean debug
      • maxDBConnections

        protected final int maxDBConnections
      • random

        protected static java.util.Random random
    • 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.
      • explainQuery

        protected void explainQuery​(java.lang.String query,
                                    java.util.List params)
                             throws ManifoldCFException
        Abstract 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 ManifoldCFException
        Prepare 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 ManifoldCFException
        Begin 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
      • performCommit

        public void performCommit()
                           throws ManifoldCFException
        Perform 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 ManifoldCFException
        End 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 ManifoldCFException
        Note 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 ManifoldCFException
        Protected 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.
      • constructIndexHintClause

        public java.lang.String constructIndexHintClause​(java.lang.String tableName,
                                                         IndexDescription description)
                                                  throws ManifoldCFException
        Construct 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)
      • 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.
      • initializeConnection

        protected void initializeConnection​(java.sql.Connection connection)
                                     throws ManifoldCFException
        Initialize 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 string
        bResults - boolean whether to load the resultset or not
        maxResults - is the maximum number of results to load: -1 if all
        params - List if params !=null, use preparedStatement
        Throws:
        ManifoldCFException
      • loadPS

        protected static void loadPS​(java.sql.PreparedStatement ps,
                                     java.util.List data)
                              throws java.sql.SQLException,
                                     ManifoldCFException
        Throws:
        java.sql.SQLException
        ManifoldCFException
      • cleanupParameters

        protected static void cleanupParameters​(java.util.List data)
                                         throws ManifoldCFException
        Clean up parameters after query has been triggered.
        Throws:
        ManifoldCFException
      • getObject

        protected java.lang.Object getObject​(java.sql.ResultSet rs,
                                             java.sql.ResultSetMetaData rsmd,
                                             int col,
                                             int desiredForm)
                                      throws ManifoldCFException
        Throws:
        ManifoldCFException