Java tutorial
/* * 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. * <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. * <p/> * {@inheritDoc} */ @Override public boolean supportsRowValueConstructorSyntaxInInList() { return true; } @Override public boolean supportsTupleDistinctCounts() { return false; } }