/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2010, 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 java.sql.CallableStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.hibernate.LockMode; import org.hibernate.LockOptions; //import org.hibernate.cfg.Environment; //import org.hibernate.type.StandardBasicTypes; /** * An abstract base class for Sybase and MS SQL Server dialects. * * @author Gavin King */ abstract class AbstractTransactSQLDialect extends Dialect { public AbstractTransactSQLDialect() { super(); registerColumnType( Types.BINARY, "binary($l)" ); registerColumnType( Types.BIT, "tinyint" ); registerColumnType( Types.BIGINT, "numeric(19,0)" ); registerColumnType( Types.SMALLINT, "smallint" ); registerColumnType( Types.TINYINT, "smallint" ); registerColumnType( Types.INTEGER, "int" ); registerColumnType( Types.CHAR, "char(1)" ); registerColumnType( Types.VARCHAR, "varchar($l)" ); registerColumnType( Types.FLOAT, "float" ); registerColumnType( Types.DOUBLE, "double precision" ); registerColumnType( Types.DATE, "datetime" ); registerColumnType( Types.TIME, "datetime" ); registerColumnType( Types.TIMESTAMP, "datetime" ); registerColumnType( Types.VARBINARY, "varbinary($l)" ); registerColumnType( Types.NUMERIC, "numeric($p,$s)" ); registerColumnType( Types.BLOB, "image" ); registerColumnType( Types.CLOB, "text" ); // 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() { //starts with 1, implicitly return "identity not null"; } @Override public boolean supportsInsertSelectIdentity() { return true; } @Override public String appendIdentitySelectToInsert(String insertSQL) { return insertSQL + "\nselect @@identity"; } @Override 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<String, String[]> keyColumnNames) { // // TODO: merge additional lockoptions support in Dialect.applyLocksToSql // 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; // int end = -1; // if ( sql.endsWith( " " + alias ) ) { // start = ( sql.length() - alias.length() ) + correction; // end = start + alias.length(); // } // else { // int position = sql.indexOf( " " + alias + " " ); // if ( position <= -1 ) { // position = sql.indexOf( " " + alias + "," ); // } // if ( position > -1 ) { // start = position + correction + 1; // end = start + alias.length(); // } // } // // if ( start > -1 ) { // final String lockHint = appendLockHint( lockMode, alias ); // buffer.replace( start, end, lockHint ); // correction += ( lockHint.length() - alias.length() ); // } // } // } // return buffer.toString(); // } @Override public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException { // 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() { // 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; } @Override public boolean supportsTuplesInSubqueries() { return false; } }