move inner classes of CommonFunctionFactory to toplevel

This commit is contained in:
Gavin King 2022-01-30 18:46:16 +01:00
parent 6f3592ac25
commit 772c4533ee
3 changed files with 192 additions and 158 deletions

View File

@ -6,33 +6,20 @@
*/
package org.hibernate.dialect.function;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Types;
import java.util.Date;
import java.util.List;
import java.util.Arrays;
import java.util.function.Supplier;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.*;
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.useArgType;
@ -1891,106 +1878,9 @@ public class CommonFunctionFactory {
.setParameterTypes(COMPARABLE)
.register();
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
final BasicType<Long> longType = typeConfiguration.getBasicTypeForJavaType( Long.class );
final BasicType<Double> doubleType = typeConfiguration.getBasicTypeForJavaType( Double.class );
final BasicType<BigInteger> bigIntegerType = typeConfiguration.getBasicTypeForJavaType( BigInteger.class );
final BasicType<BigDecimal> bigDecimalType = typeConfiguration.getBasicTypeForJavaType( BigDecimal.class );
// Resolve according to JPA spec 4.8.5
// SUM returns Long when applied to state fields of integral types (other than BigInteger);
// Double when applied to state fields of floating point types;
// BigInteger when applied to state fields of type BigInteger;
// and BigDecimal when applied to state fields of type BigDecimal.
queryEngine.getSqmFunctionRegistry().namedAggregateDescriptorBuilder( "sum" )
.setArgumentRenderingMode( inferenceArgumentRenderingMode )
.setReturnTypeResolver(
new FunctionReturnTypeResolver() {
@Override
public ReturnableType<?> resolveFunctionReturnType(
ReturnableType<?> impliedType,
List<? extends SqmTypedNode<?>> arguments,
TypeConfiguration typeConfiguration) {
if ( impliedType != null ) {
return impliedType;
}
final ReturnableType<?> argType = StandardFunctionReturnTypeResolvers.extractArgumentType(
arguments,
1
);
final BasicType<?> basicType;
if ( argType instanceof BasicType<?> ) {
basicType = (BasicType<?>) argType;
}
else {
basicType = typeConfiguration.getBasicTypeForJavaType( argType.getJavaType() );
if ( basicType == null ) {
return impliedType;
}
}
switch ( basicType.getJdbcType().getJdbcTypeCode() ) {
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
return longType;
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
return doubleType;
case Types.DECIMAL:
case Types.NUMERIC:
if ( BigInteger.class.isAssignableFrom( basicType.getJavaType() ) ) {
return bigIntegerType;
}
else {
return bigDecimalType;
}
}
return bigDecimalType;
}
@Override
public BasicValuedMapping resolveFunctionReturnType(
Supplier<BasicValuedMapping> impliedTypeAccess,
List<? extends SqlAstNode> arguments) {
if ( impliedTypeAccess != null ) {
final BasicValuedMapping basicValuedMapping = impliedTypeAccess.get();
if ( basicValuedMapping != null ) {
return basicValuedMapping;
}
}
// Resolve according to JPA spec 4.8.5
final BasicValuedMapping specifiedArgType = StandardFunctionReturnTypeResolvers.extractArgumentValuedMapping(
arguments,
1
);
switch ( specifiedArgType.getJdbcMapping().getJdbcType().getJdbcTypeCode() ) {
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
return longType;
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
return doubleType;
case Types.DECIMAL:
case Types.NUMERIC:
final Class<?> argTypeClass = specifiedArgType.getJdbcMapping()
.getJavaTypeDescriptor()
.getJavaTypeClass();
if ( BigInteger.class.isAssignableFrom( argTypeClass ) ) {
return bigIntegerType;
}
else {
return bigDecimalType;
}
}
return bigDecimalType;
}
}
)
.setReturnTypeResolver( new SumReturnTypeResolver( queryEngine.getTypeConfiguration() ) )
.setExactArgumentCount( 1 )
.register();
@ -2439,51 +2329,4 @@ public class CommonFunctionFactory {
.register();
}
private static class PowerReturnTypeResolver implements FunctionReturnTypeResolver {
private final BasicType<Double> doubleType;
private PowerReturnTypeResolver(TypeConfiguration typeConfiguration) {
this.doubleType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE );
}
@Override
public ReturnableType<?> resolveFunctionReturnType(
ReturnableType<?> impliedType,
List<? extends SqmTypedNode<?>> arguments,
TypeConfiguration typeConfiguration) {
final JdbcMapping baseType = StandardFunctionReturnTypeResolvers
.extractArgumentJdbcMapping( typeConfiguration, arguments, 1 );
final JdbcMapping powerType = StandardFunctionReturnTypeResolvers
.extractArgumentJdbcMapping( typeConfiguration, arguments, 2 );
if ( baseType.getJdbcType().isDecimal() ) {
return (ReturnableType<?>) arguments.get( 0 ).getNodeType();
}
else if ( powerType.getJdbcType().isDecimal() ) {
return (ReturnableType<?>) arguments.get( 1 ).getNodeType();
}
return typeConfiguration.getBasicTypeForJavaType( Double.class );
}
@Override
public BasicValuedMapping resolveFunctionReturnType(
Supplier<BasicValuedMapping> impliedTypeAccess, List<? extends SqlAstNode> arguments) {
final BasicValuedMapping baseMapping = StandardFunctionReturnTypeResolvers.extractArgumentValuedMapping(
arguments,
1
);
final BasicValuedMapping powerMapping = StandardFunctionReturnTypeResolvers.extractArgumentValuedMapping(
arguments,
2
);
if ( baseMapping.getJdbcMapping().getJdbcType().isDecimal() ) {
return baseMapping;
}
else if ( powerMapping.getJdbcMapping().getJdbcType().isDecimal() ) {
return powerMapping;
}
return doubleType;
}
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.function;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.BasicType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import java.util.List;
import java.util.function.Supplier;
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.extractArgumentJdbcMapping;
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.extractArgumentValuedMapping;
/**
* @author Christian Beikov
*/
class PowerReturnTypeResolver implements FunctionReturnTypeResolver {
private final BasicType<Double> doubleType;
PowerReturnTypeResolver(TypeConfiguration typeConfiguration) {
this.doubleType = typeConfiguration.getBasicTypeRegistry().resolve(StandardBasicTypes.DOUBLE);
}
@Override
public ReturnableType<?> resolveFunctionReturnType(
ReturnableType<?> impliedType,
List<? extends SqmTypedNode<?>> arguments,
TypeConfiguration typeConfiguration) {
final JdbcMapping baseType = extractArgumentJdbcMapping( typeConfiguration, arguments, 1 );
final JdbcMapping powerType = extractArgumentJdbcMapping( typeConfiguration, arguments, 2 );
if ( baseType.getJdbcType().isDecimal() ) {
return (ReturnableType<?>) arguments.get(0).getNodeType();
}
else if (powerType.getJdbcType().isDecimal()) {
return (ReturnableType<?>) arguments.get(1).getNodeType();
}
return typeConfiguration.getBasicTypeForJavaType(Double.class);
}
@Override
public BasicValuedMapping resolveFunctionReturnType(
Supplier<BasicValuedMapping> impliedTypeAccess, List<? extends SqlAstNode> arguments) {
final BasicValuedMapping baseMapping = extractArgumentValuedMapping( arguments,1 );
final BasicValuedMapping powerMapping = extractArgumentValuedMapping( arguments, 2 );
if ( baseMapping.getJdbcMapping().getJdbcType().isDecimal() ) {
return baseMapping;
}
else if ( powerMapping.getJdbcMapping().getJdbcType().isDecimal() ) {
return powerMapping;
}
return doubleType;
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.function;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.BasicType;
import org.hibernate.type.spi.TypeConfiguration;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Types;
import java.util.List;
import java.util.function.Supplier;
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.extractArgumentType;
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.extractArgumentValuedMapping;
/**
* Resolve according to JPA spec 4.8.5
*
* {@code SUM} returns:
* <ul>
* <li>{@code Long} when applied to state fields of integral types (other than {@code BigInteger});
* <li>{@code Double} when applied to state fields of floating point types;
* <li>{@code BigInteger} when applied to state fields of type {@code BigInteger};
* <li>and {@code BigDecimal} when applied to state fields of type {@code BigDecimal}.
* </ul>
*
* @author Christian Beikov
*/
class SumReturnTypeResolver implements FunctionReturnTypeResolver {
private final BasicType<Long> longType;
private final BasicType<Double> doubleType;
private final BasicType<BigInteger> bigIntegerType;
private final BasicType<BigDecimal> bigDecimalType;
public SumReturnTypeResolver(TypeConfiguration typeConfiguration) {
final BasicType<Long> longType = typeConfiguration.getBasicTypeForJavaType(Long.class);
final BasicType<Double> doubleType = typeConfiguration.getBasicTypeForJavaType(Double.class);
final BasicType<BigInteger> bigIntegerType = typeConfiguration.getBasicTypeForJavaType(BigInteger.class);
final BasicType<BigDecimal> bigDecimalType = typeConfiguration.getBasicTypeForJavaType(BigDecimal.class);
this.longType = longType;
this.doubleType = doubleType;
this.bigIntegerType = bigIntegerType;
this.bigDecimalType = bigDecimalType;
}
@Override
public ReturnableType<?> resolveFunctionReturnType(
ReturnableType<?> impliedType,
List<? extends SqmTypedNode<?>> arguments,
TypeConfiguration typeConfiguration) {
if (impliedType != null) {
return impliedType;
}
final ReturnableType<?> argType = extractArgumentType( arguments, 1 );
final BasicType<?> basicType;
if (argType instanceof BasicType<?>) {
basicType = (BasicType<?>) argType;
}
else {
basicType = typeConfiguration.getBasicTypeForJavaType( argType.getJavaType() );
if (basicType == null) {
return impliedType;
}
}
switch ( basicType.getJdbcType().getJdbcTypeCode() ) {
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
return longType;
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
return doubleType;
case Types.DECIMAL:
case Types.NUMERIC:
return BigInteger.class.isAssignableFrom( basicType.getJavaType() ) ? bigIntegerType : bigDecimalType;
}
return bigDecimalType;
}
@Override
public BasicValuedMapping resolveFunctionReturnType(
Supplier<BasicValuedMapping> impliedTypeAccess,
List<? extends SqlAstNode> arguments) {
if (impliedTypeAccess != null) {
final BasicValuedMapping basicValuedMapping = impliedTypeAccess.get();
if (basicValuedMapping != null) {
return basicValuedMapping;
}
}
// Resolve according to JPA spec 4.8.5
final BasicValuedMapping specifiedArgType = extractArgumentValuedMapping( arguments, 1 );
switch ( specifiedArgType.getJdbcMapping().getJdbcType().getJdbcTypeCode() ) {
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
return longType;
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
return doubleType;
case Types.DECIMAL:
case Types.NUMERIC:
final Class<?> argTypeClass = specifiedArgType.getJdbcMapping()
.getJavaTypeDescriptor()
.getJavaTypeClass();
return BigInteger.class.isAssignableFrom(argTypeClass) ? bigIntegerType : bigDecimalType;
}
return bigDecimalType;
}
}