HHH-15489 - Remove support for Oracle versions older than 11.2

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2022-09-20 21:55:38 +02:00 committed by Jan Schatteman
parent 6321016051
commit 89a98f2dc7
21 changed files with 1877 additions and 79 deletions

View File

@ -147,7 +147,7 @@ public class ExplicitLockingTest {
} }
@Test @Test
@RequiresDialect(value = OracleDialect.class, majorVersion = 8) @RequiresDialect(value = OracleDialect.class)
public void testFollowOnLocking(EntityManagerFactoryScope scope) { public void testFollowOnLocking(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> { scope.inTransaction( entityManager -> {
log.info("testBuildLockRequest"); log.info("testBuildLockRequest");

View File

@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 8) @RequiresDialect(value = OracleDialect.class)
@Jpa( @Jpa(
annotatedClasses = RowIdTest.Product.class annotatedClasses = RowIdTest.Product.class
) )

View File

@ -34,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 8) @RequiresDialect(value = OracleDialect.class)
@Jpa( @Jpa(
annotatedClasses = OracleCustomSQLWithStoredProcedureTest.Person.class annotatedClasses = OracleCustomSQLWithStoredProcedureTest.Person.class
) )

View File

@ -38,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 8) @RequiresDialect(value = OracleDialect.class)
@Jpa( @Jpa(
annotatedClasses = { annotatedClasses = {
Person.class, Person.class,

View File

@ -0,0 +1,501 @@
/*
* 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.community.dialect;
import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.FetchClauseType;
import org.hibernate.query.sqm.FrameExclusion;
import org.hibernate.query.sqm.FrameKind;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.sql.ast.tree.expression.Over;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.expression.Summarization;
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
import org.hibernate.sql.ast.tree.from.QueryPartTableReference;
import org.hibernate.sql.ast.tree.from.UnionTableGroup;
import org.hibernate.sql.ast.tree.from.ValuesTableReference;
import org.hibernate.sql.ast.tree.insert.InsertStatement;
import org.hibernate.sql.ast.tree.insert.Values;
import org.hibernate.sql.ast.tree.select.QueryGroup;
import org.hibernate.sql.ast.tree.select.QueryPart;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SortSpecification;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.type.SqlTypes;
/**
* A SQL AST translator for Oracle.
*
* @author Christian Beikov
*/
public class OracleLegacySqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
public OracleLegacySqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
super( sessionFactory, statement );
}
@Override
protected LockStrategy determineLockingStrategy(
QuerySpec querySpec,
ForUpdateClause forUpdateClause,
Boolean followOnLocking) {
LockStrategy strategy = super.determineLockingStrategy( querySpec, forUpdateClause, followOnLocking );
final boolean followOnLockingDisabled = Boolean.FALSE.equals( followOnLocking );
if ( strategy != LockStrategy.FOLLOW_ON && querySpec.hasSortSpecifications() ) {
if ( followOnLockingDisabled ) {
throw new IllegalQueryOperationException( "Locking with ORDER BY is not supported" );
}
strategy = LockStrategy.FOLLOW_ON;
}
// Oracle also doesn't support locks with set operators
// See https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10002.htm#i2066346
if ( strategy != LockStrategy.FOLLOW_ON && isPartOfQueryGroup() ) {
if ( followOnLockingDisabled ) {
throw new IllegalQueryOperationException( "Locking with set operators is not supported" );
}
strategy = LockStrategy.FOLLOW_ON;
}
if ( strategy != LockStrategy.FOLLOW_ON && hasSetOperations( querySpec ) ) {
if ( followOnLockingDisabled ) {
throw new IllegalQueryOperationException( "Locking with set operators is not supported" );
}
strategy = LockStrategy.FOLLOW_ON;
}
if ( strategy != LockStrategy.FOLLOW_ON && useOffsetFetchClause( querySpec ) && !isRowsOnlyFetchClauseType( querySpec ) ) {
if ( followOnLockingDisabled ) {
throw new IllegalQueryOperationException( "Locking with FETCH is not supported" );
}
strategy = LockStrategy.FOLLOW_ON;
}
if ( strategy != LockStrategy.FOLLOW_ON ) {
final boolean hasOffset;
if ( querySpec.isRoot() && hasLimit() && getLimit().getFirstRow() != null ) {
hasOffset = true;
// We must record that the generated SQL depends on the fact that there is an offset
addAppliedParameterBinding( getOffsetParameter(), null );
}
else {
hasOffset = querySpec.getOffsetClauseExpression() != null;
}
if ( hasOffset ) {
if ( followOnLockingDisabled ) {
throw new IllegalQueryOperationException( "Locking with OFFSET is not supported" );
}
strategy = LockStrategy.FOLLOW_ON;
}
}
return strategy;
}
private boolean hasSetOperations(QuerySpec querySpec) {
return querySpec.getFromClause().queryTableGroups( group -> group instanceof UnionTableGroup ? group : null ) != null;
}
private boolean isPartOfQueryGroup() {
return getQueryPartStack().findCurrentFirst( part -> part instanceof QueryGroup ? part : null ) != null;
}
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
// Check if current query part is already row numbering to avoid infinite recursion
if (getQueryPartForRowNumbering() == queryPart) {
return false;
}
final boolean hasLimit = queryPart.isRoot() && hasLimit() || queryPart.getFetchClauseExpression() != null
|| queryPart.getOffsetClauseExpression() != null;
if ( !hasLimit ) {
return false;
}
// Even if Oracle supports the OFFSET/FETCH clause, there are conditions where we still want to use the ROWNUM pagination
if ( supportsOffsetFetchClause() ) {
// When the query has no sort specifications and offset, we want to use the ROWNUM pagination as that is a special locking case
return !queryPart.hasSortSpecifications() && !hasOffset( queryPart )
// Workaround an Oracle bug, segmentation fault for insert queries with a plain query group and fetch clause
|| queryPart instanceof QueryGroup && getClauseStack().isEmpty() && getStatement() instanceof InsertStatement;
}
return true;
}
@Override
protected FetchClauseType getFetchClauseTypeForRowNumbering(QueryPart queryPart) {
final FetchClauseType fetchClauseType = super.getFetchClauseTypeForRowNumbering( queryPart );
final boolean hasOffset;
if ( queryPart.isRoot() && hasLimit() ) {
hasOffset = getLimit().getFirstRow() != null;
}
else {
hasOffset = queryPart.getOffsetClauseExpression() != null;
}
if ( queryPart instanceof QuerySpec && !hasOffset && fetchClauseType == FetchClauseType.ROWS_ONLY ) {
// We return null here, because in this particular case, we render a special rownum query
// which can be seen in #emulateFetchOffsetWithWindowFunctions
// Note that we also build upon this in #visitOrderBy
return null;
}
return fetchClauseType;
}
@Override
protected void emulateFetchOffsetWithWindowFunctions(
QueryPart queryPart,
Expression offsetExpression,
Expression fetchExpression,
FetchClauseType fetchClauseType,
boolean emulateFetchClause) {
if ( queryPart instanceof QuerySpec && offsetExpression == null && fetchClauseType == FetchClauseType.ROWS_ONLY ) {
// Special case for Oracle to support locking along with simple max results paging
final QuerySpec querySpec = (QuerySpec) queryPart;
withRowNumbering(
querySpec,
true, // we need select aliases to avoid ORA-00918: column ambiguously defined
() -> {
final QueryPart currentQueryPart = getQueryPartStack().getCurrent();
final boolean needsParenthesis;
final boolean needsWrapper;
if ( currentQueryPart instanceof QueryGroup ) {
needsParenthesis = false;
// visitQuerySpec will add the select wrapper
needsWrapper = !currentQueryPart.hasOffsetOrFetchClause();
}
else {
needsParenthesis = !querySpec.isRoot();
needsWrapper = true;
}
if ( needsWrapper ) {
if ( needsParenthesis ) {
appendSql( '(' );
}
appendSql( "select * from " );
if ( !needsParenthesis ) {
appendSql( '(' );
}
}
super.visitQuerySpec( querySpec );
if ( needsWrapper ) {
if ( !needsParenthesis ) {
appendSql( ')' );
}
}
appendSql( " where rownum<=" );
final Stack<Clause> clauseStack = getClauseStack();
clauseStack.push( Clause.WHERE );
try {
fetchExpression.accept( this );
// We render the FOR UPDATE clause in the outer query
clauseStack.pop();
clauseStack.push( Clause.FOR_UPDATE );
visitForUpdateClause( querySpec );
}
finally {
clauseStack.pop();
}
if ( needsWrapper ) {
if ( needsParenthesis ) {
appendSql( ')' );
}
}
}
);
}
else {
super.emulateFetchOffsetWithWindowFunctions(
queryPart,
offsetExpression,
fetchExpression,
fetchClauseType,
emulateFetchClause
);
}
}
@Override
protected void visitOrderBy(List<SortSpecification> sortSpecifications) {
// If we have a query part for row numbering, there is no need to render the order by clause
// as that is part of the row numbering window function already, by which we then order by in the outer query
final QueryPart queryPartForRowNumbering = getQueryPartForRowNumbering();
if ( queryPartForRowNumbering == null ) {
renderOrderBy( true, sortSpecifications );
}
else {
// This logic is tightly coupled to #emulateFetchOffsetWithWindowFunctions and #getFetchClauseTypeForRowNumbering
// so that this is rendered when we end up in the special case for Oracle that renders a rownum filter
if ( getFetchClauseTypeForRowNumbering( queryPartForRowNumbering ) == null ) {
final QuerySpec querySpec = (QuerySpec) queryPartForRowNumbering;
if ( querySpec.getOffsetClauseExpression() == null
&& ( !querySpec.isRoot() || getOffsetParameter() == null ) ) {
// When rendering `rownum` for Oracle, we need to render the order by clause still
renderOrderBy( true, sortSpecifications );
}
}
}
}
@Override
protected void visitValuesList(List<Values> valuesList) {
if ( valuesList.size() < 2 ) {
super.visitValuesList( valuesList );
}
else {
// Oracle doesn't support a multi-values insert
// So we render a select union emulation instead
String separator = "";
final Stack<Clause> clauseStack = getClauseStack();
try {
clauseStack.push( Clause.VALUES );
for ( Values values : valuesList ) {
appendSql( separator );
renderExpressionsAsSubquery( values.getExpressions() );
separator = " union all ";
}
}
finally {
clauseStack.pop();
}
}
}
@Override
public void visitValuesTableReference(ValuesTableReference tableReference) {
emulateValuesTableReferenceColumnAliasing( tableReference );
}
@Override
public void visitQueryPartTableReference(QueryPartTableReference tableReference) {
emulateQueryPartTableReferenceColumnAliasing( tableReference );
}
@Override
public void visitFunctionTableReference(FunctionTableReference tableReference) {
append( "table(" );
tableReference.getFunctionExpression().accept( this );
append( CLOSE_PARENTHESIS );
renderTableReferenceIdentificationVariable( tableReference );
}
@Override
public void visitQueryGroup(QueryGroup queryGroup) {
if ( shouldEmulateFetchClause( queryGroup ) ) {
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
}
else {
super.visitQueryGroup( queryGroup );
}
}
@Override
public void visitQuerySpec(QuerySpec querySpec) {
if ( shouldEmulateFetchClause( querySpec ) ) {
emulateFetchOffsetWithWindowFunctions( querySpec, true );
}
else {
super.visitQuerySpec( querySpec );
}
}
@Override
public void visitOffsetFetchClause(QueryPart queryPart) {
if ( !isRowNumberingCurrentQueryPart() ) {
if ( supportsOffsetFetchClause() ) {
renderOffsetFetchClause( queryPart, true );
}
else {
assertRowsOnlyFetchClauseType( queryPart );
}
}
}
@Override
protected void renderRowNumber(SelectClause selectClause, QueryPart queryPart) {
if ( !queryPart.hasSortSpecifications() ) {
// Oracle doesn't allow an empty over clause for the row_number() function
appendSql( "rownum" );
}
else {
super.renderRowNumber( selectClause, queryPart );
}
}
@Override
public void visitOver(Over<?> over) {
final Expression expression = over.getExpression();
if ( expression instanceof FunctionExpression && "row_number".equals( ( (FunctionExpression) expression ).getFunctionName() ) ) {
if ( over.getPartitions().isEmpty() && over.getOrderList().isEmpty()
&& over.getStartKind() == FrameKind.UNBOUNDED_PRECEDING
&& over.getEndKind() == FrameKind.CURRENT_ROW
&& over.getExclusion() == FrameExclusion.NO_OTHERS ) {
// Oracle doesn't allow an empty over clause for the row_number() function
append( "rownum" );
return;
}
}
super.visitOver( over );
}
@Override
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
final JdbcMappingContainer lhsExpressionType = lhs.getExpressionType();
if ( lhsExpressionType == null ) {
renderComparisonEmulateDecode( lhs, operator, rhs );
return;
}
switch ( lhsExpressionType.getJdbcMappings().get( 0 ).getJdbcType().getJdbcTypeCode() ) {
case SqlTypes.SQLXML:
// In Oracle, XMLTYPE is not "comparable", so we have to use the xmldiff function for this purpose
switch ( operator ) {
case EQUAL:
case NOT_DISTINCT_FROM:
appendSql( "0=" );
break;
case NOT_EQUAL:
case DISTINCT_FROM:
appendSql( "1=" );
break;
default:
renderComparisonEmulateDecode( lhs, operator, rhs );
return;
}
appendSql( "existsnode(xmldiff(" );
lhs.accept( this );
appendSql( ',' );
rhs.accept( this );
appendSql( "),'/*[local-name()=''xdiff'']/*')" );
break;
case SqlTypes.BLOB:
// In Oracle, BLOB types are not "comparable", so we have to use the dbms_lob.compare function for this purpose
switch ( operator ) {
case EQUAL:
appendSql( "0=" );
break;
case NOT_EQUAL:
appendSql( "-1=" );
break;
default:
renderComparisonEmulateDecode( lhs, operator, rhs );
return;
}
appendSql( "dbms_lob.compare(" );
lhs.accept( this );
appendSql( ',' );
rhs.accept( this );
appendSql( ')' );
break;
default:
renderComparisonEmulateDecode( lhs, operator, rhs );
break;
}
}
@Override
protected void renderSelectTupleComparison(
List<SqlSelection> lhsExpressions,
SqlTuple tuple,
ComparisonOperator operator) {
emulateSelectTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
}
@Override
protected void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression, boolean inSelect) {
// Oracle did not add support for CASE until 9i
if ( getDialect().getVersion().isBefore( 9 ) ) {
visitDecodeCaseSearchedExpression( caseSearchedExpression );
}
else {
super.visitCaseSearchedExpression( caseSearchedExpression, inSelect );
}
}
@Override
protected void renderPartitionItem(Expression expression) {
if ( expression instanceof Literal ) {
appendSql( "()" );
}
else if ( expression instanceof Summarization ) {
Summarization summarization = (Summarization) expression;
appendSql( summarization.getKind().sqlText() );
appendSql( OPEN_PARENTHESIS );
renderCommaSeparated( summarization.getGroupings() );
appendSql( CLOSE_PARENTHESIS );
}
else {
expression.accept( this );
}
}
@Override
protected boolean supportsDuplicateSelectItemsInQueryGroup() {
return false;
}
@Override
protected boolean supportsRowValueConstructorSyntax() {
return false;
}
@Override
protected boolean supportsRowValueConstructorSyntaxInInList() {
return getDialect().getVersion().isSameOrAfter( 8, 2 );
}
@Override
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
return false;
}
@Override
protected boolean supportsRowValueConstructorSyntaxInInSubQuery() {
return getDialect().getVersion().isSameOrAfter( 9 );
}
@Override
protected String getFromDual() {
return " from dual";
}
@Override
protected String getFromDualForSelectOnly() {
return getFromDual();
}
private boolean supportsOffsetFetchClause() {
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
}
@Override
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
final BinaryArithmeticOperator operator = arithmeticExpression.getOperator();
if ( operator == BinaryArithmeticOperator.MODULO ) {
append( "mod" );
appendSql( OPEN_PARENTHESIS );
arithmeticExpression.getLeftHandOperand().accept( this );
appendSql( ',' );
arithmeticExpression.getRightHandOperand().accept( this );
appendSql( CLOSE_PARENTHESIS );
return;
}
else {
super.visitBinaryArithmeticExpression( arithmeticExpression );
}
}
}

View File

@ -113,12 +113,14 @@ public class OracleDialect extends Dialect {
public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw"; public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw";
private static final DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 11, 2 );
private final LimitHandler limitHandler = supportsFetchClause( FetchClauseType.ROWS_ONLY ) private final LimitHandler limitHandler = supportsFetchClause( FetchClauseType.ROWS_ONLY )
? Oracle12LimitHandler.INSTANCE ? Oracle12LimitHandler.INSTANCE
: new LegacyOracleLimitHandler( getVersion() ); : new LegacyOracleLimitHandler( getVersion() );
public OracleDialect() { public OracleDialect() {
this( DatabaseVersion.make( 8, 0 ) ); this( MINIMUM_VERSION );
} }
public OracleDialect(DatabaseVersion version) { public OracleDialect(DatabaseVersion version) {
@ -129,6 +131,11 @@ public class OracleDialect extends Dialect {
super(info); super(info);
} }
@Override
protected DatabaseVersion getMinimumSupportedVersion() {
return MINIMUM_VERSION;
}
@Override @Override
public int getPreferredSqlTypeCodeForBoolean() { public int getPreferredSqlTypeCodeForBoolean() {
return Types.BIT; return Types.BIT;
@ -181,13 +188,8 @@ public class OracleDialect extends Dialect {
functionFactory.octetLength_pattern( "lengthb(?1)", "dbms_lob.getlength(?1)*2" ); functionFactory.octetLength_pattern( "lengthb(?1)", "dbms_lob.getlength(?1)*2" );
functionFactory.bitLength_pattern( "lengthb(?1)*8", "dbms_lob.getlength(?1)*16" ); functionFactory.bitLength_pattern( "lengthb(?1)*8", "dbms_lob.getlength(?1)*16" );
if ( getVersion().isBefore( 9 ) ) {
queryEngine.getSqmFunctionRegistry().register( "coalesce", new NvlCoalesceEmulation() );
}
else {
//Oracle has had coalesce() since 9.0.1 //Oracle has had coalesce() since 9.0.1
functionFactory.coalesce(); functionFactory.coalesce();
}
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
@ -240,7 +242,7 @@ public class OracleDialect extends Dialect {
@Override @Override
public String currentDate() { public String currentDate() {
return getVersion().isBefore( 9 ) ? currentTimestamp() : "current_date"; return "current_date";
} }
@Override @Override
@ -250,7 +252,7 @@ public class OracleDialect extends Dialect {
@Override @Override
public String currentTimestamp() { public String currentTimestamp() {
return getVersion().isBefore( 9 ) ? "sysdate" : currentTimestampWithTimeZone(); return currentTimestampWithTimeZone();
} }
@Override @Override
@ -260,12 +262,12 @@ public class OracleDialect extends Dialect {
@Override @Override
public String currentLocalTimestamp() { public String currentLocalTimestamp() {
return getVersion().isBefore( 9 ) ? currentTimestamp() : "localtimestamp"; return "localtimestamp";
} }
@Override @Override
public String currentTimestampWithTimeZone() { public String currentTimestampWithTimeZone() {
return getVersion().isBefore( 9 ) ? currentTimestamp() : "current_timestamp"; return "current_timestamp";
} }
@ -578,15 +580,12 @@ public class OracleDialect extends Dialect {
case DATE: case DATE:
case TIME: case TIME:
return "date"; return "date";
case TIMESTAMP:
// the only difference between date and timestamp // the only difference between date and timestamp
// on Oracle is that date has no fractional seconds // on Oracle is that date has no fractional seconds
case TIMESTAMP_WITH_TIMEZONE:
return getVersion().isBefore( 9 ) ? "date" : super.columnType( sqlTypeCode );
case TIME_WITH_TIMEZONE: case TIME_WITH_TIMEZONE:
return getVersion().isBefore( 9 ) ? "date" : "timestamp($p) with time zone"; return "timestamp($p) with time zone";
case VARCHAR: case VARCHAR:
return getVersion().isBefore( 9 ) ? "varchar2($l)" : "varchar2($l char)"; return "varchar2($l char)";
case NVARCHAR: case NVARCHAR:
return "nvarchar2($l)"; return "nvarchar2($l)";
case BINARY: case BINARY:
@ -602,21 +601,18 @@ public class OracleDialect extends Dialect {
final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry();
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( SQLXML, "SYS.XMLTYPE", this ) ); ddlTypeRegistry.addDescriptor( new DdlTypeImpl( SQLXML, "SYS.XMLTYPE", this ) );
if ( getVersion().isSameOrAfter( 10 ) ) {
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "MDSYS.SDO_GEOMETRY", this ) ); ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "MDSYS.SDO_GEOMETRY", this ) );
} }
}
@Override @Override
public TimeZoneSupport getTimeZoneSupport() { public TimeZoneSupport getTimeZoneSupport() {
return getVersion().isSameOrAfter( 9 ) ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE; return TimeZoneSupport.NATIVE;
} }
@Override @Override
protected void initDefaultProperties() { protected void initDefaultProperties() {
super.initDefaultProperties(); super.initDefaultProperties();
String newerVersion = Boolean.toString( getVersion().isSameOrAfter( 12 ) ); getDefaultProperties().setProperty( Environment.BATCH_VERSIONED_DATA, Boolean.toString( getVersion().isSameOrAfter( 12 ) ) );
getDefaultProperties().setProperty( Environment.BATCH_VERSIONED_DATA, newerVersion );
} }
@Override @Override
@ -764,32 +760,9 @@ public class OracleDialect extends Dialect {
return limitHandler; return limitHandler;
} }
@Override
public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) {
if ( getVersion().isSameOrAfter( 9 ) ) {
return super.getSelectClauseNullString( sqlType, typeConfiguration );
}
else {
switch(sqlType) {
case Types.VARCHAR:
case Types.CHAR:
return "to_char(null)";
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
case Types.TIMESTAMP_WITH_TIMEZONE:
return "to_date(null)";
default:
return "to_number(null)";
}
}
}
@Override @Override
public String getCurrentTimestampSelectString() { public String getCurrentTimestampSelectString() {
return getVersion().isBefore( 9 ) return "select systimestamp from dual";
? "select sysdate from dual"
: "select systimestamp from dual";
} }
@ -1104,12 +1077,12 @@ public class OracleDialect extends Dialect {
@Override @Override
public boolean supportsNoWait() { public boolean supportsNoWait() {
return getVersion().isSameOrAfter( 9 ); return true;
} }
@Override @Override
public boolean supportsSkipLocked() { public boolean supportsSkipLocked() {
return getVersion().isSameOrAfter( 10 ); return true;
} }
@Override @Override

View File

@ -414,17 +414,6 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
emulateSelectTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true ); emulateSelectTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
} }
@Override
protected void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression, boolean inSelect) {
// Oracle did not add support for CASE until 9i
if ( getDialect().getVersion().isBefore( 9 ) ) {
visitDecodeCaseSearchedExpression( caseSearchedExpression );
}
else {
super.visitCaseSearchedExpression( caseSearchedExpression, inSelect );
}
}
@Override @Override
protected void renderPartitionItem(Expression expression) { protected void renderPartitionItem(Expression expression) {
if ( expression instanceof Literal ) { if ( expression instanceof Literal ) {
@ -454,7 +443,7 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
@Override @Override
protected boolean supportsRowValueConstructorSyntaxInInList() { protected boolean supportsRowValueConstructorSyntaxInInList() {
return getDialect().getVersion().isSameOrAfter( 8, 2 ); return true;
} }
@Override @Override
@ -464,7 +453,7 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
@Override @Override
protected boolean supportsRowValueConstructorSyntaxInInSubQuery() { protected boolean supportsRowValueConstructorSyntaxInInSubQuery() {
return getDialect().getVersion().isSameOrAfter( 9 ); return true;
} }
@Override @Override

View File

@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
xmlMappings = "org/hibernate/orm/test/generatedkeys/select/MyEntity.hbm.xml" xmlMappings = "org/hibernate/orm/test/generatedkeys/select/MyEntity.hbm.xml"
) )
@SessionFactory @SessionFactory
@RequiresDialect(value = OracleDialect.class, majorVersion = 9) @RequiresDialect(value = OracleDialect.class)
public class SelectGeneratorTest { public class SelectGeneratorTest {
@Test @Test

View File

@ -34,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* @author Gail Badner * @author Gail Badner
*/ */
@SkipForDialect(dialectClass = MySQLDialect.class, majorVersion = 5, matchSubTypes = true, reason = "BLOB/TEXT column 'id' used in key specification without a key length") @SkipForDialect(dialectClass = MySQLDialect.class, majorVersion = 5, matchSubTypes = true, reason = "BLOB/TEXT column 'id' used in key specification without a key length")
@SkipForDialect(dialectClass = OracleDialect.class, majorVersion = 9, matchSubTypes = true, reason = "ORA-02329: column of datatype LOB cannot be unique or a primary key") @SkipForDialect(dialectClass = OracleDialect.class, matchSubTypes = true, reason = "ORA-02329: column of datatype LOB cannot be unique or a primary key")
@DomainModel( @DomainModel(
annotatedClasses = ByteArrayIdTest.DemoEntity.class annotatedClasses = ByteArrayIdTest.DemoEntity.class
) )

View File

@ -34,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* @author Gail Badner * @author Gail Badner
*/ */
@SkipForDialect(dialectClass = MySQLDialect.class, majorVersion = 5, reason = "BLOB/TEXT column 'id' used in key specification without a key length") @SkipForDialect(dialectClass = MySQLDialect.class, majorVersion = 5, reason = "BLOB/TEXT column 'id' used in key specification without a key length")
@SkipForDialect(dialectClass = OracleDialect.class, majorVersion = 9, matchSubTypes = true, reason = "ORA-02329: column of datatype LOB cannot be unique or a primary key") @SkipForDialect(dialectClass = OracleDialect.class, matchSubTypes = true, reason = "ORA-02329: column of datatype LOB cannot be unique or a primary key")
@DomainModel( @DomainModel(
annotatedClasses = PrimitiveByteArrayIdTest.DemoEntity.class annotatedClasses = PrimitiveByteArrayIdTest.DemoEntity.class
) )

View File

@ -21,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@SkipForDialect(dialectClass = OracleDialect.class, majorVersion = 8, matchSubTypes = true, @SkipForDialect(dialectClass = OracleDialect.class, matchSubTypes = true,
reason = "Oracle do not support identity key generation") reason = "Oracle do not support identity key generation")
@SkipForDialect(dialectClass = AbstractHANADialect.class, matchSubTypes = true, @SkipForDialect(dialectClass = AbstractHANADialect.class, matchSubTypes = true,
reason = "Hana do not support identity key generation") reason = "Hana do not support identity key generation")

View File

@ -28,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
xmlMappings = "org/hibernate/orm/test/mapping/generated/ComponentOwner.hbm.xml" xmlMappings = "org/hibernate/orm/test/mapping/generated/ComponentOwner.hbm.xml"
) )
@SessionFactory @SessionFactory
@RequiresDialect( value = OracleDialect.class, majorVersion = 9 ) @RequiresDialect( value = OracleDialect.class )
public class PartiallyGeneratedComponentTest { public class PartiallyGeneratedComponentTest {
@Test @Test

View File

@ -35,7 +35,7 @@ import static org.hamcrest.core.Is.is;
@TestForIssue(jiraKey = "10495") @TestForIssue(jiraKey = "10495")
@RequiresDialects( @RequiresDialects(
value = { value = {
@RequiresDialect(value = OracleDialect.class, majorVersion = 10), @RequiresDialect(value = OracleDialect.class),
@RequiresDialect(value = PostgreSQLDialect.class, majorVersion = 8, minorVersion = 1) @RequiresDialect(value = PostgreSQLDialect.class, majorVersion = 8, minorVersion = 1)
}) })
@DomainModel( @DomainModel(

View File

@ -18,7 +18,7 @@ import org.junit.jupiter.api.Test;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 9) @RequiresDialect(value = OracleDialect.class)
@TestForIssue(jiraKey = "HHH-13104") @TestForIssue(jiraKey = "HHH-13104")
@DomainModel( @DomainModel(
xmlMappings = "org/hibernate/orm/test/ops/Competition.hbm.xml" xmlMappings = "org/hibernate/orm/test/ops/Competition.hbm.xml"

View File

@ -39,7 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* @author Brett Meyer * @author Brett Meyer
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 8) @RequiresDialect(value = OracleDialect.class)
@DomainModel( @DomainModel(
annotatedClasses = { OracleQueryHintTest.Employee.class, OracleQueryHintTest.Department.class } annotatedClasses = { OracleQueryHintTest.Employee.class, OracleQueryHintTest.Department.class }
) )

View File

@ -33,7 +33,7 @@ import static org.junit.Assert.assertThat;
*/ */
@DomainModel( annotatedClasses = RowIdTest.Product.class ) @DomainModel( annotatedClasses = RowIdTest.Product.class )
@SessionFactory(statementInspectorClass = SQLStatementInspector.class) @SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@RequiresDialect( value = OracleDialect.class, majorVersion = 9) @RequiresDialect( value = OracleDialect.class)
public class RowIdTest { public class RowIdTest {
@BeforeEach @BeforeEach

View File

@ -26,7 +26,7 @@ import jakarta.persistence.criteria.CriteriaQuery;
/** /**
* @author Gavin King * @author Gavin King
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 9) @RequiresDialect(value = OracleDialect.class)
@DomainModel( @DomainModel(
xmlMappings = "org/hibernate/orm/test/rowid/Point.hbm.xml" xmlMappings = "org/hibernate/orm/test/rowid/Point.hbm.xml"
) )

View File

@ -37,7 +37,7 @@ import org.junit.jupiter.api.Test;
* *
* @author Brett Meyer * @author Brett Meyer
*/ */
@RequiresDialect(value = OracleDialect.class, majorVersion = 9) @RequiresDialect(value = OracleDialect.class)
public class SynonymValidationTest extends BaseSessionFactoryFunctionalTest { public class SynonymValidationTest extends BaseSessionFactoryFunctionalTest {
private StandardServiceRegistry ssr; private StandardServiceRegistry ssr;

View File

@ -70,7 +70,7 @@ public class OrderedSequenceStructure extends SequenceStructure {
); );
//noinspection deprecation //noinspection deprecation
if ( dialect instanceof OracleDialect && dialect.getVersion().isSameOrAfter( 8 ) ) { if ( dialect instanceof OracleDialect ) {
for ( int i = 0; i < createStrings.length; ++i ) { for ( int i = 0; i < createStrings.length; ++i ) {
createStrings[i] = createStrings[i] + ORDER; createStrings[i] = createStrings[i] + ORDER;
} }

View File

@ -61,7 +61,7 @@ public class SinglePropertyMapper extends AbstractPropertyMapper implements Simp
boolean dbLogicallyDifferent = true; boolean dbLogicallyDifferent = true;
final Dialect dialect = session.getFactory().getJdbcServices() final Dialect dialect = session.getFactory().getJdbcServices()
.getDialect(); .getDialect();
if ( ( dialect instanceof OracleDialect && dialect.getVersion().isSameOrAfter( 8 ) ) && (newObj instanceof String || oldObj instanceof String) ) { if ( ( dialect instanceof OracleDialect ) && (newObj instanceof String || oldObj instanceof String) ) {
// Don't generate new revision when database replaces empty string with NULL during INSERT or UPDATE statements. // Don't generate new revision when database replaces empty string with NULL during INSERT or UPDATE statements.
dbLogicallyDifferent = !(StringTools.isEmpty( newObj ) && StringTools.isEmpty( oldObj )); dbLogicallyDifferent = !(StringTools.isEmpty( newObj ) && StringTools.isEmpty( oldObj ));
} }