Skip to content

Commit

Permalink
Treat PREFERRED_BOOLEAN_JDBC_TYPE_CODE value BIT like BOOLEAN and onl…
Browse files Browse the repository at this point in the history
…y consider the value in CastFunction
  • Loading branch information
beikov committed Feb 24, 2021
1 parent fc3c20f commit 0fd5fe7
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 7 deletions.
Expand Up @@ -453,7 +453,13 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
//about but in certain cases it doesn't allow some useful typecasts,
//which must be emulated in a dialect-specific way

queryEngine.getSqmFunctionRegistry().register("cast", new CastFunction(this));
queryEngine.getSqmFunctionRegistry().register(
"cast",
new CastFunction(
this,
queryEngine.getPreferredSqlTypeCodeForBoolean()
)
);

//ANSI SQL extract() function is supported on the databases we care most
//about (though it is called datepart() in some of them) but HQL defines
Expand Down
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.dialect.function;

import java.sql.Types;
import java.util.List;

import org.hibernate.dialect.Dialect;
Expand All @@ -27,32 +28,52 @@
*/
public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {

private Dialect dialect;
private final Dialect dialect;
private final CastType booleanCastType;

public CastFunction(Dialect dialect) {
public CastFunction(Dialect dialect, int preferredSqlTypeCodeForBoolean) {
super(
"cast",
StandardArgumentsValidators.exactly( 2 ),
StandardFunctionReturnTypeResolvers.useArgType( 2 )
);
this.dialect = dialect;
this.booleanCastType = getBooleanCastType( preferredSqlTypeCodeForBoolean );
}

private CastType getBooleanCastType(int preferredSqlTypeCodeForBoolean) {
switch ( preferredSqlTypeCodeForBoolean ) {
case Types.BIT:
case Types.SMALLINT:
case Types.TINYINT:
return CastType.INTEGER_BOOLEAN;
}
return CastType.BOOLEAN;
}

@Override
public void render(SqlAppender sqlAppender, List<SqlAstNode> arguments, SqlAstWalker walker) {
final Expression source = (Expression) arguments.get( 0 );
final JdbcMapping sourceMapping = ( (SqlExpressable) source.getExpressionType() ).getJdbcMapping();
final CastType sourceType = sourceMapping.getCastType();
final CastType sourceType = getCastType( sourceMapping );

final CastTarget castTarget = (CastTarget) arguments.get( 1 );
final JdbcMapping targetJdbcMapping = castTarget.getExpressionType().getJdbcMapping();
final CastType targetType = targetJdbcMapping.getCastType();
final CastType targetType = getCastType( targetJdbcMapping );

String cast = dialect.castPattern( sourceType, targetType );

new PatternRenderer( cast ).render( sqlAppender, arguments, walker );
}

private CastType getCastType(JdbcMapping sourceMapping) {
final CastType castType = sourceMapping.getCastType();
if ( castType == CastType.BOOLEAN ) {
return booleanCastType;
}
return castType;
}

// @Override
// protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
// List<SqmTypedNode<?>> arguments,
Expand Down
Expand Up @@ -70,6 +70,7 @@ public static QueryEngine from(
return new QueryEngine(
() -> sessionFactory.getRuntimeMetamodels().getJpaMetamodel(),
sessionFactory.getSessionFactoryOptions().getCriteriaValueHandlingMode(),
sessionFactory.getSessionFactoryOptions().getPreferredSqlTypeCodeForBoolean(),
metadata.buildNamedQueryRepository( sessionFactory ),
hqlTranslator,
sqmTranslatorFactory,
Expand All @@ -88,10 +89,12 @@ public static QueryEngine from(
private final NativeQueryInterpreter nativeQueryInterpreter;
private final QueryInterpretationCache interpretationCache;
private final SqmFunctionRegistry sqmFunctionRegistry;
private final int preferredSqlTypeCodeForBoolean;

public QueryEngine(
Supplier<JpaMetamodel> jpaMetamodelAccess,
ValueHandlingMode criteriaValueHandlingMode,
int preferredSqlTypeCodeForBoolean,
NamedObjectRepository namedObjectRepository,
HqlTranslator hqlTranslator,
SqmTranslatorFactory sqmTranslatorFactory,
Expand All @@ -114,6 +117,7 @@ public QueryEngine(
);

this.sqmFunctionRegistry = new SqmFunctionRegistry();
this.preferredSqlTypeCodeForBoolean = preferredSqlTypeCodeForBoolean;
dialect.initializeFunctionRegistry( this );
if ( userDefinedRegistry != null ) {
userDefinedRegistry.overlay( sqmFunctionRegistry );
Expand All @@ -137,6 +141,7 @@ public QueryEngine(
public QueryEngine(
JpaMetamodel jpaMetamodel,
ValueHandlingMode criteriaValueHandlingMode,
int preferredSqlTypeCodeForBoolean,
boolean useStrictJpaCompliance,
NamedObjectRepository namedObjectRepository,
NativeQueryInterpreter nativeQueryInterpreter,
Expand All @@ -147,6 +152,7 @@ public QueryEngine(
this.nativeQueryInterpreter = nativeQueryInterpreter;

this.sqmFunctionRegistry = new SqmFunctionRegistry();
this.preferredSqlTypeCodeForBoolean = preferredSqlTypeCodeForBoolean;
dialect.initializeFunctionRegistry( this );

this.criteriaBuilder = new SqmCriteriaNodeBuilder(
Expand Down Expand Up @@ -367,4 +373,8 @@ public void close() {
sqmFunctionRegistry.close();
}
}

public int getPreferredSqlTypeCodeForBoolean() {
return preferredSqlTypeCodeForBoolean;
}
}
Expand Up @@ -7,6 +7,7 @@
package org.hibernate.type;

import java.io.Serializable;
import java.sql.Types;

import org.hibernate.dialect.Dialect;
import org.hibernate.type.descriptor.java.BooleanTypeDescriptor;
Expand Down Expand Up @@ -60,10 +61,12 @@ public String objectToSQLString(Boolean value, Dialect dialect) {

@Override
public <X> BasicType<X> resolveIndicatedType(SqlTypeDescriptorIndicators indicators) {
if ( indicators.getPreferredSqlTypeCodeForBoolean() != getSqlTypeDescriptor().getJdbcTypeCode() ) {
final int preferredSqlTypeCodeForBoolean = indicators.getPreferredSqlTypeCodeForBoolean();
// We treat BIT like BOOLEAN because it uses the same JDBC access methods
if ( preferredSqlTypeCodeForBoolean != Types.BIT && preferredSqlTypeCodeForBoolean != getSqlTypeDescriptor().getJdbcTypeCode() ) {
final SqlTypeDescriptor sqlTypeDescriptor = indicators.getTypeConfiguration()
.getSqlTypeDescriptorRegistry()
.getDescriptor( indicators.getPreferredSqlTypeCodeForBoolean() );
.getDescriptor( preferredSqlTypeCodeForBoolean );
//noinspection unchecked
return (BasicType<X>) indicators.getTypeConfiguration()
.getBasicTypeRegistry()
Expand Down
Expand Up @@ -13,6 +13,7 @@
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jpa.JpaComplianceStub;
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
Expand Down Expand Up @@ -118,6 +119,7 @@ public QueryEngine getQueryEngine() {
final QueryEngine queryEngine = new QueryEngine(
jpaMetamodel,
ValueHandlingMode.BIND,
ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( registryScope.getRegistry() ),
// we don't want strict JPA query compliance
false,
new NamedObjectRepositoryImpl( Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap() ),
Expand Down

0 comments on commit 0fd5fe7

Please sign in to comment.