/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.dialect;

import java.sql.Types;
import java.util.Locale;

import org.hibernate.LockOptions;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.CaseFragment;

A dialect for Oracle 9i databases.

Specifies to not use "ANSI join syntax" because 9i does not seem to properly handle it in all cases.
Author:Steve Ebersole
/** * A dialect for Oracle 9i databases. * <p/> * Specifies to not use "ANSI join syntax" because 9i does not seem to properly handle it in all cases. * * @author Steve Ebersole */
public class Oracle9iDialect extends Oracle8iDialect { private static final AbstractLimitHandler LIMIT_HANDLER = new AbstractLimitHandler() { @Override public String processSql(String sql, RowSelection selection) { final boolean hasOffset = LimitHelper.hasFirstRow( selection ); sql = sql.trim(); String forUpdateClause = null; boolean isForUpdate = false; final int forUpdateIndex = sql.toLowerCase(Locale.ROOT).lastIndexOf( "for update" ); if (forUpdateIndex > -1) { // save 'for update ...' and then remove it forUpdateClause = sql.substring( forUpdateIndex ); sql = sql.substring( 0, forUpdateIndex - 1 ); isForUpdate = true; } final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 ); if (hasOffset) { pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); } else { pagingSelect.append( "select * from ( " ); } pagingSelect.append( sql ); if (hasOffset) { pagingSelect.append( " ) row_ where rownum <= ?) where rownum_ > ?" ); } else { pagingSelect.append( " ) where rownum <= ?" ); } if (isForUpdate) { pagingSelect.append( " " ); pagingSelect.append( forUpdateClause ); } return pagingSelect.toString(); } @Override public boolean supportsLimit() { return true; } @Override public boolean bindLimitParametersInReverseOrder() { return true; } @Override public boolean useMaxForLimit() { return true; } }; @Override protected void registerCharacterTypeMappings() { registerColumnType( Types.CHAR, "char(1 char)" ); registerColumnType( Types.VARCHAR, 4000, "varchar2($l char)" ); registerColumnType( Types.VARCHAR, "long" ); registerColumnType( Types.NVARCHAR, "nvarchar2($l)" ); registerColumnType( Types.LONGNVARCHAR, "nvarchar2($l)" ); } @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 LimitHandler getLimitHandler() { return LIMIT_HANDLER; } @Override public String getLimitString(String sql, boolean hasOffset) { sql = sql.trim(); String forUpdateClause = null; boolean isForUpdate = false; final int forUpdateIndex = sql.toLowerCase(Locale.ROOT).lastIndexOf( "for update") ; if ( forUpdateIndex > -1 ) { // save 'for update ...' and then remove it forUpdateClause = sql.substring( forUpdateIndex ); sql = sql.substring( 0, forUpdateIndex-1 ); isForUpdate = true; } final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 ); if (hasOffset) { pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); } else { pagingSelect.append( "select * from ( " ); } pagingSelect.append( sql ); if (hasOffset) { pagingSelect.append( " ) row_ where rownum <= ?) where rownum_ > ?" ); } else { pagingSelect.append( " ) where rownum <= ?" ); } if ( isForUpdate ) { pagingSelect.append( " " ); pagingSelect.append( forUpdateClause ); } 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"; } @Override public String getForUpdateString() { return " for update"; } @Override public String getWriteLockString(int timeout) { if ( timeout == LockOptions.NO_WAIT ) { return " for update nowait"; } else if ( timeout > 0 ) { // convert from milliseconds to seconds final float seconds = timeout / 1000.0f; timeout = Math.round( seconds ); return " for update wait " + timeout; } 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.

{@inheritDoc}
/** * 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; } }