Class SDriver

  • Direct Known Subclasses:
    SDriverDB2, SDriverDerby, SDriverHSQLH2, SDriverInformix, SDriverInterbase, SDriverMSSQL, SDriverMySQL, SDriverOracle, SDriverPostgres, SDriverSapDB, SDriverSybase, SQLiteDriver

    public class SDriver
    extends java.lang.Object
    This is the internal generic database driver that contains database dependent code. Specific SimpleORM drivers extend this class and specialize its methods as required. The driver type is infered from the jdbc connection's meta data.

    (Profiling suggests that memoising these generaters could produce a 5-10% improvement in bulk updates.)

    There is now one driver instance per connection so one can say SSession.getDriver().setMyFavouriteParam(...)

    SQL 92 standard data types, I think:- boolean, Character(n), character varying(n), date, float(p), real, double precission, smallint, int | integer, decimal(p,s), numeric(p,s), time, interval, timestamp with timezone,

    • Constructor Detail

      • SDriver

        protected SDriver()
    • Method Detail

      • registerDriver

        public void registerDriver()
        Add driver to the list of possible drivers that can be found by SSession.attach. The key is returned by driverName.
      • driverName

        protected java.lang.String driverName()
        The driver name to be compared to getMetaData().getDriverName()
      • queryExecuteFactory

        protected simpleorm.sessionjdbc.SQueryExecute queryExecuteFactory​(SSessionJdbc session,
                                                                          SQuery query)
      • appendQuotedIdentifier

        protected void appendQuotedIdentifier​(java.lang.String ident,
                                              java.lang.StringBuffer buf)
        Wraps identifiers in "s to avoid reserved word issues. (Override this for dbs that use different chars, eg [xxx] for MS-SQL. We do quote these days to avoid the endless problems with reserved words.
      • appendQuotedIdentifier

        protected void appendQuotedIdentifier​(java.lang.String ident,
                                              java.lang.StringBuffer buf,
                                              char quote)
      • appendColumnName

        public void appendColumnName​(SFieldScalar field,
                                     java.lang.StringBuffer buf)
        name appended, quoted iff appropriate.
      • appendTableName

        public void appendTableName​(SRecordMeta table,
                                    java.lang.StringBuffer buf)
        name, quoted iff appropriate.
      • maxIdentNameLength

        public int maxIdentNameLength()
        The maximum size for table names and foreign key constraint names.
      • supportsLocking

        public boolean supportsLocking()
        True if exclusive locks are properly supported. Otherwise optimistic locks are always used.

      • alterTableAddColumnSQL

        public java.lang.String alterTableAddColumnSQL​(SFieldScalar field)
        These alow you to create a new SFieldMeta object at runtime and then update the table to include it. Eg. for end user customizations. ## Ideally this could be further automated so that the SRecordMeta and JDBC meta data for a table could be compared and the table automatically altered.
      • alterTableDropColumnSQL

        public java.lang.String alterTableDropColumnSQL​(SFieldScalar field)
      • createTableSQL

        public java.lang.String createTableSQL​(SRecordMeta<?> meta)
        Returns a CREATE TABLE for this table. Delegated from SRecord. This is split up into many sub-methods so that they can be selectively specialized by other drivers.
      • clauseSeparator

        protected java.lang.String clauseSeparator​(java.lang.String indent)
        Normally newline and indent to separate clauses of large SQL statement
      • wholeColumnSQL

        protected java.lang.String wholeColumnSQL​(SFieldScalar fld)
        Returns MY_COL VARCHAR(13) NOT NULL.
        See Also:
        #SMANDATORY
      • addNull

        protected void addNull​(java.lang.StringBuffer sql,
                               SFieldScalar fld)
      • columnTypeSQL

        protected java.lang.String columnTypeSQL​(SFieldScalar field,
                                                 java.lang.String defalt)
        Used to override the default. ONLY called if no fld.defaultSqlDataType has been specified, ie. only used to override the SFieldScalar.defaultSqlDataType.
      • postColumnSQL

        protected java.lang.String postColumnSQL​(SFieldMeta field)
        After NOT NULL but before the ",", ie column specific annotations.
      • primaryKeySQL

        protected java.lang.String primaryKeySQL​(SRecordMeta<?> meta)
        Return PRIMARY KEY(KCOL, KCOL) appended to end.
      • indexKeySQL

        protected java.lang.String indexKeySQL​(SRecordMeta meta)
        Needed for MySQL to create indexes on foreign keys
      • foreignKeysSQL

        protected java.lang.String foreignKeysSQL​(SRecordMeta meta)
        Returns FOREIGN KEY (FKCOL, FKCOL) REFERENCES FTABLE (KCOL, KCOL) appended to end.
      • mapForeignKeys

        protected java.lang.String mapForeignKeys​(SRecordMeta<?> meta,
                                                  boolean foreignKey)
      • makeForeignKeyIndexSQL

        protected void makeForeignKeyIndexSQL​(SRecordMeta meta,
                                              int fx,
                                              SFieldReference fldRef,
                                              java.lang.StringBuffer sbFkey,
                                              java.lang.StringBuffer sbRefed,
                                              java.lang.StringBuffer fkey)
      • postTablePreParenSQL

        protected java.lang.String postTablePreParenSQL​(SRecordMeta meta)
        Any other text to be added before the final ")"
      • postTablePostParenSQL

        protected java.lang.String postTablePostParenSQL​(SRecordMeta meta)
        Any other text to be added after the final ")". No ";".
      • selectSQL

        protected java.lang.String selectSQL​(SFieldScalar[] select,
                                             SRecordMeta from,
                                             SFieldScalar[] where,
                                             java.lang.String orderBy,
                                             boolean forUpdate,
                                             simpleorm.sessionjdbc.SQueryExecute sps)
        Returns the SQL statement for a SELECT in a structured way. Used by findOrInsert. select and where are arrays of SFieldMetas. Returns SQL statement as a string.

        This now quotes table and column names so that they become case independent.

        sps is links to the SPreparedStatement object. It can have arbitrary properties set to provide fine control over the query. Examples include limits.

      • selectSQL

        protected java.lang.String selectSQL​(SFieldScalar[] select,
                                             SRecordMeta<?> from,
                                             java.lang.String join,
                                             java.lang.String where,
                                             java.lang.String orderBy,
                                             boolean forUpdate,
                                             simpleorm.sessionjdbc.SQueryExecute sps)
      • forUpdateSQL

        protected java.lang.String forUpdateSQL​(boolean forUpdate)
        Returns update clause, may not be valid in certain lock modes etc. Right at the end of the query.

        Oracle, Postgresql, and new in MS SQL 2005 support data versioning or snapshots. This means that repeatable read is achieved by caching the previous value read instead of using read locks. This approach makes it critical to add FOR UPDATE where appropriate or there is effectively no locking.

        Indeed, in Oracle, you are guaranteed that several SELECTS will return the same value, but a subsequent SELECT FOR UPDATE in the same transaction may return a different value.

      • limitSQL

        protected java.lang.String limitSQL​(long offset,
                                            long limit)
        Drivers that choose to implement a QUERY offset strategy should return the limit statment here
        Parameters:
        offset - number of rows to skip
        limit - number of rows to retrieve
        Returns:
        LIMIT + OFFSET string statment
      • fromSQL

        protected void fromSQL​(SRecordMeta from,
                               SRecordMeta[] joinTables,
                               java.lang.StringBuffer res)
        Returns the FROM Table, Table... clause
      • joinSQL

        protected java.lang.String joinSQL​(SRecordMeta[] joinTables)
      • postFromSQL

        protected java.lang.String postFromSQL​(boolean forUpdate)
        For MSSQL. Just after all the tables in the From clause.
      • updateSQL

        protected java.lang.String updateSQL​(java.util.ArrayList<SFieldScalar> updates,
                                             SRecordMeta from,
                                             java.util.ArrayList<SFieldScalar> where,
                                             SRecordInstance instance,
                                             java.lang.Object[] keyMetaValues)
        Returns the SQL statement for an UPDATE in a structured way. Used by flush(). updates and where are SSArrayLists of SFieldMetas. Returns SQL statement as a string.
      • insertSQL

        protected java.lang.String insertSQL​(java.util.ArrayList<SFieldScalar> updates,
                                             SRecordMeta from)
        Returns the SQL statement for an INSERT in a structured way. Used by flush(). updates and where are SSArrayLists of SFieldMetas. Returns SQL statement as a string.
      • deleteSQL

        protected java.lang.String deleteSQL​(SRecordMeta from,
                                             java.util.ArrayList where,
                                             SRecordInstance instance,
                                             java.lang.Object[] keyMetaValues)
        Returns the SQL statement for an DELETE in a structured way. Used by flush(). where are SSArrayLists of SFieldMetas. Returns SQL statement as a string.
      • whereSQL

        protected void whereSQL​(java.lang.StringBuffer ret,
                                java.util.ArrayList<SFieldScalar> where,
                                SRecordInstance instance,
                                java.lang.Object[] keyMetaValues)
        Produces the WHERE clause of UPDATE and DELETE statements. Needs to know the instance values so that it can use the IS NULL test (for optimisitic locking).
      • getOffsetStrategy

        protected SDriver.OffsetStrategy getOffsetStrategy()
        JDBC prefered, if jdbc driver has a sensible scrollable resultset implemntation QUERY if database would handle it better via some proprietary sql extension (eg. LIMIT) BULK Simpleorm will get the whole resultset and skip de first row. Worst case scenario :(

        Defaults to BULK

      • generateKeySelectMax

        protected long generateKeySelectMax​(SRecordMeta rec,
                                            SFieldScalar keyFld)
        Generates a new key using SELECT MAX+1. This will (hopefully) be specialized for each database driver to be correct. Note that there is a global counter kept so it will actually work OK if all the updates are from one JVM. Amazing that there is still no standard way to do this in SQL.

        ## (There is scope to optimize this at some point so that one JDBC call can both generate the sequence number and insert a new record. But that means that the new record's key is not available until insert time which causes problems for foreign keys. Alternatively one can get batches of 10 (say) sequences at a time and then use an internal counter, but this will leave big holes in the sequence. Defer this to version 1.)

      • supportsKeySequences

        public boolean supportsKeySequences()
      • createSequenceDDL

        protected java.lang.String createSequenceDDL​(java.lang.String name)
      • dropSequenceDDL

        protected java.lang.String dropSequenceDDL​(java.lang.String name)
      • dropTableNoError

        public void dropTableNoError​(java.lang.String table)
        Utility routine for dropping tables called by SSession. Driver specific versions should only hide table non existent errors (and not warn about them).
      • getLogger

        public SLog getLogger()