Allow implicit casting of types if implied and actual type are both numeric and change floor/ceil to return argument type

This commit is contained in:
Christian Beikov 2021-01-25 22:23:19 +01:00
parent 5d768af983
commit e1aa2d941f
4 changed files with 26 additions and 20 deletions

View File

@ -809,7 +809,8 @@ public static void lastDay_eomonth(QueryEngine queryEngine) {
public static void ceiling_ceil(QueryEngine queryEngine) { public static void ceiling_ceil(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "ceil" ) queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "ceil" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setInvariantType( StandardBasicTypes.DOUBLE ) // To avoid truncating to a specific data type, we default to using the argument type
.setReturnTypeResolver( useArgType(1) )
.register(); .register();
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "ceiling", "ceil" ); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "ceiling", "ceil" );
} }
@ -1463,12 +1464,14 @@ public static void math(QueryEngine queryEngine) {
.register(); .register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("floor") queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("floor")
.setInvariantType( StandardBasicTypes.LONG ) // To avoid truncating to a specific data type, we default to using the argument type
.setReturnTypeResolver( useArgType(1) )
.setExactArgumentCount(1) .setExactArgumentCount(1)
.register(); .register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("ceiling") queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("ceiling")
.setInvariantType( StandardBasicTypes.LONG ) // To avoid truncating to a specific data type, we default to using the argument type
.setReturnTypeResolver( useArgType(1) )
.setExactArgumentCount(1) .setExactArgumentCount(1)
.register(); .register();

View File

@ -154,7 +154,7 @@ private SelfRenderingSqmFunction<Integer> extractWeek(
intType, intType,
builder builder
), ),
intType, intType, // Implicit cast to int
queryEngine, queryEngine,
typeConfiguration typeConfiguration
); );
@ -177,7 +177,7 @@ private SelfRenderingSqmFunction<Long> toLong(
.findFunctionDescriptor("floor") .findFunctionDescriptor("floor")
.generateSqmExpression( .generateSqmExpression(
arg, arg,
longType, longType, // Implicit cast to long
queryEngine, queryEngine,
typeConfiguration typeConfiguration
); );

View File

@ -2960,7 +2960,7 @@ public SqmExpression<?> visitCeilingFunction(HqlParser.CeilingFunctionContext ct
return getFunctionDescriptor("ceiling").generateSqmExpression( return getFunctionDescriptor("ceiling").generateSqmExpression(
arg, arg,
resolveExpressableTypeBasic( Long.class ), (AllowableFunctionReturnType<?>) arg.getNodeType(),
creationContext.getQueryEngine(), creationContext.getQueryEngine(),
creationContext.getJpaMetamodel().getTypeConfiguration() creationContext.getJpaMetamodel().getTypeConfiguration()
); );
@ -2972,7 +2972,7 @@ public SqmExpression<?> visitFloorFunction(HqlParser.FloorFunctionContext ctx) {
return getFunctionDescriptor("floor").generateSqmExpression( return getFunctionDescriptor("floor").generateSqmExpression(
arg, arg,
resolveExpressableTypeBasic( Long.class ), (AllowableFunctionReturnType<?>) arg.getNodeType(),
creationContext.getQueryEngine(), creationContext.getQueryEngine(),
creationContext.getJpaMetamodel().getTypeConfiguration() creationContext.getJpaMetamodel().getTypeConfiguration()
); );

View File

@ -140,8 +140,7 @@ private static boolean isAssignableTo(
int impliedTypeCode = ((BasicType<?>) implied).getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(); int impliedTypeCode = ((BasicType<?>) implied).getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode();
int definedTypeCode = ((BasicType<?>) defined).getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(); int definedTypeCode = ((BasicType<?>) defined).getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode();
return impliedTypeCode == definedTypeCode return impliedTypeCode == definedTypeCode
|| isInteger(impliedTypeCode) && isInteger(definedTypeCode) || isNumeric( impliedTypeCode ) && isNumeric( definedTypeCode );
|| isFloat(impliedTypeCode) && isFloat(definedTypeCode);
} }
private static BasicValuedMapping useImpliedTypeIfPossible( private static BasicValuedMapping useImpliedTypeIfPossible(
@ -181,20 +180,24 @@ private static boolean areCompatible(
int impliedTypeCode = implied.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(); int impliedTypeCode = implied.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode();
int definedTypeCode = defined.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(); int definedTypeCode = defined.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode();
return impliedTypeCode == definedTypeCode return impliedTypeCode == definedTypeCode
|| isInteger(impliedTypeCode) && isInteger(definedTypeCode) || isNumeric( impliedTypeCode ) && isNumeric( definedTypeCode );
|| isFloat(impliedTypeCode) && isFloat(definedTypeCode);
} }
private static boolean isInteger(int type) { private static boolean isNumeric(int type) {
return type == Types.INTEGER switch ( type ) {
|| type == Types.BIGINT case Types.SMALLINT:
|| type == Types.SMALLINT case Types.TINYINT:
|| type == Types.TINYINT; case Types.INTEGER:
} case Types.BIGINT:
case Types.FLOAT:
private static boolean isFloat(int type) { case Types.REAL:
return type == Types.FLOAT || type == Types.DOUBLE; case Types.DOUBLE:
case Types.NUMERIC:
case Types.DECIMAL:
return true;
}
return false;
} }
private static AllowableFunctionReturnType<?> extractArgumentType(List<SqmTypedNode<?>> arguments, int position) { private static AllowableFunctionReturnType<?> extractArgumentType(List<SqmTypedNode<?>> arguments, int position) {