|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectnet.java.ao.DatabaseProvider
net.java.ao.db.SQLServerDatabaseProvider
public class SQLServerDatabaseProvider
Nested Class Summary |
---|
Nested classes/interfaces inherited from class net.java.ao.DatabaseProvider |
---|
DatabaseProvider.RenderFieldOptions, DatabaseProvider.SqlListener |
Field Summary |
---|
Fields inherited from class net.java.ao.DatabaseProvider |
---|
logger, sqlLogger |
Constructor Summary | |
---|---|
SQLServerDatabaseProvider(DisposableDataSource dataSource)
|
|
SQLServerDatabaseProvider(DisposableDataSource dataSource,
String schema)
|
Method Summary | ||
---|---|---|
protected boolean |
considerPrecision(DDLField field)
Determines whether or not the database allows explicit precisions for the field in question. |
|
protected String |
convertTypeToString(DatabaseType<?> type)
Converts the specified type into the database-specific DDL String value. |
|
protected Set<String> |
getReservedWords()
Retrieves the set of all reserved words for the underlying database. |
|
ResultSet |
getTables(Connection conn)
Returns a result set of all of the tables (and associated meta) in the database. |
|
|
insertReturningKey(EntityManager manager,
Connection conn,
Class<T> pkType,
String pkField,
boolean pkIdentity,
String table,
DBParam... params)
Generates an INSERT statement to be used to create a new row in the database, returning the primary key value. |
|
Object |
parseValue(int type,
String value)
Parses the database-agnostic String value relevant to the specified SQL
type in int form (as defined by Types and returns
the Java value which corresponds. |
|
protected String[] |
renderAlterTableAddColumn(DDLTable table,
DDLField field)
Generates the database-specific DDL statements required to add a column to an existing table. |
|
protected List<String> |
renderAlterTableChangeColumn(DDLTable table,
DDLField oldField,
DDLField field)
Generates the database-specific DDL statements required to change the given column from its old specification to the given DDL value. |
|
protected String |
renderAlterTableChangeColumnStatement(DDLTable table,
DDLField oldField,
DDLField field,
DatabaseProvider.RenderFieldOptions options)
Generates the database-specific DDL statement only for altering a table and changing a column. |
|
protected String |
renderAlterTableDropKey(DDLForeignKey key)
Generates the database-specific DDL statement required to remove a foreign key from a table. |
|
protected String |
renderAutoIncrement()
Generates the DDL fragment required to specify an INTEGER field as auto-incremented. |
|
protected String |
renderFieldDefault(DDLTable table,
DDLField field)
|
|
protected DatabaseProvider.RenderFieldOptions |
renderFieldOptionsInAlterColumn()
|
|
protected String |
renderFieldPrecision(DDLField field)
Renders the statement fragment for the given field representative of its precision only. |
|
protected String |
renderFunction(DatabaseFunction func)
Renders the specified DatabaseFunction in its
database-specific form. |
|
protected String |
renderOnUpdate(DDLField field)
Renders the appropriate field suffix to allow for the OnUpdate functionality. |
|
protected String |
renderQueryLimit(Query query)
Renders the LIMIT portion of the query in the database-specific SQL dialect. |
|
protected String |
renderQuerySelect(Query query,
TableNameConverter converter,
boolean count)
Renders the SELECT portion of a given Query instance in the
manner required by the database-specific SQL implementation. |
|
protected String |
renderTriggerForField(DDLTable table,
DDLField field)
Renders the trigger which corresponds to the specified field, or null if none. |
|
void |
setQueryResultSetProperties(ResultSet res,
Query query)
Allows the provider to set database-specific options on a ResultSet instance prior to its use by the library. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
public SQLServerDatabaseProvider(DisposableDataSource dataSource)
public SQLServerDatabaseProvider(DisposableDataSource dataSource, String schema)
Method Detail |
---|
public void setQueryResultSetProperties(ResultSet res, Query query) throws SQLException
DatabaseProvider
ResultSet
instance prior to its use by the library.
This allows for features such as row offsetting even on
databases that don't support it (such as Oracle, Derby,
etc).
setQueryResultSetProperties
in class DatabaseProvider
res
- The ResultSet
to modify.query
- The query instance which was run to produce
the result set.
SQLException
public ResultSet getTables(Connection conn) throws SQLException
DatabaseProvider
Returns a result set of all of the tables (and associated
meta) in the database. The fields of the result set must
correspond with those specified in the
DatabaseMetaData#getTables(String, String, String, String[])
method. In fact, the default implementation merely calls
this method passing (null, null, "", null)
.
For databases (such as PostgreSQL) where this is unsuitable,
different parameters can be specified to the getTables
method in the override, or an entirely new implementation
written, as long as the result set corresponds in fields to
the JDBC spec.
getTables
in class DatabaseProvider
conn
- The connection to use in retrieving the database tables.
SQLException
DatabaseMetaData.getTables(String, String, String, String[])
public Object parseValue(int type, String value)
DatabaseProvider
Parses the database-agnostic String
value relevant to the specified SQL
type in int
form (as defined by Types
and returns
the Java value which corresponds. This method is completely database-agnostic, as are
all of all of its delegate methods.
WARNING: This method is being considered for removal to another
class (perhaps TypeManager
?) as it is not a database-specific function and thus
confuses the purpose of this class. Do not rely upon it heavily. (better yet, don't rely on it
at all from external code. It's not designed to be part of the public API)
parseValue
in class DatabaseProvider
type
- The JDBC integer type of the database field against which to parse the
value.value
- The database-agnostic String value to parse into a proper Java object
with respect to the specified SQL type.
protected List<String> renderAlterTableChangeColumn(DDLTable table, DDLField oldField, DDLField field)
DatabaseProvider
Generates the database-specific DDL statements required to change the given column from its old specification to the given DDL value. This method will also generate the appropriate statements to remove old triggers and functions, as well as add new ones according to the requirements of the new field definition.
The default implementation of this method functions in the manner specified by the MySQL database. Some databases will have to perform more complicated actions (such as dropping and re-adding the field) in order to satesfy the same use-case. Such databases should print a warning to stderr to ensure that the end-developer is aware of such restrictions.
Thus, the specification for this method allows for data loss. Nevertheless, if the database supplies a mechanism to accomplish the task without data loss, it should be applied.
For maximum flexibility, the default implementation of this method
only deals with the dropping and addition of functions and triggers.
The actual generation of the ALTER TABLE statement is done in the
#renderAlterTableChangeColumnStatement(net.java.ao.schema.ddl.DDLTable, net.java.ao.schema.ddl.DDLField, net.java.ao.schema.ddl.DDLField, boolean)
method.
renderAlterTableChangeColumn
in class DatabaseProvider
table
- The table containing the column to change.oldField
- The old column definition.field
- The new column definition (defining the resultant DDL).
DatabaseProvider.getTriggerNameForField(DDLTable, DDLField)
,
DatabaseProvider.getFunctionNameForField(DDLTable, DDLField)
,
DatabaseProvider.renderFunctionForField(DDLTable, DDLField)
,
DatabaseProvider.renderTriggerForField(DDLTable, DDLField)
protected DatabaseProvider.RenderFieldOptions renderFieldOptionsInAlterColumn()
renderFieldOptionsInAlterColumn
in class DatabaseProvider
protected String renderQuerySelect(Query query, TableNameConverter converter, boolean count)
DatabaseProvider
Renders the SELECT portion of a given Query
instance in the
manner required by the database-specific SQL implementation. Usually,
this is as simple as "SELECT id FROM table"
or "SELECT DISTINCT
* FROM table"
. However, some databases require the limit and offset
parameters to be specified as part of the SELECT clause. For example,
on HSQLDB, a Query for the "id" field limited to 10 rows would render
SELECT like this: SELECT TOP 10 id FROM table
.
There is usually no need to call this method directly. Under normal
operations it functions as a delegate for DatabaseProvider.renderQuery(Query, TableNameConverter, boolean)
.
renderQuerySelect
in class DatabaseProvider
query
- The Query instance from which to determine the SELECT properties.converter
- The name converter to allow conversion of the query entity
interface into a proper table name.count
- Whether or not the query should be rendered as a SELECT COUNT(*)
.
protected String renderQueryLimit(Query query)
DatabaseProvider
Renders the LIMIT portion of the query in the database-specific SQL
dialect. There is wide variety in database implementations of this
particular SQL clause. In fact, many database do not support it at all.
If the database in question does not support LIMIT, this method should
be overridden to return an empty String. For such databases, LIMIT
should be implemented by overriding DatabaseProvider.setQueryResultSetProperties(ResultSet, Query)
and DatabaseProvider.setQueryStatementProperties(Statement, Query)
.
An example return value: " LIMIT 10,2"
There is usually no need to call this method directly. Under normal
operations it functions as a delegate for DatabaseProvider.renderQuery(Query, TableNameConverter, boolean)
.
renderQueryLimit
in class DatabaseProvider
query
- The Query instance from which to determine the LIMIT properties.
protected String renderAutoIncrement()
DatabaseProvider
Generates the DDL fragment required to specify an INTEGER field as
auto-incremented. For databases which do not support such flags (which
is just about every database exception MySQL), ""
is an
acceptable return value. This method should never return null
as it would cause the field rendering method to throw a NullPointerException
.
renderAutoIncrement
in class DatabaseProvider
protected String renderOnUpdate(DDLField field)
DatabaseProvider
Renders the appropriate field suffix to allow for the
OnUpdate
functionality. For most databases (read:
all but MySQL) this will return an empty String. This is
because few databases provide an implicit ON UPDATE syntax for
fields. As such, most databases will be compelled to return
an empty String and implement the functionality using triggers.
renderOnUpdate
in class DatabaseProvider
field
- The field for which the ON UPDATE clause should
be rendered.
protected String convertTypeToString(DatabaseType<?> type)
DatabaseProvider
DatabaseType#getDefaultName()
method. Subclass implementations should be sure to make a super
call in order to ensure that both default naming and future special
cases are handled appropriately.
convertTypeToString
in class DatabaseProvider
type
- The type instance to convert to a DDL string.
DatabaseType.getDefaultName()
protected boolean considerPrecision(DDLField field)
DatabaseProvider
Determines whether or not the database allows explicit precisions
for the field in question. This is to support databases such as
Derby which do not support precisions for certain types. By
default, this method returns true
.
More often than not, all that is required for this determination is the type. As such, the method signature may change in a future release.
considerPrecision
in class DatabaseProvider
field
- The field for which precision should/shouldn't be rendered.
true
if precision should be rendered, otherwise
false
.protected String renderFieldDefault(DDLTable table, DDLField field)
renderFieldDefault
in class DatabaseProvider
protected String renderFieldPrecision(DDLField field)
DatabaseProvider
Renders the statement fragment for the given field representative of its precision only. Consider the following statement:
ALTER TABLE ADD COLUMN name VARCHAR(255)
In this statement, the bit which is rendered by this method is the
"(255)
" (without quotes). This is intended to allow
maximum flexibility in field type rendering (as required by PostgreSQL
and others which sometimes render types separately from the rest of
the field info). The default implementation should suffice for every
conceivable database. Any sort of odd functionality relating to
type precision rendering should be handled in the DatabaseProvider.considerPrecision(DDLField)
method if possible.
renderFieldPrecision
in class DatabaseProvider
field
- The field for which the precision must be rendered.
protected String renderFunction(DatabaseFunction func)
DatabaseProvider
Renders the specified DatabaseFunction
in its
database-specific form. For example, for MySQL the
CURRENT_DATE
enum value would be rendered as
"CURRENT_DATE
" (without the quotes). For functions
which do not have a database equivalent, a default literal value
of the appropriate type should be returned. For example, if MySQL
did not define either a CURRENT_DATE or a CURRENT_TIMESTAMP
function, the appropriate return value for both functions would
be '0000-00-00 00:00:00'
(including the quotes).
This is to prevent migrations from failing even in cases where
non-standard functions are used.
As of 1.0, no unconventional functions are allowed by the
DatabaseFunction
enum, thus no database should have any
problems with any allowed functions.
renderFunction
in class DatabaseProvider
func
- The abstract function to be rendered.
protected String renderTriggerForField(DDLTable table, DDLField field)
DatabaseProvider
null
if none. This is to allow for databases which
require the use of triggers to provide functionality such as ON
UPDATE. The default implementation returns null
.
renderTriggerForField
in class DatabaseProvider
table
- The table containing the field for which a trigger
may need to be rendered.field
- The field for which the trigger should be rendered,
if any.
null
.DatabaseProvider.getTriggerNameForField(DDLTable, DDLField)
protected String renderAlterTableChangeColumnStatement(DDLTable table, DDLField oldField, DDLField field, DatabaseProvider.RenderFieldOptions options)
DatabaseProvider
DatabaseProvider.renderAlterTableChangeColumn(DDLTable, DDLField, DDLField)
method,
for which it is a primary delegate. The default implementation of this
method functions according to the MySQL specification.
renderAlterTableChangeColumnStatement
in class DatabaseProvider
table
- The table containing the column to change.oldField
- The old column definition.field
- The new column definition (defining the resultant DDL).
DatabaseProvider.renderField(net.java.ao.schema.ddl.DDLTable, net.java.ao.schema.ddl.DDLField, DatabaseProvider.RenderFieldOptions)
protected String[] renderAlterTableAddColumn(DDLTable table, DDLField field)
DatabaseProvider
@OnUpdate
annotation, chances are there will be a trigger and possibly a
function along with the ALTER statement. These "extra"
functions are properly ordered and will only be appended if
their values are not null
. Because of this, very
few database providers will need to override this method.
renderAlterTableAddColumn
in class DatabaseProvider
table
- The table which should receive the new column.field
- The column to add to the specified table.
DatabaseProvider.renderFunctionForField(DDLTable, DDLField)
,
DatabaseProvider.renderTriggerForField(DDLTable, DDLField)
protected String renderAlterTableDropKey(DDLForeignKey key)
DatabaseProvider
null
value returned. This method assumes that the
DatabaseProvider.renderForeignKey(DDLForeignKey)
method properly names
the foreign key according to the DDLForeignKey.getFKName()
method.
renderAlterTableDropKey
in class DatabaseProvider
key
- The foreign key to be removed. As this instance contains
all necessary data (such as domestic table, field, etc), no
additional parameters are required.
null
.public <T> T insertReturningKey(EntityManager manager, Connection conn, Class<T> pkType, String pkField, boolean pkIdentity, String table, DBParam... params) throws SQLException
DatabaseProvider
Generates an INSERT statement to be used to create a new row in the
database, returning the primary key value. This method also invokes
the delegate method, DatabaseProvider.executeInsertReturningKey(EntityManager, java.sql.Connection, Class, String, String, DBParam...)
passing the appropriate parameters and query. This method is required
because some databases do not support the JDBC parameter
RETURN_GENERATED_KEYS
(such as HSQLDB and PostgreSQL).
Also, some databases (such as MS SQL Server) require odd tricks to
support explicit value passing to auto-generated fields. This method
should take care of any extra queries or odd SQL generation required
to implement both auto-generated primary key returning, as well as
explicit primary key value definition.
Overriding implementations of this method should be sure to use the
Connection
instance passed to the method, not a new
instance generated using the DatabaseProvider.getConnection()
method. This is
because this method is in fact a delegate invoked by EntityManager
as part of the entity creation process and may be part of a transaction,
a bulk creation or some more complicated operation. Both optimization
and usage patterns on the API dictate that the specified connection
instance be used. Implementations may assume that the given connection
instance is never null
.
The default implementation of this method should be sufficient for any
fully compliant ANSI SQL database with a properly implemented JDBC
driver. Note that this method should not not actually execute
the SQL it generates, but pass it on to the DatabaseProvider.executeInsertReturningKey(EntityManager, java.sql.Connection, Class, String, String, DBParam...)
method, allowing for functional delegation and better extensibility.
However, this method may execute any additional statements required to
prepare for the INSERTion (as in the case of MS SQL Server which requires
some config parameters to be set on the database itself prior to INSERT).
insertReturningKey
in class DatabaseProvider
manager
- The EntityManager
which was used to dispatch
the INSERT in question.conn
- The connection to be used in the eventual execution of the
generated SQL statement.pkType
- The Java type of the primary key value. Can be used to
perform a linear search for a specified primary key value in the
params
list. The return value of the method must be of
the same type.pkField
- The database field which is the primary key for the
table in question. Can be used to perform a linear search for a
specified primary key value in the params
list.pkIdentity
- Flag indicating whether or not the primary key field
is auto-incremented by the database (IDENTITY field).table
- The name of the table into which the row is to be INSERTed.params
- A varargs array of parameters to be passed to the
INSERT statement. This may include a specified value for the
primary key.
SQLException
- If the INSERT fails in the delegate method, or
if any additional statements fail with an exception.DatabaseProvider.executeInsertReturningKey(EntityManager, java.sql.Connection, Class, String, String, DBParam...)
protected Set<String> getReservedWords()
DatabaseProvider
Set
instance returned from this
method should guarentee O(1) lookup times, otherwise ORM performance
will suffer greatly.
getReservedWords
in class DatabaseProvider
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |