com.triactive.jdo.store
Class DatabaseAdapter

java.lang.Object
  extended bycom.triactive.jdo.store.DatabaseAdapter
Direct Known Subclasses:
CloudscapeAdapter, DB2Adapter, FirebirdAdapter, MSSQLServerAdapter, MySQLAdapter, OracleAdapter, PostgreSQLAdapter, SAPDBAdapter

public class DatabaseAdapter
extends java.lang.Object

Provides methods for adapting SQL language elements to a specific vendor's database. A database adapter is primarily used to map generic JDBC data types and SQL identifiers to specific types/identifiers suitable for the database in use.

Each database adapter corresponds to a particular combination of database, database version, driver, and driver version, as provided by the driver's own metadata. Database adapters cannot be constructed directly, but must be obtained using the getInstance(java.sql.Connection) method.

Author:
Mike Martin, Christopher Walk
See Also:
DatabaseMetaData

Field Summary
protected  int databaseMajorVersion
          The major version number of the underlying database.
protected  int databaseMinorVersion
          The minor version number of the underlying database.
protected  java.lang.String databaseProductName
          The name of the underlying database.
protected  java.lang.String databaseProductVersion
          The version number of the underlying database as a string.
protected  java.lang.String identifierQuoteString
          The String used to quote SQL identifiers.
protected  java.util.HashSet keywords
          The set of SQL keywords for this DBMS, in upper-case.
protected  int maxColumnNameLength
          The maximum length to be used for a column name.
protected  int maxConstraintNameLength
          The maximum length to be used for a table constraint name.
protected  int maxIndexNameLength
          The maximum length to be used for an index name.
protected  int maxTableNameLength
          The maximum length to be used for a table name.
protected  boolean storesLowerCaseIdentifiers
          true if the database stores all identifiers in lower-case.
protected  boolean storesUpperCaseIdentifiers
          true if the database stores all identifiers in upper-case.
protected  java.util.HashMap typeMappings
           
protected  java.util.HashMap typesByTypeNumber
           
 
Constructor Summary
protected DatabaseAdapter(java.sql.DatabaseMetaData metadata)
          Constructs a database adapter based on the given JDBC metadata.
 
Method Summary
 void closeConnection(java.sql.Connection conn)
           
 boolean createIndexesBeforeForeignKeys()
           
protected  void createTypeInfo(java.sql.DatabaseMetaData metadata)
          Creates TypeInfo objects for all of the data types and indexes them in the typesByTypeNumber map by their JDBC data type number.
 java.lang.String getAddCandidateKeyStatement(SQLIdentifier ckName, CandidateKey ck)
          Returns the appropriate SQL to add a candidate key to its table.
 java.lang.String getAddForeignKeyStatement(SQLIdentifier fkName, ForeignKey fk)
          Returns the appropriate SQL to add a foreign key to its table.
 java.lang.String getAddPrimaryKeyStatement(SQLIdentifier pkName, PrimaryKey pk)
          Returns the appropriate SQL to add a primary key to its table.
 java.sql.Connection getConnection(javax.sql.DataSource ds, java.lang.String userName, java.lang.String password, int isolationLevel)
           
 java.lang.String getCreateIndexStatement(SQLIdentifier idxName, Index idx)
          Returns the appropriate SQL to add an index to its table.
 java.lang.String getCreateTableStatement(BaseTable table, Column[] columns)
          Returns the appropriate SQL to create the given table having the given columns.
 java.lang.String getDropTableStatement(BaseTable table)
          Returns the appropriate SQL to drop the given table.
 java.lang.String getDropViewStatement(View view)
          Returns the appropriate SQL to drop the given view.
 java.lang.String getIdentifierQuoteString()
           
static DatabaseAdapter getInstance(java.sql.Connection conn)
          Returns a DatabaseAdapter object appropriate for the database currently underlying the given Connection.
 Mapping getMapping(java.lang.Class c)
           
 Mapping getMapping(ClassBaseTable table, int relativeFieldNumber)
           
 ColumnMapping getMapping(Column col)
           
protected  java.lang.Class getMappingClass(java.lang.Class c)
           
 int getMaxColumnNameLength()
           
 int getMaxConstraintNameLength()
           
 int getMaxIndexNameLength()
           
 int getMaxTableNameLength()
           
 java.lang.String getSchemaName(java.sql.Connection conn)
           
 SQLState getSQLState(java.sql.SQLException se)
          Returns a SQLState object for the specified SQLException, if one is present and valid.
 TypeInfo getTypeInfo(int dataType)
          Returns type information for the database type that best implements the given JDBC type.
 TypeInfo getTypeInfo(int[] candidateDataTypes)
          Returns type information for the first one of the given candidate JDBC data types supported by this database.
 int getUnlimitedLengthPrecisionValue(TypeInfo typeInfo)
          Returns the precision value to be used when creating string columns of "unlimited" length.
 java.lang.String getVendorID()
           
 boolean includeOrderByColumnsInSelect()
           
 boolean isEmbeddedType(java.lang.Class c)
           
 boolean isSQLKeyword(java.lang.String word)
          Tests if a given string is a SQL key word.
 NumericExpression lengthMethod(CharacterExpression str)
          Returns the appropriate SQL expression for the JDOQL String.length() method.
 ColumnInfo newColumnInfo(java.sql.ResultSet rs)
          A factory for ColumnInfo objects.
 javax.jdo.JDOException newDataStoreException(java.lang.String message, java.sql.SQLException e)
          Create the appropriate JDODataStoreException or JDOFatalDataStoreException for the given SQLException based on whether the action causing the exception has aborted the current transaction.
 ForeignKeyInfo newForeignKeyInfo(java.sql.ResultSet rs)
          A factory for ForeignKeyInfo objects.
 QueryStatement newQueryStatement(Table table)
           
 QueryStatement newQueryStatement(Table table, SQLIdentifier rangeVar)
           
 TableExpression newTableExpression(QueryStatement qs, Table table, SQLIdentifier rangeVar)
          Returns a new TableExpression object appropriate for this DBMS.
protected  TypeInfo newTypeInfo(java.sql.ResultSet rs)
          A factory for TypeInfo objects.
protected  java.util.Set parseKeywordList(java.lang.String list)
           
 boolean storesLowerCaseIdentifiers()
           
 boolean storesUpperCaseIdentifiers()
           
 CharacterExpression substringMethod(CharacterExpression str, NumericExpression begin)
          Returns the appropriate SQL expression for the JDOQL String.substring(str,begin) method.
 CharacterExpression substringMethod(CharacterExpression str, NumericExpression begin, NumericExpression end)
          Returns the appropriate SQL expression for the JDOQL String.substring(str,begin,end) method.
 boolean supportsAlterTableDropConstraint()
           
 boolean supportsBooleanComparison()
           
 boolean supportsDeferredConstraints()
           
 boolean supportsNullsInCandidateKeys()
           
 java.lang.String toString()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

databaseProductName

protected java.lang.String databaseProductName
The name of the underlying database.


databaseProductVersion

protected java.lang.String databaseProductVersion
The version number of the underlying database as a string.


databaseMajorVersion

protected int databaseMajorVersion
The major version number of the underlying database.


databaseMinorVersion

protected int databaseMinorVersion
The minor version number of the underlying database.


maxTableNameLength

protected int maxTableNameLength
The maximum length to be used for a table name.


maxConstraintNameLength

protected int maxConstraintNameLength
The maximum length to be used for a table constraint name.


maxIndexNameLength

protected int maxIndexNameLength
The maximum length to be used for an index name.


maxColumnNameLength

protected int maxColumnNameLength
The maximum length to be used for a column name.


storesLowerCaseIdentifiers

protected boolean storesLowerCaseIdentifiers
true if the database stores all identifiers in lower-case.


storesUpperCaseIdentifiers

protected boolean storesUpperCaseIdentifiers
true if the database stores all identifiers in upper-case.


identifierQuoteString

protected java.lang.String identifierQuoteString
The String used to quote SQL identifiers.


keywords

protected final java.util.HashSet keywords
The set of SQL keywords for this DBMS, in upper-case.


typesByTypeNumber

protected final java.util.HashMap typesByTypeNumber

typeMappings

protected final java.util.HashMap typeMappings
Constructor Detail

DatabaseAdapter

protected DatabaseAdapter(java.sql.DatabaseMetaData metadata)
Constructs a database adapter based on the given JDBC metadata.

Parameters:
metadata - the database metadata.
Method Detail

getInstance

public static DatabaseAdapter getInstance(java.sql.Connection conn)
                                   throws java.sql.SQLException
Returns a DatabaseAdapter object appropriate for the database currently underlying the given Connection. Multiple calls to this method with connections having the same database/driver/version will return the same DatabaseAdapter object.

Parameters:
conn - An open database connection.
Returns:
a database adapter object for the database underlying the given connection.
Throws:
java.sql.SQLException - If a database error occurs.

getVendorID

public java.lang.String getVendorID()

getMaxTableNameLength

public int getMaxTableNameLength()

getMaxConstraintNameLength

public int getMaxConstraintNameLength()

getMaxIndexNameLength

public int getMaxIndexNameLength()

getMaxColumnNameLength

public int getMaxColumnNameLength()

storesLowerCaseIdentifiers

public boolean storesLowerCaseIdentifiers()

storesUpperCaseIdentifiers

public boolean storesUpperCaseIdentifiers()

getSQLState

public SQLState getSQLState(java.sql.SQLException se)
Returns a SQLState object for the specified SQLException, if one is present and valid.

Parameters:
se - A caught SQL exception.
Returns:
A SQLState object, or null if se does not contain a valid 5-character SQLSTATE.

newDataStoreException

public javax.jdo.JDOException newDataStoreException(java.lang.String message,
                                                    java.sql.SQLException e)
Create the appropriate JDODataStoreException or JDOFatalDataStoreException for the given SQLException based on whether the action causing the exception has aborted the current transaction.

For historical reasons, the design of this method is flawed. To conform correctly to the spec, if a JDOFatalDataStoreException is returned then there should be some coordination with the appropriate PersistenceManager and its Transaction to allow them to reflect the fact that a transaction is no longer active. At the least, that means that this method would have to be passed a reference to a PersistenceManager.

An outstanding question remains how we can reliably determine via JDBC whether or not a failed statement has aborted the current database transaction. Bottom line, this area is ripe for refactoring.

The current implementation in this class always returns a new JDODataStoreException and never a JDOFatalDataStoreException.

Parameters:
message - The message to include in the JDODataStoreException.
e - The SQLException to create a JDODataStoreException for.
Returns:
A JDODataStoreException or JDOFatalDataStoreException that wraps the given SQLException. A fatal exception is used to indicate that the active transaction has been aborted.

createTypeInfo

protected void createTypeInfo(java.sql.DatabaseMetaData metadata)
                       throws java.sql.SQLException
Creates TypeInfo objects for all of the data types and indexes them in the typesByTypeNumber map by their JDBC data type number.

Throws:
java.sql.SQLException

newTypeInfo

protected TypeInfo newTypeInfo(java.sql.ResultSet rs)
A factory for TypeInfo objects. This method should always be used instead of directly constructing TypeInfo objects in order to give the DatabaseAdapter an opportunity to modify and/or correct the metadata obtained from the JDBC driver. The type information object is constructed from the current row of the given result set. The ResultSet object passed must have been obtained from a call to DatabaseMetaData.getTypeInfo().

The constructor only retrieves the values from the current row; the caller is required to advance to the next row with ResultSet.next().

Parameters:
rs - The result set returned from DatabaseMetaData.getTypeInfo().
Returns:
A TypeInfo object constructed from the current result set row, or null if the type indicated by this row should be excluded from use.

newColumnInfo

public ColumnInfo newColumnInfo(java.sql.ResultSet rs)
A factory for ColumnInfo objects. This method should always be used instead of directly constructing ColumnInfo objects in order to give the DatabaseAdapter an opportunity to modify and/or correct the metadata obtained from the JDBC driver. The column information object is constructed from the current row of the given result set. The ResultSet object passed must have been obtained from a call to DatabaseMetaData.getColumns().

The constructor only retrieves the values from the current row; the caller is required to advance to the next row with ResultSet.next().

Parameters:
rs - The result set returned from DatabaseMetaData.getColumns().

newForeignKeyInfo

public ForeignKeyInfo newForeignKeyInfo(java.sql.ResultSet rs)
A factory for ForeignKeyInfo objects. This method should always be used instead of directly constructing ForeignKeyInfo objects in order to give the DatabaseAdapter an opportunity to modify and/or correct the metadata obtained from the JDBC driver. The column information object is constructed from the current row of the given result set. The ResultSet object passed must have been obtained from a call to DatabaseMetaData.getImportedKeys() or DatabaseMetaData.getExportedKeys().

The constructor only retrieves the values from the current row; the caller is required to advance to the next row with ResultSet.next().

Parameters:
rs - The result set returned from DatabaseMetaData.get??portedKeys().

parseKeywordList

protected java.util.Set parseKeywordList(java.lang.String list)

isSQLKeyword

public boolean isSQLKeyword(java.lang.String word)
Tests if a given string is a SQL key word.

The list of key words tested against is defined to contain all SQL/92 key words, plus any additional key words reported by the JDBC driver for this adapter via DatabaseMetaData.getSQLKeywords().

In general, use of a SQL key word as an identifier should be avoided. SQL/92 key words are divided into reserved and non-reserved words. If a reserved word is used as an identifier it must be quoted with double quotes. Strictly speaking, the same is not true of non-reserved words. However, as C.J. Date writes in A Guide To The SQL Standard:

The rule by which it is determined within the standard that one key word needs to be reserved while another need not is not clear to this writer. In practice, it is probably wise to treat all key words as reserved.

Parameters:
word - The word to test.
Returns:
true if word is a SQL key word for this DBMS. The comparison is case-insensitive.
See Also:
SQL92Constants

getTypeInfo

public TypeInfo getTypeInfo(int dataType)
                     throws UnsupportedDataTypeException
Returns type information for the database type that best implements the given JDBC type.

Parameters:
dataType - JDBC type number of the data type.
Returns:
type information for the best matching type.
Throws:
UnsupportedDataTypeException

getTypeInfo

public TypeInfo getTypeInfo(int[] candidateDataTypes)
                     throws UnsupportedDataTypeException
Returns type information for the first one of the given candidate JDBC data types supported by this database.

Parameters:
candidateDataTypes - array of JDBC type numbers of the data types to be checked in order of preference.
Returns:
type information for the first supported type.
Throws:
UnsupportedDataTypeException

getUnlimitedLengthPrecisionValue

public int getUnlimitedLengthPrecisionValue(TypeInfo typeInfo)
Returns the precision value to be used when creating string columns of "unlimited" length. Usually, if this value is needed it is provided in the database metadata (TypeInfo.precision). However, for some types in some databases the value must be computed specially.

Parameters:
typeInfo - the typeInfo object for which the precision value is needed.
Returns:
the precision value to be used when creating the column, or -1 if no value should be used.

isEmbeddedType

public boolean isEmbeddedType(java.lang.Class c)

getMapping

public Mapping getMapping(java.lang.Class c)

getMapping

public ColumnMapping getMapping(Column col)

getMapping

public Mapping getMapping(ClassBaseTable table,
                          int relativeFieldNumber)

getMappingClass

protected java.lang.Class getMappingClass(java.lang.Class c)

getConnection

public java.sql.Connection getConnection(javax.sql.DataSource ds,
                                         java.lang.String userName,
                                         java.lang.String password,
                                         int isolationLevel)
                                  throws java.sql.SQLException
Throws:
java.sql.SQLException

closeConnection

public void closeConnection(java.sql.Connection conn)
                     throws java.sql.SQLException
Throws:
java.sql.SQLException

getSchemaName

public java.lang.String getSchemaName(java.sql.Connection conn)
                               throws java.sql.SQLException
Throws:
java.sql.SQLException

getIdentifierQuoteString

public java.lang.String getIdentifierQuoteString()

createIndexesBeforeForeignKeys

public boolean createIndexesBeforeForeignKeys()

includeOrderByColumnsInSelect

public boolean includeOrderByColumnsInSelect()

supportsAlterTableDropConstraint

public boolean supportsAlterTableDropConstraint()

supportsDeferredConstraints

public boolean supportsDeferredConstraints()

supportsBooleanComparison

public boolean supportsBooleanComparison()

supportsNullsInCandidateKeys

public boolean supportsNullsInCandidateKeys()

newQueryStatement

public QueryStatement newQueryStatement(Table table)

newQueryStatement

public QueryStatement newQueryStatement(Table table,
                                        SQLIdentifier rangeVar)

newTableExpression

public TableExpression newTableExpression(QueryStatement qs,
                                          Table table,
                                          SQLIdentifier rangeVar)
Returns a new TableExpression object appropriate for this DBMS. This should be an instance of one of the three built-in styles of table expression: TableExprAsSubjoins is the default, which arguably produces the most readable SQL but doesn't work on all DBMS's. TableExprAsSubjoins should work anywhere, but may be less efficient.

Parameters:
qs - The query statement in which the table expression will be included.
table - The main table in the expression.
rangeVar - The SQL alias, or "range variable", to assign to the expression or to the main table.

getCreateTableStatement

public java.lang.String getCreateTableStatement(BaseTable table,
                                                Column[] columns)
Returns the appropriate SQL to create the given table having the given columns. No column constraints or key definitions should be included. It should return something like:

 CREATE TABLE FOO ( BAR VARCHAR(30), BAZ INTEGER )
 

Parameters:
table - The table to create.
columns - The columns of the table.
Returns:
The text of the SQL statement.

getAddPrimaryKeyStatement

public java.lang.String getAddPrimaryKeyStatement(SQLIdentifier pkName,
                                                  PrimaryKey pk)
Returns the appropriate SQL to add a primary key to its table. It should return something like:

 ALTER TABLE FOO ADD CONSTRAINT FOO_PK PRIMARY KEY (BAR)
 

Parameters:
pkName - The name of the primary key to add.
pk - An object describing the primary key.
Returns:
The text of the SQL statement.

getAddCandidateKeyStatement

public java.lang.String getAddCandidateKeyStatement(SQLIdentifier ckName,
                                                    CandidateKey ck)
Returns the appropriate SQL to add a candidate key to its table. It should return something like:

 ALTER TABLE FOO ADD CONSTRAINT FOO_CK UNIQUE (BAZ)
 

Parameters:
ckName - The name of the candidate key to add.
ck - An object describing the candidate key.
Returns:
The text of the SQL statement.

getAddForeignKeyStatement

public java.lang.String getAddForeignKeyStatement(SQLIdentifier fkName,
                                                  ForeignKey fk)
Returns the appropriate SQL to add a foreign key to its table. It should return something like:

 ALTER TABLE FOO ADD CONSTRAINT FOO_FK1 FOREIGN KEY (BAR, BAZ) REFERENCES ABC (COL1, COL2)
 

Parameters:
fkName - The name of the foreign key to add.
fk - An object describing the foreign key.
Returns:
The text of the SQL statement.

getCreateIndexStatement

public java.lang.String getCreateIndexStatement(SQLIdentifier idxName,
                                                Index idx)
Returns the appropriate SQL to add an index to its table. It should return something like:

 CREATE INDEX FOO_N1 ON FOO (BAR,BAZ)
 CREATE UNIQUE INDEX FOO_U1 ON FOO (BAR,BAZ)
 

Parameters:
idxName - The name of the index to add.
idx - An object describing the index.
Returns:
The text of the SQL statement.

getDropTableStatement

public java.lang.String getDropTableStatement(BaseTable table)
Returns the appropriate SQL to drop the given table. It should return something like:

 DROP TABLE FOO CASCADE
 

Parameters:
table - The table to drop.
Returns:
The text of the SQL statement.

getDropViewStatement

public java.lang.String getDropViewStatement(View view)
Returns the appropriate SQL to drop the given view. It should return something like:

 DROP VIEW FOO
 

Parameters:
view - The view to drop.
Returns:
The text of the SQL statement.

lengthMethod

public NumericExpression lengthMethod(CharacterExpression str)
Returns the appropriate SQL expression for the JDOQL String.length() method. It should return something like:

 CHAR_LENGTH(str)
 

Parameters:
str - The argument to the length() method.
Returns:
The text of the SQL expression.

substringMethod

public CharacterExpression substringMethod(CharacterExpression str,
                                           NumericExpression begin)
Returns the appropriate SQL expression for the JDOQL String.substring(str,begin) method. It should return something like:

 SUBSTRING(str FROM begin)
 
Note that the value of begin is base 0 (Java-style), while most SQL string functions use base 1.

Parameters:
str - The first argument to the substring() method.
begin - The second argument to the substring() method.
Returns:
The text of the SQL expression.

substringMethod

public CharacterExpression substringMethod(CharacterExpression str,
                                           NumericExpression begin,
                                           NumericExpression end)
Returns the appropriate SQL expression for the JDOQL String.substring(str,begin,end) method. It should return something like:

 SUBSTRING(str FROM begin FOR len)
 
Note that the value of begin is base 0 (Java-style), while most SQL string functions use base 1. Note also that an end position is given, while most SQL substring functions take a length.

Parameters:
str - The first argument to the substring() method.
begin - The second argument to the substring() method.
end - The third argument to the substring() method.
Returns:
The text of the SQL expression.

toString

public java.lang.String toString()


Copyright ? 2001 TriActive, Inc. All Rights Reserved.