HHH-8159 - Apply fixups indicated by analysis tools

This commit is contained in:
Steve Ebersole 2013-04-24 13:28:26 -05:00
parent 8c28ba8463
commit 5fc70fc5ab
118 changed files with 3687 additions and 2579 deletions

View File

@ -132,7 +132,7 @@ public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
final StringBuilder expression = new StringBuilder();
boolean lower = false;
if ( ignoreCase ) {
int sqlType = sqlTypes[i];
final int sqlType = sqlTypes[i];
lower = sqlType == Types.VARCHAR
|| sqlType == Types.CHAR
|| sqlType == Types.LONGVARCHAR;

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@ -125,34 +126,48 @@ public AbstractTransactSQLDialect() {
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getNullColumnString() {
return "";
}
@Override
public boolean qualifyIndexName() {
return false;
}
@Override
public String getForUpdateString() {
return "";
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString() {
return "select @@identity";
}
@Override
public String getIdentityColumnString() {
return "identity not null"; //starts with 1, implicitly
//starts with 1, implicitly
return "identity not null";
}
@Override
public boolean supportsInsertSelectIdentity() {
return true;
}
@Override
public String appendIdentitySelectToInsert(String insertSQL) {
return insertSQL + "\nselect @@identity";
}
@ -162,17 +177,19 @@ public String appendLockHint(LockOptions lockOptions, String tableName) {
return lockOptions.getLockMode().greaterThan( LockMode.READ ) ? tableName + " holdlock" : tableName;
}
@Override
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
// TODO: merge additional lockoptions support in Dialect.applyLocksToSql
Iterator itr = aliasedLockOptions.getAliasLockIterator();
StringBuilder buffer = new StringBuilder( sql );
final Iterator itr = aliasedLockOptions.getAliasLockIterator();
final StringBuilder buffer = new StringBuilder( sql );
int correction = 0;
while ( itr.hasNext() ) {
final Map.Entry entry = (Map.Entry) itr.next();
final LockMode lockMode = (LockMode) entry.getValue();
if ( lockMode.greaterThan( LockMode.READ ) ) {
final String alias = (String) entry.getKey();
int start = -1, end = -1;
int start = -1;
int end = -1;
if ( sql.endsWith( " " + alias ) ) {
start = ( sql.length() - alias.length() ) + correction;
end = start + alias.length();
@ -198,69 +215,89 @@ public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map ke
return buffer.toString();
}
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
return col; // sql server just returns automatically
// sql server just returns automatically
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
boolean isResultSet = ps.execute();
// This assumes you will want to ignore any update counts
while ( !isResultSet && ps.getUpdateCount() != -1 ) {
isResultSet = ps.getMoreResults();
}
// You may still have other ResultSets or update counts left to process here
// but you can't do it now or the ResultSet you just got will be closed
return ps.getResultSet();
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public String getCurrentTimestampSelectString() {
return "select getdate()";
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String generateTemporaryTableName(String baseTableName) {
return "#" + baseTableName;
}
@Override
public boolean dropTemporaryTableAfterUse() {
return true; // sql-server, at least needed this dropped after use; strange!
// sql-server, at least needed this dropped after use; strange!
return true;
}
@Override
public String getSelectGUIDString() {
return "select newid()";
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsUnionAll() {
return true;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return true;
}
@Override
public boolean doesRepeatableReadCauseReadersToBlockWriters() {
return true;
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;
}

View File

@ -21,18 +21,16 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.MappingException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.NoArgSQLFunction;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.CUBRIDLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.type.StandardBasicTypes;
@ -42,6 +40,9 @@
* @author Seok Jeong Il
*/
public class CUBRIDDialect extends Dialect {
/**
* Constructs a CUBRIDDialect
*/
public CUBRIDDialect() {
super();
@ -128,11 +129,29 @@ public CUBRIDDialect() {
registerFunction( "systime", new NoArgSQLFunction( "systime", StandardBasicTypes.TIME, false ) );
registerFunction( "timestamp", new StandardSQLFunction( "timestamp", StandardBasicTypes.TIMESTAMP ) );
registerFunction("current_timestamp", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIMESTAMP, false) );
registerFunction("sys_timestamp", new NoArgSQLFunction("sys_timestamp", StandardBasicTypes.TIMESTAMP, false) );
registerFunction(
"current_timestamp", new NoArgSQLFunction(
"current_timestamp",
StandardBasicTypes.TIMESTAMP,
false
)
);
registerFunction(
"sys_timestamp", new NoArgSQLFunction(
"sys_timestamp",
StandardBasicTypes.TIMESTAMP,
false
)
);
registerFunction( "systimestamp", new NoArgSQLFunction( "systimestamp", StandardBasicTypes.TIMESTAMP, false ) );
registerFunction( "localtime", new NoArgSQLFunction( "localtime", StandardBasicTypes.TIMESTAMP, false ) );
registerFunction("localtimestamp", new NoArgSQLFunction("localtimestamp", StandardBasicTypes.TIMESTAMP, false) );
registerFunction(
"localtimestamp", new NoArgSQLFunction(
"localtimestamp",
StandardBasicTypes.TIMESTAMP,
false
)
);
registerFunction( "day", new StandardSQLFunction( "day", StandardBasicTypes.INTEGER ) );
registerFunction( "dayofmonth", new StandardSQLFunction( "dayofmonth", StandardBasicTypes.INTEGER ) );
@ -229,116 +248,133 @@ public CUBRIDDialect() {
registerKeyword( "SEARCH" );
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentityInsertString() {
return "NULL";
}
@Override
public boolean supportsColumnCheck() {
return false;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
public String getIdentitySelectString() {
return "select last_insert_id()";
}
@Override
protected String getIdentityColumnString() {
return "not null auto_increment"; //starts with 1, implicitly
//starts with 1, implicitly
return "not null auto_increment";
}
/*
* CUBRID supports "ADD [COLUMN | ATTRIBUTE]"
*/
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + sequenceName + ".next_value from table({1}) as T(X)";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create serial " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop serial " + sequenceName;
}
@Override
public String getDropForeignKeyString() {
return " drop foreign key ";
}
@Override
public boolean qualifyIndexName() {
return false;
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
@Override
public String getQuerySequencesString() {
return "select name from db_serial";
}
/**
* The character specific to this dialect used to close a quoted identifier.
* CUBRID supports square brackets (MSSQL style), backticks (MySQL style),
* as well as double quotes (Oracle style).
*
* @return The dialect's specific open quote character.
*/
@Override
public char openQuote() {
return '[';
}
@Override
public char closeQuote() {
return ']';
}
@Override
public String getForUpdateString() {
return " ";
}
@Override
public boolean supportsUnionAll() {
return true;
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public String getCurrentTimestampSelectString() {
return "select now()";
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsIfExistsBeforeTableName() {
return true;
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;
}
@Override
public LimitHandler buildLimitHandler(String sql, RowSelection selection) {
return new CUBRIDLimitHandler( this, sql, selection );
}

View File

@ -58,15 +58,11 @@
import org.hibernate.type.StandardBasicTypes;
/**
* Cach&eacute; 2007.1 dialect. This class is required in order to use Hibernate with Intersystems Cach&eacute; SQL.<br>
* <br>
* Compatible with Cach&eacute; 2007.1.
* <br>
* <head>
* <title>Cach&eacute; and Hibernate</title>
* </head>
* <body>
* <h1>Cach&eacute; and Hibernate</h1>
* Cach&eacute; 2007.1 dialect.
*
* This class is required in order to use Hibernate with Intersystems Cach&eacute; SQL. Compatible with
* Cach&eacute; 2007.1.
*
* <h2>PREREQUISITES</h2>
* These setup instructions assume that both Cach&eacute; and Hibernate are installed and operational.
* <br>
@ -144,11 +140,9 @@
* </tr>
* </table>
* <p/>
* <dl>
* <dt><b>Note 1</b></dt>
* <dd>Please contact your administrator for the userid and password you should use when attempting access via JDBC.
* By default, these are chosen to be "_SYSTEM" and "SYS" respectively as noted in the SQL standard.</dd>
* </dl>
* <b>NOTE:</b> Please contact your administrator for the userid and password you should use when
* attempting access via JDBC. By default, these are chosen to be "_SYSTEM" and "SYS" respectively
* as noted in the SQL standard.
* <br>
* <h2>CACH&Eacute; VERSION URL</h2>
* This is the standard URL for the JDBC driver.
@ -239,16 +233,14 @@ protected final void commonRegistration() {
registerColumnType( Types.DOUBLE, "double" );
registerColumnType( Types.FLOAT, "float" );
registerColumnType( Types.INTEGER, "integer" );
registerColumnType( Types.LONGVARBINARY, "longvarbinary" ); // binary %Stream
registerColumnType( Types.LONGVARCHAR, "longvarchar" ); // character %Stream
registerColumnType( Types.LONGVARBINARY, "longvarbinary" );
registerColumnType( Types.LONGVARCHAR, "longvarchar" );
registerColumnType( Types.NUMERIC, "numeric($p,$s)" );
registerColumnType( Types.REAL, "real" );
registerColumnType( Types.SMALLINT, "smallint" );
registerColumnType( Types.TIMESTAMP, "timestamp" );
registerColumnType( Types.TIME, "time" );
registerColumnType( Types.TINYINT, "tinyint" );
// TBD should this be varbinary($1)?
// registerColumnType(Types.VARBINARY, "binary($1)");
registerColumnType( Types.VARBINARY, "longvarbinary" );
registerColumnType( Types.VARCHAR, "varchar($l)" );
registerColumnType( Types.BLOB, "longvarbinary" );
@ -256,7 +248,6 @@ protected final void commonRegistration() {
getDefaultProperties().setProperty( Environment.USE_STREAMS_FOR_BINARY, "false" );
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
//getDefaultProperties().setProperty(Environment.STATEMENT_BATCH_SIZE, NO_BATCH);
getDefaultProperties().setProperty( Environment.USE_SQL_COMMENTS, "false" );
@ -267,7 +258,6 @@ protected final void commonRegistration() {
registerFunction( "asin", new StandardJDBCEscapeFunction( "asin", StandardBasicTypes.DOUBLE ) );
registerFunction( "atan", new StandardJDBCEscapeFunction( "atan", StandardBasicTypes.DOUBLE ) );
registerFunction( "bit_length", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "($length(?1)*8)" ) );
// hibernate impelemnts cast in Dialect.java
registerFunction( "ceiling", new StandardSQLFunction( "ceiling", StandardBasicTypes.INTEGER ) );
registerFunction( "char", new StandardJDBCEscapeFunction( "char", StandardBasicTypes.CHARACTER ) );
registerFunction( "character_length", new StandardSQLFunction( "character_length", StandardBasicTypes.INTEGER ) );
@ -311,9 +301,6 @@ protected final void commonRegistration() {
registerFunction( "left", new StandardJDBCEscapeFunction( "left", StandardBasicTypes.STRING ) );
registerFunction( "len", new StandardSQLFunction( "len", StandardBasicTypes.INTEGER ) );
registerFunction( "$length", new VarArgsSQLFunction( "$length(", ",", ")" ) );
// aggregate functions shouldn't be registered, right?
//registerFunction( "list", new StandardSQLFunction("list",StandardBasicTypes.STRING) );
// stopped on $list
registerFunction( "$list", new VarArgsSQLFunction( "$list(", ",", ")" ) );
registerFunction( "$listdata", new VarArgsSQLFunction( "$listdata(", ",", ")" ) );
registerFunction( "$listfind", new VarArgsSQLFunction( "$listfind(", ",", ")" ) );
@ -391,21 +378,20 @@ protected final void register71Functions() {
// DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean hasAlterTable() {
// Does this dialect support the ALTER TABLE syntax?
return true;
}
@Override
public boolean qualifyIndexName() {
// Do we need to qualify index names with the schema name?
return false;
}
/**
* The syntax used to add a foreign key constraint to a table.
*
* @return String
*/
@Override
@SuppressWarnings("StringBufferReplaceableByString")
public String getAddForeignKeyConstraintString(
String constraintName,
String[] foreignKey,
@ -419,97 +405,120 @@ public String getAddForeignKeyConstraintString(
.append( " FOREIGN KEY " )
.append( constraintName )
.append( " (" )
.append( StringHelper.join( ", ", foreignKey ) ) // identifier-commalist
.append( StringHelper.join( ", ", foreignKey ) )
.append( ") REFERENCES " )
.append( referencedTable )
.append( " (" )
.append( StringHelper.join( ", ", primaryKey ) ) // identifier-commalist
.append( StringHelper.join( ", ", primaryKey ) )
.append( ") " )
.toString();
}
/**
* Does this dialect support check constraints?
*
* @return {@code false} (Cache does not support check constraints)
*/
@SuppressWarnings("UnusedDeclaration")
public boolean supportsCheck() {
// Does this dialect support check constraints?
return false;
}
@Override
public String getAddColumnString() {
// The syntax used to add a column to a table
return " add column";
}
@Override
public String getCascadeConstraintsString() {
// Completely optional cascading drop clause.
return "";
}
@Override
public boolean dropConstraints() {
// Do we need to drop constraints before dropping tables in this dialect?
return true;
}
@Override
public boolean supportsCascadeDelete() {
return true;
}
@Override
public boolean hasSelfReferentialForeignKeyBug() {
return true;
}
// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String generateTemporaryTableName(String baseTableName) {
String name = super.generateTemporaryTableName( baseTableName );
final String name = super.generateTemporaryTableName( baseTableName );
return name.length() > 25 ? name.substring( 1, 25 ) : name;
}
@Override
public String getCreateTemporaryTableString() {
return "create global temporary table";
}
@Override
public Boolean performTemporaryTableDDLInIsolation() {
return Boolean.FALSE;
}
@Override
public String getCreateTemporaryTablePostfix() {
return "";
}
@Override
public boolean dropTemporaryTableAfterUse() {
return true;
}
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public Class getNativeIdentifierGeneratorClass() {
return IdentityGenerator.class;
}
@Override
public boolean hasDataTypeInIdentityColumn() {
// Whether this dialect has an Identity clause added to the data type or a completely seperate identity
// data type
return true;
}
@Override
public String getIdentityColumnString() throws MappingException {
// The keyword used to specify an identity column, if identity column key generation is supported.
return "identity";
}
@Override
public String getIdentitySelectString() {
return "SELECT LAST_IDENTITY() FROM %TSQL_sys.snf";
}
// SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsSequences() {
return false;
}
@ -539,25 +548,12 @@ public boolean supportsSequences() {
// lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public boolean supportsForUpdate() {
// Does this dialect support the FOR UPDATE syntax?
return false;
}
public boolean supportsForUpdateOf() {
// Does this dialect support FOR UPDATE OF, allowing particular rows to be locked?
return false;
}
public boolean supportsForUpdateNowait() {
// Does this dialect support the Oracle-style FOR UPDATE NOWAIT syntax?
return false;
}
@Override
public boolean supportsOuterJoinForUpdate() {
return false;
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
// Set your transaction mode to READ_COMMITTED before using
@ -586,28 +582,40 @@ else if ( lockMode.greaterThan( LockMode.READ ) ) {
// LIMIT support (ala TOP) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@SuppressWarnings("deprecation")
public boolean supportsLimit() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsLimitOffset() {
return false;
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsVariableLimit() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean bindLimitParametersFirst() {
// Does the LIMIT clause come at the start of the SELECT statement, rather than at the end?
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean useMaxForLimit() {
// Does the LIMIT clause take a "maximum" row number instead of a total number of returned rows?
return true;
}
@Override
@SuppressWarnings("deprecation")
public String getLimitString(String sql, boolean hasOffset) {
if ( hasOffset ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
@ -615,7 +623,7 @@ public String getLimitString(String sql, boolean hasOffset) {
// This does not support the Cache SQL 'DISTINCT BY (comma-list)' extensions,
// but this extension is not supported through Hibernate anyway.
int insertionPoint = sql.startsWith( "select distinct" ) ? 15 : 6;
final int insertionPoint = sql.startsWith( "select distinct" ) ? 15 : 6;
return new StringBuilder( sql.length() + 8 )
.append( sql )
@ -625,10 +633,12 @@ public String getLimitString(String sql, boolean hasOffset) {
// callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
ps.execute();
return (ResultSet) ps.getObject( 1 );
@ -636,42 +646,46 @@ public ResultSet getResultSet(CallableStatement ps) throws SQLException {
// miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public String getLowercaseFunction() {
// The name of the SQL function that transforms a string to lowercase
return "lower";
}
@Override
public String getNullColumnString() {
// The keyword used to specify a nullable column.
return " null";
}
@Override
public JoinFragment createOuterJoinFragment() {
// Create an OuterJoinGenerator for this dialect.
return new CacheJoinFragment();
}
@Override
public String getNoColumnsInsertString() {
// The keyword used to insert a row without specifying
// any column values
return " default values";
}
@Override
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
return new CacheSQLExceptionConversionDelegate( this );
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}
public static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
/**
* Extract the name of the violated constraint from the given SQLException.
*
* @param sqle The exception that was the result of the constraint violation.
* @return The extracted constraint name.
* The Cache ViolatedConstraintNameExtracter.
*/
public static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
@Override
public String extractConstraintName(SQLException sqle) {
return extractUsingTemplate( "constraint (", ") violated", sqle.getMessage() );
}
@ -680,14 +694,17 @@ public String extractConstraintName(SQLException sqle) {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean areStringComparisonsCaseInsensitive() {
return true;
}
@Override
public boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
return false;
}

View File

@ -42,6 +42,8 @@ public interface ColumnAliasExtractor {
* @param position The column position
*
* @return The alias
*
* @throws SQLException Indicates a problem accessing the JDBC ResultSetMetaData
*/
public String extractColumnAlias(ResultSetMetaData metaData, int position) throws SQLException;
@ -58,6 +60,7 @@ public String extractColumnAlias(ResultSetMetaData metaData, int position) throw
/**
* An extractor which uses {@link ResultSetMetaData#getColumnName}
*/
@SuppressWarnings("UnusedDeclaration")
public static final ColumnAliasExtractor COLUMN_NAME_EXTRACTOR = new ColumnAliasExtractor() {
@Override
public String extractColumnAlias(ResultSetMetaData metaData, int position) throws SQLException {

View File

@ -31,31 +31,38 @@
* @author Kristoffer Dyrkorn
*/
public class DB2390Dialect extends DB2Dialect {
@Override
public boolean supportsSequences() {
return false;
}
@Override
public String getIdentitySelectString() {
return "select identity_val_local() from sysibm.sysdummy1";
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsLimitOffset() {
return false;
}
@Override
public boolean useMaxForLimit() {
return true;
}
@Override
public boolean supportsVariableLimit() {
return false;
}
@Override
public String getLimitString(String sql, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
@ -63,12 +70,7 @@ public String getLimitString(String sql, int offset, int limit) {
if ( limit == 0 ) {
return sql;
}
return new StringBuilder( sql.length() + 40 )
.append( sql )
.append( " fetch first " )
.append( limit )
.append( " rows only " )
.toString();
return sql + " fetch first " + limit + " rows only ";
}
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.dialect;
/**
* An SQL dialect for DB2/400. This class provides support for DB2 Universal Database for iSeries,
* also known as DB2/400.
@ -31,31 +30,38 @@
* @author Peter DeGregorio (pdegregorio)
*/
public class DB2400Dialect extends DB2Dialect {
@Override
public boolean supportsSequences() {
return false;
}
@Override
public String getIdentitySelectString() {
return "select identity_val_local() from sysibm.sysdummy1";
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsLimitOffset() {
return false;
}
@Override
public boolean useMaxForLimit() {
return true;
}
@Override
public boolean supportsVariableLimit() {
return false;
}
@Override
public String getLimitString(String sql, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
@ -63,14 +69,10 @@ public String getLimitString(String sql, int offset, int limit) {
if ( limit == 0 ) {
return sql;
}
return new StringBuilder( sql.length() + 40 )
.append( sql )
.append( " fetch first " )
.append( limit )
.append( " rows only " )
.toString();
return sql + " fetch first " + limit + " rows only ";
}
@Override
public String getForUpdateString() {
return " for update with rs";
}

View File

@ -50,9 +50,11 @@
* @author Gavin King
*/
public class DB2Dialect extends Dialect {
private final UniqueDelegate uniqueDelegate;
/**
* Constructs a DB2Dialect
*/
public DB2Dialect() {
super();
registerColumnType( Types.BIT, "smallint" );
@ -181,117 +183,137 @@ public DB2Dialect() {
uniqueDelegate = new DB2UniqueDelegate( this );
}
@Override
public String getLowercaseFunction() {
return "lcase";
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString() {
return "values identity_val_local()";
}
@Override
public String getIdentityColumnString() {
return "generated by default as identity"; //not null ... (start with 1) is implicit
return "generated by default as identity";
}
@Override
public String getIdentityInsertString() {
return "default";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "values nextval for " + sequenceName;
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName + " restrict";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
public String getQuerySequencesString() {
return "select seqname from sysibm.syssequences";
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsLimit() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsVariableLimit() {
return false;
}
@Override
@SuppressWarnings("deprecation")
public String getLimitString(String sql, int offset, int limit) {
if ( offset == 0 ) {
return sql + " fetch first " + limit + " rows only";
}
StringBuilder pagingSelect = new StringBuilder( sql.length() + 200 )
.append(
"select * from ( select inner2_.*, rownumber() over(order by order of inner2_) as rownumber_ from ( "
)
.append( sql ) //nest the main query in an outer select
.append( " fetch first " )
.append( limit )
.append( " rows only ) as inner2_ ) as inner1_ where rownumber_ > " )
.append( offset )
.append( " order by rownumber_" );
return pagingSelect.toString();
//nest the main query in an outer select
return "select * from ( select inner2_.*, rownumber() over(order by order of inner2_) as rownumber_ from ( "
+ sql + " fetch first " + limit + " rows only ) as inner2_ ) as inner1_ where rownumber_ > "
+ offset + " order by rownumber_";
}
/**
* {@inheritDoc}
* <p/>
*
* DB2 does have a one-based offset, however this was actually already handled in the limit string building
* (the '?+1' bit). To not mess up inheritors, I'll leave that part alone and not touch the offset here.
*
* @param zeroBasedFirstResult The user-supplied, zero-based offset
*
* @return zeroBasedFirstResult
*/
@Override
@SuppressWarnings("deprecation")
public int convertToFirstRowValue(int zeroBasedFirstResult) {
return zeroBasedFirstResult;
}
@Override
@SuppressWarnings("deprecation")
public String getForUpdateString() {
return " for read only with rs use and keep update locks";
}
@Override
@SuppressWarnings("deprecation")
public boolean useMaxForLimit() {
return true;
}
@Override
public boolean supportsOuterJoinForUpdate() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
//as far as I know, DB2 doesn't support this
@Override
public boolean supportsLockTimeouts() {
//as far as I know, DB2 doesn't support this
return false;
}
@Override
public String getSelectClauseNullString(int sqlType) {
String literal;
@ -315,32 +337,16 @@ public String getSelectClauseNullString(int sqlType) {
return "nullif(" + literal + ',' + literal + ')';
}
public static void main(String[] args) {
System.out.println( new DB2Dialect().getLimitString( "/*foo*/ select * from foos", true ) );
System.out.println( new DB2Dialect().getLimitString( "/*foo*/ select distinct * from foos", true ) );
System.out
.println(
new DB2Dialect().getLimitString(
"/*foo*/ select * from foos foo order by foo.bar, foo.baz",
true
)
);
System.out
.println(
new DB2Dialect().getLimitString(
"/*foo*/ select distinct * from foos foo order by foo.bar, foo.baz",
true
)
);
}
@Override
public boolean supportsUnionAll() {
return true;
}
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
boolean isResultSet = ps.execute();
@ -348,39 +354,45 @@ public ResultSet getResultSet(CallableStatement ps) throws SQLException {
while ( !isResultSet && ps.getUpdateCount() != -1 ) {
isResultSet = ps.getMoreResults();
}
ResultSet rs = ps.getResultSet();
// You may still have other ResultSets or update counts left to process here
// but you can't do it now or the ResultSet you just got will be closed
return rs;
return ps.getResultSet();
}
@Override
public boolean supportsCommentOn() {
return true;
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String getCreateTemporaryTableString() {
return "declare global temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return "not logged";
}
@Override
public String generateTemporaryTableName(String baseTableName) {
return "session." + super.generateTemporaryTableName( baseTableName );
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public String getCurrentTimestampSelectString() {
return "values current timestamp";
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
@ -389,10 +401,8 @@ public boolean isCurrentTimestampSelectStringCallable() {
/**
* {@inheritDoc}
* <p/>
* DB2 is know to support parameters in the <tt>SELECT</tt> clause, but only in casted form
* NOTE : DB2 is know to support parameters in the <tt>SELECT</tt> clause, but only in casted form
* (see {@link #requiresCastingOfParametersInSelectClause()}).
*
* @return True.
*/
@Override
public boolean supportsParametersInInsertSelect() {
@ -400,38 +410,45 @@ public boolean supportsParametersInInsertSelect() {
}
/**
* {@inheritDoc}
* <p/>
* DB2 in fact does require that parameters appearing in the select clause be wrapped in cast() calls
* to tell the DB parser the type of the select value.
*
* @return True.
*/
@Override
public boolean requiresCastingOfParametersInSelectClause() {
return true;
}
@Override
public boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
return false;
}
//DB2 v9.1 doesn't support 'cross join' syntax
@Override
public String getCrossJoinSeparator() {
//DB2 v9.1 doesn't support 'cross join' syntax
return ", ";
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsLobValueChangePropogation() {
return false;
}
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return true;
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;

View File

@ -22,26 +22,29 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* A Dialect for accessing Oracle through DataDirect driver
*/
@SuppressWarnings("deprecation")
public class DataDirectOracle9Dialect extends Oracle9Dialect {
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
return col; // sql server just returns automatically
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
boolean isResultSet = ps.execute();
// This assumes you will want to ignore any update counts
while (!isResultSet && ps.getUpdateCount() != -1) {
isResultSet = ps.getMoreResults();
}
ResultSet rs = ps.getResultSet();
// You may still have other ResultSets or update counts left to process here
// but you can't do it now or the ResultSet you just got will be closed
return rs;
}
return ps.getResultSet();
}
}

View File

@ -48,17 +48,25 @@
*/
@Deprecated
public class DerbyDialect extends DB2Dialect {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, DerbyDialect.class.getName());
@SuppressWarnings("deprecation")
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
DerbyDialect.class.getName()
);
private int driverVersionMajor;
private int driverVersionMinor;
/**
* Constructs a DerbyDialect
*/
@SuppressWarnings("deprecation")
public DerbyDialect() {
super();
if ( this.getClass() == DerbyDialect.class ) {
LOG.deprecatedDerbyDialect();
}
registerFunction( "concat", new DerbyConcatFunction() );
registerFunction( "trim", new AnsiTrimFunction() );
registerColumnType( Types.BLOB, "blob" );
@ -69,7 +77,7 @@ public DerbyDialect() {
}
}
@SuppressWarnings({ "UnnecessaryUnboxing" })
@SuppressWarnings({"UnnecessaryUnboxing", "unchecked"})
private void determineDriverVersion() {
try {
// locate the derby sysinfo class and query its version info
@ -95,9 +103,6 @@ public String getCrossJoinSeparator() {
return ", ";
}
/**
* Return the case statement modified for Cloudscape.
*/
@Override
public CaseFragment createCaseFragment() {
return new DerbyCaseFragment();
@ -138,13 +143,14 @@ public boolean supportsLimit() {
return isTenPointFiveReleaseOrNewer();
}
//HHH-4531
@Override
public boolean supportsCommentOn() {
//HHH-4531
return false;
}
@Override
@SuppressWarnings("deprecation")
public boolean supportsLimitOffset() {
return isTenPointFiveReleaseOrNewer();
}
@ -180,8 +186,7 @@ public String getReadLockString(int timeout) {
*/
@Override
public String getLimitString(String query, final int offset, final int limit) {
StringBuilder sb = new StringBuilder(query.length() + 50);
final StringBuilder sb = new StringBuilder(query.length() + 50);
final String normalizedSelect = query.toLowerCase().trim();
final int forUpdateIndex = normalizedSelect.lastIndexOf( "for update") ;

View File

@ -36,7 +36,11 @@
* @author Simon Johnston
* @author Scott Marlow
*/
@SuppressWarnings("deprecation")
public class DerbyTenFiveDialect extends DerbyDialect {
/**
* Constructs a DerbyTenFiveDialect
*/
public DerbyTenFiveDialect() {
super();
registerFunction( "concat", new DerbyConcatFunction() );

View File

@ -26,13 +26,20 @@
import java.sql.Types;
/**
* Dialect for Derby 10.7
*
* @author Strong Liu
*/
public class DerbyTenSevenDialect extends DerbyTenSixDialect {
/**
* Constructs a DerbyTenSevenDialect
*/
public DerbyTenSevenDialect() {
super();
registerColumnType( Types.BOOLEAN, "boolean" );
}
@Override
public String toBooleanValueString(boolean bool) {
return String.valueOf( bool );
}

View File

@ -33,6 +33,9 @@
* @author Scott Marlow
*/
public class DerbyTenSixDialect extends DerbyTenFiveDialect {
/**
* Constructs a DerbyTenSixDialect
*/
public DerbyTenSixDialect() {
super();
}

View File

@ -23,14 +23,42 @@
*/
package org.hibernate.dialect;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.NullPrecedence;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.*;
import org.hibernate.dialect.lock.*;
import org.hibernate.dialect.function.CastFunction;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.lock.LockingStrategy;
import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy;
import org.hibernate.dialect.lock.OptimisticLockingStrategy;
import org.hibernate.dialect.lock.PessimisticForceIncrementLockingStrategy;
import org.hibernate.dialect.lock.PessimisticReadSelectLockingStrategy;
import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy;
import org.hibernate.dialect.lock.SelectLockingStrategy;
import org.hibernate.dialect.pagination.LegacyLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
@ -52,39 +80,47 @@
import org.hibernate.internal.util.io.StreamCopier;
import org.hibernate.mapping.Column;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.sql.*;
import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.ANSIJoinFragment;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.jboss.logging.Logger;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.*;
import java.util.*;
/**
* Represents a dialect of SQL implemented by a particular RDBMS.
* Subclasses implement Hibernate compatibility with different systems.<br>
* <br>
* Subclasses should provide a public default constructor that <tt>register()</tt>
* a set of type mappings and default Hibernate properties.<br>
* <br>
* Subclasses should be immutable.
* Represents a dialect of SQL implemented by a particular RDBMS. Subclasses implement Hibernate compatibility
* with different systems. Subclasses should provide a public default constructor that register a set of type
* mappings and default Hibernate properties. Subclasses should be immutable.
*
* @author Gavin King, David Channon
*/
@SuppressWarnings("deprecation")
public abstract class Dialect implements ConversionContext {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
Dialect.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Dialect.class.getName());
/**
* Defines a default batch size constant
*/
public static final String DEFAULT_BATCH_SIZE = "15";
/**
* Defines a "no batching" batch size constant
*/
public static final String NO_BATCH = "0";
/**
* Characters used for quoting SQL identifiers
* Characters used as opening for quoting SQL identifiers
*/
public static final String QUOTE = "`\"[";
/**
* Characters used as closing for quoting SQL identifiers
*/
public static final String CLOSED_QUOTE = "`\"]";
private final TypeNames typeNames = new TypeNames();
@ -194,8 +230,7 @@ protected Dialect() {
* @throws HibernateException If no dialect was specified, or if it could not be instantiated.
*/
public static Dialect getDialect() throws HibernateException {
String dialectName = Environment.getProperties().getProperty( Environment.DIALECT );
return instantiateDialect( dialectName );
return instantiateDialect( Environment.getProperties().getProperty( Environment.DIALECT ) );
}
@ -208,7 +243,7 @@ public static Dialect getDialect() throws HibernateException {
* @throws HibernateException If no dialect was specified, or if it could not be instantiated.
*/
public static Dialect getDialect(Properties props) throws HibernateException {
String dialectName = props.getProperty( Environment.DIALECT );
final String dialectName = props.getProperty( Environment.DIALECT );
if ( dialectName == null ) {
return getDialect();
}
@ -256,7 +291,7 @@ public String toString() {
* @throws HibernateException If no mapping was specified for that type.
*/
public String getTypeName(int code) throws HibernateException {
String result = typeNames.get( code );
final String result = typeNames.get( code );
if ( result == null ) {
throw new HibernateException( "No default type mapping for (java.sql.Types) " + code );
}
@ -276,9 +311,11 @@ public String getTypeName(int code) throws HibernateException {
* @throws HibernateException If no mapping was specified for that type.
*/
public String getTypeName(int code, long length, int precision, int scale) throws HibernateException {
String result = typeNames.get( code, length, precision, scale );
final String result = typeNames.get( code, length, precision, scale );
if ( result == null ) {
throw new HibernateException(String.format( "No type mapping for java.sql.Types code: %s, length: %s", code, length ));
throw new HibernateException(
String.format( "No type mapping for java.sql.Types code: %s, length: %s", code, length )
);
}
return result;
}
@ -294,6 +331,17 @@ public String getCastTypeName(int code) {
return getTypeName( code, Column.DEFAULT_LENGTH, Column.DEFAULT_PRECISION, Column.DEFAULT_SCALE );
}
/**
* Return an expression casting the value to the specified type
*
* @param value The value to cast
* @param jdbcTypeCode The JDBC type code to cast to
* @param length The type length
* @param precision The type precision
* @param scale The type scale
*
* @return The cast expression
*/
public String cast(String value, int jdbcTypeCode, int length, int precision, int scale) {
if ( jdbcTypeCode == Types.CHAR ) {
return "cast(" + value + " as char(" + length + "))";
@ -303,10 +351,32 @@ public String cast(String value, int jdbcTypeCode, int length, int precision, in
}
}
/**
* Return an expression casting the value to the specified type. Simply calls
* {@link #cast(String, int, int, int, int)} passing {@link Column#DEFAULT_PRECISION} and
* {@link Column#DEFAULT_SCALE} as the precision/scale.
*
* @param value The value to cast
* @param jdbcTypeCode The JDBC type code to cast to
* @param length The type length
*
* @return The cast expression
*/
public String cast(String value, int jdbcTypeCode, int length) {
return cast( value, jdbcTypeCode, length, Column.DEFAULT_PRECISION, Column.DEFAULT_SCALE );
}
/**
* Return an expression casting the value to the specified type. Simply calls
* {@link #cast(String, int, int, int, int)} passing {@link Column#DEFAULT_LENGTH} as the length
*
* @param value The value to cast
* @param jdbcTypeCode The JDBC type code to cast to
* @param precision The type precision
* @param scale The type scale
*
* @return The cast expression
*/
public String cast(String value, int jdbcTypeCode, int precision, int scale) {
return cast( value, jdbcTypeCode, Column.DEFAULT_LENGTH, precision, scale );
}
@ -417,8 +487,10 @@ public NClob mergeNClob(NClob original, NClob target, SessionImplementor session
public Blob mergeBlob(Blob original, Blob target, SessionImplementor session) {
if ( original != target ) {
try {
OutputStream connectedStream = target.setBinaryStream( 1L ); // the BLOB just read during the load phase of merge
InputStream detachedStream = original.getBinaryStream(); // the BLOB from the detached state
// the BLOB just read during the load phase of merge
final OutputStream connectedStream = target.setBinaryStream( 1L );
// the BLOB from the detached state
final InputStream detachedStream = original.getBinaryStream();
StreamCopier.copy( detachedStream, connectedStream );
return target;
}
@ -435,8 +507,10 @@ public Blob mergeBlob(Blob original, Blob target, SessionImplementor session) {
public Clob mergeClob(Clob original, Clob target, SessionImplementor session) {
if ( original != target ) {
try {
OutputStream connectedStream = target.setAsciiStream( 1L ); // the CLOB just read during the load phase of merge
InputStream detachedStream = original.getAsciiStream(); // the CLOB from the detached state
// the CLOB just read during the load phase of merge
final OutputStream connectedStream = target.setAsciiStream( 1L );
// the CLOB from the detached state
final InputStream detachedStream = original.getAsciiStream();
StreamCopier.copy( detachedStream, connectedStream );
return target;
}
@ -453,8 +527,10 @@ public Clob mergeClob(Clob original, Clob target, SessionImplementor session) {
public NClob mergeNClob(NClob original, NClob target, SessionImplementor session) {
if ( original != target ) {
try {
OutputStream connectedStream = target.setAsciiStream( 1L ); // the NCLOB just read during the load phase of merge
InputStream detachedStream = original.getAsciiStream(); // the NCLOB from the detached state
// the NCLOB just read during the load phase of merge
final OutputStream connectedStream = target.setAsciiStream( 1L );
// the NCLOB from the detached state
final InputStream detachedStream = original.getAsciiStream();
StreamCopier.copy( detachedStream, connectedStream );
return target;
}
@ -478,7 +554,7 @@ public Blob mergeBlob(Blob original, Blob target, SessionImplementor session) {
return null;
}
try {
LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session );
final LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session );
return original == null
? lobCreator.createBlob( ArrayHelper.EMPTY_BYTE_ARRAY )
: lobCreator.createBlob( original.getBinaryStream(), original.length() );
@ -494,7 +570,7 @@ public Clob mergeClob(Clob original, Clob target, SessionImplementor session) {
return null;
}
try {
LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session );
final LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session );
return original == null
? lobCreator.createClob( "" )
: lobCreator.createClob( original.getCharacterStream(), original.length() );
@ -510,7 +586,7 @@ public NClob mergeNClob(NClob original, NClob target, SessionImplementor session
return null;
}
try {
LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session );
final LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session );
return original == null
? lobCreator.createNClob( "" )
: lobCreator.createNClob( original.getCharacterStream(), original.length() );
@ -538,7 +614,7 @@ public LobMergeStrategy getLobMergeStrategy() {
*/
@SuppressWarnings( {"UnusedDeclaration"})
public String getHibernateTypeName(int code) throws HibernateException {
String result = hibernateTypeNames.get( code );
final String result = hibernateTypeNames.get( code );
if ( result == null ) {
throw new HibernateException( "No Hibernate type mapping for java.sql.Types code: " + code );
}
@ -558,13 +634,14 @@ public String getHibernateTypeName(int code) throws HibernateException {
* @throws HibernateException If no mapping was specified for that type.
*/
public String getHibernateTypeName(int code, int length, int precision, int scale) throws HibernateException {
String result = hibernateTypeNames.get( code, length, precision, scale );
final String result = hibernateTypeNames.get( code, length, precision, scale );
if ( result == null ) {
throw new HibernateException(
"No Hibernate type mapping for java.sql.Types code: " +
code +
", length: " +
String.format(
"No Hibernate type mapping for type [code=%s, length=%s]",
code,
length
)
);
}
return result;
@ -1153,7 +1230,7 @@ public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode)
* @return The appropriate for update fragment.
*/
public String getForUpdateString(LockOptions lockOptions) {
LockMode lockMode = lockOptions.getLockMode();
final LockMode lockMode = lockOptions.getLockMode();
return getForUpdateString( lockMode, lockOptions.getTimeOut() );
}
@ -1267,7 +1344,7 @@ public String getForUpdateString(String aliases) {
@SuppressWarnings( {"unchecked"})
public String getForUpdateString(String aliases, LockOptions lockOptions) {
LockMode lockMode = lockOptions.getLockMode();
Iterator<Map.Entry<String, LockMode>> itr = lockOptions.getAliasLockIterator();
final Iterator<Map.Entry<String, LockMode>> itr = lockOptions.getAliasLockIterator();
while ( itr.hasNext() ) {
// seek the highest lock mode
final Map.Entry<String, LockMode>entry = itr.next();
@ -1531,8 +1608,7 @@ public int registerResultSetOutParameter(CallableStatement statement, String nam
*/
public ResultSet getResultSet(CallableStatement statement) throws SQLException {
throw new UnsupportedOperationException(
getClass().getName() +
" does not support resultsets via stored procedures"
getClass().getName() + " does not support resultsets via stored procedures"
);
}
@ -1549,8 +1625,7 @@ public ResultSet getResultSet(CallableStatement statement) throws SQLException {
*/
public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {
throw new UnsupportedOperationException(
getClass().getName() +
" does not support resultsets via stored procedures"
getClass().getName() + " does not support resultsets via stored procedures"
);
}
@ -1567,8 +1642,7 @@ public ResultSet getResultSet(CallableStatement statement, int position) throws
*/
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
throw new UnsupportedOperationException(
getClass().getName() +
" does not support resultsets via stored procedures"
getClass().getName() + " does not support resultsets via stored procedures"
);
}
@ -1677,6 +1751,8 @@ public SQLExceptionConverter buildSQLExceptionConverter() {
* the a vendor-specific ErrorCode rather than the SQLState.
* <p/>
* Specific Dialects may override to return whatever is most appropriate for that vendor.
*
* @return The SQLExceptionConversionDelegate for this dialect
*/
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
return null;
@ -1767,6 +1843,7 @@ public String getLowercaseFunction() {
/**
* The name of the SQL function that can do case insensitive <b>like</b> comparison.
*
* @return The dialect-specific "case insensitive" like function.
*/
public String getCaseInsensitiveLike(){
@ -1774,8 +1851,10 @@ public String getCaseInsensitiveLike(){
}
/**
* @return {@code true} if the underlying Database supports case insensitive like comparison, {@code false} otherwise.
* The default is {@code false}.
* Does this dialect support case insensitive LIKE restrictions?
*
* @return {@code true} if the underlying database supports case insensitive like comparison,
* {@code false} otherwise. The default is {@code false}.
*/
public boolean supportsCaseInsensitiveLike(){
return false;
@ -1949,7 +2028,7 @@ public String getAddForeignKeyConstraintString(
String referencedTable,
String[] primaryKey,
boolean referencesPrimaryKey) {
StringBuilder res = new StringBuilder( 30 );
final StringBuilder res = new StringBuilder( 30 );
res.append( " add constraint " )
.append( constraintName )
@ -1977,6 +2056,11 @@ public String getAddPrimaryKeyConstraintString(String constraintName) {
return " add constraint " + constraintName + " primary key ";
}
/**
* Does the database/driver have bug in deleting rows that refer to other rows being deleted in the same query?
*
* @return {@code true} if the database/driver has this bug
*/
public boolean hasSelfReferentialForeignKeyBug() {
return false;
}
@ -1990,28 +2074,68 @@ public String getNullColumnString() {
return "";
}
/**
* Does this dialect/database support commenting on tables, columns, etc?
*
* @return {@code true} if commenting is supported
*/
public boolean supportsCommentOn() {
return false;
}
/**
* Get the comment into a form supported for table definition.
*
* @param comment The comment to apply
*
* @return The comment fragment
*/
public String getTableComment(String comment) {
return "";
}
/**
* Get the comment into a form supported for column definition.
*
* @param comment The comment to apply
*
* @return The comment fragment
*/
public String getColumnComment(String comment) {
return "";
}
/**
* For dropping a table, can the phrase "if exists" be applied before the table name?
* <p/>
* NOTE : Only one or the other (or neither) of this and {@link #supportsIfExistsAfterTableName} should return true
*
* @return {@code true} if the "if exists" can be applied before the table name
*/
public boolean supportsIfExistsBeforeTableName() {
return false;
}
/**
* For dropping a table, can the phrase "if exists" be applied after the table name?
* <p/>
* NOTE : Only one or the other (or neither) of this and {@link #supportsIfExistsBeforeTableName} should return true
*
* @return {@code true} if the "if exists" can be applied after the table name
*/
public boolean supportsIfExistsAfterTableName() {
return false;
}
/**
* Generate a DROP TABLE statement
*
* @param tableName The name of the table to drop
*
* @return The DROP TABLE command
*/
public String getDropTableString(String tableName) {
StringBuilder buf = new StringBuilder( "drop table " );
final StringBuilder buf = new StringBuilder( "drop table " );
if ( supportsIfExistsBeforeTableName() ) {
buf.append( "if exists " );
}
@ -2042,6 +2166,11 @@ public boolean supportsTableCheck() {
return true;
}
/**
* Does this dialect support cascaded delete on foreign key definitions?
*
* @return {@code true} indicates that the dialect does support cascaded delete on foreign keys.
*/
public boolean supportsCascadeDelete() {
return true;
}
@ -2056,12 +2185,13 @@ public String getCascadeConstraintsString() {
}
/**
* @return Returns the separator to use for defining cross joins when translating HQL queries.
* Returns the separator to use for defining cross joins when translating HQL queries.
* <p/>
* Typically this will be either [<tt> cross join </tt>] or [<tt>, </tt>]
* <p/>
* Note that the spaces are important!
*
* @return The cross join separator
*/
public String getCrossJoinSeparator() {
return " cross join ";
@ -2165,6 +2295,8 @@ public boolean replaceResultVariableInOrderByClauseWithPosition() {
}
/**
* Renders an ordering fragment
*
* @param expression The SQL order expression. In case of {@code @OrderBy} annotation user receives property placeholder
* (e.g. attribute name enclosed in '{' and '}' signs).
* @param collation Collation string in format {@code collate IDENTIFIER}, or {@code null}
@ -2422,14 +2554,26 @@ public boolean useFollowOnLocking() {
return false;
}
public UniqueDelegate getUniqueDelegate() {
return uniqueDelegate;
}
/**
* Negate an expression
*
* @param expression The expression to negate
*
* @return The negated expression
*/
public String getNotExpression(String expression) {
return "not " + expression;
}
/**
* Get the UniqueDelegate supported by this dialect
*
* @return The UniqueDelegate
*/
public UniqueDelegate getUniqueDelegate() {
return uniqueDelegate;
}
/**
* Does this dialect support the <tt>UNIQUE</tt> column syntax?
*
@ -2468,6 +2612,10 @@ public String getAddUniqueConstraintString(String constraintName) {
}
/**
* Is the combination of not-null and unique supported?
*
* @return deprecated
*
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
*/
@Deprecated

View File

@ -23,18 +23,18 @@
*/
package org.hibernate.dialect;
/**
* An SQL dialect for Firebird.
*
* @author Reha CENANI
*/
public class FirebirdDialect extends InterbaseDialect {
@Override
public String getDropSequenceString(String sequenceName) {
return "drop generator " + sequenceName;
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
return new StringBuilder( sql.length() + 20 )
.append( sql )
@ -42,12 +42,13 @@ public String getLimitString(String sql, boolean hasOffset) {
.toString();
}
@Override
public boolean bindLimitParametersFirst() {
return true;
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return true;
}
}

View File

@ -53,6 +53,9 @@
*/
public class FrontBaseDialect extends Dialect {
/**
* Constructs a FrontBaseDialect
*/
public FrontBaseDialect() {
super();
@ -74,37 +77,43 @@ public FrontBaseDialect() {
registerColumnType( Types.CLOB, "clob" );
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public String getCascadeConstraintsString() {
return " cascade";
}
@Override
public boolean dropConstraints() {
return false;
}
/**
* Does this dialect support the <tt>FOR UPDATE</tt> syntax. No!
*
* @return false always. FrontBase doesn't support this syntax,
* which was dropped with SQL92
* FrontBase doesn't support this syntax, which was dropped with SQL92.
* <p/>
* {@inheritDoc}
*/
@Override
public String getForUpdateString() {
return "";
}
public String getCurrentTimestampCallString() {
@Override
public String getCurrentTimestampSelectString() {
// TODO : not sure this is correct, could not find docs on how to do this.
return "{?= call current_timestamp}";
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return true;
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// Frontbase has no known variation of a "SELECT ... FOR UPDATE" syntax...
if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {

View File

@ -50,11 +50,16 @@
* @author Thomas Mueller
*/
public class H2Dialect extends Dialect {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, H2Dialect.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
H2Dialect.class.getName()
);
private final String querySequenceString;
/**
* Constructs a H2Dialect
*/
public H2Dialect() {
super();
@ -190,89 +195,107 @@ public H2Dialect() {
registerFunction( "user", new NoArgSQLFunction( "user", StandardBasicTypes.STRING ) );
getDefaultProperties().setProperty( AvailableSettings.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" ); // http://code.google.com/p/h2database/issues/detail?id=235
// http://code.google.com/p/h2database/issues/detail?id=235
getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" );
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentityColumnString() {
return "generated by default as identity"; // not null is implicit
// not null is implicit
return "generated by default as identity";
}
@Override
public String getIdentitySelectString() {
return "call identity()";
}
@Override
public String getIdentityInsertString() {
return "null";
}
@Override
public String getForUpdateString() {
return " for update";
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
return new StringBuilder( sql.length() + 20 )
.append( sql )
.append( hasOffset ? " limit ? offset ?" : " limit ?" )
.toString();
return sql + (hasOffset ? " limit ? offset ?" : " limit ?");
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return true;
}
@Override
public boolean bindLimitParametersFirst() {
return false;
}
@Override
public boolean supportsIfExistsAfterTableName() {
return true;
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return "next value for " + sequenceName;
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "call next value for " + sequenceName;
}
@Override
public String getQuerySequencesString() {
return querySequenceString;
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}
private static ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
/**
* Extract the name of the violated constraint from the given SQLException.
*
@ -285,7 +308,7 @@ public String extractConstraintName(SQLException sqle) {
// 23001: Unique index or primary key violation: {0}
if ( sqle.getSQLState().startsWith( "23" ) ) {
final String message = sqle.getMessage();
int idx = message.indexOf( "violation: " );
final int idx = message.indexOf( "violation: " );
if ( idx > 0 ) {
constraintName = message.substring( idx + "violation: ".length() );
}
@ -299,28 +322,27 @@ public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
SQLExceptionConversionDelegate delegate = super.buildSQLExceptionConversionDelegate();
if (delegate == null) {
delegate = new SQLExceptionConversionDelegate() {
@Override
public JDBCException convert(SQLException sqlException, String message, String sql) {
JDBCException exception = null;
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
int errorCode = JdbcExceptionHelper.extractErrorCode(sqlException);
if (40001 == errorCode) { // DEADLOCK DETECTED
exception = new LockAcquisitionException(message, sqlException, sql);
if (40001 == errorCode) {
// DEADLOCK DETECTED
return new LockAcquisitionException(message, sqlException, sql);
}
if (50200 == errorCode) { // LOCK NOT AVAILABLE
exception = new PessimisticLockException(message, sqlException, sql);
if (50200 == errorCode) {
// LOCK NOT AVAILABLE
return new PessimisticLockException(message, sqlException, sql);
}
if ( 90006 == errorCode ) {
// NULL not allowed for column [90006-145]
final String constraintName = getViolatedConstraintNameExtracter().extractConstraintName( sqlException );
exception = new ConstraintViolationException( message, sqlException, sql, constraintName );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
return exception;
return null;
}
};
}
@ -356,18 +378,22 @@ public boolean dropTemporaryTableAfterUse() {
return false;
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public String getCurrentTimestampSelectString() {
return "call current_timestamp()";
}
@Override
public boolean supportsUnionAll() {
return true;
}

View File

@ -66,8 +66,10 @@
* @author Fred Toussi
*/
public class HSQLDialect extends Dialect {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, HSQLDialect.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
HSQLDialect.class.getName()
);
/**
* version is 18 for 1.8 or 20 for 2.0
@ -75,12 +77,15 @@ public class HSQLDialect extends Dialect {
private int hsqldbVersion = 18;
/**
* Constructs a HSQLDialect
*/
public HSQLDialect() {
super();
try {
Class props = ReflectHelper.classForName( "org.hsqldb.persist.HsqlDatabaseProperties" );
String versionString = (String) props.getDeclaredField( "THIS_VERSION" ).get( null );
final Class props = ReflectHelper.classForName( "org.hsqldb.persist.HsqlDatabaseProperties" );
final String versionString = (String) props.getDeclaredField( "THIS_VERSION" ).get( null );
hsqldbVersion = Integer.parseInt( versionString.substring( 0, 1 ) ) * 10;
hsqldbVersion += Integer.parseInt( versionString.substring( 2, 3 ) );
@ -208,8 +213,7 @@ public HSQLDialect() {
// special functions
// from v. 2.2.0 ROWNUM() is supported in all modes as the equivalent of Oracle ROWNUM
if ( hsqldbVersion > 21 ) {
registerFunction("rownum",
new NoArgSQLFunction("rownum", StandardBasicTypes.INTEGER));
registerFunction( "rownum", new NoArgSQLFunction( "rownum", StandardBasicTypes.INTEGER ) );
}
// function templates
@ -218,30 +222,38 @@ public HSQLDialect() {
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentityColumnString() {
return "generated by default as identity (start with 1)"; //not null is implicit
//not null is implicit
return "generated by default as identity (start with 1)";
}
@Override
public String getIdentitySelectString() {
return "call identity()";
}
@Override
public String getIdentityInsertString() {
return hsqldbVersion < 20 ? "null" : "default";
}
@Override
public boolean supportsLockTimeouts() {
return false;
}
@Override
public String getForUpdateString() {
if ( hsqldbVersion >= 20 ) {
return " for update";
@ -251,10 +263,12 @@ public String getForUpdateString() {
}
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
if ( hsqldbVersion < 20 ) {
return new StringBuilder( sql.length() + 10 )
@ -266,70 +280,72 @@ public String getLimitString(String sql, boolean hasOffset) {
.toString();
}
else {
return new StringBuilder( sql.length() + 20 )
.append( sql )
.append( hasOffset ? " offset ? limit ?" : " limit ?" )
.toString();
return sql + (hasOffset ? " offset ? limit ?" : " limit ?");
}
}
@Override
public boolean bindLimitParametersFirst() {
return hsqldbVersion < 20;
}
@Override
public boolean supportsIfExistsAfterTableName() {
return true;
}
@Override
public boolean supportsColumnCheck() {
return hsqldbVersion >= 20;
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
protected String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
protected String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return "next value for " + sequenceName;
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "call next value for " + sequenceName;
}
@Override
public String getQuerySequencesString() {
// this assumes schema support, which is present in 1.8.0 and later...
return "select sequence_name from information_schema.system_sequences";
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return hsqldbVersion < 20 ? EXTRACTER_18 : EXTRACTER_20;
}
private static ViolatedConstraintNameExtracter EXTRACTER_18 = new TemplatedViolatedConstraintNameExtracter() {
/**
* Extract the name of the violated constraint from the given SQLException.
*
* @param sqle The exception that was the result of the constraint violation.
* @return The extracted constraint name.
*/
private static final ViolatedConstraintNameExtracter EXTRACTER_18 = new TemplatedViolatedConstraintNameExtracter() {
@Override
public String extractConstraintName(SQLException sqle) {
String constraintName = null;
int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == -8 ) {
constraintName = extractUsingTemplate(
@ -361,12 +377,12 @@ else if ( errorCode == -177 ) {
* HSQLDB 2.0 messages have changed
* messages may be localized - therefore use the common, non-locale element " table: "
*/
private static ViolatedConstraintNameExtracter EXTRACTER_20 = new TemplatedViolatedConstraintNameExtracter() {
private static final ViolatedConstraintNameExtracter EXTRACTER_20 = new TemplatedViolatedConstraintNameExtracter() {
@Override
public String extractConstraintName(SQLException sqle) {
String constraintName = null;
int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == -8 ) {
constraintName = extractUsingTemplate(
@ -392,6 +408,7 @@ else if ( errorCode == -177 ) {
}
};
@Override
public String getSelectClauseNullString(int sqlType) {
String literal;
switch ( sqlType ) {
@ -432,11 +449,13 @@ public String getSelectClauseNullString(int sqlType) {
return literal;
}
@Override
public boolean supportsUnionAll() {
return true;
}
// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate uses this information for temporary tables that it uses for its own operations
// therefore the appropriate strategy is taken with different versions of HSQLDB
@ -446,37 +465,24 @@ public boolean supportsUnionAll() {
// the definition and data is private to the session and table declaration
// can happen in the middle of a transaction
/**
* Does this dialect support temporary tables?
*
* @return True if temp tables are supported; false otherwise.
*/
@Override
public boolean supportsTemporaryTables() {
return true;
}
/**
* With HSQLDB 2.0, the table name is qualified with MODULE to assist the drop
* statement (in-case there is a global name beginning with HT_)
*
* @param baseTableName The table name from which to base the temp table name.
*
* @return The generated temp table name.
*/
@Override
public String generateTemporaryTableName(String baseTableName) {
if ( hsqldbVersion < 20 ) {
return "HT_" + baseTableName;
}
else {
// With HSQLDB 2.0, the table name is qualified with MODULE to assist the drop
// statement (in-case there is a global name beginning with HT_)
return "MODULE.HT_" + baseTableName;
}
}
/**
* Command used to create a temporary table.
*
* @return The command used to create a temporary table.
*/
@Override
public String getCreateTemporaryTableString() {
if ( hsqldbVersion < 20 ) {
return "create global temporary table";
@ -486,40 +492,19 @@ public String getCreateTemporaryTableString() {
}
}
/**
* No fragment is needed if data is not needed beyond commit, otherwise
* should add "on commit preserve rows"
*
* @return Any required postfix.
*/
@Override
public String getCreateTemporaryTablePostfix() {
return "";
}
/**
* Command used to drop a temporary table.
*
* @return The command used to drop a temporary table.
*/
@Override
public String getDropTemporaryTableString() {
return "drop table";
}
/**
* Different behavior for GLOBAL TEMPORARY (1.8) and LOCAL TEMPORARY (2.0)
* <p/>
* Possible return values and their meanings:<ul>
* <li>{@link Boolean#TRUE} - Unequivocally, perform the temporary table DDL
* in isolation.</li>
* <li>{@link Boolean#FALSE} - Unequivocally, do <b>not</b> perform the
* temporary table DDL in isolation.</li>
* <li><i>null</i> - defer to the JDBC driver response in regards to
* {@link java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()}</li>
* </ul>
*
* @return see the result matrix above.
*/
@Override
public Boolean performTemporaryTableDDLInIsolation() {
// Different behavior for GLOBAL TEMPORARY (1.8) and LOCAL TEMPORARY (2.0)
if ( hsqldbVersion < 20 ) {
return Boolean.TRUE;
}
@ -528,20 +513,13 @@ public Boolean performTemporaryTableDDLInIsolation() {
}
}
/**
* Do we need to drop the temporary table after use?
*
* todo - clarify usage by Hibernate
*
* Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end
* of the session (by default, data is cleared at commit).<p>
*
* Version 2.x LOCAL TEMPORARY table definitions do not persist beyond
* the end of the session (by default, data is cleared at commit).
*
* @return True if the table should be dropped.
*/
@Override
public boolean dropTemporaryTableAfterUse() {
// Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end
// of the session (by default, data is cleared at commit).<p>
//
// Version 2.x LOCAL TEMPORARY table definitions do not persist beyond
// the end of the session (by default, data is cleared at commit).
return true;
}
@ -552,44 +530,25 @@ public boolean dropTemporaryTableAfterUse() {
* be treated as a callable statement. It is equivalent to
* "select current_timestamp from dual" in some databases.
* HSQLDB 2.0 also supports VALUES CURRENT_TIMESTAMP
*
* @return True if the current timestamp can be retrieved; false otherwise.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
/**
* Should the value returned by {@link #getCurrentTimestampSelectString}
* be treated as callable. Typically this indicates that JDBC escape
* syntax is being used...<p>
*
* CALL CURRENT_TIMESTAMP is used but this should not
* be treated as a callable statement.
*
* @return True if the {@link #getCurrentTimestampSelectString} return
* is callable; false otherwise.
*/
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
/**
* Retrieve the command used to retrieve the current timestamp from the
* database.
*
* @return The command.
*/
@Override
public String getCurrentTimestampSelectString() {
return "call current_timestamp";
}
/**
* The name of the database-specific SQL function for retrieving the
* current timestamp.
*
* @return The function name.
*/
@Override
public String getCurrentTimestampSQLFunctionName() {
// the standard SQL function name is current_timestamp...
return "current_timestamp";
@ -598,14 +557,10 @@ public String getCurrentTimestampSQLFunctionName() {
/**
* For HSQLDB 2.0, this is a copy of the base class implementation.
* For HSQLDB 1.8, only READ_UNCOMMITTED is supported.
*
* @param lockable The persister for the entity to be locked.
* @param lockMode The type of lock to be acquired.
*
* @return The appropriate locking strategy.
*
* @since 3.2
* <p/>
* {@inheritDoc}
*/
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT ) {
return new PessimisticForceIncrementLockingStrategy( lockable, lockMode );
@ -631,7 +586,7 @@ else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT ) {
}
}
public static class ReadUncommittedLockingStrategy extends SelectLockingStrategy {
private static class ReadUncommittedLockingStrategy extends SelectLockingStrategy {
public ReadUncommittedLockingStrategy(Lockable lockable, LockMode lockMode) {
super( lockable, lockMode );
}
@ -645,6 +600,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
}
}
@Override
public boolean supportsCommentOn() {
return hsqldbVersion >= 20;
}
@ -656,54 +612,32 @@ public boolean supportsEmptyInList() {
return false;
}
/**
* todo - needs usage clarification
*
* If the SELECT statement is always part of a UNION, then the type of
* parameter is resolved by v. 2.0, but not v. 1.8 (assuming the other
* SELECT in the UNION has a column reference in the same position and
* can be type-resolved).
*
* On the other hand if the SELECT statement is isolated, all versions of
* HSQLDB require casting for "select ? from .." to work.
*
* @return True if select clause parameter must be cast()ed
*
* @since 3.2
*/
@Override
public boolean requiresCastingOfParametersInSelectClause() {
return true;
}
/**
* For the underlying database, is READ_COMMITTED isolation implemented by
* forcing readers to wait for write locks to be released?
*
* @return True if writers block readers to achieve READ_COMMITTED; false otherwise.
*/
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return hsqldbVersion >= 20;
}
/**
* For the underlying database, is REPEATABLE_READ isolation implemented by
* forcing writers to wait for read locks to be released?
*
* @return True if readers block writers to achieve REPEATABLE_READ; false otherwise.
*/
@Override
public boolean doesRepeatableReadCauseReadersToBlockWriters() {
return hsqldbVersion >= 20;
}
@Override
public boolean supportsLobValueChangePropogation() {
return false;
}
@Override
public String toBooleanValueString(boolean bool) {
return String.valueOf( bool );
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.SQLException;
import java.sql.Types;
@ -51,16 +52,20 @@ public InformixDialect() {
registerColumnType( Types.BIGINT, "int8" );
registerColumnType( Types.BINARY, "byte" );
registerColumnType(Types.BIT, "smallint"); // Informix doesn't have a bit type
// Informix doesn't have a bit type
registerColumnType( Types.BIT, "smallint" );
registerColumnType( Types.CHAR, "char($l)" );
registerColumnType( Types.DATE, "date" );
registerColumnType( Types.DECIMAL, "decimal" );
registerColumnType( Types.DOUBLE, "float" );
registerColumnType( Types.FLOAT, "smallfloat" );
registerColumnType( Types.INTEGER, "integer" );
registerColumnType(Types.LONGVARBINARY, "blob"); // or BYTE
registerColumnType(Types.LONGVARCHAR, "clob"); // or TEXT?
registerColumnType(Types.NUMERIC, "decimal"); // or MONEY
// or BYTE
registerColumnType( Types.LONGVARBINARY, "blob" );
// or TEXT?
registerColumnType( Types.LONGVARCHAR, "clob" );
// or MONEY
registerColumnType( Types.NUMERIC, "decimal" );
registerColumnType( Types.REAL, "smallfloat" );
registerColumnType( Types.SMALLINT, "smallint" );
registerColumnType( Types.TIMESTAMP, "datetime year to fraction(5)" );
@ -74,43 +79,49 @@ public InformixDialect() {
registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "(", "||", ")" ) );
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString(String table, String column, int type)
throws MappingException {
return type==Types.BIGINT ?
"select dbinfo('serial8') from informix.systables where tabid=1" :
"select dbinfo('sqlca.sqlerrd1') from informix.systables where tabid=1";
return type == Types.BIGINT
? "select dbinfo('serial8') from informix.systables where tabid=1"
: "select dbinfo('sqlca.sqlerrd1') from informix.systables where tabid=1";
}
@Override
public String getIdentityColumnString(int type) throws MappingException {
return type == Types.BIGINT ?
"serial8 not null" :
"serial not null";
}
@Override
public boolean hasDataTypeInIdentityColumn() {
return false;
}
/**
* The syntax used to add a foreign key constraint to a table.
* Informix constraint name must be at the end.
* @return String
* <p/>
* {@inheritDoc}
*/
@Override
public String getAddForeignKeyConstraintString(
String constraintName,
String[] foreignKey,
String referencedTable,
String[] primaryKey,
boolean referencesPrimaryKey) {
StringBuilder result = new StringBuilder( 30 )
final StringBuilder result = new StringBuilder( 30 )
.append( " add constraint " )
.append( " foreign key (" )
.append( StringHelper.join( ", ", foreignKey ) )
@ -129,53 +140,66 @@ public String getAddForeignKeyConstraintString(
}
/**
* The syntax used to add a primary key constraint to a table.
* Informix constraint name must be at the end.
* @return String
* <p/>
* {@inheritDoc}
*/
@Override
public String getAddPrimaryKeyConstraintString(String constraintName) {
return " add constraint primary key constraint " + constraintName + " ";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName + " restrict";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName ) + " from informix.systables where tabid=1";
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return sequenceName + ".nextval";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
public String getQuerySequencesString() {
return "select tabname from informix.systables where tabtype='Q'";
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public boolean useMaxForLimit() {
return true;
}
@Override
public boolean supportsLimitOffset() {
return false;
}
@Override
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
@ -186,39 +210,43 @@ public String getLimitString(String querySelect, int offset, int limit) {
.toString();
}
@Override
public boolean supportsVariableLimit() {
return false;
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}
private static ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
/**
* Extract the name of the violated constraint from the given SQLException.
*
* @param sqle The exception that was the result of the constraint violation.
* @return The extracted constraint name.
*/
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
@Override
public String extractConstraintName(SQLException sqle) {
String constraintName = null;
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == -268 ) {
constraintName = extractUsingTemplate( "Unique constraint (", ") violated.", sqle.getMessage() );
}
else if ( errorCode == -691 ) {
constraintName = extractUsingTemplate( "Missing key in referenced table for referential constraint (", ").", sqle.getMessage() );
constraintName = extractUsingTemplate(
"Missing key in referenced table for referential constraint (",
").",
sqle.getMessage()
);
}
else if ( errorCode == -692 ) {
constraintName = extractUsingTemplate( "Key value for constraint (", ") is still being referenced.", sqle.getMessage() );
constraintName = extractUsingTemplate(
"Key value for constraint (",
") is still being referenced.",
sqle.getMessage()
);
}
if ( constraintName != null ) {
// strip table-owner because Informix always returns constraint names as "<table-owner>.<constraint-name>"
int i = constraintName.indexOf('.');
final int i = constraintName.indexOf( '.' );
if ( i != -1 ) {
constraintName = constraintName.substring( i + 1 );
}
@ -229,46 +257,33 @@ else if ( errorCode == -692 ) {
};
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public String getCurrentTimestampSelectString() {
return "select distinct current timestamp from informix.systables";
}
/**
* Overrides {@link Dialect#supportsTemporaryTables()} to return
* {@code true} when invoked.
*
* @return {@code true} when invoked
*/
@Override
public boolean supportsTemporaryTables() {
return true;
}
/**
* Overrides {@link Dialect#getCreateTemporaryTableString()} to
* return "{@code create temp table}" when invoked.
*
* @return "{@code create temp table}" when invoked
*/
@Override
public String getCreateTemporaryTableString() {
return "create temp table";
}
/**
* Overrides {@link Dialect#getCreateTemporaryTablePostfix()} to
* return "{@code with no log}" when invoked.
*
* @return "{@code with no log}" when invoked
*/
@Override
public String getCreateTemporaryTablePostfix() {
return "with no log";
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import java.util.Properties;
@ -39,62 +40,62 @@
* @author Raymond Fan
*/
public class Ingres10Dialect extends Ingres9Dialect {
/**
* Constructs a Ingres10Dialect
*/
public Ingres10Dialect() {
super();
registerBooleanSupport();
}
// Boolean column type support
/**
* The SQL literal value to which this database maps boolean values.
*
* @param bool The boolean value
* @return The appropriate SQL literal.
*/
public String toBooleanValueString(boolean bool) {
return bool ? "true" : "false";
registerDefaultProperties();
}
protected void registerBooleanSupport() {
// Column type
// Boolean type (mapping/BooleanType) mapping maps SQL BIT to Java
// Boolean. In order to create a boolean column, BIT needs to be mapped
// to boolean as well, similar to H2Dialect.
registerColumnType( Types.BIT, "boolean" );
registerColumnType( Types.BOOLEAN, "boolean" );
}
// Functions
private void registerDefaultProperties() {
// true, false and unknown are now valid values
// Remove the query substitutions previously added in IngresDialect.
Properties properties = getDefaultProperties();
String querySubst = properties.getProperty(Environment.QUERY_SUBSTITUTIONS);
final Properties properties = getDefaultProperties();
final String querySubst = properties.getProperty( Environment.QUERY_SUBSTITUTIONS );
if ( querySubst != null ) {
String newQuerySubst = querySubst.replace("true=1,false=0","");
final String newQuerySubst = querySubst.replace( "true=1,false=0", "" );
properties.setProperty( Environment.QUERY_SUBSTITUTIONS, newQuerySubst );
}
}
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public String toBooleanValueString(boolean bool) {
return bool ? "true" : "false";
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public boolean hasDataTypeInIdentityColumn() {
return true;
}
@Override
public String getIdentitySelectString() {
return "select last_identity()";
}
@Override
public String getIdentityColumnString() {
return "not null generated by default as identity";
}
@Override
public String getIdentityInsertString() {
return "default";
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.dialect.function.NoArgSQLFunction;
@ -46,6 +47,9 @@
* @author Raymond Fan
*/
public class Ingres9Dialect extends IngresDialect {
/**
* Constructs a Ingres9Dialect
*/
public Ingres9Dialect() {
super();
registerDateTimeFunctions();
@ -58,7 +62,13 @@ public Ingres9Dialect() {
*/
protected void registerDateTimeFunctions() {
registerFunction( "current_time", new NoArgSQLFunction( "current_time", StandardBasicTypes.TIME, false ) );
registerFunction("current_timestamp", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIMESTAMP, false));
registerFunction(
"current_timestamp", new NoArgSQLFunction(
"current_timestamp",
StandardBasicTypes.TIMESTAMP,
false
)
);
registerFunction( "current_date", new NoArgSQLFunction( "current_date", StandardBasicTypes.DATE, false ) );
}
@ -72,175 +82,97 @@ protected void registerDateTimeColumnTypes() {
// lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Does this dialect support <tt>FOR UPDATE</tt> in conjunction with outer
* joined rows?
*
* @return True if outer joined rows can be locked via <tt>FOR UPDATE</tt>.
*/
@Override
public boolean supportsOuterJoinForUpdate() {
return false;
}
/**
* Is <tt>FOR UPDATE OF</tt> syntax supported?
*
* @return True if the database supports <tt>FOR UPDATE OF</tt> syntax;
* false otherwise.
*/
@Override
public boolean forUpdateOfColumns() {
return true;
}
// SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Get the select command used to retrieve the last generated sequence
* value.
*
* @return Statement to retrieve last generated sequence value
*/
@Override
public String getIdentitySelectString() {
return "select last_identity()";
}
/**
* Get the select command used retrieve the names of all sequences.
*
* @return The select command; or null if sequences are not supported.
* @see org.hibernate.tool.hbm2ddl.SchemaUpdate
*/
@Override
public String getQuerySequencesString() {
return "select seq_name from iisequences";
}
/**
* Does this dialect support "pooled" sequences. Not aware of a better name
* for this. Essentially can we specify the initial and increment values?
*
* @return True if such "pooled" sequences are supported; false otherwise.
* @see #getCreateSequenceStrings(String, int, int)
* @see #getCreateSequenceString(String, int, int)
*/
@Override
public boolean supportsPooledSequences() {
return true;
}
// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Should the value returned by {@link #getCurrentTimestampSelectString} be
* treated as callable. Typically this indicates that JDBC escape sytnax is
* being used...
*
* @return True if the {@link #getCurrentTimestampSelectString} return is
* callable; false otherwise.
*/
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
/**
* Does this dialect support a way to retrieve the database's current
* timestamp value?
*
* @return True if the current timestamp can be retrieved; false otherwise.
*/
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
/**
* Retrieve the command used to retrieve the current timestammp from the
* database.
*
* @return The command.
*/
@Override
public String getCurrentTimestampSelectString() {
return "select current_timestamp";
}
/**
* Expression for current_timestamp
*/
@Override
public String getCurrentTimestampSQLFunctionName() {
return "current_timestamp";
}
// union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Does this dialect support UNION ALL, which is generally a faster variant
* of UNION?
*
* @return True if UNION ALL is supported; false otherwise.
*/
@Override
public boolean supportsUnionAll() {
return true;
}
// Informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* For the underlying database, is READ_COMMITTED isolation implemented by
* forcing readers to wait for write locks to be released?
*
* @return true
*/
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return true;
}
/**
* For the underlying database, is REPEATABLE_READ isolation implemented by
* forcing writers to wait for read locks to be released?
*
* @return true
*/
@Override
public boolean doesRepeatableReadCauseReadersToBlockWriters() {
return true;
}
// limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Does this dialect's LIMIT support (if any) additionally support
* specifying an offset?
*
* @return true
*/
@Override
public boolean supportsLimitOffset() {
return true;
}
/**
* Does this dialect support bind variables (i.e., prepared statememnt
* parameters) for its limit/offset?
*
* @return false
*/
@Override
public boolean supportsVariableLimit() {
return false;
}
/**
* Does the <tt>LIMIT</tt> clause take a "maximum" row number instead
* of a total number of returned rows?
*/
@Override
public boolean useMaxForLimit() {
return false;
}
/**
* Add a <tt>LIMIT</tt> clause to the given SQL <tt>SELECT</tt>
*
* @return the modified SQL
*/
@Override
public String getLimitString(String querySelect, int offset, int limit) {
StringBuilder soff = new StringBuilder(" offset " + offset);
StringBuilder slim = new StringBuilder(" fetch first " + limit + " rows only");
StringBuilder sb = new StringBuilder(querySelect.length() +
soff.length() + slim.length()).append(querySelect);
final StringBuilder soff = new StringBuilder( " offset " + offset );
final StringBuilder slim = new StringBuilder( " fetch first " + limit + " rows only" );
final StringBuilder sb = new StringBuilder( querySelect.length() + soff.length() + slim.length() )
.append( querySelect );
if ( offset > 0 ) {
sb.append( soff );
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.cfg.Environment;
@ -34,12 +35,20 @@
/**
* An SQL dialect for Ingres 9.2.
* <p/>
* Known limitations:
* <ul>
* <li> Only supports simple constants or columns on the left side of an IN, making (1,2,3) in (...) or (&lt;subselect&gt;) in (...) non-supported.
* <li> Supports only 39 digits in decimal.
* <li> Explicitly set USE_GET_GENERATED_KEYS property to false.
* <li> Perform string casts to varchar; removes space padding.
* Known limitations: <ul>
* <li>
* Only supports simple constants or columns on the left side of an IN,
* making {@code (1,2,3) in (...)} or {@code (subselect) in (...)} non-supported.
* </li>
* <li>
* Supports only 39 digits in decimal.
* </li>
* <li>
* Explicitly set USE_GET_GENERATED_KEYS property to false.
* </li>
* <li>
* Perform string casts to varchar; removes space padding.
* </li>
* </ul>
*
* @author Ian Booth
@ -47,8 +56,11 @@
* @author Max Rydahl Andersen
* @author Raymond Fan
*/
@SuppressWarnings("deprecation")
public class IngresDialect extends Dialect {
/**
* Constructs a IngresDialect
*/
public IngresDialect() {
super();
registerColumnType( Types.BIT, "tinyint" );
@ -161,129 +173,73 @@ public IngresDialect() {
// substitions of true and false.
getDefaultProperties().setProperty( Environment.QUERY_SUBSTITUTIONS, "true=1,false=0" );
}
/**
* Expression for created UUID string
*/
@Override
public String getSelectGUIDString() {
return "select uuid_to_char(uuid_create())";
}
/**
* Do we need to drop constraints before dropping tables in this dialect?
*
* @return boolean
*/
@Override
public boolean dropConstraints() {
return false;
}
/**
* Does this dialect support <tt>FOR UPDATE OF</tt>, allowing
* particular rows to be locked?
*
* @return True (Ingres does support "for update of" syntax...)
*/
public boolean supportsForUpdateOf() {
return true;
}
/**
* The syntax used to add a column to a table (optional).
*/
@Override
public String getAddColumnString() {
return "add column";
}
/**
* The keyword used to specify a nullable column.
*
* @return String
*/
@Override
public String getNullColumnString() {
return " with null";
}
/**
* Does this dialect support sequences?
*
* @return boolean
*/
@Override
public boolean supportsSequences() {
return true;
}
/**
* The syntax that fetches the next value of a sequence, if sequences are supported.
*
* @param sequenceName the name of the sequence
*
* @return String
*/
@Override
public String getSequenceNextValString(String sequenceName) {
return "select nextval for " + sequenceName;
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return sequenceName + ".nextval";
}
/**
* The syntax used to create a sequence, if sequences are supported.
*
* @param sequenceName the name of the sequence
*
* @return String
*/
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
/**
* The syntax used to drop a sequence, if sequences are supported.
*
* @param sequenceName the name of the sequence
*
* @return String
*/
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName + " restrict";
}
/**
* A query used to find all sequences
*/
@Override
public String getQuerySequencesString() {
return "select seq_name from iisequence";
}
/**
* The name of the SQL function that transforms a string to
* lowercase
*
* @return String
*/
@Override
public String getLowercaseFunction() {
return "lowercase";
}
/**
* Does this <tt>Dialect</tt> have some kind of <tt>LIMIT</tt> syntax?
*/
@Override
public boolean supportsLimit() {
return true;
}
/**
* Does this dialect support an offset?
*/
@Override
public boolean supportsLimitOffset() {
return false;
}
/**
* Add a <tt>LIMIT</tt> clause to the given SQL <tt>SELECT</tt>
*
* @return the modified SQL
*/
@Override
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
@ -294,64 +250,59 @@ public String getLimitString(String querySelect, int offset, int limit) {
.toString();
}
@Override
public boolean supportsVariableLimit() {
return false;
}
/**
* Does the <tt>LIMIT</tt> clause take a "maximum" row number instead
* of a total number of returned rows?
*/
@Override
public boolean useMaxForLimit() {
return true;
}
/**
* Does this dialect support temporary tables?
*/
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String getCreateTemporaryTableString() {
return "declare global temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return "on commit preserve rows with norecovery";
}
@Override
public String generateTemporaryTableName(String baseTableName) {
return "session." + super.generateTemporaryTableName( baseTableName );
}
/**
* Expression for current_timestamp
*/
@Override
public String getCurrentTimestampSQLFunctionName() {
return "date(now)";
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsSubselectAsInPredicateLHS() {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExpectedLobUsagePattern () {
return false;
}
/**
* Ingres does not support the syntax `count(distinct a,b)`?
*
* @return False, not supported.
*/
@Override
public boolean supportsTupleDistinctCounts() {
return false;
}

View File

@ -34,8 +34,12 @@
*
* @author Gavin King
*/
@SuppressWarnings("deprecation")
public class InterbaseDialect extends Dialect {
/**
* Constructs a InterbaseDialect
*/
public InterbaseDialect() {
super();
registerColumnType( Types.BIT, "smallint" );
@ -61,58 +65,73 @@ public InterbaseDialect() {
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName ) + " from RDB$DATABASE";
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return "gen_id( " + sequenceName + ", 1 )";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create generator " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "delete from RDB$GENERATORS where RDB$GENERATOR_NAME = '" + sequenceName.toUpperCase() + "'";
}
@Override
public String getQuerySequencesString() {
return "select RDB$GENERATOR_NAME from RDB$GENERATORS";
}
@Override
public String getForUpdateString() {
return " with lock";
}
@Override
public String getForUpdateString(String aliases) {
return " for update of " + aliases + " with lock";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
return hasOffset ? sql + " rows ? to ?" : sql + " rows ?";
}
@Override
public boolean bindLimitParametersFirst() {
return false;
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return false;
}
public String getCurrentTimestampCallString() {
@Override
public String getCurrentTimestampSelectString() {
// TODO : not sure which (either?) is correct, could not find docs on how to do this.
// did find various blogs and forums mentioning that select CURRENT_TIMESTAMP
// does not work...
@ -120,6 +139,7 @@ public String getCurrentTimestampCallString() {
// return "select CURRENT_TIMESTAMP from RDB$DATABASE";
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return true;
}

View File

@ -22,17 +22,17 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.cfg.Environment;
/**
* A <tt>Dialect</tt> for JDataStore.
* A Dialect for JDataStore.
*
* @author Vishy Kasar
*/
public class JDataStoreDialect extends Dialect {
/**
* Creates new JDataStoreDialect
*/
@ -60,38 +60,48 @@ public JDataStoreDialect() {
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getCascadeConstraintsString() {
return " cascade";
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString() {
return null; // NOT_SUPPORTED_SHOULD_USE_JDBC3_PreparedStatement.getGeneratedKeys_method
// NOT_SUPPORTED_SHOULD_USE_JDBC3_PreparedStatement.getGeneratedKeys_method
return null;
}
@Override
public String getIdentityColumnString() {
return "autoincrement";
}
@Override
public String getNoColumnsInsertString() {
return "default values";
}
@Override
public boolean supportsColumnCheck() {
return false;
}
@Override
public boolean supportsTableCheck() {
return false;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.LockMode;
@ -47,6 +48,9 @@
* @author Gabe Hicks
*/
public class MckoiDialect extends Dialect {
/**
* Constructs a MckoiDialect
*/
public MckoiDialect() {
super();
registerColumnType( Types.BIT, "bit" );
@ -81,38 +85,47 @@ public MckoiDialect() {
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName );
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return "nextval('" + sequenceName + "')";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getForUpdateString() {
return "";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public CaseFragment createCaseFragment() {
return new MckoiCaseFragment();
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// Mckoi has no known variation of a "SELECT ... FOR UPDATE" syntax...
if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
/**
@ -30,6 +31,7 @@
* @author Steve Ebersole
*/
public class MySQL5Dialect extends MySQLDialect {
@Override
protected void registerVarcharTypes() {
registerColumnType( Types.VARCHAR, "longtext" );
// registerColumnType( Types.VARCHAR, 16777215, "mediumtext" );
@ -37,12 +39,7 @@ protected void registerVarcharTypes() {
registerColumnType( Types.LONGVARCHAR, "longtext" );
}
/**
* Does this dialect support column-level check constraints?
*
* @return True if column-level CHECK constraints are supported; false
* otherwise.
*/
@Override
public boolean supportsColumnCheck() {
return false;
}

View File

@ -23,22 +23,24 @@
*/
package org.hibernate.dialect;
/**
* @author Gavin King, Scott Marlow
/** A Dialect for MySQL 5 using InnoDB engine
*
* @author Gavin King,
* @author Scott Marlow
*/
public class MySQL5InnoDBDialect extends MySQL5Dialect {
@Override
public boolean supportsCascadeDelete() {
return true;
}
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB";
}
@Override
public boolean hasSelfReferentialForeignKeyBug() {
return true;
}
}

View File

@ -45,8 +45,12 @@
*
* @author Gavin King
*/
@SuppressWarnings("deprecation")
public class MySQLDialect extends Dialect {
/**
* Constructs a MySQLDialect
*/
public MySQLDialect() {
super();
registerColumnType( Types.BIT, "bit" );
@ -191,108 +195,125 @@ protected void registerVarcharTypes() {
registerColumnType( Types.LONGVARCHAR, "longtext" );
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public boolean qualifyIndexName() {
return false;
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString() {
return "select last_insert_id()";
}
@Override
public String getIdentityColumnString() {
return "not null auto_increment"; //starts with 1, implicitly
//starts with 1, implicitly
return "not null auto_increment";
}
@Override
public String getAddForeignKeyConstraintString(
String constraintName,
String[] foreignKey,
String referencedTable,
String[] primaryKey, boolean referencesPrimaryKey
) {
String cols = StringHelper.join(", ", foreignKey);
return new StringBuilder(30)
.append(" add index ")
.append(constraintName)
.append(" (")
.append(cols)
.append("), add constraint ")
.append(constraintName)
.append(" foreign key (")
.append(cols)
.append(") references ")
.append(referencedTable)
.append(" (")
.append( StringHelper.join(", ", primaryKey) )
.append(')')
.toString();
String[] primaryKey,
boolean referencesPrimaryKey) {
final String cols = StringHelper.join( ", ", foreignKey );
final String referencedCols = StringHelper.join( ", ", primaryKey );
return String.format(
" add index %s (%s), add constraint %s foreign key (%s) references %s (%s)",
constraintName,
cols,
constraintName,
cols,
referencedTable,
referencedCols
);
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getDropForeignKeyString() {
return " drop foreign key ";
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
return sql + (hasOffset ? " limit ?, ?" : " limit ?");
}
@Override
public char closeQuote() {
return '`';
}
@Override
public char openQuote() {
return '`';
}
@Override
public boolean supportsIfExistsBeforeTableName() {
return true;
}
@Override
public String getSelectGUIDString() {
return "select uuid()";
}
@Override
public boolean supportsCascadeDelete() {
return false;
}
@Override
public String getTableComment(String comment) {
return " comment='" + comment + "'";
}
@Override
public String getColumnComment(String comment) {
return " comment '" + comment + "'";
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String getCreateTemporaryTableString() {
return "create temporary table if not exists";
}
@Override
public String getDropTemporaryTableString() {
return "drop temporary table";
}
@Override
public Boolean performTemporaryTableDDLInIsolation() {
// because we [drop *temporary* table...] we do not
// have to doAfterTransactionCompletion these in isolation.
return Boolean.FALSE;
}
@Override
public String getCastTypeName(int code) {
switch ( code ) {
case Types.INTEGER:
@ -306,22 +327,27 @@ public String getCastTypeName(int code) {
}
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public String getCurrentTimestampSelectString() {
return "select now()";
}
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
boolean isResultSet = ps.execute();
while ( !isResultSet && ps.getUpdateCount() != -1 ) {
@ -330,6 +356,7 @@ public ResultSet getResultSet(CallableStatement ps) throws SQLException {
return ps.getResultSet();
}
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}
@ -355,14 +382,17 @@ public String renderOrderByElement(String expression, String collation, String o
// locking support
@Override
public String getForUpdateString() {
return " for update";
}
@Override
public String getWriteLockString(int timeout) {
return " for update";
}
@Override
public String getReadLockString(int timeout) {
return " lock in share mode";
}
@ -370,19 +400,23 @@ public String getReadLockString(int timeout) {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean areStringComparisonsCaseInsensitive() {
return true;
}
@Override
public boolean supportsLobValueChangePropogation() {
// note: at least my local MySQL 5.1 install shows this not working...
return false;
}
@Override
public boolean supportsSubqueryOnMutatingTable() {
return false;
}

View File

@ -23,22 +23,24 @@
*/
package org.hibernate.dialect;
/**
* A Dialect for MySQL using InnoDB engine
*
* @author Gavin King
*/
public class MySQLInnoDBDialect extends MySQLDialect {
@Override
public boolean supportsCascadeDelete() {
return true;
}
@Override
public String getTableTypeString() {
return " type=InnoDB";
}
@Override
public boolean hasSelfReferentialForeignKeyBug() {
return true;
}
}

View File

@ -23,18 +23,19 @@
*/
package org.hibernate.dialect;
/**
* A Dialect for MySQL using the MyISAM engine
*
* @author Gavin King
*/
public class MySQLMyISAMDialect extends MySQLDialect {
@Override
public String getTableTypeString() {
return " type=MyISAM";
}
@Override
public boolean dropConstraints() {
return false;
}
}

View File

@ -22,31 +22,33 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import org.hibernate.LockOptions;
import org.hibernate.sql.ANSIJoinFragment;
import org.hibernate.sql.JoinFragment;
/**
* A dialect specifically for use with Oracle 10g.
* <p/>
* The main difference between this dialect and {@link Oracle9iDialect}
* is the use of "ANSI join syntax". This dialect also retires the use
* of the <tt>oracle.jdbc.driver</tt> package in favor of
* <tt>oracle.jdbc</tt>.
* is the use of "ANSI join syntax".
*
* @author Steve Ebersole
*/
public class Oracle10gDialect extends Oracle9iDialect {
/**
* Constructs a Oracle10gDialect
*/
public Oracle10gDialect() {
super();
}
@Override
public JoinFragment createOuterJoinFragment() {
return new ANSIJoinFragment();
}
@Override
public String getWriteLockString(int timeout) {
if ( timeout == LockOptions.SKIP_LOCKED ) {
return getForUpdateSkipLockedString();
@ -56,10 +58,12 @@ public String getWriteLockString(int timeout) {
}
}
@Override
public String getForUpdateSkipLockedString() {
return " for update skip locked";
}
@Override
public String getForUpdateSkipLockedString(String aliases) {
return getForUpdateString() + " of " + aliases + " skip locked";
}

View File

@ -58,10 +58,13 @@
*
* @author Steve Ebersole
*/
@SuppressWarnings("deprecation")
public class Oracle8iDialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
/**
* Constructs a Oracle8iDialect
*/
public Oracle8iDialect() {
super();
registerCharacterTypeMappings();
@ -217,19 +220,11 @@ protected SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Support for the oracle proprietary join syntax...
*
* @return The orqacle join fragment
*/
@Override
public JoinFragment createOuterJoinFragment() {
return new OracleJoinFragment();
}
/**
* {@inheritDoc}
*/
@Override
public String getCrossJoinSeparator() {
return ", ";
@ -238,13 +233,14 @@ public String getCrossJoinSeparator() {
/**
* Map case support to the Oracle DECODE function. Oracle did not
* add support for CASE until 9i.
*
* @return The oracle CASE -> DECODE fragment
* <p/>
* {@inheritDoc}
*/
@Override
public CaseFragment createCaseFragment() {
return new DecodeCaseFragment();
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
@ -254,7 +250,7 @@ public String getLimitString(String sql, boolean hasOffset) {
isForUpdate = true;
}
StringBuilder pagingSelect = new StringBuilder( sql.length()+100 );
final StringBuilder pagingSelect = new StringBuilder( sql.length()+100 );
if (hasOffset) {
pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " );
}
@ -286,6 +282,7 @@ public String getLimitString(String sql, boolean hasOffset) {
public String getBasicSelectClauseNullString(int sqlType) {
return super.getSelectClauseNullString( sqlType );
}
@Override
public String getSelectClauseNullString(int sqlType) {
switch(sqlType) {
@ -300,10 +297,12 @@ public String getSelectClauseNullString(int sqlType) {
return "to_number(null)";
}
}
@Override
public String getCurrentTimestampSelectString() {
return "select sysdate from dual";
}
@Override
public String getCurrentTimestampSQLFunctionName() {
return "sysdate";
@ -311,70 +310,88 @@ public String getCurrentTimestampSQLFunctionName() {
// features which remain constant across 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName ) + " from dual";
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return sequenceName + ".nextval";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName; //starts with 1, implicitly
//starts with 1, implicitly
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getCascadeConstraintsString() {
return " cascade constraints";
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getForUpdateNowaitString() {
return " for update nowait";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getForUpdateString(String aliases) {
return getForUpdateString() + " of " + aliases;
}
@Override
public String getForUpdateNowaitString(String aliases) {
return getForUpdateString() + " of " + aliases + " nowait";
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return true;
}
@Override
public boolean useMaxForLimit() {
return true;
}
@Override
public boolean forUpdateOfColumns() {
return true;
}
@Override
public String getQuerySequencesString() {
return " select sequence_name from all_sequences"
@ -384,16 +401,18 @@ public String getQuerySequencesString() {
+ " where asq.sequence_name = us.table_name"
+ " and asq.sequence_owner = us.table_owner";
}
@Override
public String getSelectGUIDString() {
return "select rawtohex(sys_guid()) from dual";
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}
private static ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
/**
* Extract the name of the violated constraint from the given SQLException.
@ -402,7 +421,7 @@ public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
* @return The extracted constraint name.
*/
public String extractConstraintName(SQLException sqle) {
int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == 1 || errorCode == 2291 || errorCode == 2292 ) {
return extractUsingTemplate( "(", ")", sqle.getMessage() );
}
@ -476,88 +495,61 @@ else if ( 4020 == errorCode ) {
};
}
public static final String ORACLE_TYPES_CLASS_NAME = "oracle.jdbc.OracleTypes";
public static final String DEPRECATED_ORACLE_TYPES_CLASS_NAME = "oracle.jdbc.driver.OracleTypes";
public static final int INIT_ORACLETYPES_CURSOR_VALUE = -99;
// not final-static to avoid possible classcast exceptions if using different oracle drivers.
private int oracleCursorTypeSqlType = INIT_ORACLETYPES_CURSOR_VALUE;
public int getOracleCursorTypeSqlType() {
if ( oracleCursorTypeSqlType == INIT_ORACLETYPES_CURSOR_VALUE ) {
// todo : is there really any reason to kkeep trying if this fails once?
oracleCursorTypeSqlType = extractOracleCursorTypeValue();
}
return oracleCursorTypeSqlType;
}
protected int extractOracleCursorTypeValue() {
Class oracleTypesClass;
try {
oracleTypesClass = ReflectHelper.classForName( ORACLE_TYPES_CLASS_NAME );
}
catch ( ClassNotFoundException cnfe ) {
try {
oracleTypesClass = ReflectHelper.classForName( DEPRECATED_ORACLE_TYPES_CLASS_NAME );
}
catch ( ClassNotFoundException e ) {
throw new HibernateException( "Unable to locate OracleTypes class", e );
}
}
try {
return oracleTypesClass.getField( "CURSOR" ).getInt( null );
}
catch ( Exception se ) {
throw new HibernateException( "Unable to access OracleTypes.CURSOR value", se );
}
}
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
// register the type of the out param - an Oracle specific type
statement.registerOutParameter( col, getOracleCursorTypeSqlType() );
statement.registerOutParameter( col, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() );
col++;
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
ps.execute();
return (ResultSet) ps.getObject( 1 );
}
@Override
public boolean supportsUnionAll() {
return true;
}
@Override
public boolean supportsCommentOn() {
return true;
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String generateTemporaryTableName(String baseTableName) {
String name = super.generateTemporaryTableName(baseTableName);
final String name = super.generateTemporaryTableName( baseTableName );
return name.length() > 30 ? name.substring( 1, 30 ) : name;
}
@Override
public String getCreateTemporaryTableString() {
return "create global temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return "on commit delete rows";
}
@Override
public boolean dropTemporaryTableAfterUse() {
return false;
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
@ -573,9 +565,6 @@ public boolean supportsExistsInSelect() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getInExpressionCountLimit()
*/
@Override
public int getInExpressionCountLimit() {
return PARAM_LIST_SIZE_LIMIT;

View File

@ -30,7 +30,6 @@
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.NoArgSQLFunction;
import org.hibernate.dialect.function.NvlFunction;
@ -41,22 +40,30 @@
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.type.StandardBasicTypes;
/**
* An SQL dialect for Oracle 9 (uses ANSI-style syntax where possible).
*
* @author Gavin King
* @author David Channon
*
* @deprecated Use either Oracle9iDialect or Oracle10gDialect instead
* @author Gavin King, David Channon
*/
@SuppressWarnings("deprecation")
@Deprecated
public class Oracle9Dialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Oracle9Dialect.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
Oracle9Dialect.class.getName()
);
/**
* Constructs a Oracle9Dialect
*/
public Oracle9Dialect() {
super();
LOG.deprecatedOracle9Dialect();
@ -125,7 +132,13 @@ public Oracle9Dialect() {
registerFunction( "current_date", new NoArgSQLFunction( "current_date", StandardBasicTypes.DATE, false ) );
registerFunction( "current_time", new NoArgSQLFunction( "current_timestamp", StandardBasicTypes.TIME, false ) );
registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIMESTAMP, false) );
registerFunction(
"current_timestamp", new NoArgSQLFunction(
"current_timestamp",
StandardBasicTypes.TIMESTAMP,
false
)
);
registerFunction( "last_day", new StandardSQLFunction( "last_day", StandardBasicTypes.DATE ) );
registerFunction( "sysdate", new NoArgSQLFunction( "sysdate", StandardBasicTypes.DATE, false ) );
@ -168,50 +181,63 @@ public Oracle9Dialect() {
registerFunction( "str", new StandardSQLFunction( "to_char", StandardBasicTypes.STRING ) );
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName ) + " from dual";
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return sequenceName + ".nextval";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName; //starts with 1, implicitly
//starts with 1, implicitly
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getCascadeConstraintsString() {
return " cascade constraints";
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getForUpdateNowaitString() {
return " for update nowait";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsPooledSequences() {
return true;
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
@ -221,7 +247,7 @@ public String getLimitString(String sql, boolean hasOffset) {
isForUpdate = true;
}
StringBuilder pagingSelect = new StringBuilder( sql.length()+100 );
final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
if ( hasOffset ) {
pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " );
}
@ -243,48 +269,50 @@ public String getLimitString(String sql, boolean hasOffset) {
return pagingSelect.toString();
}
@Override
public String getForUpdateString(String aliases) {
return getForUpdateString() + " of " + aliases;
}
@Override
public String getForUpdateNowaitString(String aliases) {
return getForUpdateString() + " of " + aliases + " nowait";
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return true;
}
@Override
public boolean useMaxForLimit() {
return true;
}
@Override
public boolean forUpdateOfColumns() {
return true;
}
@Override
public String getQuerySequencesString() {
return "select sequence_name from user_sequences";
}
@Override
public String getSelectGUIDString() {
return "select rawtohex(sys_guid()) from dual";
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}
private static ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
/**
* Extract the name of the violated constraint from the given SQLException.
*
* @param sqle The exception that was the result of the constraint violation.
* @return The extracted constraint name.
*/
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
@Override
public String extractConstraintName(SQLException sqle) {
int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == 1 || errorCode == 2291 || errorCode == 2292 ) {
return extractUsingTemplate( "constraint (", ") violated", sqle.getMessage() );
}
@ -296,83 +324,83 @@ else if ( errorCode == 1400 ) {
return null;
}
}
};
// not final-static to avoid possible classcast exceptions if using different oracle drivers.
int oracletypes_cursor_value = 0;
@Override
public int registerResultSetOutParameter(java.sql.CallableStatement statement, int col) throws SQLException {
if(oracletypes_cursor_value==0) {
try {
Class types = ReflectHelper.classForName("oracle.jdbc.driver.OracleTypes");
oracletypes_cursor_value = types.getField("CURSOR").getInt(types.newInstance());
} catch (Exception se) {
throw new HibernateException("Problem while trying to load or access OracleTypes.CURSOR value",se);
}
}
// register the type of the out param - an Oracle specific type
statement.registerOutParameter(col, oracletypes_cursor_value);
statement.registerOutParameter( col, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() );
col++;
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
ps.execute();
return (ResultSet) ps.getObject( 1 );
}
@Override
public boolean supportsUnionAll() {
return true;
}
@Override
public boolean supportsCommentOn() {
return true;
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String generateTemporaryTableName(String baseTableName) {
String name = super.generateTemporaryTableName(baseTableName);
final String name = super.generateTemporaryTableName( baseTableName );
return name.length() > 30 ? name.substring( 1, 30 ) : name;
}
@Override
public String getCreateTemporaryTableString() {
return "create global temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return "on commit delete rows";
}
@Override
public boolean dropTemporaryTableAfterUse() {
return false;
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public String getCurrentTimestampSelectString() {
return "select systimestamp from dual";
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getInExpressionCountLimit()
*/
@Override
public int getInExpressionCountLimit() {
return PARAM_LIST_SIZE_LIMIT;

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.LockOptions;
@ -42,17 +43,20 @@ protected void registerCharacterTypeMappings() {
registerColumnType( Types.VARCHAR, 4000, "varchar2($l char)" );
registerColumnType( Types.VARCHAR, "long" );
}
@Override
protected void registerDateTimeTypeMappings() {
registerColumnType( Types.DATE, "date" );
registerColumnType( Types.TIME, "date" );
registerColumnType( Types.TIMESTAMP, "timestamp" );
}
@Override
public CaseFragment createCaseFragment() {
// Oracle did add support for ANSI CASE statements in 9i
return new ANSICaseFragment();
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
@ -66,7 +70,7 @@ public String getLimitString(String sql, boolean hasOffset) {
isForUpdate = true;
}
StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
if (hasOffset) {
pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " );
}
@ -88,25 +92,28 @@ public String getLimitString(String sql, boolean hasOffset) {
return pagingSelect.toString();
}
@Override
public String getSelectClauseNullString(int sqlType) {
return getBasicSelectClauseNullString( sqlType );
}
@Override
public String getCurrentTimestampSelectString() {
return "select systimestamp from dual";
}
@Override
public String getCurrentTimestampSQLFunctionName() {
// the standard SQL function name is current_timestamp...
return "current_timestamp";
}
// locking support
@Override
public String getForUpdateString() {
return " for update";
}
@Override
public String getWriteLockString(int timeout) {
if ( timeout == LockOptions.NO_WAIT ) {
@ -114,25 +121,31 @@ public String getWriteLockString(int timeout) {
}
else if ( timeout > 0 ) {
// convert from milliseconds to seconds
float seconds = timeout / 1000.0f;
final float seconds = timeout / 1000.0f;
timeout = Math.round(seconds);
return " for update wait " + timeout;
}
else
else {
return " for update";
}
}
@Override
public String getReadLockString(int timeout) {
return getWriteLockString( timeout );
}
/**
* HHH-4907, I don't know if oracle 8 supports this syntax, so I'd think it is better add this
* method here. Reopen this issue if you found/know 8 supports it.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return true;
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;

View File

@ -38,11 +38,17 @@
* @deprecated Use Oracle8iDialect instead.
* @author Gavin King
*/
@SuppressWarnings("deprecation")
@Deprecated
public class OracleDialect extends Oracle9Dialect {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
OracleDialect.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, OracleDialect.class.getName());
/**
* Constructs a (DEPRECATED) Oracle9Dialect
*/
public OracleDialect() {
super();
LOG.deprecatedOracleDialect();
@ -57,6 +63,7 @@ public OracleDialect() {
public JoinFragment createOuterJoinFragment() {
return new OracleJoinFragment();
}
@Override
public CaseFragment createCaseFragment() {
return new DecodeCaseFragment();
@ -72,7 +79,7 @@ public String getLimitString(String sql, boolean hasOffset) {
isForUpdate = true;
}
StringBuilder pagingSelect = new StringBuilder( sql.length()+100 );
final StringBuilder pagingSelect = new StringBuilder( sql.length()+100 );
if (hasOffset) {
pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " );
}

View File

@ -0,0 +1,128 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
/**
* A Helper for dealing with the OracleTypes class
*
* @author Steve Ebersole
*/
public class OracleTypesHelper {
private static final CoreMessageLogger log = Logger.getMessageLogger( CoreMessageLogger.class, OracleTypesHelper.class.getName() );
/**
* Singleton access
*/
public static final OracleTypesHelper INSTANCE = new OracleTypesHelper();
private static final String ORACLE_TYPES_CLASS_NAME = "oracle.jdbc.OracleTypes";
private static final String DEPRECATED_ORACLE_TYPES_CLASS_NAME = "oracle.jdbc.driver.OracleTypes";
private final int oracleCursorTypeSqlType;
private OracleTypesHelper() {
int typeCode = -99;
try {
typeCode = extractOracleCursorTypeValue();
}
catch (Exception e) {
log.warn( "Unable to resolve Oracle CURSOR JDBC type code", e );
}
oracleCursorTypeSqlType = typeCode;
}
private int extractOracleCursorTypeValue() {
try {
return locateOracleTypesClass().getField( "CURSOR" ).getInt( null );
}
catch ( Exception se ) {
throw new HibernateException( "Unable to access OracleTypes.CURSOR value", se );
}
}
private Class locateOracleTypesClass() {
try {
return ReflectHelper.classForName( ORACLE_TYPES_CLASS_NAME );
}
catch (ClassNotFoundException e) {
try {
return ReflectHelper.classForName( DEPRECATED_ORACLE_TYPES_CLASS_NAME );
}
catch (ClassNotFoundException e2) {
throw new HibernateException(
String.format(
"Unable to locate OracleTypes class using either known FQN [%s, %s]",
ORACLE_TYPES_CLASS_NAME,
DEPRECATED_ORACLE_TYPES_CLASS_NAME
),
e
);
}
}
}
public int getOracleCursorTypeSqlType() {
return oracleCursorTypeSqlType;
}
// initial code as copied from Oracle8iDialect
//
// private int oracleCursorTypeSqlType = INIT_ORACLETYPES_CURSOR_VALUE;
//
// public int getOracleCursorTypeSqlType() {
// if ( oracleCursorTypeSqlType == INIT_ORACLETYPES_CURSOR_VALUE ) {
// // todo : is there really any reason to keep trying if this fails once?
// oracleCursorTypeSqlType = extractOracleCursorTypeValue();
// }
// return oracleCursorTypeSqlType;
// }
//
// private int extractOracleCursorTypeValue() {
// Class oracleTypesClass;
// try {
// oracleTypesClass = ReflectHelper.classForName( ORACLE_TYPES_CLASS_NAME );
// }
// catch ( ClassNotFoundException cnfe ) {
// try {
// oracleTypesClass = ReflectHelper.classForName( DEPRECATED_ORACLE_TYPES_CLASS_NAME );
// }
// catch ( ClassNotFoundException e ) {
// throw new HibernateException( "Unable to locate OracleTypes class", e );
// }
// }
//
// try {
// return oracleTypesClass.getField( "CURSOR" ).getInt( null );
// }
// catch ( Exception se ) {
// throw new HibernateException( "Unable to access OracleTypes.CURSOR value", se );
// }
// }
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.LockMode;
@ -36,20 +37,22 @@
import org.hibernate.persister.entity.Lockable;
/**
* A <tt>Dialect</tt> for Pointbase.
* A Dialect for Pointbase.
*
* @author Ed Mackenzie
*/
public class PointbaseDialect extends org.hibernate.dialect.Dialect {
/**
* Creates new PointbaseDialect
*/
public PointbaseDialect() {
super();
registerColumnType( Types.BIT, "smallint" ); //no pointbase BIT
//no pointbase BIT
registerColumnType( Types.BIT, "smallint" );
registerColumnType( Types.BIGINT, "bigint" );
registerColumnType( Types.SMALLINT, "smallint" );
registerColumnType( Types.TINYINT, "smallint" ); //no pointbase TINYINT
//no pointbase TINYINT
registerColumnType( Types.TINYINT, "smallint" );
registerColumnType( Types.INTEGER, "integer" );
registerColumnType( Types.CHAR, "char(1)" );
registerColumnType( Types.VARCHAR, "varchar($l)" );
@ -66,22 +69,27 @@ public PointbaseDialect() {
registerColumnType( Types.NUMERIC, "numeric($p,$s)" );
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getCascadeConstraintsString() {
return " cascade";
}
@Override
public String getForUpdateString() {
return "";
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// Pointbase has no known variation of a "SELECT ... FOR UPDATE" syntax...
if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {

View File

@ -57,8 +57,12 @@
*
* @author Gavin King
*/
@SuppressWarnings("deprecation")
public class PostgreSQL81Dialect extends Dialect {
/**
* Constructs a PostgreSQL81Dialect
*/
public PostgreSQL81Dialect() {
super();
registerColumnType( Types.BIT, "bool" );
@ -156,9 +160,6 @@ public PostgreSQL81Dialect() {
getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
}
/**
* {@inheritDoc}
*/
@Override
public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
SqlTypeDescriptor descriptor;
@ -183,87 +184,100 @@ public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
return descriptor;
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName );
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return "nextval ('" + sequenceName + "')";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName; //starts with 1, implicitly
//starts with 1, implicitly
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getCascadeConstraintsString() {
return " cascade";
}
@Override
public boolean dropConstraints() {
return true;
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public String getQuerySequencesString() {
return "select relname from pg_class where relkind='S'";
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getLimitString(String sql, boolean hasOffset) {
return new StringBuilder( sql.length()+20 )
.append( sql )
.append( hasOffset ? " limit ? offset ?" : " limit ?" )
.toString();
return sql + (hasOffset ? " limit ? offset ?" : " limit ?");
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return true;
}
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getForUpdateString(String aliases) {
return getForUpdateString() + " of " + aliases;
}
@Override
public String getIdentitySelectString(String table, String column, int type) {
return new StringBuilder().append("select currval('")
.append(table)
.append('_')
.append(column)
.append("_seq')")
.toString();
return "select currval('" + table + '_' + column + "_seq')";
}
@Override
public String getIdentityColumnString(int type) {
return type==Types.BIGINT ?
"bigserial not null" :
"serial not null";
}
@Override
public boolean hasDataTypeInIdentityColumn() {
return false;
}
@Override
public String getNoColumnsInsertString() {
return "default values";
}
@Override
public String getCaseInsensitiveLike(){
return "ilike";
}
@ -273,77 +287,88 @@ public boolean supportsCaseInsensitiveLike() {
return true;
}
@Override
public Class getNativeIdentifierGeneratorClass() {
return SequenceGenerator.class;
}
@Override
public boolean supportsOuterJoinForUpdate() {
return false;
}
@Override
public boolean useInputStreamToInsertBlob() {
return false;
}
@Override
public boolean supportsUnionAll() {
return true;
}
/**
* Workaround for postgres bug #1453
* <p/>
* {@inheritDoc}
*/
@Override
public String getSelectClauseNullString(int sqlType) {
String typeName = getTypeName( sqlType, 1, 1, 0 );
//trim off the length/precision/scale
int loc = typeName.indexOf('(');
final int loc = typeName.indexOf( '(' );
if ( loc > -1 ) {
typeName = typeName.substring( 0, loc );
}
return "null::" + typeName;
}
@Override
public boolean supportsCommentOn() {
return true;
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String getCreateTemporaryTableString() {
return "create temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return "on commit drop";
}
/*public boolean dropTemporaryTableAfterUse() {
//we have to, because postgres sets current tx
//to rollback only after a failed create table
return true;
}*/
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public String getCurrentTimestampSelectString() {
return "select now()";
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;
}
@Override
public String toBooleanValueString(boolean bool) {
return bool ? "true" : "false";
}
@Override
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}
@ -352,10 +377,10 @@ public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
* Constraint-name extractor for Postgres constraint violation exceptions.
* Orginally contributed by Denny Bartelt.
*/
private static ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
public String extractConstraintName(SQLException sqle) {
try {
int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) );
final int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) );
switch (sqlState) {
// CHECK VIOLATION
case 23514: return extractUsingTemplate( "violates check constraint \"","\"", sqle.getMessage() );
@ -370,7 +395,8 @@ public String extractConstraintName(SQLException sqle) {
// ALL OTHER
default: return null;
}
} catch (NumberFormatException nfe) {
}
catch (NumberFormatException nfe) {
return null;
}
}
@ -383,11 +409,13 @@ public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
public JDBCException convert(SQLException sqlException, String message, String sql) {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
if ( "40P01".equals( sqlState ) ) { // DEADLOCK DETECTED
if ( "40P01".equals( sqlState ) ) {
// DEADLOCK DETECTED
return new LockAcquisitionException( message, sqlException, sql );
}
if ( "55P03".equals( sqlState ) ) { // LOCK NOT AVAILABLE
if ( "55P03".equals( sqlState ) ) {
// LOCK NOT AVAILABLE
return new PessimisticLockException( message, sqlException, sql );
}
@ -397,35 +425,37 @@ public JDBCException convert(SQLException sqlException, String message, String s
};
}
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
// Register the type of the out param - PostgreSQL uses Types.OTHER
statement.registerOutParameter( col++, Types.OTHER );
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
ps.execute();
return (ResultSet) ps.getObject( 1 );
}
@Override
public boolean supportsPooledSequences() {
return true;
}
//only necessary for postgre < 7.4
//http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/doc/src/sgml/ref/create_sequence.sgml
/**
* only necessary for postgre < 7.4 See http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/doc/src/sgml/ref/create_sequence.sgml
* <p/>
* {@inheritDoc}
*/
@Override
protected String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize) {
return getCreateSequenceString( sequenceName ) + " start " + initialValue + " increment " + incrementSize;
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// seems to not really...
// public boolean supportsRowValueConstructorSyntax() {
// return true;
// }
@Override
public boolean supportsEmptyInList() {
return false;
}
@ -445,25 +475,32 @@ public boolean supportsUnboundedLobLocatorMaterialization() {
return false;
}
// locking support
@Override
public String getForUpdateString() {
return " for update";
}
@Override
public String getWriteLockString(int timeout) {
if ( timeout == LockOptions.NO_WAIT )
if ( timeout == LockOptions.NO_WAIT ) {
return " for update nowait";
else
}
else {
return " for update";
}
public String getReadLockString(int timeout) {
if ( timeout == LockOptions.NO_WAIT )
return " for share nowait";
else
return " for share";
}
@Override
public String getReadLockString(int timeout) {
if ( timeout == LockOptions.NO_WAIT ) {
return " for share nowait";
}
else {
return " for share";
}
}
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.dialect;
/**
* An SQL dialect for Postgres
* <p/>
@ -32,6 +31,7 @@
* For the effects in regards to Hibernate see <a href="http://in.relation.to/15492.lace">http://in.relation.to/15492.lace</a>
*
* @author Gavin King
*
* @deprecated use {@link PostgreSQL82Dialect} instead
*/
@Deprecated

View File

@ -37,8 +37,11 @@
*
* @author Jim Mlodgenski
*/
@SuppressWarnings("deprecation")
public class PostgresPlusDialect extends PostgreSQLDialect {
/**
* Constructs a PostgresPlusDialect
*/
public PostgresPlusDialect() {
super();
@ -65,25 +68,30 @@ public PostgresPlusDialect() {
registerFunction( "next_day", new StandardSQLFunction( "next_day", StandardBasicTypes.DATE ) );
}
@Override
public String getCurrentTimestampSelectString() {
return "select sysdate";
}
@Override
public String getCurrentTimestampSQLFunctionName() {
return "sysdate";
}
@Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
statement.registerOutParameter( col, Types.REF );
col++;
return col;
}
@Override
public ResultSet getResultSet(CallableStatement ps) throws SQLException {
ps.execute();
return (ResultSet) ps.getObject( 1 );
}
@Override
public String getSelectGUIDString() {
return "select uuid_generate_v1";
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
/**
@ -41,6 +42,9 @@
*
*/
public class ProgressDialect extends Dialect {
/**
* Constructs a ProgressDialect
*/
public ProgressDialect() {
super();
registerColumnType( Types.BIT, "bit" );
@ -59,14 +63,17 @@ public ProgressDialect() {
registerColumnType( Types.NUMERIC, "numeric($p,$s)" );
}
@Override
public boolean hasAlterTable(){
return false;
}
@Override
public String getAddColumnString() {
return "add column";
}
@Override
public boolean qualifyIndexName() {
return false;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.jboss.logging.Logger;
@ -48,7 +49,7 @@
* This is the Hibernate dialect for the Unisys 2200 Relational Database (RDMS).
* This dialect was developed for use with Hibernate 3.0.5. Other versions may
* require modifications to the dialect.
*
* <p/>
* Version History:
* Also change the version displayed below in the constructor
* 1.1
@ -56,10 +57,16 @@
*
* @author Ploski and Hanson
*/
@SuppressWarnings("deprecation")
public class RDMSOS2200Dialect extends Dialect {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
RDMSOS2200Dialect.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, RDMSOS2200Dialect.class.getName());
/**
* Constructs a RDMSOS2200Dialect
*/
public RDMSOS2200Dialect() {
super();
// Display the dialect version.
@ -215,7 +222,10 @@ public RDMSOS2200Dialect() {
/**
* RDMS does not support qualifing index names with the schema name.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean qualifyIndexName() {
return false;
}
@ -225,7 +235,10 @@ public boolean qualifyIndexName() {
* driver does not support this feature, so a false is return.
* The base dialect also returns a false, but we will leave this over-ride
* in to make sure it stays false.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean forUpdateOfColumns() {
return false;
}
@ -235,102 +248,116 @@ public boolean forUpdateOfColumns() {
* set to an empty string. Whenever, the driver does support this feature,
* the returned string should be " FOR UPDATE OF". Note that RDMS does not
* support the string 'FOR UPDATE' string.
* <p/>
* {@inheritDoc}
*/
@Override
public String getForUpdateString() {
return ""; // Original Dialect.java returns " for update";
// Original Dialect.java returns " for update";
return "";
}
// Verify the state of this new method in Hibernate 3.0 Dialect.java
/**
* RDMS does not support Cascade Deletes.
* Need to review this in the future when support is provided.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean supportsCascadeDelete() {
return false; // Origial Dialect.java returns true;
return false;
}
/**
* Currently, RDMS-JDBC does not support ForUpdate.
* Need to review this in the future when support is provided.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean supportsOuterJoinForUpdate() {
return false;
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getNullColumnString() {
// The keyword used to specify a nullable column.
return " null";
}
// *** Sequence methods - start. The RDMS dialect needs these
// methods to make it possible to use the Native Id generator
@Override
public boolean supportsSequences() {
return true;
}
@Override
public String getSequenceNextValString(String sequenceName) {
// The where clause was added to eliminate this statement from Brute Force Searches.
return "select permuted_id('NEXT',31) from rdms.rdms_dummy where key_col = 1 ";
}
@Override
public String getCreateSequenceString(String sequenceName) {
// We must return a valid RDMS/RSA command from this method to
// prevent RDMS/RSA from issuing *ERROR 400
return "";
}
@Override
public String getDropSequenceString(String sequenceName) {
// We must return a valid RDMS/RSA command from this method to
// prevent RDMS/RSA from issuing *ERROR 400
return "";
}
// *** Sequence methods - end
@Override
public String getCascadeConstraintsString() {
// Used with DROP TABLE to delete all records in the table.
return " including contents";
}
@Override
public CaseFragment createCaseFragment() {
return new DecodeCaseFragment();
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public boolean supportsLimitOffset() {
return false;
}
@Override
public String getLimitString(String sql, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
}
return new StringBuilder( sql.length() + 40 )
.append( sql )
.append( " fetch first " )
.append( limit )
.append( " rows only " )
.toString();
return sql + " fetch first " + limit + " rows only ";
}
@Override
public boolean supportsVariableLimit() {
return false;
}
@Override
public boolean supportsUnionAll() {
// RDMS supports the UNION ALL clause.
return true;
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// RDMS has no known variation of a "SELECT ... FOR UPDATE" syntax...
if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT ) {

View File

@ -22,10 +22,6 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Defines how we need to reference columns in the group-by, having, and order-by
@ -33,18 +29,14 @@
*
* @author Steve Ebersole
*/
public class ResultColumnReferenceStrategy implements Serializable {
private static final Map INSTANCES = new HashMap();
public enum ResultColumnReferenceStrategy {
/**
* This strategy says to reference the result columns by the qualified column name
* found in the result source. This strategy is not strictly allowed by ANSI SQL
* but is Hibernate's legacy behavior and is also the fastest of the strategies; thus
* it should be used if supported by the underlying database.
*/
public static final ResultColumnReferenceStrategy SOURCE = new ResultColumnReferenceStrategy( "source");
SOURCE,
/**
* For databases which do not support {@link #SOURCE}, ANSI SQL defines two allowable
* approaches. One is to reference the result column by the alias it is given in the
@ -52,8 +44,7 @@ public class ResultColumnReferenceStrategy implements Serializable {
* <p/>
* The other QNSI SQL compliant approach is {@link #ORDINAL}.
*/
public static final ResultColumnReferenceStrategy ALIAS = new ResultColumnReferenceStrategy( "alias" );
ALIAS,
/**
* For databases which do not support {@link #SOURCE}, ANSI SQL defines two allowable
* approaches. One is to reference the result column by the ordinal position at which
@ -61,29 +52,25 @@ public class ResultColumnReferenceStrategy implements Serializable {
* <p/>
* The other QNSI SQL compliant approach is {@link #ALIAS}.
*/
public static final ResultColumnReferenceStrategy ORDINAL = new ResultColumnReferenceStrategy( "ordinal" );
ORDINAL;
static {
ResultColumnReferenceStrategy.INSTANCES.put( ResultColumnReferenceStrategy.SOURCE.name, ResultColumnReferenceStrategy.SOURCE );
ResultColumnReferenceStrategy.INSTANCES.put( ResultColumnReferenceStrategy.ALIAS.name, ResultColumnReferenceStrategy.ALIAS );
ResultColumnReferenceStrategy.INSTANCES.put( ResultColumnReferenceStrategy.ORDINAL.name, ResultColumnReferenceStrategy.ORDINAL );
/**
* Resolves the strategy by name, in a case insensitive manner. If the name cannot be resolved, {@link #SOURCE}
* is returned as the default.
*
* @param name The strategy name to resolve
*
* @return The resolved strategy
*/
public static ResultColumnReferenceStrategy resolveByName(String name) {
if ( ALIAS.name().equalsIgnoreCase( name ) ) {
return ALIAS;
}
private final String name;
public ResultColumnReferenceStrategy(String name) {
this.name = name;
else if ( ORDINAL.name().equalsIgnoreCase( name ) ) {
return ORDINAL;
}
else {
return SOURCE;
}
public String toString() {
return name;
}
private Object readResolve() throws ObjectStreamException {
return parse( name );
}
public static ResultColumnReferenceStrategy parse(String name) {
return ( ResultColumnReferenceStrategy ) ResultColumnReferenceStrategy.INSTANCES.get( name );
}
}

View File

@ -37,10 +37,13 @@
/**
* An SQL dialect compatible with SAP DB.
*
* @author Brad Clow
*/
public class SAPDBDialect extends Dialect {
/**
* Constructs a SAPDBDialect
*/
public SAPDBDialect() {
super();
registerColumnType( Types.BIT, "boolean" );
@ -137,21 +140,24 @@ public SAPDBDialect() {
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getAddForeignKeyConstraintString(
String constraintName,
String[] foreignKey,
String referencedTable,
String[] primaryKey, boolean referencesPrimaryKey
) {
StringBuilder res = new StringBuilder(30)
String[] primaryKey,
boolean referencesPrimaryKey) {
final StringBuilder res = new StringBuilder( 30 )
.append( " foreign key " )
.append( constraintName )
.append( " (" )
@ -168,50 +174,62 @@ public String getAddForeignKeyConstraintString(
return res.toString();
}
@Override
public String getAddPrimaryKeyConstraintString(String constraintName) {
return " primary key ";
}
@Override
public String getNullColumnString() {
return " null";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select " + getSelectSequenceNextValString( sequenceName ) + " from dual";
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return sequenceName + ".nextval";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getQuerySequencesString() {
return "select sequence_name from domain.sequences";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public CaseFragment createCaseFragment() {
return new DecodeCaseFragment();
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String getCreateTemporaryTablePostfix() {
return "ignore rollback";
}
@Override
public String generateTemporaryTableName(String baseTableName) {
return "temp." + super.generateTemporaryTableName( baseTableName );
}

View File

@ -45,9 +45,13 @@
* @author Yoryos Valotasios
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@SuppressWarnings("deprecation")
public class SQLServer2005Dialect extends SQLServerDialect {
private static final int MAX_LENGTH = 8000;
/**
* Constructs a SQLServer2005Dialect
*/
public SQLServer2005Dialect() {
// HHH-3965 fix
// As per http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx
@ -74,14 +78,16 @@ public LimitHandler buildLimitHandler(String sql, RowSelection selection) {
return new SQLServer2005LimitHandler( sql, selection );
}
@Override // since SQLServer2005 the nowait hint is supported
@Override
public String appendLockHint(LockOptions lockOptions, String tableName) {
// NOTE : since SQLServer2005 the nowait hint is supported
if ( lockOptions.getLockMode() == LockMode.UPGRADE_NOWAIT ) {
return tableName + " with (updlock, rowlock, nowait)";
}
LockMode mode = lockOptions.getLockMode();
boolean isNoWait = lockOptions.getTimeOut() == LockOptions.NO_WAIT;
String noWaitStr = isNoWait? ", nowait" :"";
final LockMode mode = lockOptions.getLockMode();
final boolean isNoWait = lockOptions.getTimeOut() == LockOptions.NO_WAIT;
final String noWaitStr = isNoWait ? ", nowait" : "";
switch ( mode ) {
case UPGRADE_NOWAIT:
return tableName + " with (updlock, rowlock, nowait)";

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.dialect.function.NoArgSQLFunction;
@ -33,6 +34,9 @@
* @author Gavin King
*/
public class SQLServer2008Dialect extends SQLServer2005Dialect {
/**
* Constructs a SQLServer2008Dialect
*/
public SQLServer2008Dialect() {
registerColumnType( Types.DATE, "date" );
registerColumnType( Types.TIME, "time" );

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.Types;
import org.hibernate.LockMode;
@ -38,10 +39,13 @@
*
* @author Gavin King
*/
@SuppressWarnings("deprecation")
public class SQLServerDialect extends AbstractTransactSQLDialect {
private static final int PARAM_LIST_SIZE_LIMIT = 2100;
/**
* Constructs a SQLServerDialect
*/
public SQLServerDialect() {
registerColumnType( Types.VARBINARY, "image" );
registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" );
@ -69,7 +73,7 @@ public String getNoColumnsInsertString() {
}
static int getAfterSelectInsertPoint(String sql) {
int selectIndex = sql.toLowerCase().indexOf( "select" );
final int selectIndex = sql.toLowerCase().indexOf( "select" );
final int selectDistinctIndex = sql.toLowerCase().indexOf( "select distinct" );
return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
}
@ -87,6 +91,8 @@ public String getLimitString(String querySelect, int offset, int limit) {
/**
* Use <tt>insert table(...) values(...) select SCOPE_IDENTITY()</tt>
* <p/>
* {@inheritDoc}
*/
@Override
public String appendIdentitySelectToInsert(String insertSQL) {
@ -125,7 +131,7 @@ public char openQuote() {
@Override
public String appendLockHint(LockOptions lockOptions, String tableName) {
LockMode mode = lockOptions.getLockMode();
final LockMode mode = lockOptions.getLockMode();
switch ( mode ) {
case UPGRADE:
case UPGRADE_NOWAIT:
@ -141,8 +147,13 @@ public String appendLockHint(LockOptions lockOptions, String tableName) {
}
}
// The current_timestamp is more accurate, but only known to be supported
// in SQL Server 7.0 and later (i.e., Sybase not known to support it at all)
/**
* The current_timestamp is more accurate, but only known to be supported in SQL Server 7.0 and later and
* Sybase not known to support it at all
* <p/>
* {@inheritDoc}
*/
@Override
public String getCurrentTimestampSelectString() {
return "select current_timestamp";
@ -176,27 +187,23 @@ public boolean supportsLobValueChangePropogation() {
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return false; // here assume SQLServer2005 using snapshot isolation, which does not have this problem
// here assume SQLServer2005 using snapshot isolation, which does not have this problem
return false;
}
@Override
public boolean doesRepeatableReadCauseReadersToBlockWriters() {
return false; // here assume SQLServer2005 using snapshot isolation, which does not have this problem
// here assume SQLServer2005 using snapshot isolation, which does not have this problem
return false;
}
/**
* {@inheritDoc}
*
* @see org.hibernate.dialect.Dialect#getSqlTypeDescriptorOverride(int)
*/
@Override
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
return sqlCode == Types.TINYINT ? SmallIntTypeDescriptor.INSTANCE : super.getSqlTypeDescriptorOverride(sqlCode);
return sqlCode == Types.TINYINT ?
SmallIntTypeDescriptor.INSTANCE :
super.getSqlTypeDescriptorOverride( sqlCode );
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getInExpressionCountLimit()
*/
@Override
public int getInExpressionCountLimit() {
return PARAM_LIST_SIZE_LIMIT;

View File

@ -22,22 +22,29 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Sybase11JoinFragment;
/**
* A SQL dialect suitable for use with Sybase 11.9.2 (specifically: avoids ANSI JOIN syntax)
*
* @author Colm O' Flaherty
*/
public class Sybase11Dialect extends SybaseDialect {
/**
* Constructs a Sybase11Dialect
*/
public Sybase11Dialect() {
super();
}
@Override
public JoinFragment createOuterJoinFragment() {
return new Sybase11JoinFragment();
}
@Override
public String getCrossJoinSeparator() {
return ", ";
}

View File

@ -27,16 +27,11 @@
import java.util.Map;
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.QueryTimeoutException;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.type.StandardBasicTypes;
@ -49,6 +44,9 @@
*/
public class SybaseASE157Dialect extends SybaseASE15Dialect {
/**
* Constructs a SybaseASE157Dialect
*/
public SybaseASE157Dialect() {
super();
@ -60,40 +58,43 @@ public SybaseASE157Dialect() {
registerFunction( "charindex", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "charindex(?1, ?2, ?3)" ) );
}
//HHH-7298 I don't know if this would break something or cause some side affects
//but it is required to use 'select for update'
@Override
public String getTableTypeString() {
//HHH-7298 I don't know if this would break something or cause some side affects
//but it is required to use 'select for update'
return " lock datarows";
}
// support Lob Locator
@Override
public boolean supportsExpectedLobUsagePattern() {
return true;
}
@Override
public boolean supportsLobValueChangePropogation() {
return false;
}
// support 'select ... for update [of columns]'
@Override
public boolean forUpdateOfColumns() {
return true;
}
@Override
public String getForUpdateString() {
return " for update";
}
@Override
public String getForUpdateString(String aliases) {
return getForUpdateString() + " of " + aliases;
}
@Override
public String appendLockHint(LockOptions mode, String tableName) {
return tableName;
}
@Override
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
@ -118,6 +119,4 @@ public JDBCException convert(SQLException sqlException, String message, String s
}
};
}
}

View File

@ -41,6 +41,9 @@
* @author Gavin King
*/
public class SybaseASE15Dialect extends SybaseDialect {
/**
* Constructs a SybaseASE15Dialect
*/
public SybaseASE15Dialect() {
super();
@ -391,10 +394,12 @@ private void registerSybaseKeywords() {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsCascadeDelete() {
return false;
}
@Override
public int getMaxAliasLength() {
return 30;
}
@ -404,11 +409,15 @@ public int getMaxAliasLength() {
* <p/>
* If the DB is configured to be case-sensitive, then this return
* value will be incorrect.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean areStringComparisonsCaseInsensitive() {
return true;
}
@Override
public String getCurrentTimestampSQLFunctionName() {
return "getdate()";
}
@ -417,11 +426,15 @@ public String getCurrentTimestampSQLFunctionName() {
* Actually Sybase does not support LOB locators at al.
*
* @return false.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean supportsExpectedLobUsagePattern() {
return false;
}
@Override
public String getCrossJoinSeparator() {
return ", ";
}

View File

@ -28,13 +28,15 @@
* SQL Dialect for Sybase Anywhere
* extending Sybase (Enterprise) Dialect
* (Tested on ASA 8.x)
* @author ?
*/
public class SybaseAnywhereDialect extends SybaseDialect {
/**
* Sybase Anywhere syntax would require a "DEFAULT" for each column specified,
* but I suppose Hibernate use this syntax only with tables with just 1 column
* <p/>
* {@inheritDoc}
*/
@Override
public String getNoColumnsInsertString() {
return "values (default)";
}
@ -44,11 +46,15 @@ public String getNoColumnsInsertString() {
* <p/>
* NOTE : Also, the DROP statement syntax used by Hibernate to drop constraints is
* not compatible with ASA.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean dropConstraints() {
return false;
}
@Override
public boolean supportsInsertSelectIdentity() {
return false;
}

View File

@ -36,12 +36,8 @@
* @author Brett Meyer
*/
public class SybaseDialect extends AbstractTransactSQLDialect {
private static final int PARAM_LIST_SIZE_LIMIT = 250000;
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getInExpressionCountLimit()
*/
@Override
public int getInExpressionCountLimit() {
return PARAM_LIST_SIZE_LIMIT;

View File

@ -37,7 +37,6 @@
* @author Jay Nance
*/
public class TeradataDialect extends Dialect {
private static final int PARAM_LIST_SIZE_LIMIT = 1024;
/**
@ -63,7 +62,8 @@ public TeradataDialect() {
registerColumnType( Types.DATE, "DATE" );
registerColumnType( Types.TIME, "TIME" );
registerColumnType( Types.TIMESTAMP, "TIMESTAMP" );
registerColumnType( Types.BOOLEAN, "BYTEINT" ); // hibernate seems to ignore this type...
// hibernate seems to ignore this type...
registerColumnType( Types.BOOLEAN, "BYTEINT" );
registerColumnType( Types.BLOB, "BLOB" );
registerColumnType( Types.CLOB, "CLOB" );
@ -113,87 +113,87 @@ public TeradataDialect() {
}
/**
* Does this dialect support the <tt>FOR UPDATE</tt> syntax?
*
* @return empty string ... Teradata does not support <tt>FOR UPDATE<tt> syntax
* Teradata does not support <tt>FOR UPDATE</tt> syntax
* <p/>
* {@inheritDoc}
*/
@Override
public String getForUpdateString() {
return "";
}
@Override
public boolean supportsIdentityColumns() {
return false;
}
@Override
public boolean supportsSequences() {
return false;
}
@Override
public String getAddColumnString() {
return "Add Column";
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String getCreateTemporaryTableString() {
return "create global temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return " on commit preserve rows";
}
@Override
public Boolean performTemporaryTableDDLInIsolation() {
return Boolean.TRUE;
}
@Override
public boolean dropTemporaryTableAfterUse() {
return false;
}
/**
* Get the name of the database type associated with the given
* <tt>java.sql.Types</tt> typecode.
*
* @param code <tt>java.sql.Types</tt> typecode
* @param length the length or precision of the column
* @param precision the precision of the column
* @param scale the scale of the column
*
* @return the database type name
*
* @throws HibernateException
*/
public String getTypeName(int code, int length, int precision, int scale) throws HibernateException {
/*
* We might want a special case for 19,2. This is very common for money types
* and here it is converted to 18,1
*/
float f = precision > 0 ? ( float ) scale / ( float ) precision : 0;
int p = ( precision > 18 ? 18 : precision );
int s = ( precision > 18 ? ( int ) ( 18.0 * f ) : ( scale > 18 ? 18 : scale ) );
@Override
public String getTypeName(int code, long length, int precision, int scale) throws HibernateException {
// We might want a special case for 19,2. This is very common for money types
// and here it is converted to 18,1
final float f = precision > 0 ? (float) scale / (float) precision : 0;
final int p = ( precision > 18 ? 18 : precision );
final int s = ( precision > 18 ? (int) ( 18.0 * f ) : ( scale > 18 ? 18 : scale ) );
return super.getTypeName( code, length, p, s );
}
@Override
public boolean supportsCascadeDelete() {
return false;
}
@Override
public boolean supportsCircularCascadeDeleteConstraints() {
return false;
}
@Override
public boolean areStringComparisonsCaseInsensitive() {
return true;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public String getSelectClauseNullString(int sqlType) {
String v = "null";
@ -235,33 +235,37 @@ public String getSelectClauseNullString(int sqlType) {
case Types.DATALINK:
case Types.BOOLEAN:
break;
default:
break;
}
return v;
}
@Override
public String getCreateMultisetTableString() {
return "create multiset table ";
}
@Override
public boolean supportsLobValueChangePropogation() {
return false;
}
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return true;
}
@Override
public boolean doesRepeatableReadCauseReadersToBlockWriters() {
return true;
}
@Override
public boolean supportsBindAsCallableArgument() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.dialect.Dialect#getInExpressionCountLimit()
*/
@Override
public int getInExpressionCountLimit() {
return PARAM_LIST_SIZE_LIMIT;

View File

@ -44,7 +44,7 @@
/**
* A SQL dialect for TimesTen 5.1.
*
* <p/>
* Known limitations:
* joined-subclass support because of no CASE support in TimesTen
* No support for subqueries that includes aggregation
@ -57,8 +57,11 @@
*
* @author Sherry Listgarten and Max Andersen
*/
@SuppressWarnings("deprecation")
public class TimesTenDialect extends Dialect {
/**
* Constructs a TimesTenDialect
*/
public TimesTenDialect() {
super();
registerColumnType( Types.BIT, "TINYINT" );
@ -95,83 +98,97 @@ public TimesTenDialect() {
}
@Override
public boolean dropConstraints() {
return true;
}
@Override
public boolean qualifyIndexName() {
return false;
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public String getSelectSequenceNextValString(String sequenceName) {
return sequenceName + ".nextval";
}
@Override
public String getSequenceNextValString(String sequenceName) {
return "select first 1 " + sequenceName + ".nextval from sys.tables";
}
@Override
public String getCreateSequenceString(String sequenceName) {
return "create sequence " + sequenceName;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
@Override
public String getQuerySequencesString() {
return "select NAME from sys.sequences";
}
@Override
public JoinFragment createOuterJoinFragment() {
return new OracleJoinFragment();
}
@Override
public String getCrossJoinSeparator() {
return ", ";
}
// new methods in dialect3
/*public boolean supportsForUpdateNowait() {
return false;
}*/
@Override
public String getForUpdateString() {
return "";
}
@Override
public boolean supportsColumnCheck() {
return false;
}
@Override
public boolean supportsTableCheck() {
return false;
}
@Override
public boolean supportsLimitOffset() {
return false;
}
@Override
public boolean supportsVariableLimit() {
return false;
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public boolean useMaxForLimit() {
return true;
}
@Override
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
@ -182,35 +199,43 @@ public String getLimitString(String querySelect, int offset, int limit) {
.toString();
}
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
}
@Override
public String getCurrentTimestampSelectString() {
return "select first 1 sysdate from sys.tables";
}
@Override
public boolean isCurrentTimestampSelectStringCallable() {
return false;
}
@Override
public boolean supportsTemporaryTables() {
return true;
}
@Override
public String generateTemporaryTableName(String baseTableName) {
String name = super.generateTemporaryTableName(baseTableName);
final String name = super.generateTemporaryTableName( baseTableName );
return name.length() > 30 ? name.substring( 1, 30 ) : name;
}
@Override
public String getCreateTemporaryTableString() {
return "create global temporary table";
}
@Override
public String getCreateTemporaryTablePostfix() {
return "on commit delete rows";
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// TimesTen has no known variation of a "SELECT ... FOR UPDATE" syntax...
if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT ) {
@ -238,6 +263,7 @@ else if ( lockMode.greaterThan( LockMode.READ ) ) {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
@ -30,10 +31,8 @@
import org.hibernate.internal.util.StringHelper;
/**
* This class maps a type to names. Associations
* may be marked with a capacity. Calling the get()
* method with a type and actual size n will return
* the associated name with smallest capacity >= n,
* This class maps a type to names. Associations may be marked with a capacity. Calling the get()
* method with a type and actual size n will return the associated name with smallest capacity >= n,
* if available and an unmarked default type otherwise.
* Eg, setting
* <pre>
@ -62,32 +61,48 @@
* @author Christoph Beck
*/
public class TypeNames {
private Map<Integer, Map<Long, String>> weighted = new HashMap<Integer, Map<Long, String>>();
/**
* Holds default type mappings for a typeCode. This is the non-sized mapping
*/
private Map<Integer, String> defaults = new HashMap<Integer, String>();
/**
* get default type name for specified type
* @param typecode the type key
* @return the default type name associated with specified key
* Holds the weighted mappings for a typeCode. The nested map is a TreeMap to sort its contents
* based on the key (the weighting) to ensure proper iteration ordering during {@link #get(int, long, int, int)}
*/
public String get(int typecode) throws MappingException {
String result = defaults.get( typecode );
if (result==null) throw new MappingException("No Dialect mapping for JDBC type: " + typecode);
private Map<Integer, Map<Long, String>> weighted = new HashMap<Integer, Map<Long, String>>();
/**
* get default type name for specified type
*
* @param typeCode the type key
*
* @return the default type name associated with specified key
*
* @throws MappingException Indicates that no registrations were made for that typeCode
*/
public String get(int typeCode) throws MappingException {
final String result = defaults.get( typeCode );
if ( result == null ) {
throw new MappingException( "No Dialect mapping for JDBC type: " + typeCode );
}
return result;
}
/**
* get type name for specified type and size
*
* @param typeCode the type key
* @param size the SQL length
* @param scale the SQL scale
* @param precision the SQL precision
* @return the associated name with smallest capacity >= size,
* if available and the default type name otherwise
*
* @return the associated name with smallest capacity >= size, if available and the default type name otherwise
*
* @throws MappingException Indicates that no registrations were made for that typeCode
*/
public String get(int typeCode, long size, int precision, int scale) throws MappingException {
Map<Long, String> map = weighted.get( typeCode );
final Map<Long, String> map = weighted.get( typeCode );
if ( map != null && map.size() > 0 ) {
// iterate entries ordered by capacity to find first fit
for ( Map.Entry<Long, String> entry: map.entrySet() ) {
@ -96,6 +111,10 @@ public String get(int typeCode, long size, int precision, int scale) throws Mapp
}
}
}
// if we get here one of 2 things happened:
// 1) There was no weighted registration for that typeCode
// 2) There was no weighting whose max capacity was big enough to contain size
return replace( get( typeCode ), size, precision, scale );
}
@ -106,24 +125,30 @@ private static String replace(String type, long size, int precision, int scale)
}
/**
* set a type name for specified type key and capacity
* @param typecode the type key
* Register a weighted typeCode mapping
*
* @param typeCode the JDBC type code
* @param capacity The capacity for this weighting
* @param value The mapping (type name)
*/
public void put(int typecode, long capacity, String value) {
Map<Long, String> map = weighted.get( typecode );
if (map == null) {// add new ordered map
public void put(int typeCode, long capacity, String value) {
Map<Long, String> map = weighted.get( typeCode );
if ( map == null ) {
// add new ordered map
map = new TreeMap<Long, String>();
weighted.put( typecode, map );
weighted.put( typeCode, map );
}
map.put( capacity, value );
}
/**
* set a default type name for specified type key
* @param typecode the type key
* Register a default (non-weighted) typeCode mapping
*
* @param typeCode the type key
* @param value The mapping (type name)
*/
public void put(int typecode, String value) {
defaults.put( typecode, value );
public void put(int typeCode, String value) {
defaults.put( typeCode, value );
}
}

View File

@ -79,27 +79,32 @@ public final String render(Type argumentType, List args, SessionFactoryImplement
if ( args.size() == 1 ) {
// we have the form: trim(trimSource)
// so we trim leading and trailing spaces
return resolveBothSpaceTrimFunction().render( argumentType, args, factory ); // EARLY EXIT!!!!
return resolveBothSpaceTrimFunction().render( argumentType, args, factory );
}
else if ( "from".equalsIgnoreCase( (String) args.get( 0 ) ) ) {
// we have the form: trim(from trimSource).
// This is functionally equivalent to trim(trimSource)
return resolveBothSpaceTrimFromFunction().render( argumentType, args, factory ); // EARLY EXIT!!!!
return resolveBothSpaceTrimFromFunction().render( argumentType, args, factory );
}
else {
// otherwise, a trim-specification and/or a trim-character
// have been specified; we need to decide which options
// are present and "do the right thing"
boolean leading = true; // should leading trim-characters be trimmed?
boolean trailing = true; // should trailing trim-characters be trimmed?
String trimCharacter; // the trim-character (what is to be trimmed off?)
String trimSource; // the trim-source (from where should it be trimmed?)
// should leading trim-characters be trimmed?
boolean leading = true;
// should trailing trim-characters be trimmed?
boolean trailing = true;
// the trim-character (what is to be trimmed off?)
String trimCharacter;
// the trim-source (from where should it be trimmed?)
String trimSource;
// potentialTrimCharacterArgIndex = 1 assumes that a
// trim-specification has been specified. we handle the
// exception to that explicitly
int potentialTrimCharacterArgIndex = 1;
String firstArg = ( String ) args.get( 0 );
final String firstArg = (String) args.get( 0 );
if ( "leading".equalsIgnoreCase( firstArg ) ) {
trailing = false;
}
@ -107,12 +112,13 @@ else if ( "trailing".equalsIgnoreCase( firstArg ) ) {
leading = false;
}
else if ( "both".equalsIgnoreCase( firstArg ) ) {
// nothing to do here
}
else {
potentialTrimCharacterArgIndex = 0;
}
String potentialTrimCharacter = ( String ) args.get( potentialTrimCharacterArgIndex );
final String potentialTrimCharacter = (String) args.get( potentialTrimCharacterArgIndex );
if ( "from".equalsIgnoreCase( potentialTrimCharacter ) ) {
trimCharacter = "' '";
trimSource = (String) args.get( potentialTrimCharacterArgIndex + 1 );
@ -131,7 +137,7 @@ else if ( potentialTrimCharacterArgIndex + 1 >= args.size() ) {
}
}
List<String> argsToUse = new ArrayList<String>();
final List<String> argsToUse = new ArrayList<String>();
argsToUse.add( trimSource );
argsToUse.add( trimCharacter );

View File

@ -34,20 +34,51 @@
* @author Steve Ebersole
*/
public class AnsiTrimEmulationFunction extends AbstractAnsiTrimEmulationFunction {
/**
* The default {@code ltrim} function name
*/
public static final String LTRIM = "ltrim";
/**
* The default {@code rtrim} function name
*/
public static final String RTRIM = "rtrim";
/**
* The default {@code replace} function name
*/
public static final String REPLACE = "replace";
/**
* The placeholder used to represent whitespace
*/
public static final String SPACE_PLACEHOLDER = "${space}$";
/**
* The SQLFunctionTemplate pattern for the trimming leading spaces
*/
public static final String LEADING_SPACE_TRIM_TEMPLATE = LTRIM + "(?1)";
/**
* The SQLFunctionTemplate pattern for the trimming trailing spaces
*/
public static final String TRAILING_SPACE_TRIM_TEMPLATE = RTRIM + "(?1)";
/**
* The SQLFunctionTemplate pattern for the trimming both leading and trailing spaces
*/
public static final String BOTH_SPACE_TRIM_TEMPLATE = LTRIM + "(" + RTRIM + "(?1))";
public static final String BOTH_SPACE_TRIM_FROM_TEMPLATE = LTRIM + "(" + RTRIM + "(?2))"; //skip the FROM keyword in params
/**
* The SQLFunctionTemplate pattern for the trimming both leading and trailing spaces, with the optional FROM keyword.
* Different because we need to skip the FROM keyword in the SQLFunctionTemplate processing
*/
public static final String BOTH_SPACE_TRIM_FROM_TEMPLATE = LTRIM + "(" + RTRIM + "(?2))";
/**
* A template for the series of calls required to trim non-space chars from the beginning of text.
* <p/>
* NOTE : essentially we:</ol>
* NOTE : essentially we:<ol>
* <li>replace all space chars with the text '${space}$'</li>
* <li>replace all the actual replacement chars with space chars</li>
* <li>perform left-trimming (that removes any of the space chars we just added which occur at the beginning of the text)</li>
@ -206,6 +237,7 @@ public AnsiTrimEmulationFunction(String ltrimFunctionName, String rtrimFunctionN
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveBothSpaceTrimFunction() {
return bothSpaceTrim;
}
@ -213,6 +245,7 @@ protected SQLFunction resolveBothSpaceTrimFunction() {
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveBothSpaceTrimFromFunction() {
return bothSpaceTrimFrom;
}
@ -220,6 +253,7 @@ protected SQLFunction resolveBothSpaceTrimFromFunction() {
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveLeadingSpaceTrimFunction() {
return leadingSpaceTrim;
}
@ -227,6 +261,7 @@ protected SQLFunction resolveLeadingSpaceTrimFunction() {
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveTrailingSpaceTrimFunction() {
return trailingSpaceTrim;
}
@ -234,6 +269,7 @@ protected SQLFunction resolveTrailingSpaceTrimFunction() {
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveBothTrimFunction() {
return bothTrim;
}
@ -241,6 +277,7 @@ protected SQLFunction resolveBothTrimFunction() {
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveLeadingTrimFunction() {
return leadingTrim;
}
@ -248,6 +285,7 @@ protected SQLFunction resolveLeadingTrimFunction() {
/**
* {@inheritDoc}
*/
@Override
protected SQLFunction resolveTrailingTrimFunction() {
return trailingTrim;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/**
@ -31,14 +32,11 @@
*/
public class AnsiTrimFunction extends TrimFunctionTemplate {
protected String render(Options options, String trimSource, SessionFactoryImplementor factory) {
return new StringBuilder()
.append( "trim(" )
.append( options.getTrimSpecification().getName() )
.append( ' ' )
.append( options.getTrimCharacter() )
.append( " from " )
.append( trimSource )
.append( ')' )
.toString();
return String.format(
"trim(%s %s from %s)",
options.getTrimSpecification().getName(),
options.getTrimCharacter(),
trimSource
);
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.sql.Types;
/**
@ -34,6 +35,11 @@
public class AvgWithArgumentCastFunction extends StandardAnsiSqlAggregationFunctions.AvgFunction {
private final String castType;
/**
* Constructs a AvgWithArgumentCastFunction
*
* @param castType The type to cast the avg argument to
*/
public AvgWithArgumentCastFunction(String castType) {
this.castType = castType;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.QueryException;
@ -30,29 +31,34 @@
import org.hibernate.type.Type;
/**
* ANSI-SQL style <tt>cast(foo as type)</tt> where the type is
* a Hibernate type
* ANSI-SQL style {@code cast(foo as type)} where the type is a Hibernate type
*
* @author Gavin King
*/
public class CastFunction implements SQLFunction {
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@Override
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
return columnType; // this is really just a guess, unless the caller properly identifies the 'type' argument here
// this is really just a guess, unless the caller properly identifies the 'type' argument here
return columnType;
}
@Override
public String render(Type columnType, List args, SessionFactoryImplementor factory) throws QueryException {
if ( args.size()!=2 ) {
throw new QueryException("cast() requires two arguments");
}
String type = (String) args.get(1);
int[] sqlTypeCodes = factory.getTypeResolver().heuristicType(type).sqlTypes(factory);
final String type = (String) args.get( 1 );
final int[] sqlTypeCodes = factory.getTypeResolver().heuristicType( type ).sqlTypes( factory );
if ( sqlTypeCodes.length!=1 ) {
throw new QueryException("invalid Hibernate type for cast()");
}
@ -61,13 +67,6 @@ public String render(Type columnType, List args, SessionFactoryImplementor facto
//TODO: never reached, since getExplicitHibernateTypeName() actually throws an exception!
sqlType = type;
}
/*else {
//trim off the length/precision/scale
int loc = sqlType.indexOf('(');
if (loc>-1) {
sqlType = sqlType.substring(0, loc);
}
}*/
return "cast(" + args.get( 0 ) + " as " + sqlType + ')';
}

View File

@ -32,32 +32,41 @@
/**
* Emulation of <tt>locate()</tt> on Sybase
*
* @author Nathan Moon
*/
public class CharIndexFunction implements SQLFunction {
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@Override
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
return StandardBasicTypes.INTEGER;
}
@Override
public String render(Type columnType, List args, SessionFactoryImplementor factory) throws QueryException {
boolean threeArgs = args.size() > 2;
Object pattern = args.get(0);
Object string = args.get(1);
Object start = threeArgs ? args.get(2) : null;
final boolean threeArgs = args.size() > 2;
final Object pattern = args.get( 0 );
final Object string = args.get( 1 );
final Object start = threeArgs ? args.get( 2 ) : null;
StringBuilder buf = new StringBuilder();
final StringBuilder buf = new StringBuilder();
buf.append( "charindex(" ).append( pattern ).append( ", " );
if (threeArgs) buf.append( "right(");
if (threeArgs) {
buf.append( "right(" );
}
buf.append( string );
if (threeArgs) buf.append( ", char_length(" ).append( string ).append(")-(").append( start ).append("-1))");
if (threeArgs) {
buf.append( ", char_length(" ).append( string ).append( ")-(" ).append( start ).append( "-1))" );
}
buf.append( ')' );
return buf.toString();
}

View File

@ -34,13 +34,16 @@
* Classic AVG sqlfunction that return types as it was done in Hibernate 3.1
*
* @author Max Rydahl Andersen
*
*/
public class ClassicAvgFunction extends StandardSQLFunction {
/**
* Constructs a ClassicAvgFunction
*/
public ClassicAvgFunction() {
super( "avg" );
}
@Override
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
int[] sqlTypes;
try {
@ -49,8 +52,12 @@ public Type getReturnType(Type columnType, Mapping mapping) throws QueryExceptio
catch ( MappingException me ) {
throw new QueryException( me );
}
if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in avg()" );
int sqlType = sqlTypes[0];
if ( sqlTypes.length != 1 ) {
throw new QueryException( "multi-column type in avg()" );
}
final int sqlType = sqlTypes[0];
if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) {
return StandardBasicTypes.FLOAT;
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
@ -30,13 +31,16 @@
* Classic COUNT sqlfunction that return types as it was done in Hibernate 3.1
*
* @author Max Rydahl Andersen
*
*/
public class ClassicCountFunction extends StandardSQLFunction {
/**
* Constructs a ClassicCountFunction
*/
public ClassicCountFunction() {
super( "count" );
}
@Override
public Type getReturnType(Type columnType, Mapping mapping) {
return StandardBasicTypes.INTEGER;
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.dialect.function;
/**
* Classic SUM sqlfunction that return types as it was done in Hibernate 3.1
*
@ -31,6 +30,9 @@
*
*/
public class ClassicSumFunction extends StandardSQLFunction {
/**
* Constructs a ClassicSumFunction
*/
public ClassicSumFunction() {
super( "sum" );
}

View File

@ -34,28 +34,39 @@
* @author Jonathan Levinson
*/
public class ConditionalParenthesisFunction extends StandardSQLFunction {
/**
* Constructs a ConditionalParenthesisFunction with the given name
*
* @param name The function name
*/
public ConditionalParenthesisFunction(String name) {
super( name );
}
/**
* Constructs a ConditionalParenthesisFunction with the given name
*
* @param name The function name
* @param type The function return type
*/
public ConditionalParenthesisFunction(String name, Type type) {
super( name, type );
}
@Override
public boolean hasParenthesesIfNoArguments() {
return false;
}
public String render(List args, SessionFactoryImplementor factory) {
final boolean hasArgs = !args.isEmpty();
StringBuilder buf = new StringBuilder();
buf.append( getName() );
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
final boolean hasArgs = !arguments.isEmpty();
final StringBuilder buf = new StringBuilder( getName() );
if ( hasArgs ) {
buf.append( "(" );
for ( int i = 0; i < args.size(); i++ ) {
buf.append( args.get( i ) );
if ( i < args.size() - 1 ) {
for ( int i = 0; i < arguments.size(); i++ ) {
buf.append( arguments.get( i ) );
if ( i < arguments.size() - 1 ) {
buf.append( ", " );
}
}

View File

@ -36,24 +36,28 @@
* @author Jonathan Levinson
*/
public class ConvertFunction implements SQLFunction {
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
return StandardBasicTypes.STRING;
}
@Override
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
if ( args.size() != 2 && args.size() != 3 ) {
throw new QueryException( "convert() requires two or three arguments" );
}
String type = ( String ) args.get( 1 );
final String type = (String) args.get( 1 );
if ( args.size() == 2 ) {
return "{fn convert(" + args.get( 0 ) + " , " + type + ")}";

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.Iterator;
import java.util.List;
@ -51,6 +52,7 @@ public class DerbyConcatFunction implements SQLFunction {
* <p/>
* Here we always return <tt>true</tt>
*/
@Override
public boolean hasArguments() {
return true;
}
@ -60,6 +62,7 @@ public boolean hasArguments() {
* <p/>
* Here we always return <tt>true</tt>
*/
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@ -69,6 +72,7 @@ public boolean hasParenthesesIfNoArguments() {
* <p/>
* Here we always return {@link StandardBasicTypes#STRING}.
*/
@Override
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
return StandardBasicTypes.STRING;
}
@ -83,25 +87,23 @@ public Type getReturnType(Type argumentType, Mapping mapping) throws QueryExcept
* arg elements in <tt>cast</tt> function calls, use the concatenation operator on the <tt>cast</tt>
* returns, and then wrap that whole thing in a call to the Derby <tt>varchar</tt> function.
*/
@Override
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
boolean areAllArgsParams = true;
Iterator itr = args.iterator();
while ( itr.hasNext() ) {
final String arg = ( String ) itr.next();
// first figure out if all arguments are dynamic (jdbc parameters) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
boolean areAllArgumentsDynamic = true;
for ( Object arg1 : args ) {
final String arg = (String) arg1;
if ( !"?".equals( arg ) ) {
areAllArgsParams = false;
// we found a non-dynamic argument
areAllArgumentsDynamic = false;
break;
}
}
if ( areAllArgsParams ) {
if ( areAllArgumentsDynamic ) {
return join(
args.iterator(),
new StringTransformer() {
public String transform(String string) {
return "cast( ? as varchar(32672) )";
}
},
CAST_STRING_TRANSFORMER,
new StringJoinTemplate() {
public String getBeginning() {
return "varchar( ";
@ -118,11 +120,7 @@ public String getEnding() {
else {
return join(
args.iterator(),
new StringTransformer() {
public String transform(String string) {
return string;
}
},
NO_TRANSFORM_STRING_TRANSFORMER,
new StringJoinTemplate() {
public String getBeginning() {
return "(";
@ -139,9 +137,31 @@ public String getEnding() {
}
private static interface StringTransformer {
/**
* Transform a string to another
*
* @param string The String to be transformed
*
* @return The transformed form
*/
public String transform(String string);
}
private static final StringTransformer CAST_STRING_TRANSFORMER = new StringTransformer() {
@Override
public String transform(String string) {
// expectation is that incoming string is "?"
return "cast( ? as varchar(32672) )";
}
};
private static final StringTransformer NO_TRANSFORM_STRING_TRANSFORMER = new StringTransformer() {
@Override
public String transform(String string) {
return string;
}
};
private static interface StringJoinTemplate {
/**
* Getter for property 'beginning'.
@ -165,7 +185,7 @@ private static interface StringJoinTemplate {
private static String join(Iterator/*<String>*/ elements, StringTransformer elementTransformer, StringJoinTemplate template) {
// todo : make this available via StringHelper?
StringBuilder buffer = new StringBuilder( template.getBeginning() );
final StringBuilder buffer = new StringBuilder( template.getBeginning() );
while ( elements.hasNext() ) {
final String element = (String) elements.next();
buffer.append( elementTransformer.transform( element ) );

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.QueryException;
@ -39,28 +40,45 @@ public class NoArgSQLFunction implements SQLFunction {
private boolean hasParenthesesIfNoArguments;
private String name;
/**
* Constructs a NoArgSQLFunction
*
* @param name The function name
* @param returnType The function return type
*/
public NoArgSQLFunction(String name, Type returnType) {
this( name, returnType, true );
}
/**
* Constructs a NoArgSQLFunction
*
* @param name The function name
* @param returnType The function return type
* @param hasParenthesesIfNoArguments Does the function call need parenthesis if there are no arguments?
*/
public NoArgSQLFunction(String name, Type returnType, boolean hasParenthesesIfNoArguments) {
this.returnType = returnType;
this.hasParenthesesIfNoArguments = hasParenthesesIfNoArguments;
this.name = name;
}
@Override
public boolean hasArguments() {
return false;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return hasParenthesesIfNoArguments;
}
@Override
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
return returnType;
}
@Override
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
if ( args.size() > 0 ) {
throw new QueryException( "function takes no arguments: " + name );

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.QueryException;
@ -35,30 +36,32 @@
* @author Gavin King
*/
public class NvlFunction implements SQLFunction {
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@Override
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
return argumentType;
}
@Override
@SuppressWarnings("unchecked")
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
int lastIndex = args.size()-1;
Object last = args.remove(lastIndex);
final int lastIndex = args.size()-1;
final Object last = args.remove( lastIndex );
if ( lastIndex==0 ) {
return last.toString();
}
Object secondLast = args.get(lastIndex-1);
String nvl = "nvl(" + secondLast + ", " + last + ")";
final Object secondLast = args.get( lastIndex-1 );
final String nvl = "nvl(" + secondLast + ", " + last + ")";
args.set( lastIndex-1, nvl );
return render( argumentType, args, factory );
}
}

View File

@ -32,35 +32,48 @@
/**
* Emulation of <tt>locate()</tt> on PostgreSQL
*
* @author Gavin King
*/
public class PositionSubstringFunction implements SQLFunction {
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
return StandardBasicTypes.INTEGER;
}
@Override
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
boolean threeArgs = args.size() > 2;
Object pattern = args.get(0);
Object string = args.get(1);
Object start = threeArgs ? args.get(2) : null;
final boolean threeArgs = args.size() > 2;
final Object pattern = args.get( 0 );
final Object string = args.get( 1 );
final Object start = threeArgs ? args.get( 2 ) : null;
StringBuilder buf = new StringBuilder();
if (threeArgs) buf.append('(');
final StringBuilder buf = new StringBuilder();
if (threeArgs) {
buf.append( '(' );
}
buf.append( "position(" ).append( pattern ).append( " in " );
if (threeArgs) buf.append( "substring(");
if (threeArgs) {
buf.append( "substring(");
}
buf.append( string );
if (threeArgs) buf.append( ", " ).append( start ).append(')');
if (threeArgs) {
buf.append( ", " ).append( start ).append( ')' );
}
buf.append( ')' );
if (threeArgs) buf.append('+').append( start ).append("-1)");
if (threeArgs) {
buf.append( '+' ).append( start ).append( "-1)" );
}
return buf.toString();
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.QueryException;
@ -70,7 +71,6 @@ public interface SQLFunction {
*/
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException;
/**
* Render the function call as SQL fragment.
* <p/>

View File

@ -28,25 +28,51 @@
import org.hibernate.dialect.Dialect;
/**
* Defines a registry for SQLFunction instances
*
* @author Steve Ebersole
*/
public class SQLFunctionRegistry {
private final Dialect dialect;
private final Map<String, SQLFunction> userFunctions;
/**
* Constructs a SQLFunctionRegistry
*
* @param dialect The dialect
* @param userFunctions Any application-supplied function definitions
*/
public SQLFunctionRegistry(Dialect dialect, Map<String, SQLFunction> userFunctions) {
this.dialect = dialect;
this.userFunctions = new HashMap<String, SQLFunction>( userFunctions );
}
/**
* Find a SQLFunction by name
*
* @param functionName The name of the function to locate
*
* @return The located function, maye return {@code null}
*/
public SQLFunction findSQLFunction(String functionName) {
String name = functionName.toLowerCase();
SQLFunction userFunction = userFunctions.get( name );
final String name = functionName.toLowerCase();
final SQLFunction userFunction = userFunctions.get( name );
return userFunction != null
? userFunction
: dialect.getFunctions().get( name );
}
/**
* Does this registry contain the named function
*
* @param functionName The name of the function to attempt to locate
*
* @return {@code true} if the registry contained that function
*/
@SuppressWarnings("UnusedDeclaration")
public boolean hasFunction(String functionName) {
String name = functionName.toLowerCase();
final String name = functionName.toLowerCase();
return userFunctions.containsKey( name ) || dialect.getFunctions().containsKey( name );
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.QueryException;
@ -30,11 +31,13 @@
import org.hibernate.type.Type;
/**
* Represents HQL functions that can have different representations in different SQL dialects.
* Represents HQL functions that can have different representations in different SQL dialects where that
* difference can be handled via a template/pattern.
* <p/>
* E.g. in HQL we can define function <code>concat(?1, ?2)</code> to concatenate two strings
* p1 and p2. Target SQL function will be dialect-specific, e.g. <code>(?1 || ?2)</code> for
* Oracle, <code>concat(?1, ?2)</code> for MySql, <code>(?1 + ?2)</code> for MS SQL.
* Each dialect will define a template as a string (exactly like above) marking function
* p1 and p2. Dialects would register different versions of this class *using the same name* (concat) but with
* different templates or patterns; <code>(?1 || ?2)</code> for Oracle, <code>concat(?1, ?2)</code> for MySql,
* <code>(?1 + ?2)</code> for MS SQL. Each dialect will define a template as a string (exactly like above) marking function
* parameters with '?' followed by parameter's index (first index is 1).
*
* @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
@ -44,47 +47,50 @@ public class SQLFunctionTemplate implements SQLFunction {
private final TemplateRenderer renderer;
private final boolean hasParenthesesIfNoArgs;
/**
* Constructs a SQLFunctionTemplate
*
* @param type The functions return type
* @param template The function template
*/
public SQLFunctionTemplate(Type type, String template) {
this( type, template, true );
}
/**
* Constructs a SQLFunctionTemplate
*
* @param type The functions return type
* @param template The function template
* @param hasParenthesesIfNoArgs If there are no arguments, are parentheses required?
*/
public SQLFunctionTemplate(Type type, String template, boolean hasParenthesesIfNoArgs) {
this.type = type;
this.renderer = new TemplateRenderer( template );
this.hasParenthesesIfNoArgs = hasParenthesesIfNoArgs;
}
/**
* {@inheritDoc}
*/
@Override
public String render(Type argumentType, List args, SessionFactoryImplementor factory) {
return renderer.render( args, factory );
}
/**
* {@inheritDoc}
*/
@Override
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
return type;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasArguments() {
return renderer.getAnticipatedNumberOfArguments() > 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasParenthesesIfNoArguments() {
return hasParenthesesIfNoArgs;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return renderer.getTemplate();
}

View File

@ -45,9 +45,12 @@ public class StandardAnsiSqlAggregationFunctions {
* Definition of a standard ANSI SQL compliant <tt>COUNT</tt> function
*/
public static class CountFunction extends StandardSQLFunction {
/**
* Singleton access
*/
public static final CountFunction INSTANCE = new CountFunction();
public CountFunction() {
protected CountFunction() {
super( "count", StandardBasicTypes.LONG );
}
@ -62,34 +65,36 @@ public String render(Type firstArgumentType, List arguments, SessionFactoryImple
}
private String renderCountDistinct(List arguments) {
StringBuilder buffer = new StringBuilder();
final StringBuilder buffer = new StringBuilder();
buffer.append( "count(distinct " );
String sep = "";
Iterator itr = arguments.iterator();
itr.next(); // intentionally skip first
final Iterator itr = arguments.iterator();
// intentionally skip first
itr.next();
while ( itr.hasNext() ) {
buffer.append( sep )
.append( itr.next() );
buffer.append( sep ).append( itr.next() );
sep = ", ";
}
return buffer.append( ")" ).toString();
}
}
/**
* Definition of a standard ANSI SQL compliant <tt>AVG</tt> function
*/
public static class AvgFunction extends StandardSQLFunction {
/**
* Singleton access
*/
public static final AvgFunction INSTANCE = new AvgFunction();
public AvgFunction() {
protected AvgFunction() {
super( "avg", StandardBasicTypes.DOUBLE );
}
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) throws QueryException {
int jdbcTypeCode = determineJdbcTypeCode( firstArgumentType, factory );
final int jdbcTypeCode = determineJdbcTypeCode( firstArgumentType, factory );
return render( jdbcTypeCode, arguments.get( 0 ).toString(), factory );
}
@ -106,6 +111,7 @@ protected final int determineJdbcTypeCode(Type firstArgumentType, SessionFactory
}
}
@SuppressWarnings("UnusedParameters")
protected String render(int firstArgumentJdbcType, String argument, SessionFactoryImplementor factory) {
return "avg(" + renderArgument( argument, firstArgumentJdbcType ) + ")";
}
@ -115,44 +121,49 @@ protected String renderArgument(String argument, int firstArgumentJdbcType) {
}
}
/**
* Definition of a standard ANSI SQL compliant <tt>MAX</tt> function
*/
public static class MaxFunction extends StandardSQLFunction {
/**
* Singleton access
*/
public static final MaxFunction INSTANCE = new MaxFunction();
public MaxFunction() {
protected MaxFunction() {
super( "max" );
}
}
/**
* Definition of a standard ANSI SQL compliant <tt>MIN</tt> function
*/
public static class MinFunction extends StandardSQLFunction {
/**
* Singleton access
*/
public static final MinFunction INSTANCE = new MinFunction();
public MinFunction() {
protected MinFunction() {
super( "min" );
}
}
/**
* Definition of a standard ANSI SQL compliant <tt>SUM</tt> function
*/
public static class SumFunction extends StandardSQLFunction {
/**
* Singleton access
*/
public static final SumFunction INSTANCE = new SumFunction();
public SumFunction() {
protected SumFunction() {
super( "sum" );
}
protected final int determineJdbcTypeCode(Type type, Mapping mapping) throws QueryException {
try {
final int[] jdbcTypeCodes = type.sqlTypes( mapping );
if ( jdbcTypeCodes.length != 1 ) {
throw new QueryException( "multiple-column type in sum()" );
}
return jdbcTypeCodes[0];
}
catch ( MappingException me ) {
throw new QueryException( me );
}
}
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) {
final int jdbcType = determineJdbcTypeCode( firstArgumentType, mapping );
@ -193,8 +204,27 @@ else if ( jdbcType == Types.BIGINT
// as a last resort, return the type of the first argument
return firstArgumentType;
}
protected final int determineJdbcTypeCode(Type type, Mapping mapping) throws QueryException {
try {
final int[] jdbcTypeCodes = type.sqlTypes( mapping );
if ( jdbcTypeCodes.length != 1 ) {
throw new QueryException( "multiple-column type in sum()" );
}
return jdbcTypeCodes[0];
}
catch ( MappingException me ) {
throw new QueryException( me );
}
}
}
/**
* Push the functions defined on StandardAnsiSqlAggregationFunctions into the given map
*
* @param functionMap The map of functions to push to
*/
public static void primeFunctionMap(Map<String, SQLFunction> functionMap) {
functionMap.put( AvgFunction.INSTANCE.getName(), AvgFunction.INSTANCE );
functionMap.put( CountFunction.INSTANCE.getName(), CountFunction.INSTANCE );
@ -202,4 +232,7 @@ public static void primeFunctionMap(Map<String, SQLFunction> functionMap) {
functionMap.put( MinFunction.INSTANCE.getName(), MinFunction.INSTANCE );
functionMap.put( SumFunction.INSTANCE.getName(), SumFunction.INSTANCE );
}
private StandardAnsiSqlAggregationFunctions() {
}
}

View File

@ -35,18 +35,22 @@
* @author Steve Ebersole
*/
public class StandardJDBCEscapeFunction extends StandardSQLFunction {
public StandardJDBCEscapeFunction(String name) {
super( name );
}
/**
* Constructs a StandardJDBCEscapeFunction
*
* @param name The function name
* @param typeValue The function return type
*/
public StandardJDBCEscapeFunction(String name, Type typeValue) {
super( name, typeValue );
}
@Override
public String render(Type argumentType, List args, SessionFactoryImplementor factory) {
return "{fn " + super.render( argumentType, args, factory ) + "}";
}
@Override
public String toString() {
return "{fn " + getName() + "...}";
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.engine.spi.Mapping;
@ -84,32 +85,24 @@ public Type getType() {
return registeredType;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasArguments() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) {
return registeredType == null ? firstArgumentType : registeredType;
}
/**
* {@inheritDoc}
*/
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
StringBuilder buf = new StringBuilder();
final StringBuilder buf = new StringBuilder();
buf.append( name ).append( '(' );
for ( int i = 0; i < arguments.size(); i++ ) {
buf.append( arguments.get( i ) );
@ -120,6 +113,7 @@ public String render(Type firstArgumentType, List arguments, SessionFactoryImple
return buf.append( ')' ).toString();
}
@Override
public String toString() {
return name;
}

View File

@ -36,21 +36,28 @@
* @author Steve Ebersole
*/
public class TemplateRenderer {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TemplateRenderer.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
TemplateRenderer.class.getName()
);
private final String template;
private final String[] chunks;
private final int[] paramIndexes;
/**
* Constructs a template renderer
*
* @param template The template
*/
@SuppressWarnings({ "UnnecessaryUnboxing" })
public TemplateRenderer(String template) {
this.template = template;
List<String> chunkList = new ArrayList<String>();
List<Integer> paramList = new ArrayList<Integer>();
StringBuilder chunk = new StringBuilder( 10 );
StringBuilder index = new StringBuilder( 2 );
final List<String> chunkList = new ArrayList<String>();
final List<Integer> paramList = new ArrayList<Integer>();
final StringBuilder chunk = new StringBuilder( 10 );
final StringBuilder index = new StringBuilder( 2 );
for ( int i = 0; i < template.length(); ++i ) {
char c = template.charAt( i );
@ -96,13 +103,21 @@ public int getAnticipatedNumberOfArguments() {
return paramIndexes.length;
}
/**
* The rendering code.
*
* @param args The arguments to inject into the template
* @param factory The SessionFactory
*
* @return The rendered template with replacements
*/
@SuppressWarnings({ "UnusedDeclaration" })
public String render(List args, SessionFactoryImplementor factory) {
int numberOfArguments = args.size();
final int numberOfArguments = args.size();
if ( getAnticipatedNumberOfArguments() > 0 && numberOfArguments != getAnticipatedNumberOfArguments() ) {
LOG.missingArguments( getAnticipatedNumberOfArguments(), numberOfArguments );
}
StringBuilder buf = new StringBuilder();
final StringBuilder buf = new StringBuilder();
for ( int i = 0; i < chunks.length; ++i ) {
if ( i < paramIndexes.length ) {
final int index = paramIndexes[i] - 1;

View File

@ -36,18 +36,22 @@
* @author Steve Ebersole
*/
public abstract class TrimFunctionTemplate implements SQLFunction {
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return false;
}
@Override
public Type getReturnType(Type firstArgument, Mapping mapping) throws QueryException {
return StandardBasicTypes.STRING;
}
@Override
public String render(Type firstArgument, List args, SessionFactoryImplementor factory) throws QueryException {
final Options options = new Options();
final String trimSource;
@ -70,7 +74,7 @@ else if ( "from".equalsIgnoreCase( ( String ) args.get( 0 ) ) ) {
// trim-specification has been specified. we handle the
// exception to that explicitly
int potentialTrimCharacterArgIndex = 1;
String firstArg = ( String ) args.get( 0 );
final String firstArg = (String) args.get( 0 );
if ( "leading".equalsIgnoreCase( firstArg ) ) {
options.setTrimSpecification( Specification.LEADING );
}
@ -84,7 +88,7 @@ else if ( "both".equalsIgnoreCase( firstArg ) ) {
potentialTrimCharacterArgIndex = 0;
}
String potentialTrimCharacter = ( String ) args.get( potentialTrimCharacterArgIndex );
final String potentialTrimCharacter = (String) args.get( potentialTrimCharacterArgIndex );
if ( "from".equalsIgnoreCase( potentialTrimCharacter ) ) {
trimSource = (String) args.get( potentialTrimCharacterArgIndex + 1 );
}
@ -106,7 +110,7 @@ else if ( potentialTrimCharacterArgIndex + 1 >= args.size() ) {
protected abstract String render(Options options, String trimSource, SessionFactoryImplementor factory);
public static class Options {
protected static class Options {
public static final String DEFAULT_TRIM_CHARACTER = "' '";
private String trimCharacter = DEFAULT_TRIM_CHARACTER;
@ -129,7 +133,7 @@ public void setTrimSpecification(Specification trimSpecification) {
}
}
public static class Specification {
protected static class Specification {
public static final Specification LEADING = new Specification( "leading" );
public static final Specification TRAILING = new Specification( "trailing" );
public static final Specification BOTH = new Specification( "both" );

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.QueryException;
@ -73,33 +74,24 @@ public VarArgsSQLFunction(String begin, String sep, String end) {
this( null, begin, sep, end );
}
/**
* {@inheritDoc}
* <p/>
* Always returns true here.
*/
@Override
public boolean hasArguments() {
return true;
}
/**
* {@inheritDoc}
* <p/>
* Always returns true here.
*/
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
return registeredType == null ? firstArgumentType : registeredType;
}
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) {
StringBuilder buf = new StringBuilder().append( begin );
final StringBuilder buf = new StringBuilder().append( begin );
for ( int i = 0; i < arguments.size(); i++ ) {
buf.append( transformArgument( (String) arguments.get( i ) ) );
if ( i < arguments.size() - 1 ) {

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.persister.entity.Lockable;
@ -70,7 +71,7 @@ else if ( timeout == LockOptions.SKIP_LOCKED) {
private String noWaitSql;
public String getNoWaitSql() {
protected String getNoWaitSql() {
if ( noWaitSql == null ) {
noWaitSql = generateLockString( LockOptions.NO_WAIT );
}
@ -79,7 +80,7 @@ public String getNoWaitSql() {
private String skipLockedSql;
public String getSkipLockedSql() {
protected String getSkipLockedSql() {
if ( skipLockedSql == null ) {
skipLockedSql = generateLockString( LockOptions.SKIP_LOCKED );
}

View File

@ -51,6 +51,7 @@ public interface LockingStrategy {
* @param object The object logically being locked (currently not used)
* @param timeout timeout in milliseconds, 0 = no wait, -1 = wait indefinitely
* @param session The session from which the lock request originated
*
* @throws StaleObjectStateException Indicates an inability to locate the database row as part of acquiring
* the requested lock.
* @throws LockingStrategyException Indicates a failure in the lock attempt

View File

@ -33,13 +33,26 @@
public abstract class LockingStrategyException extends HibernateException {
private final Object entity;
/**
* Constructs a LockingStrategyException
*
* @param entity The entity we were trying to lock
* @param message Message explaining the condition
*/
public LockingStrategyException(Object entity, String message) {
super( message );
this.entity = entity;
}
public LockingStrategyException(Object entity, String message, Throwable root) {
super( message, root );
/**
* Constructs a LockingStrategyException
*
* @param entity The entity we were trying to lock
* @param message Message explaining the condition
* @param cause The underlying cause
*/
public LockingStrategyException(Object entity, String message, Throwable cause) {
super( message, cause );
this.entity = entity;
}

View File

@ -29,11 +29,24 @@
* @author Steve Ebersole
*/
public class OptimisticEntityLockException extends LockingStrategyException {
/**
* Constructs a OptimisticEntityLockException
*
* @param entity The entity we were trying to lock
* @param message Message explaining the condition
*/
public OptimisticEntityLockException(Object entity, String message) {
super( entity, message );
}
public OptimisticEntityLockException(Object entity, String message, Throwable root) {
super( entity, message, root );
/**
* Constructs a OptimisticEntityLockException
*
* @param entity The entity we were trying to lock
* @param message Message explaining the condition
* @param cause The underlying cause
*/
public OptimisticEntityLockException(Object entity, String message, Throwable cause) {
super( entity, message, cause );
}
}

View File

@ -65,11 +65,9 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
if ( !lockable.isVersioned() ) {
throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
EntityEntry entry = session.getPersistenceContext().getEntry( object );
EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess( object, entry );
EventSource source = (EventSource) session;
final EntityEntry entry = session.getPersistenceContext().getEntry( object );
// Register the EntityIncrementVersionProcess action to run just prior to transaction commit.
source.getActionQueue().registerProcess( incrementVersion );
( (EventSource) session ).getActionQueue().registerProcess( new EntityIncrementVersionProcess( object, entry ) );
}
protected LockMode getLockMode() {

View File

@ -43,7 +43,6 @@
* @since 3.5
*/
public class OptimisticLockingStrategy implements LockingStrategy {
private final Lockable lockable;
private final LockMode lockMode;
@ -66,11 +65,9 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
if ( !lockable.isVersioned() ) {
throw new OptimisticLockException( object, "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
EntityEntry entry = session.getPersistenceContext().getEntry(object);
EventSource source = (EventSource)session;
EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess(object, entry);
final EntityEntry entry = session.getPersistenceContext().getEntry(object);
// Register the EntityVerifyVersionProcess action to run just prior to transaction commit.
source.getActionQueue().registerProcess(verifyVersion);
( (EventSource) session ).getActionQueue().registerProcess( new EntityVerifyVersionProcess( object, entry ) );
}
protected LockMode getLockMode() {

View File

@ -31,7 +31,14 @@
* @author Steve Ebersole
*/
public class PessimisticEntityLockException extends LockingStrategyException {
public PessimisticEntityLockException(Object entity, String message, JDBCException root) {
super( entity, message, root );
/**
* Constructs a PessimisticEntityLockException
*
* @param entity The entity we were trying to lock
* @param message Message explaining the condition
* @param cause The underlying cause
*/
public PessimisticEntityLockException(Object entity, String message, JDBCException cause) {
super( entity, message, cause );
}
}

View File

@ -64,9 +64,9 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
if ( !lockable.isVersioned() ) {
throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
EntityEntry entry = session.getPersistenceContext().getEntry( object );
final EntityEntry entry = session.getPersistenceContext().getEntry( object );
final EntityPersister persister = entry.getPersister();
Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
entry.forceLocked( object, nextVersion );
}

View File

@ -70,10 +70,10 @@ public PessimisticReadSelectLockingStrategy(Lockable lockable, LockMode lockMode
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -85,7 +85,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
);
}
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
@ -118,10 +118,10 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
}
protected String generateLockString(int lockTimeout) {
SessionFactoryImplementor factory = getLockable().getFactory();
LockOptions lockOptions = new LockOptions( getLockMode() );
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
SimpleSelect select = new SimpleSelect( factory.getDialect() )
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )

View File

@ -52,7 +52,6 @@
* @since 3.5
*/
public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
PessimisticReadUpdateLockingStrategy.class.getName()
@ -89,10 +88,11 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
if ( !lockable.isVersioned() ) {
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
SessionFactoryImplementor factory = session.getFactory();
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -104,8 +104,9 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
if ( affected < 0 ) { // todo: should this instead check for exactly one row modified?
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
// todo: should this instead check for exactly one row modified?
if ( affected < 0 ) {
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
}
@ -132,8 +133,8 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
}
protected String generateLockString() {
SessionFactoryImplementor factory = lockable.getFactory();
Update update = new Update( factory.getDialect() );
final SessionFactoryImplementor factory = lockable.getFactory();
final Update update = new Update( factory.getDialect() );
update.setTableName( lockable.getRootTableName() );
update.addPrimaryKeyColumns( lockable.getRootTableIdentifierColumnNames() );
update.setVersionColumnName( lockable.getVersionColumnName() );

View File

@ -69,10 +69,10 @@ public PessimisticWriteSelectLockingStrategy(Lockable lockable, LockMode lockMod
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -84,7 +84,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
);
}
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
@ -116,10 +116,10 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
}
protected String generateLockString(int lockTimeout) {
SessionFactoryImplementor factory = getLockable().getFactory();
LockOptions lockOptions = new LockOptions( getLockMode() );
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
SimpleSelect select = new SimpleSelect( factory.getDialect() )
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )

View File

@ -52,7 +52,6 @@
* @since 3.5
*/
public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
PessimisticWriteUpdateLockingStrategy.class.getName()
@ -88,10 +87,11 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
if ( !lockable.isVersioned() ) {
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
SessionFactoryImplementor factory = session.getFactory();
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -103,8 +103,9 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
if ( affected < 0 ) { // todo: should this instead check for exactly one row modified?
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
// todo: should this instead check for exactly one row modified?
if ( affected < 0 ) {
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
}
@ -130,8 +131,8 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
}
protected String generateLockString() {
SessionFactoryImplementor factory = lockable.getFactory();
Update update = new Update( factory.getDialect() );
final SessionFactoryImplementor factory = lockable.getFactory();
final Update update = new Update( factory.getDialect() );
update.setTableName( lockable.getRootTableName() );
update.addPrimaryKeyColumns( lockable.getRootTableIdentifierColumnNames() );
update.setVersionColumnName( lockable.getVersionColumnName() );

View File

@ -61,9 +61,7 @@ public SelectLockingStrategy(Lockable lockable, LockMode lockMode) {
super( lockable, lockMode );
}
/**
* @see LockingStrategy#lock
*/
@Override
public void lock(
Serializable id,
Object version,
@ -71,9 +69,9 @@ public void lock(
int timeout,
SessionImplementor session) throws StaleObjectStateException, JDBCException {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
final SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -85,7 +83,7 @@ public void lock(
);
}
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
@ -114,10 +112,10 @@ public void lock(
}
protected String generateLockString(int timeout) {
SessionFactoryImplementor factory = getLockable().getFactory();
LockOptions lockOptions = new LockOptions( getLockMode() );
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( timeout );
SimpleSelect select = new SimpleSelect( factory.getDialect() )
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )

View File

@ -49,7 +49,6 @@
* @since 3.2
*/
public class UpdateLockingStrategy implements LockingStrategy {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
UpdateLockingStrategy.class.getName()
@ -91,10 +90,11 @@ public void lock(
if ( !lockable.isVersioned() ) {
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
// todo : should we additionally check the current isolation mode explicitly?
SessionFactoryImplementor factory = session.getFactory();
final SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -106,7 +106,7 @@ public void lock(
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
if ( affected < 0 ) {
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
@ -130,8 +130,8 @@ public void lock(
}
protected String generateLockString() {
SessionFactoryImplementor factory = lockable.getFactory();
Update update = new Update( factory.getDialect() );
final SessionFactoryImplementor factory = lockable.getFactory();
final Update update = new Update( factory.getDialect() );
update.setTableName( lockable.getRootTableName() );
update.addPrimaryKeyColumns( lockable.getRootTableIdentifierColumnNames() );
update.setVersionColumnName( lockable.getVersionColumnName() );

View File

@ -0,0 +1,4 @@
/**
* Support for Dialect-specific locking strategies
*/
package org.hibernate.dialect.lock;

View File

@ -25,10 +25,12 @@ public AbstractLimitHandler(String sql, RowSelection selection) {
this.selection = selection;
}
@Override
public boolean supportsLimit() {
return false;
}
@Override
public boolean supportsLimitOffset() {
return supportsLimit();
}
@ -112,20 +114,24 @@ public int convertToFirstRowValue(int zeroBasedFirstResult) {
return zeroBasedFirstResult;
}
@Override
public String getProcessedSql() {
throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName() );
}
@Override
public int bindLimitParametersAtStartOfQuery(PreparedStatement statement, int index)
throws SQLException {
return bindLimitParametersFirst() ? bindLimitParameters( statement, index ) : 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(PreparedStatement statement, int index)
throws SQLException {
return !bindLimitParametersFirst() ? bindLimitParameters( statement, index ) : 0;
}
@Override
public void setMaxRows(PreparedStatement statement) throws SQLException {
}
@ -142,10 +148,10 @@ protected int bindLimitParameters(PreparedStatement statement, int index)
if ( !supportsVariableLimit() || !LimitHelper.hasMaxRows( selection ) ) {
return 0;
}
int firstRow = convertToFirstRowValue( LimitHelper.getFirstRow( selection ) );
int lastRow = getMaxOrLimit();
boolean hasFirstRow = supportsLimitOffset() && ( firstRow > 0 || forceLimitUsage() );
boolean reverse = bindLimitParametersInReverseOrder();
final int firstRow = convertToFirstRowValue( LimitHelper.getFirstRow( selection ) );
final int lastRow = getMaxOrLimit();
final boolean hasFirstRow = supportsLimitOffset() && ( firstRow > 0 || forceLimitUsage() );
final boolean reverse = bindLimitParametersInReverseOrder();
if ( hasFirstRow ) {
statement.setInt( index + ( reverse ? 1 : 0 ), firstRow );
}

View File

@ -1,37 +1,69 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.pagination;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.RowSelection;
/**
* Limit handler that delegates all operations to the underlying dialect.
* Limit handler for CUBRID
*
* @author Esen Sagynov (kadishmal at gmail dot com)
*/
public class CUBRIDLimitHandler extends AbstractLimitHandler {
@SuppressWarnings("FieldCanBeLocal")
private final Dialect dialect;
/**
* Constructs a CUBRIDLimitHandler
*
* @param dialect Currently not used
* @param sql The SQL
* @param selection The row selection options
*/
public CUBRIDLimitHandler(Dialect dialect, String sql, RowSelection selection) {
super( sql, selection );
this.dialect = dialect;
}
@Override
public boolean supportsLimit() {
return true;
}
@Override
public String getProcessedSql() {
if ( LimitHelper.useLimit( this, selection ) ) {
// useLimitOffset: whether "offset" is set or not;
// if set, use "LIMIT offset, row_count" syntax;
// if not, use "LIMIT row_count"
boolean useLimitOffset = LimitHelper.hasFirstRow(selection);
return new StringBuilder(sql.length() + 20).append(sql)
.append(useLimitOffset ? " limit ?, ?" : " limit ?").toString();
final boolean useLimitOffset = LimitHelper.hasFirstRow( selection );
return sql + (useLimitOffset ? " limit ?, ?" : " limit ?");
}
else {
return sql; // or return unaltered SQL
// or return unaltered SQL
return sql;
}
}
}

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.pagination;
import org.hibernate.dialect.Dialect;
@ -8,46 +31,63 @@
*
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@SuppressWarnings("deprecation")
public class LegacyLimitHandler extends AbstractLimitHandler {
private final Dialect dialect;
/**
* Constructs a LegacyLimitHandler
*
* @param dialect The dialect
* @param sql The sql
* @param selection The row selection
*/
public LegacyLimitHandler(Dialect dialect, String sql, RowSelection selection) {
super( sql, selection );
this.dialect = dialect;
}
@Override
public boolean supportsLimit() {
return dialect.supportsLimit();
}
@Override
public boolean supportsLimitOffset() {
return dialect.supportsLimitOffset();
}
@Override
public boolean supportsVariableLimit() {
return dialect.supportsVariableLimit();
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return dialect.bindLimitParametersInReverseOrder();
}
@Override
public boolean bindLimitParametersFirst() {
return dialect.bindLimitParametersFirst();
}
@Override
public boolean useMaxForLimit() {
return dialect.useMaxForLimit();
}
@Override
public boolean forceLimitUsage() {
return dialect.forceLimitUsage();
}
@Override
public int convertToFirstRowValue(int zeroBasedFirstResult) {
return dialect.convertToFirstRowValue( zeroBasedFirstResult );
}
@Override
public String getProcessedSql() {
boolean useLimitOffset = supportsLimit() && supportsLimitOffset()
&& LimitHelper.hasFirstRow( selection ) && LimitHelper.hasMaxRows( selection );

View File

@ -1,10 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.pagination;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.engine.spi.RowSelection;
/**
* Contract defining dialect-specific LIMIT clause handling. Typically implementers might consider extending
* {@link AbstractLimitHandler} class.

View File

@ -1,24 +1,81 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection;
/**
* A helper for dealing with LimitHandler implementations
*
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
public class LimitHelper {
/**
* Is a max row limit indicated?
*
* @param selection The row selection options
*
* @return Whether a max row limit was indicated
*/
public static boolean hasMaxRows(RowSelection selection) {
return selection != null && selection.getMaxRows() != null && selection.getMaxRows() > 0;
}
/**
* Should limit be applied?
*
* @param limitHandler The limit handler
* @param selection The row selection
*
* @return Whether limiting is indicated
*/
public static boolean useLimit(LimitHandler limitHandler, RowSelection selection) {
return limitHandler.supportsLimit() && hasMaxRows( selection );
}
/**
* Is a first row limit indicated?
*
* @param selection The row selection options
*
* @return Whether a first row limit in indicated
*/
public static boolean hasFirstRow(RowSelection selection) {
return getFirstRow( selection ) > 0;
}
/**
* Retrieve the indicated first row for pagination
*
* @param selection The row selection options
*
* @return The first row
*/
public static int getFirstRow(RowSelection selection) {
return ( selection == null || selection.getFirstRow() == null ) ? 0 : selection.getFirstRow();
}
public static boolean hasMaxRows(RowSelection selection) {
return selection != null && selection.getMaxRows() != null && selection.getMaxRows() > 0;
private LimitHelper() {
}
}

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.pagination;
import java.sql.PreparedStatement;
@ -11,22 +34,32 @@
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
public class NoopLimitHandler extends AbstractLimitHandler {
/**
* Constructs a NoopLimitHandler
*
* @param sql The SQL
* @param selection The row selection options
*/
public NoopLimitHandler(String sql, RowSelection selection) {
super( sql, selection );
}
@Override
public String getProcessedSql() {
return sql;
}
@Override
public int bindLimitParametersAtStartOfQuery(PreparedStatement statement, int index) {
return 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(PreparedStatement statement, int index) {
return 0;
}
@Override
public void setMaxRows(PreparedStatement statement) throws SQLException {
if ( LimitHelper.hasMaxRows( selection ) ) {
statement.setMaxRows( selection.getMaxRows() + convertToFirstRowValue( LimitHelper.getFirstRow( selection ) ) );

Some files were not shown because too many files have changed in this diff Show More