Nuxeo ECM Projects 5.4.3-SNAPSHOT

org.nuxeo.ecm.core.storage.sql.jdbc.dialect
Class Dialect

java.lang.Object
  extended by org.nuxeo.ecm.core.storage.sql.jdbc.dialect.Dialect
Direct Known Subclasses:
DialectDerby, DialectH2, DialectHSQLDB, DialectMySQL, DialectOracle, DialectPostgreSQL, DialectSQLServer

public abstract class Dialect
extends Object

A Dialect encapsulates knowledge about database-specific behavior.

Author:
Florent Guillaume

Nested Class Summary
static class Dialect.FulltextMatchInfo
          Information needed to express fulltext search with scoring.
static class Dialect.FulltextQuery
          Structured fulltext query.
static class Dialect.FulltextQueryAnalyzer
           
static class Dialect.JDBCInfo
           
 
Field Summary
static String ARRAY_SEP
           
 
Constructor Summary
Dialect(DatabaseMetaData metadata, BinaryManager binaryManager, RepositoryDescriptor repositoryDescriptor)
           
 
Method Summary
static Dialect.FulltextQuery analyzeFulltextQuery(String query)
          Analyzes a fulltext query into a generic datastructure that can be used for each specific database.
 char closeQuote()
           
 Array createArrayOf(int type, Object[] elements, Connection connection)
          Factory method for creating Array objects, suitable for passing to PreparedStatement.setArray(int, java.sql.Array).
static Dialect createDialect(Connection connection, BinaryManager binaryManager, RepositoryDescriptor repositoryDescriptor)
          Creates a Dialect by connecting to the datasource to check what database is used.
abstract  boolean doesUpdateFromRepeatSelf()
          When doing an UPDATE t SET ...
 void existingTableDetected(Connection connection, Table table, Model model, Database database)
          Called after an existing table has been detected in the database.
static boolean fulltextHasPhrase(Dialect.FulltextQuery ft)
          Checks if a fulltext search has a phrase in it.
 String getAddColumnString()
           
 String getAddForeignKeyConstraintString(String constraintName, String[] foreignKeys, String referencedTable, String[] primaryKeys, boolean referencesPrimaryKey)
           
 String getAddPrimaryKeyConstraintString(String constraintName)
           
 String getAncestorsIdsSql()
          Gets the SQL query to get the ancestors of a set of ids.
 BinaryManager getBinaryManager()
           
 String getBlobLengthFunction()
          Gets the SQL function that returns the length of a blob, in bytes.
 String getCascadeDropConstraintsString()
           
 String getClobCast(boolean inOrderBy)
          When using a CLOB field in an expression, is some casting required and with what pattern?
 String getClusterDeleteInvalidations()
          Gets the SQL to delete invalidations for this cluster node.
 String getClusterGetInvalidations()
          Gets the SQL to query invalidations for this cluster node.
 String getClusterInsertInvalidations()
          Gets the SQL to send an invalidation to the cluster.
 String getColumnName(String name)
           
 String getConnectionSchema(Connection connection)
          Gets the schema to use to query metadata about existing tables.
abstract  String getCreateFulltextIndexSql(String indexName, String quotedIndexName, Table table, List<Column> columns, Model model)
          Gets a CREATE INDEX statement for a fulltext index.
 String getCreateIndexSql(String indexName, String tableName, List<String> columnNames)
          Gets a CREATE INDEX statement for a normal index.
abstract  String getDialectFulltextQuery(String query)
          Get the dialect-specific version of a fulltext query.
 String getForeignKeyConstraintName(String tableName, String foreignColumnName, String foreignTableName)
           
 String getFreeVariableSetterForType(ColumnType type)
          Gets the JDBC expression setting a free value for this column type.
abstract  Serializable getFromResultSet(ResultSet rs, int index, Column column)
           
abstract  int getFulltextIndexedColumns()
          Specifies what columns of the fulltext table have to be indexed.
abstract  Dialect.FulltextMatchInfo getFulltextScoredMatchInfo(String fulltextQuery, String indexName, int nthMatch, Column mainColumn, Model model, Database database)
          Gets the SQL information needed to do a a fulltext match, either with a direct expression in the WHERE clause, or using a join with an additional table.
 int getFulltextType()
          Gets the type of a fulltext column has known by JDBC.
 String getIdentityGeneratedKeySql(Column column)
          Gets the SQL query to execute to retrieve the last generated identity key.
 String getIndexName(String tableName, List<String> columnNames)
           
abstract  String getInTreeSql(String idColumnName)
          Gets the expression to use to check tree membership.
abstract  Dialect.JDBCInfo getJDBCTypeAndString(ColumnType type)
          Gets the JDBC type and string from Nuxeo's type abstraction.
 String getMatchMixinType(Column mixinsColumn, String mixin, boolean positive, String[] returnParam)
          Gets the SQL fragment to match a mixin type.
abstract  boolean getMaterializeFulltextSyntheticColumn()
          Does the fulltext synthetic column have to be materialized.
 int getMaximumArgsForIn()
          Maximum number of values in a IN (?, ?, ...) statement.
 String getNoColumnsInsertString()
           
 String getNullColumnString()
           
 String getPagingClause(long limit, long offset)
          Gets paging clause to be appended at the end of select statement
 List<String> getPostCreateIdentityColumnSql(Column column)
          Gets additional SQL statements to execute after the CREATE TABLE when creating an identity column.
 List<String> getPostCreateTableSqls(Table table, Model model, Database database)
          Gets the sql statements to call after a table has been created.
 String getPrepareUserReadAclsSql()
          Gets the SQL expression to prepare the user read acls cache.
 String getPrimaryKeyConstraintName(String tableName)
           
 String getReadAclsCheckSql(String idColumnName)
          Gets the expression to check if access is allowed using read acl the dialect must suppportsReadAcl
 String getRebuildReadAclsSql()
          Gets the statement to rebuild the wall read acls
abstract  String getSecurityCheckSql(String idColumnName)
          Gets the expression to use to check security.
abstract  String getSQLStatementsFilename()
          Gets the name of the file containing the SQL statements.
abstract  Map<String,Serializable> getSQLStatementsProperties(Model model, Database database)
          Gets the properties to use with the SQL statements.
 String getTableName(String name)
           
 String getTableTypeString(Table table)
           
abstract  String getTestSQLStatementsFilename()
           
 String getUpdateReadAclsSql()
          Gets the statement to update the read acls
 String getValidationQuery()
          A query that, when executed, will make at least a round-trip to the server to check that the connection is alive.
 boolean hasIdentityGeneratedKey()
          True if the dialect returns the generated key for the identity from the insert statement.
 boolean hasNullEmptyString()
          Does the dialect have an empty string identical to NULL (Oracle).
 boolean isAllowedConversion(int expected, int actual, String actualName, int actualSize)
          Check mismatches between expected and actual JDBC types read from database introspection.
 boolean isClusteringDeleteNeeded()
          Does clustering fetch of invalidations ( getClusterGetInvalidations()) need a separate delete for them ( getClusterDeleteInvalidations()).
 boolean isClusteringSupported()
          Checks that clustering is supported.
 boolean isConnectionClosedException(Throwable t)
          Checks if an exception received means that the low level connection has been trashed and must be reset.
 boolean isIdentityAlreadyPrimary()
          Checks if an identity column is already defined as a primary key and does not need a separate index added.
static Dialect.JDBCInfo jdbcInfo(String string, int jdbcType)
           
static Dialect.JDBCInfo jdbcInfo(String string, int length, int jdbcType)
           
 boolean needsAliasForDerivedTable()
          Whether a derived table (subselect in a FROM statement) needs an alias.
 boolean needsOracleJoins()
          Whether implicit Oracle joins (instead of explicit ANSI joins) are needed.
 boolean needsOrderByKeysAfterDistinct()
          When doing a SELECT DISTINCT that uses a ORDER BY, do the keys along which we order have to be mentioned in the DISTINCT clause?
 boolean needsOriginalColumnInGroupBy()
          Whether a GROUP BY can only be used with the original column name and not an alias.
 boolean needsPrepareUserReadAcls()
          The dialect need an extra SQL statement to populate a user read acl cache before running the query.
 char openQuote()
           
 void performAdditionalStatements(Connection connection)
          Let the dialect processes additional statements after tables creation and conditional statements.
 void performPostOpenStatements(Connection connection)
          Let the dialect perform additional statements just after the connection is opened.
 boolean preCreateTable(Connection connection, Table table, Model model, Database database)
          Called before a table is created, when it's been determined that it doesn't exist yet.
 boolean qualifyIndexName()
           
abstract  void setToPreparedStatement(PreparedStatement ps, int index, Serializable value, Column column)
           
 boolean storesUpperCaseIdentifiers()
           
 boolean supportsAncestorsTable()
          Checks if the dialect supports an ancestors table.
 boolean supportsArrays()
          Does the dialect support passing ARRAY values (to stored procedures mostly).
 boolean supportsArraysReturnInsteadOfRows()
          Does a stored function returning an result set need to access it as a single array instead of iterating over a normal result set's rows.
 boolean supportsCircularCascadeDeleteConstraints()
           
 boolean supportsIfExistsAfterTableName()
           
 boolean supportsIfExistsBeforeTableName()
           
 boolean supportsIlike()
          Does the dialect support ILIKE operator
 boolean supportsMultipleFulltextIndexes()
          SQL Server supports only one fulltext index.
 boolean supportsPaging()
          Indicates if dialect supports paging
 boolean supportsReadAcl()
          Does the dialect support an optimized read security checks
 boolean supportsSysNameArray()
          Checks if the dialect supports storing arrays of system names (for mixins for instance).
abstract  boolean supportsUpdateFrom()
          Does the dialect support UPDATE t SET ...
 boolean supportsWith()
          Does the dialect support SQL-99 WITH common table expressions.
 String toBooleanValueString(boolean bool)
           
static String toHexString(byte[] bytes)
           
static String translateFulltext(Dialect.FulltextQuery ft, String or, String and, String andNot, String phraseQuote)
          Translate fulltext into a common pattern used by many servers.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

ARRAY_SEP

public static final String ARRAY_SEP
See Also:
Constant Field Values
Constructor Detail

Dialect

public Dialect(DatabaseMetaData metadata,
               BinaryManager binaryManager,
               RepositoryDescriptor repositoryDescriptor)
        throws StorageException
Throws:
StorageException
Method Detail

jdbcInfo

public static Dialect.JDBCInfo jdbcInfo(String string,
                                        int jdbcType)

jdbcInfo

public static Dialect.JDBCInfo jdbcInfo(String string,
                                        int length,
                                        int jdbcType)

createDialect

public static Dialect createDialect(Connection connection,
                                    BinaryManager binaryManager,
                                    RepositoryDescriptor repositoryDescriptor)
                             throws StorageException
Creates a Dialect by connecting to the datasource to check what database is used.

Throws:
StorageException - if a SQL connection problem occurs

getBinaryManager

public BinaryManager getBinaryManager()

getConnectionSchema

public String getConnectionSchema(Connection connection)
                           throws SQLException
Gets the schema to use to query metadata about existing tables.

Throws:
SQLException

getJDBCTypeAndString

public abstract Dialect.JDBCInfo getJDBCTypeAndString(ColumnType type)
Gets the JDBC type and string from Nuxeo's type abstraction.


isAllowedConversion

public boolean isAllowedConversion(int expected,
                                   int actual,
                                   String actualName,
                                   int actualSize)
Check mismatches between expected and actual JDBC types read from database introspection.


setToPreparedStatement

public abstract void setToPreparedStatement(PreparedStatement ps,
                                            int index,
                                            Serializable value,
                                            Column column)
                                     throws SQLException
Throws:
SQLException

getFromResultSet

public abstract Serializable getFromResultSet(ResultSet rs,
                                              int index,
                                              Column column)
                                       throws SQLException
Throws:
SQLException

storesUpperCaseIdentifiers

public boolean storesUpperCaseIdentifiers()

openQuote

public char openQuote()

closeQuote

public char closeQuote()

toBooleanValueString

public String toBooleanValueString(boolean bool)

toHexString

public static String toHexString(byte[] bytes)

getTableName

public String getTableName(String name)

getColumnName

public String getColumnName(String name)

getPrimaryKeyConstraintName

public String getPrimaryKeyConstraintName(String tableName)

getForeignKeyConstraintName

public String getForeignKeyConstraintName(String tableName,
                                          String foreignColumnName,
                                          String foreignTableName)

getIndexName

public String getIndexName(String tableName,
                           List<String> columnNames)

getCreateIndexSql

public String getCreateIndexSql(String indexName,
                                String tableName,
                                List<String> columnNames)
Gets a CREATE INDEX statement for a normal index.


getFulltextIndexedColumns

public abstract int getFulltextIndexedColumns()
Specifies what columns of the fulltext table have to be indexed.

Returns:
0 for none, 1 for the synthetic one, 2 for the individual ones

supportsMultipleFulltextIndexes

public boolean supportsMultipleFulltextIndexes()
SQL Server supports only one fulltext index.


getMaterializeFulltextSyntheticColumn

public abstract boolean getMaterializeFulltextSyntheticColumn()
Does the fulltext synthetic column have to be materialized.


getCreateFulltextIndexSql

public abstract String getCreateFulltextIndexSql(String indexName,
                                                 String quotedIndexName,
                                                 Table table,
                                                 List<Column> columns,
                                                 Model model)
Gets a CREATE INDEX statement for a fulltext index.


analyzeFulltextQuery

public static Dialect.FulltextQuery analyzeFulltextQuery(String query)
Analyzes a fulltext query into a generic datastructure that can be used for each specific database.

List of terms containing only negative words are suppressed. Otherwise negative words are put at the end of the lists of terms.


translateFulltext

public static String translateFulltext(Dialect.FulltextQuery ft,
                                       String or,
                                       String and,
                                       String andNot,
                                       String phraseQuote)
Translate fulltext into a common pattern used by many servers.


fulltextHasPhrase

public static boolean fulltextHasPhrase(Dialect.FulltextQuery ft)
Checks if a fulltext search has a phrase in it.


getDialectFulltextQuery

public abstract String getDialectFulltextQuery(String query)
Get the dialect-specific version of a fulltext query.

Parameters:
query - the CMIS-syntax-based fulltext query string
Returns:
the dialect native fulltext query string

getFulltextScoredMatchInfo

public abstract Dialect.FulltextMatchInfo getFulltextScoredMatchInfo(String fulltextQuery,
                                                                     String indexName,
                                                                     int nthMatch,
                                                                     Column mainColumn,
                                                                     Model model,
                                                                     Database database)
Gets the SQL information needed to do a a fulltext match, either with a direct expression in the WHERE clause, or using a join with an additional table.


getMatchMixinType

public String getMatchMixinType(Column mixinsColumn,
                                String mixin,
                                boolean positive,
                                String[] returnParam)
Gets the SQL fragment to match a mixin type.


supportsPaging

public boolean supportsPaging()
Indicates if dialect supports paging

Returns:
true if the dialect supports paging

getPagingClause

public String getPagingClause(long limit,
                              long offset)
Gets paging clause to be appended at the end of select statement


getFulltextType

public int getFulltextType()
Gets the type of a fulltext column has known by JDBC.

This is used for setNull.


getFreeVariableSetterForType

public String getFreeVariableSetterForType(ColumnType type)
Gets the JDBC expression setting a free value for this column type.

Needed for columns that need an expression around the value being set, usually for conversion (this is the case for PostgreSQL fulltext TSVECTOR columns for instance).

Parameters:
type - the column type
Returns:
the expression containing a free variable

getNoColumnsInsertString

public String getNoColumnsInsertString()

getNullColumnString

public String getNullColumnString()

getTableTypeString

public String getTableTypeString(Table table)

getAddPrimaryKeyConstraintString

public String getAddPrimaryKeyConstraintString(String constraintName)

getAddForeignKeyConstraintString

public String getAddForeignKeyConstraintString(String constraintName,
                                               String[] foreignKeys,
                                               String referencedTable,
                                               String[] primaryKeys,
                                               boolean referencesPrimaryKey)

qualifyIndexName

public boolean qualifyIndexName()

supportsIfExistsBeforeTableName

public boolean supportsIfExistsBeforeTableName()

supportsIfExistsAfterTableName

public boolean supportsIfExistsAfterTableName()

getCascadeDropConstraintsString

public String getCascadeDropConstraintsString()

supportsCircularCascadeDeleteConstraints

public boolean supportsCircularCascadeDeleteConstraints()

getAddColumnString

public String getAddColumnString()

supportsUpdateFrom

public abstract boolean supportsUpdateFrom()
Does the dialect support UPDATE t SET ... FROM t, u WHERE ... ?


doesUpdateFromRepeatSelf

public abstract boolean doesUpdateFromRepeatSelf()
When doing an UPDATE t SET ... FROM t, u WHERE ..., does the FROM clause need to repeate the updated table (t).


needsOrderByKeysAfterDistinct

public boolean needsOrderByKeysAfterDistinct()
When doing a SELECT DISTINCT that uses a ORDER BY, do the keys along which we order have to be mentioned in the DISTINCT clause?


needsAliasForDerivedTable

public boolean needsAliasForDerivedTable()
Whether a derived table (subselect in a FROM statement) needs an alias.


needsOriginalColumnInGroupBy

public boolean needsOriginalColumnInGroupBy()
Whether a GROUP BY can only be used with the original column name and not an alias.


needsOracleJoins

public boolean needsOracleJoins()
Whether implicit Oracle joins (instead of explicit ANSI joins) are needed.


needsPrepareUserReadAcls

public boolean needsPrepareUserReadAcls()
The dialect need an extra SQL statement to populate a user read acl cache before running the query.

Since:
5.4.3

getClobCast

public String getClobCast(boolean inOrderBy)
When using a CLOB field in an expression, is some casting required and with what pattern?

Needed for Derby and H2.

Parameters:
inOrderBy - true if the expression is for an ORDER BY column
Returns:
a pattern for String.format with one parameter for the column name and one for the width, or null if no cast is required

getSecurityCheckSql

public abstract String getSecurityCheckSql(String idColumnName)
Gets the expression to use to check security.

Parameters:
idColumnName - the quoted name of the id column to use
Returns:
an SQL expression with two parameters (principals and permissions) that is true if access is allowed

supportsAncestorsTable

public boolean supportsAncestorsTable()
Checks if the dialect supports an ancestors table.


getInTreeSql

public abstract String getInTreeSql(String idColumnName)
Gets the expression to use to check tree membership.

Parameters:
idColumnName - the quoted name of the id column to use
Returns:
an SQL expression with one parameters for the based id that is true if the document is under base id

supportsArrays

public boolean supportsArrays()
Does the dialect support passing ARRAY values (to stored procedures mostly).

If not, we'll simulate them using a string and a separator.

Returns:
true if ARRAY values are supported

supportsArraysReturnInsteadOfRows

public boolean supportsArraysReturnInsteadOfRows()
Does a stored function returning an result set need to access it as a single array instead of iterating over a normal result set's rows.

Oracle needs this.


supportsSysNameArray

public boolean supportsSysNameArray()
Checks if the dialect supports storing arrays of system names (for mixins for instance).


createArrayOf

public Array createArrayOf(int type,
                           Object[] elements,
                           Connection connection)
                    throws SQLException
Factory method for creating Array objects, suitable for passing to PreparedStatement.setArray(int, java.sql.Array).

(An equivalent method is defined by JDBC4 on the Connection class.)

Parameters:
type - the SQL type of the elements
elements - the elements of the array
connection - the connection
Returns:
an Array holding the elements
Throws:
SQLException

getSQLStatementsFilename

public abstract String getSQLStatementsFilename()
Gets the name of the file containing the SQL statements.


getTestSQLStatementsFilename

public abstract String getTestSQLStatementsFilename()

getSQLStatementsProperties

public abstract Map<String,Serializable> getSQLStatementsProperties(Model model,
                                                                    Database database)
Gets the properties to use with the SQL statements.


isClusteringSupported

public boolean isClusteringSupported()
Checks that clustering is supported.


isClusteringDeleteNeeded

public boolean isClusteringDeleteNeeded()
Does clustering fetch of invalidations ( getClusterGetInvalidations()) need a separate delete for them ( getClusterDeleteInvalidations()).


getClusterInsertInvalidations

public String getClusterInsertInvalidations()
Gets the SQL to send an invalidation to the cluster.

Returns:
an SQL statement with parameters for: id, fragments, kind

getClusterGetInvalidations

public String getClusterGetInvalidations()
Gets the SQL to query invalidations for this cluster node.

Returns:
an SQL statement returning a result set

getClusterDeleteInvalidations

public String getClusterDeleteInvalidations()
Gets the SQL to delete invalidations for this cluster node.

Returns:
an SQL statement returning a result set

supportsIlike

public boolean supportsIlike()
Does the dialect support ILIKE operator


supportsReadAcl

public boolean supportsReadAcl()
Does the dialect support an optimized read security checks


supportsWith

public boolean supportsWith()
Does the dialect support SQL-99 WITH common table expressions.


hasNullEmptyString

public boolean hasNullEmptyString()
Does the dialect have an empty string identical to NULL (Oracle).


getMaximumArgsForIn

public int getMaximumArgsForIn()
Maximum number of values in a IN (?, ?, ...) statement.

Beyond this size we'll do the query in several chunks.

PostgreSQL is limited to 65535 values in a prepared statement.

Oracle is limited to 1000 expressions in a list (ORA-01795).


getUpdateReadAclsSql

public String getUpdateReadAclsSql()
Gets the statement to update the read acls


getRebuildReadAclsSql

public String getRebuildReadAclsSql()
Gets the statement to rebuild the wall read acls


getReadAclsCheckSql

public String getReadAclsCheckSql(String idColumnName)
Gets the expression to check if access is allowed using read acl the dialect must suppportsReadAcl

Parameters:
idColumnName - the quoted name of the read acl_id column to use
Returns:
an SQL expression with one parameter (principals) that is true if access is allowed

getPrepareUserReadAclsSql

public String getPrepareUserReadAclsSql()
Gets the SQL expression to prepare the user read acls cache. This can be used to populate a table cache.

Returns:
and SQL expression with one parameter (principals)
Since:
5.4.3

preCreateTable

public boolean preCreateTable(Connection connection,
                              Table table,
                              Model model,
                              Database database)
                       throws SQLException
Called before a table is created, when it's been determined that it doesn't exist yet.

Returns:
false if the table must actually not be created
Throws:
SQLException

getPostCreateTableSqls

public List<String> getPostCreateTableSqls(Table table,
                                           Model model,
                                           Database database)
Gets the sql statements to call after a table has been created.

Used for migrations/upgrades.


existingTableDetected

public void existingTableDetected(Connection connection,
                                  Table table,
                                  Model model,
                                  Database database)
                           throws SQLException
Called after an existing table has been detected in the database.

Used for migrations/upgrades.

Throws:
SQLException

isConnectionClosedException

public boolean isConnectionClosedException(Throwable t)
Checks if an exception received means that the low level connection has been trashed and must be reset.


performAdditionalStatements

public void performAdditionalStatements(Connection connection)
                                 throws SQLException
Let the dialect processes additional statements after tables creation and conditional statements. Can be used for specific upgrade procedure.

Parameters:
connection -
Throws:
SQLException

getValidationQuery

public String getValidationQuery()
A query that, when executed, will make at least a round-trip to the server to check that the connection is alive.

The query should throw an error if the connection is dead.


getBlobLengthFunction

public String getBlobLengthFunction()
Gets the SQL function that returns the length of a blob, in bytes.


performPostOpenStatements

public void performPostOpenStatements(Connection connection)
                               throws SQLException
Let the dialect perform additional statements just after the connection is opened.

Throws:
SQLException

getPostCreateIdentityColumnSql

public List<String> getPostCreateIdentityColumnSql(Column column)
Gets additional SQL statements to execute after the CREATE TABLE when creating an identity column.

Oracle needs both a sequence and a trigger.


isIdentityAlreadyPrimary

public boolean isIdentityAlreadyPrimary()
Checks if an identity column is already defined as a primary key and does not need a separate index added.

MySQL defines the identity column directly as primary key.


hasIdentityGeneratedKey

public boolean hasIdentityGeneratedKey()
True if the dialect returns the generated key for the identity from the insert statement.

Oracle needs a separate call to CURRVAL.


getIdentityGeneratedKeySql

public String getIdentityGeneratedKeySql(Column column)
Gets the SQL query to execute to retrieve the last generated identity key.

Oracle needs a separate call to CURRVAL.


getAncestorsIdsSql

public String getAncestorsIdsSql()
Gets the SQL query to get the ancestors of a set of ids.

Returns:
null if not available

Nuxeo ECM Projects 5.4.3-SNAPSHOT

Copyright © 2011 Nuxeo SAS. All Rights Reserved.