HHH-15752 Add Boolean support to oracle dialect

This commit is contained in:
Emmanuel Jannetti 2024-03-28 10:50:58 +01:00 committed by Christian Beikov
parent fcab4df57d
commit 320e282ccc
5 changed files with 34 additions and 10 deletions

View File

@ -66,6 +66,8 @@ public final class BooleanDecoder {
return "decode(?1,1,'Y',0,'N',null)"; return "decode(?1,1,'Y',0,'N',null)";
case TF_BOOLEAN: case TF_BOOLEAN:
return "decode(?1,'T','Y','F','N',null)"; return "decode(?1,'T','Y','F','N',null)";
case BOOLEAN:
return "decode(?1,true,'Y',false,'N',null)";
case INTEGER: case INTEGER:
case LONG: case LONG:
return "decode(abs(sign(?1)),1,'Y',0,'N',null)"; return "decode(abs(sign(?1)),1,'Y',0,'N',null)";
@ -81,6 +83,8 @@ public final class BooleanDecoder {
return "decode(?1,1,'T',0,'F',null)"; return "decode(?1,1,'T',0,'F',null)";
case YN_BOOLEAN: case YN_BOOLEAN:
return "decode(?1,'Y','T','N','F',null)"; return "decode(?1,'Y','T','N','F',null)";
case BOOLEAN:
return "decode(?1,true,'T',false,'F',null)";
case INTEGER: case INTEGER:
case LONG: case LONG:
return "decode(abs(sign(?1)),1,'T',0,'F',null)"; return "decode(abs(sign(?1)),1,'T',0,'F',null)";

View File

@ -253,7 +253,7 @@ public class OracleDialect extends Dialect {
@Override @Override
public int getPreferredSqlTypeCodeForBoolean() { public int getPreferredSqlTypeCodeForBoolean() {
return Types.BIT; return getVersion().isSameOrAfter( 23 ) ? super.getPreferredSqlTypeCodeForBoolean() : Types.BIT;
} }
@Override @Override
@ -425,7 +425,6 @@ public class OracleDialect extends Dialect {
} }
/** /**
* Oracle doesn't have any sort of {@link Types#BOOLEAN}
* type or {@link Types#TIME} type, and its default behavior * type or {@link Types#TIME} type, and its default behavior
* for casting dates and timestamps to and from strings is just awful. * for casting dates and timestamps to and from strings is just awful.
*/ */
@ -453,6 +452,11 @@ public class OracleDialect extends Dialect {
} }
break; break;
case BOOLEAN: case BOOLEAN:
result = BooleanDecoder.toBoolean( from );
if ( result != null ) {
return result;
}
break;
case TF_BOOLEAN: case TF_BOOLEAN:
result = BooleanDecoder.toTrueFalseBoolean( from ); result = BooleanDecoder.toTrueFalseBoolean( from );
if ( result != null ) { if ( result != null ) {
@ -461,6 +465,7 @@ public class OracleDialect extends Dialect {
break; break;
case STRING: case STRING:
switch ( from ) { switch ( from ) {
case BOOLEAN:
case INTEGER_BOOLEAN: case INTEGER_BOOLEAN:
case TF_BOOLEAN: case TF_BOOLEAN:
case YN_BOOLEAN: case YN_BOOLEAN:
@ -700,9 +705,12 @@ public class OracleDialect extends Dialect {
protected String columnType(int sqlTypeCode) { protected String columnType(int sqlTypeCode) {
switch ( sqlTypeCode ) { switch ( sqlTypeCode ) {
case BOOLEAN: case BOOLEAN:
// still, after all these years... if ( getVersion().isSameOrAfter( 23 ) ) {
return super.columnType( sqlTypeCode );
}
else {
return "number(1,0)"; return "number(1,0)";
}
case TINYINT: case TINYINT:
return "number(3,0)"; return "number(3,0)";
case SMALLINT: case SMALLINT:
@ -902,8 +910,10 @@ public class OracleDialect extends Dialect {
@Override @Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry ); super.contributeTypes( typeContributions, serviceRegistry );
if ( getVersion().isBefore( 23 ) ) {
// starting 23c we support Boolean type natively
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE ); typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
}
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE ); typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) { if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
typeContributions.contributeJdbcType( OracleJdbcHelper.getStructJdbcType( serviceRegistry ) ); typeContributions.contributeJdbcType( OracleJdbcHelper.getStructJdbcType( serviceRegistry ) );

View File

@ -25,9 +25,11 @@ import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.Struct; import org.hibernate.annotations.Struct;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.procedure.ProcedureParameter; import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;
import org.hibernate.testing.jdbc.SharedDriverManagerTypeCacheClearingIntegrator; import org.hibernate.testing.jdbc.SharedDriverManagerTypeCacheClearingIntegrator;
@ -252,6 +254,7 @@ public class JsonWithArrayEmbeddableTest {
@Test @Test
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class)
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testUpdateAllAggregateMembers(SessionFactoryScope scope) { public void testUpdateAllAggregateMembers(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
entityManager -> { entityManager -> {

View File

@ -49,6 +49,7 @@ import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting; import org.hibernate.testing.orm.junit.Setting;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -283,6 +284,7 @@ public class StructWithArrayEmbeddableTest implements AdditionalMappingContribut
} }
@Test @Test
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testSelectionItems(SessionFactoryScope scope) { public void testSelectionItems(SessionFactoryScope scope) {
scope.inSession( scope.inSession(
entityManager -> { entityManager -> {

View File

@ -73,6 +73,7 @@ public class BooleanArrayTest {
} }
@Test @Test
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testById(SessionFactoryScope scope) { public void testById(SessionFactoryScope scope) {
scope.inSession( em -> { scope.inSession( em -> {
TableWithBooleanArrays tableRecord; TableWithBooleanArrays tableRecord;
@ -88,6 +89,7 @@ public class BooleanArrayTest {
} }
@Test @Test
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testQueryById(SessionFactoryScope scope) { public void testQueryById(SessionFactoryScope scope) {
scope.inSession( em -> { scope.inSession( em -> {
TypedQuery<TableWithBooleanArrays> tq = em.createNamedQuery( "TableWithBooleanArrays.JPQL.getById", TableWithBooleanArrays.class ); TypedQuery<TableWithBooleanArrays> tq = em.createNamedQuery( "TableWithBooleanArrays.JPQL.getById", TableWithBooleanArrays.class );
@ -99,6 +101,7 @@ public class BooleanArrayTest {
@Test @Test
@SkipForDialect(dialectClass = AbstractHANADialect.class, reason = "For some reason, HANA can't intersect VARBINARY values, but funnily can do a union...") @SkipForDialect(dialectClass = AbstractHANADialect.class, reason = "For some reason, HANA can't intersect VARBINARY values, but funnily can do a union...")
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testQuery(SessionFactoryScope scope) { public void testQuery(SessionFactoryScope scope) {
scope.inSession( em -> { scope.inSession( em -> {
TypedQuery<TableWithBooleanArrays> tq = em.createNamedQuery( "TableWithBooleanArrays.JPQL.getByData", TableWithBooleanArrays.class ); TypedQuery<TableWithBooleanArrays> tq = em.createNamedQuery( "TableWithBooleanArrays.JPQL.getByData", TableWithBooleanArrays.class );
@ -109,6 +112,7 @@ public class BooleanArrayTest {
} }
@Test @Test
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testNativeQueryById(SessionFactoryScope scope) { public void testNativeQueryById(SessionFactoryScope scope) {
scope.inSession( em -> { scope.inSession( em -> {
TypedQuery<TableWithBooleanArrays> tq = em.createNamedQuery( "TableWithBooleanArrays.Native.getById", TableWithBooleanArrays.class ); TypedQuery<TableWithBooleanArrays> tq = em.createNamedQuery( "TableWithBooleanArrays.Native.getById", TableWithBooleanArrays.class );
@ -136,6 +140,7 @@ public class BooleanArrayTest {
@Test @Test
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsStructuralArrays.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsStructuralArrays.class)
@SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required")
public void testNativeQueryUntyped(SessionFactoryScope scope) { public void testNativeQueryUntyped(SessionFactoryScope scope) {
scope.inSession( em -> { scope.inSession( em -> {
Query q = em.createNamedQuery( "TableWithBooleanArrays.Native.getByIdUntyped" ); Query q = em.createNamedQuery( "TableWithBooleanArrays.Native.getByIdUntyped" );