Class SDriver
- java.lang.Object
-
- simpleorm.sessionjdbc.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,
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
SDriver.OffsetStrategy
-
Constructor Summary
Constructors Modifier Constructor Description protected
SDriver()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description protected void
addNull(java.lang.StringBuffer sql, SFieldScalar fld)
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.java.lang.String
alterTableDropColumnSQL(SFieldScalar field)
void
appendColumnName(SFieldScalar field, java.lang.StringBuffer buf)
name appended, quoted iff appropriate.protected void
appendQuotedIdentifier(java.lang.String ident, java.lang.StringBuffer buf)
Wraps identifiers in "s to avoid reserved word issues.protected void
appendQuotedIdentifier(java.lang.String ident, java.lang.StringBuffer buf, char quote)
void
appendTableName(SRecordMeta table, java.lang.StringBuffer buf)
name, quoted iff appropriate.protected java.lang.String
clauseSeparator(java.lang.String indent)
Normally newline and indent to separate clauses of large SQL statementprotected java.lang.String
columnTypeSQL(SFieldScalar field, java.lang.String defalt)
Used to override the default.protected java.lang.String
createSequenceDDL(java.lang.String name)
java.lang.String
createTableSQL(SRecordMeta<?> meta)
Returns aCREATE TABLE
for this table.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.protected java.lang.String
driverName()
The driver name to be compared to getMetaData().getDriverName()protected java.lang.String
dropSequenceDDL(java.lang.String name)
void
dropTableNoError(java.lang.String table)
Utility routine for dropping tables called by SSession.protected java.lang.String
foreignKeysSQL(SRecordMeta meta)
ReturnsFOREIGN KEY (FKCOL, FKCOL) REFERENCES FTABLE (KCOL, KCOL)
appended to end.protected java.lang.String
forUpdateSQL(boolean forUpdate)
Returns update clause, may not be valid in certain lock modes etc.protected void
fromSQL(SRecordMeta from, SRecordMeta[] joinTables, java.lang.StringBuffer res)
Returns the FROM Table, Table...protected long
generateKeySelectMax(SRecordMeta rec, SFieldScalar keyFld)
Generates a new key using SELECT MAX+1.protected long
generateKeySequence(SRecordMeta<?> rec, SFieldScalar keyFld)
SLog
getLogger()
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.SSessionJdbc
getSession()
protected java.lang.String
indexKeySQL(SRecordMeta meta)
Needed for MySQL to create indexes on foreign keysprotected java.lang.String
insertSQL(java.util.ArrayList<SFieldScalar> updates, SRecordMeta from)
Returns the SQL statement for an INSERT in a structured way.protected java.lang.String
joinSQL(SRecordMeta[] joinTables)
protected java.lang.String
limitSQL(long offset, long limit)
Drivers that choose to implement a QUERY offset strategy should return the limit statment hereprotected void
makeForeignKeyIndexSQL(SRecordMeta meta, int fx, SFieldReference fldRef, java.lang.StringBuffer sbFkey, java.lang.StringBuffer sbRefed, java.lang.StringBuffer fkey)
protected java.lang.String
mapForeignKeys(SRecordMeta<?> meta, boolean foreignKey)
int
maxIdentNameLength()
The maximum size for table names and foreign key constraint names.protected java.lang.String
postColumnSQL(SFieldMeta field)
After NOT NULL but before the ",", ie column specific annotations.protected java.lang.String
postFromSQL(boolean forUpdate)
For MSSQL.protected java.lang.String
postTablePostParenSQL(SRecordMeta meta)
Any other text to be added after the final ")".protected java.lang.String
postTablePreParenSQL(SRecordMeta meta)
Any other text to be added before the final ")"protected java.lang.String
primaryKeySQL(SRecordMeta<?> meta)
ReturnPRIMARY KEY(KCOL, KCOL)
appended to end.protected simpleorm.sessionjdbc.SQueryExecute
queryExecuteFactory(SSessionJdbc session, SQuery query)
void
registerDriver()
Add driver to the list of possible drivers that can be found by SSession.attach.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)
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.boolean
supportsKeySequences()
boolean
supportsLocking()
True if exclusive locks are properly supported.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.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.protected java.lang.String
wholeColumnSQL(SFieldScalar fld)
ReturnsMY_COL VARCHAR(13) NOT NULL
.
-
-
-
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 aCREATE 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)
ReturnsMY_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)
ReturnPRIMARY 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)
ReturnsFOREIGN 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
andwhere
are arrays ofSFieldMeta
s. 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 skiplimit
- 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
andwhere
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
andwhere
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.)
-
generateKeySequence
protected long generateKeySequence(SRecordMeta<?> rec, SFieldScalar keyFld)
-
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).
-
getSession
public SSessionJdbc getSession()
-
getLogger
public SLog getLogger()
-
-