Various improvements:
* Sprinkle some @Nullable annotations to better understand nullness guarantees * Fix some potential NPEs * Improve Oracle array_agg emulation * Prepare for aggregate component array support
This commit is contained in:
parent
75e1f17139
commit
940c898ecf
|
@ -24,6 +24,7 @@ import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
|||
import org.hibernate.query.sqm.produce.function.FunctionArgumentException;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
|
@ -44,6 +45,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.NUMERIC;
|
||||
|
||||
/**
|
||||
|
@ -240,7 +243,7 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final SqmExpressible<?> expressible = arguments.get( 0 ).getExpressible();
|
||||
|
|
|
@ -10,15 +10,17 @@ import java.util.List;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.BasicTypeReference;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Simplified API allowing users to contribute
|
||||
* {@link org.hibernate.query.sqm.function.SqmFunctionDescriptor}s
|
||||
|
@ -42,15 +44,7 @@ public class StandardSQLFunction extends NamedSqmFunctionDescriptor {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return type == null ? null : typeConfiguration.getBasicTypeRegistry().resolve( type );
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
|||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -21,6 +22,8 @@ import java.math.BigInteger;
|
|||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.extractArgumentType;
|
||||
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.extractArgumentValuedMapping;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
@ -59,15 +62,7 @@ class SumReturnTypeResolver implements FunctionReturnTypeResolver {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
if ( impliedType != null ) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
|||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
|
@ -35,6 +36,7 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL;
|
||||
|
@ -129,15 +131,7 @@ public class TimestampdiffFunction
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final BasicType<?> invariantType;
|
||||
|
|
|
@ -15,11 +15,14 @@ import org.hibernate.metamodel.model.domain.DomainType;
|
|||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.BasicPluralType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link FunctionReturnTypeResolver} that resolves the array type based on an argument.
|
||||
* The inferred type and implied type have precedence though.
|
||||
|
@ -37,10 +40,12 @@ public class ArrayViaArgumentReturnTypeResolver implements FunctionReturnTypeRes
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final MappingModelExpressible<?> inferredType = inferredTypeSupplier.get();
|
||||
final MappingModelExpressible<?> inferredType = converter == null
|
||||
? null
|
||||
: converter.resolveFunctionImpliedReturnType();
|
||||
if ( inferredType != null ) {
|
||||
if ( inferredType instanceof ReturnableType<?> ) {
|
||||
return (ReturnableType<?>) inferredType;
|
||||
|
|
|
@ -14,10 +14,13 @@ import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
|||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link FunctionReturnTypeResolver} that resolves an array type based on the arguments,
|
||||
* which are supposed to be of the element type. The inferred type and implied type have precedence though.
|
||||
|
@ -41,10 +44,12 @@ public class ArrayViaElementArgumentReturnTypeResolver implements FunctionReturn
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final MappingModelExpressible<?> inferredType = inferredTypeSupplier.get();
|
||||
final MappingModelExpressible<?> inferredType = converter == null
|
||||
? null
|
||||
: converter.resolveFunctionImpliedReturnType();
|
||||
if ( inferredType != null ) {
|
||||
if ( inferredType instanceof ReturnableType<?> ) {
|
||||
return (ReturnableType<?>) inferredType;
|
||||
|
|
|
@ -15,11 +15,14 @@ import org.hibernate.metamodel.model.domain.DomainType;
|
|||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.BasicPluralType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link FunctionReturnTypeResolver} that resolves the array element type based on an argument.
|
||||
* The inferred type and implied type have precedence though.
|
||||
|
@ -37,10 +40,12 @@ public class ElementViaArrayArgumentReturnTypeResolver implements FunctionReturn
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final MappingModelExpressible<?> inferredType = inferredTypeSupplier.get();
|
||||
final MappingModelExpressible<?> inferredType = converter == null
|
||||
? null
|
||||
: converter.resolveFunctionImpliedReturnType();
|
||||
if ( inferredType != null ) {
|
||||
if ( inferredType instanceof ReturnableType<?> ) {
|
||||
return (ReturnableType<?>) inferredType;
|
||||
|
|
|
@ -278,6 +278,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
containingTableExpression = rootTableExpression;
|
||||
columnExpression = rootTableKeyColumnNames[ columnPosition ];
|
||||
}
|
||||
final NavigableRole role = navigableRole.append( bootPropertyDescriptor.getName() );
|
||||
final SelectablePath selectablePath;
|
||||
final String columnDefinition;
|
||||
final Long length;
|
||||
|
@ -310,18 +311,18 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
|
||||
attributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
role,
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
declarer,
|
||||
(BasicType<?>) subtype,
|
||||
basicValue.getResolution().getLegacyResolvedBasicType(),
|
||||
containingTableExpression,
|
||||
columnExpression,
|
||||
selectablePath,
|
||||
selectable.isFormula(),
|
||||
selectable.getCustomReadExpression(),
|
||||
selectable.getWriteExpr( ( (BasicType<?>) subtype ).getJdbcMapping(), dialect ),
|
||||
selectable.getWriteExpr( basicValue.getResolution().getJdbcMapping(), dialect ),
|
||||
columnDefinition,
|
||||
length,
|
||||
precision,
|
||||
|
|
|
@ -5702,6 +5702,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
if ( attrType instanceof BasicType ) {
|
||||
final NavigableRole role = getNavigableRole().append( bootProperty.getName() );
|
||||
final String attrColumnExpression;
|
||||
final boolean isAttrColumnExpressionFormula;
|
||||
final String customReadExpr;
|
||||
|
@ -5774,12 +5775,12 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
return MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
attrName,
|
||||
getNavigableRole().append( bootProperty.getName() ),
|
||||
role,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootProperty,
|
||||
this,
|
||||
(BasicType<?>) attrType,
|
||||
(BasicType<?>) value.getType(),
|
||||
tableExpression,
|
||||
attrColumnExpression,
|
||||
null,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.criteria;
|
||||
|
||||
import jakarta.persistence.TupleElement;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
@ -17,10 +18,10 @@ import org.hibernate.type.descriptor.java.JavaType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JpaTupleElement<T> extends TupleElement<T>, JpaCriteriaNode {
|
||||
JavaType<T> getJavaTypeDescriptor();
|
||||
@Nullable JavaType<T> getJavaTypeDescriptor();
|
||||
|
||||
@Override
|
||||
default Class<? extends T> getJavaType() {
|
||||
default @Nullable Class<? extends T> getJavaType() {
|
||||
// todo (6.0) : can this signature just return `Class<T>`?
|
||||
return getJavaTypeDescriptor() == null ? null : getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Representation of a function call in the SQL AST for impls that know how to
|
||||
* render themselves.
|
||||
|
@ -44,8 +46,8 @@ public class SelfRenderingFunctionSqlAstExpression
|
|||
private final String functionName;
|
||||
private final FunctionRenderer renderer;
|
||||
private final List<? extends SqlAstNode> sqlAstArguments;
|
||||
private final ReturnableType<?> type;
|
||||
private final JdbcMappingContainer expressible;
|
||||
private final @Nullable ReturnableType<?> type;
|
||||
private final @Nullable JdbcMappingContainer expressible;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #SelfRenderingFunctionSqlAstExpression(String, FunctionRenderer, List, ReturnableType, JdbcMappingContainer)} instead
|
||||
|
@ -55,8 +57,8 @@ public class SelfRenderingFunctionSqlAstExpression
|
|||
String functionName,
|
||||
FunctionRenderingSupport renderer,
|
||||
List<? extends SqlAstNode> sqlAstArguments,
|
||||
ReturnableType<?> type,
|
||||
JdbcMappingContainer expressible) {
|
||||
@Nullable ReturnableType<?> type,
|
||||
@Nullable JdbcMappingContainer expressible) {
|
||||
this.functionName = functionName;
|
||||
this.renderer = renderer::render;
|
||||
this.sqlAstArguments = sqlAstArguments;
|
||||
|
@ -69,8 +71,8 @@ public class SelfRenderingFunctionSqlAstExpression
|
|||
String functionName,
|
||||
FunctionRenderer renderer,
|
||||
List<? extends SqlAstNode> sqlAstArguments,
|
||||
ReturnableType<?> type,
|
||||
JdbcMappingContainer expressible) {
|
||||
@Nullable ReturnableType<?> type,
|
||||
@Nullable JdbcMappingContainer expressible) {
|
||||
this.functionName = functionName;
|
||||
this.renderer = renderer;
|
||||
this.sqlAstArguments = sqlAstArguments;
|
||||
|
@ -108,7 +110,7 @@ public class SelfRenderingFunctionSqlAstExpression
|
|||
return renderer;
|
||||
}
|
||||
|
||||
protected ReturnableType<?> getType() {
|
||||
protected @Nullable ReturnableType<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,14 @@ package org.hibernate.query.sqm.internal;
|
|||
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
public class NoParamSqmCopyContext extends SimpleSqmCopyContext {
|
||||
@Override
|
||||
public <T> T getCopy(T original) {
|
||||
public <T> @Nullable T getCopy(T original) {
|
||||
if ( original instanceof SqmParameter<?> ) {
|
||||
return original;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import java.util.IdentityHashMap;
|
|||
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
|
@ -18,7 +20,7 @@ public class SimpleSqmCopyContext implements SqmCopyContext {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <T> T getCopy(T original) {
|
||||
public <T> @Nullable T getCopy(T original) {
|
||||
return (T) map.get( original );
|
||||
}
|
||||
|
||||
|
|
|
@ -336,10 +336,12 @@ public class TypecheckUtil {
|
|||
* @see TypecheckUtil#assertAssignable(String, SqmPath, SqmTypedNode, SessionFactoryImplementor)
|
||||
*/
|
||||
public static void assertComparable(Expression<?> x, Expression<?> y, SessionFactoryImplementor factory) {
|
||||
SqmExpression<?> left = (SqmExpression<?>) x;
|
||||
SqmExpression<?> right = (SqmExpression<?>) y;
|
||||
if ( left.getTupleLength() != null && right.getTupleLength() != null
|
||||
&& left.getTupleLength().intValue() != right.getTupleLength().intValue() ) {
|
||||
final SqmExpression<?> left = (SqmExpression<?>) x;
|
||||
final SqmExpression<?> right = (SqmExpression<?>) y;
|
||||
final Integer leftTupleLength = left.getTupleLength();
|
||||
final Integer rightTupleLength;
|
||||
if ( leftTupleLength != null && ( rightTupleLength = right.getTupleLength() ) != null
|
||||
&& leftTupleLength.intValue() != rightTupleLength.intValue() ) {
|
||||
throw new SemanticException( "Cannot compare tuples of different lengths" );
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.query.sqm.produce.function;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.sql.FakeSqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -16,6 +18,8 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Pluggable strategy for resolving a function return type for a specific call.
|
||||
*
|
||||
|
@ -32,10 +36,10 @@ public interface FunctionReturnTypeResolver {
|
|||
* of `some_function`.
|
||||
*
|
||||
* @return The resolved type.
|
||||
* @deprecated Use {@link #resolveFunctionReturnType(ReturnableType, Supplier, List, TypeConfiguration)} instead
|
||||
* @deprecated Use {@link #resolveFunctionReturnType(ReturnableType, SqmToSqlAstConverter, List, TypeConfiguration)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
default ReturnableType<?> resolveFunctionReturnType(
|
||||
default @Nullable ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
|
@ -52,13 +56,44 @@ public interface FunctionReturnTypeResolver {
|
|||
* of `some_function`.
|
||||
*
|
||||
* @return The resolved type.
|
||||
* @deprecated Use {@link #resolveFunctionReturnType(ReturnableType, SqmToSqlAstConverter, List, TypeConfiguration)} instead
|
||||
*/
|
||||
default ReturnableType<?> resolveFunctionReturnType(
|
||||
@Deprecated(forRemoval = true)
|
||||
default @Nullable ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, arguments, typeConfiguration );
|
||||
return resolveFunctionReturnType( impliedType, new FakeSqmToSqlAstConverter( null ) {
|
||||
@Override
|
||||
public MappingModelExpressible<?> resolveFunctionImpliedReturnType() {
|
||||
return inferredTypeSupplier.get();
|
||||
}
|
||||
}, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the return type for a function given its context-implied type and
|
||||
* the arguments to this call.
|
||||
* <p>
|
||||
* The <em>context-implied</em> type is the type implied by where the function
|
||||
* occurs in the query. E.g., for an equality predicate (`something = some_function`)
|
||||
* the implied type of the return from `some_function` would be defined by the type
|
||||
* of `some_function`.
|
||||
*
|
||||
* @return The resolved type.
|
||||
*/
|
||||
default @Nullable ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType(
|
||||
impliedType,
|
||||
converter == null ? () -> null : converter::resolveFunctionImpliedReturnType,
|
||||
arguments,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
|||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.NullSqmExpressible;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -26,6 +27,8 @@ import org.hibernate.sql.ast.tree.expression.Expression;
|
|||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -51,15 +54,7 @@ public class StandardFunctionReturnTypeResolvers {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return isAssignableTo( invariantType, impliedType ) ? impliedType : invariantType;
|
||||
|
@ -84,15 +79,7 @@ public class StandardFunctionReturnTypeResolvers {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
ReturnableType<?> argType = extractArgumentType( arguments, argPosition );
|
||||
|
@ -133,15 +120,7 @@ public class StandardFunctionReturnTypeResolvers {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
for ( int i = 0; i < arguments.size(); i++ ) {
|
||||
|
|
|
@ -5364,6 +5364,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return inferredType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInTypeInference() {
|
||||
return inImpliedResultTypeInference || inTypeInference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressible<?> resolveFunctionImpliedReturnType() {
|
||||
if ( inImpliedResultTypeInference || functionImpliedResultTypeAccess == null ) {
|
||||
|
|
|
@ -95,6 +95,11 @@ public class FakeSqmToSqlAstConverter extends BaseSemanticQueryWalker implements
|
|||
public void registerQueryTransformer(QueryTransformer transformer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInTypeInference() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressible<?> resolveFunctionImpliedReturnType() {
|
||||
return null;
|
||||
|
|
|
@ -35,6 +35,12 @@ public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAs
|
|||
|
||||
void registerQueryTransformer(QueryTransformer transformer);
|
||||
|
||||
/**
|
||||
* Returns whether the state of the translation is currently in type inference mode.
|
||||
* This is useful to avoid type inference based on other incomplete inference information.
|
||||
*/
|
||||
boolean isInTypeInference();
|
||||
|
||||
/**
|
||||
* Returns the function return type implied from the context within which it is used.
|
||||
* If there is no current function being processed or no context implied type, the return is <code>null</code>.
|
||||
|
|
|
@ -10,12 +10,14 @@ import org.hibernate.Incubating;
|
|||
import org.hibernate.query.sqm.internal.NoParamSqmCopyContext;
|
||||
import org.hibernate.query.sqm.internal.SimpleSqmCopyContext;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface SqmCopyContext {
|
||||
|
||||
<T> T getCopy(T original);
|
||||
<T> @Nullable T getCopy(T original);
|
||||
|
||||
<T> T registerCopy(T original, T copy);
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.query.sqm.tree;
|
|||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Optional contract for SqmNode implementations which are
|
||||
* typed
|
||||
|
@ -19,17 +21,17 @@ public interface SqmTypedNode<T> extends SqmNode, SqmExpressibleAccessor<T>, Sqm
|
|||
/**
|
||||
* The Java type descriptor for this node.
|
||||
*/
|
||||
default JavaType<T> getNodeJavaType() {
|
||||
default @Nullable JavaType<T> getNodeJavaType() {
|
||||
final SqmExpressible<T> nodeType = getNodeType();
|
||||
return nodeType != null ? nodeType.getExpressibleJavaType() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
default SqmExpressible<T> getExpressible() {
|
||||
default @Nullable SqmExpressible<T> getExpressible() {
|
||||
return getNodeType();
|
||||
}
|
||||
|
||||
SqmExpressible<T> getNodeType();
|
||||
@Nullable SqmExpressible<T> getNodeType();
|
||||
|
||||
@Override
|
||||
SqmTypedNode<T> copy(SqmCopyContext context);
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.internal.util.NullnessUtil;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
|
@ -79,12 +80,12 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
|
||||
@Override
|
||||
public SqmPathSource<T> getNodeType() {
|
||||
return (SqmPathSource<T>) super.getNodeType();
|
||||
return (SqmPathSource<T>) NullnessUtil.castNonNull( super.getNodeType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<T> getReferencedPathSource() {
|
||||
return (SqmPathSource<T>) super.getNodeType();
|
||||
return (SqmPathSource<T>) NullnessUtil.castNonNull( super.getNodeType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.function.Consumer;
|
|||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.persistence.metamodel.PluralAttribute;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
|
@ -104,7 +105,7 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
|
|||
SqmPathSource<T> getNodeType();
|
||||
|
||||
@Override
|
||||
default void applyInferableType(SqmExpressible<?> type) {
|
||||
default void applyInferableType(@Nullable SqmExpressible<?> type) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType2;
|
||||
|
||||
|
@ -28,7 +29,7 @@ import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType2;
|
|||
*/
|
||||
public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> implements SqmExpression<T> {
|
||||
|
||||
public AbstractSqmExpression(SqmExpressible<? super T> type, NodeBuilder criteriaBuilder) {
|
||||
public AbstractSqmExpression(@Nullable SqmExpressible<? super T> type, NodeBuilder criteriaBuilder) {
|
||||
super( type, criteriaBuilder );
|
||||
}
|
||||
|
||||
|
@ -38,10 +39,10 @@ public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> i
|
|||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressible<?> type) {
|
||||
public void applyInferableType(@Nullable SqmExpressible<?> type) {
|
||||
}
|
||||
|
||||
protected void internalApplyInferableType(SqmExpressible<?> newType) {
|
||||
protected void internalApplyInferableType(@Nullable SqmExpressible<?> newType) {
|
||||
SqmTreeCreationLogger.LOGGER.debugf(
|
||||
"Applying inferable type to SqmExpression [%s] : %s -> %s",
|
||||
this,
|
||||
|
@ -138,13 +139,7 @@ public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> i
|
|||
}
|
||||
|
||||
@Override
|
||||
public JpaSelection<T> alias(String name) {
|
||||
setAlias( name );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<T> getJavaTypeDescriptor() {
|
||||
public @Nullable JavaType<T> getJavaTypeDescriptor() {
|
||||
return getNodeType() == null ? null : getNodeType().getExpressibleJavaType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.hibernate.query.BindableType;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Common support for SqmParameter impls
|
||||
*
|
||||
|
@ -28,7 +30,7 @@ public abstract class AbstractSqmParameter<T> extends AbstractSqmExpression<T> i
|
|||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressible<?> type) {
|
||||
public void applyInferableType(@Nullable SqmExpressible<?> type) {
|
||||
if ( type != null ) {
|
||||
if ( type instanceof PluralPersistentAttribute ) {
|
||||
final PluralPersistentAttribute<?, ?, ?> pluralPersistentAttribute =
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.hibernate.query.sqm.SqmExpressible;
|
|||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
@ -25,7 +27,7 @@ public class SqmAny<T> extends AbstractSqmExpression<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressible<T> getNodeType() {
|
||||
public @Nullable SqmExpressible<T> getNodeType() {
|
||||
return subquery.getNodeType();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.hibernate.query.sqm.SqmExpressible;
|
|||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
@ -25,7 +27,7 @@ public class SqmEvery<T> extends AbstractSqmExpression<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressible<T> getNodeType() {
|
||||
public @Nullable SqmExpressible<T> getNodeType() {
|
||||
return subquery.getNodeType();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.math.BigInteger;
|
|||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
|
@ -40,7 +41,7 @@ public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>
|
|||
* Can change as a result of calls to {@link #applyInferableType}
|
||||
*/
|
||||
@Override
|
||||
SqmExpressible<T> getNodeType();
|
||||
@Nullable SqmExpressible<T> getNodeType();
|
||||
|
||||
/**
|
||||
* Used to apply type information based on the expression's usage
|
||||
|
@ -51,7 +52,7 @@ public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>
|
|||
* an implicit cast)
|
||||
*/
|
||||
@Internal
|
||||
void applyInferableType(SqmExpressible<?> type);
|
||||
void applyInferableType(@Nullable SqmExpressible<?> type);
|
||||
|
||||
@Override
|
||||
default void visitSubSelectableNodes(Consumer<SqmSelectableNode<?>> jpaSelectionConsumer) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -111,7 +112,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressible<?> type) {
|
||||
public void applyInferableType(@Nullable SqmExpressible<?> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.math.BigInteger;
|
|||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.util.NullnessUtil;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
|
@ -67,7 +68,7 @@ public class SqmHqlNumericLiteral<N extends Number> extends SqmLiteral<N> {
|
|||
|
||||
@Override
|
||||
public BasicDomainType<N> getNodeType() {
|
||||
return (BasicDomainType<N>) super.getNodeType();
|
||||
return (BasicDomainType<N>) NullnessUtil.castNonNull( super.getNodeType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,8 @@ import org.hibernate.query.sqm.SqmExpressible;
|
|||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
* @author Marco Belladelli
|
||||
|
@ -86,7 +88,7 @@ public class SqmOver<T> extends AbstractSqmExpression<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressible<T> getNodeType() {
|
||||
public @Nullable SqmExpressible<T> getNodeType() {
|
||||
return expression.getNodeType();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.criteria.JpaParameterExpression;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
|
@ -65,9 +64,6 @@ public interface SqmParameter<T> extends SqmExpression<T>, JpaParameterExpressio
|
|||
*/
|
||||
BindableType<T> getAnticipatedType();
|
||||
|
||||
@Override
|
||||
SqmExpressible<T> getNodeType();
|
||||
|
||||
/**
|
||||
* Make a copy
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Base support for {@link JpaSelection} impls.
|
||||
*
|
||||
|
@ -21,7 +23,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
|||
public abstract class AbstractJpaSelection<T>
|
||||
extends AbstractJpaTupleElement<T>
|
||||
implements SqmSelectableNode<T>, JpaSelection<T> {
|
||||
protected AbstractJpaSelection(SqmExpressible<? super T> sqmExpressible, NodeBuilder criteriaBuilder) {
|
||||
protected AbstractJpaSelection(@Nullable SqmExpressible<? super T> sqmExpressible, NodeBuilder criteriaBuilder) {
|
||||
super( sqmExpressible, criteriaBuilder );
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
|||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Base support for {@link JpaTupleElement} impls
|
||||
*
|
||||
|
@ -22,10 +24,10 @@ public abstract class AbstractJpaTupleElement<T>
|
|||
extends AbstractSqmNode
|
||||
implements SqmVisitableNode, JpaTupleElement<T> {
|
||||
|
||||
private SqmExpressible<T> expressibleType;
|
||||
private String alias;
|
||||
private @Nullable SqmExpressible<T> expressibleType;
|
||||
private @Nullable String alias;
|
||||
|
||||
protected AbstractJpaTupleElement(SqmExpressible<? super T> expressibleType, NodeBuilder criteriaBuilder) {
|
||||
protected AbstractJpaTupleElement(@Nullable SqmExpressible<? super T> expressibleType, NodeBuilder criteriaBuilder) {
|
||||
super( criteriaBuilder );
|
||||
setExpressibleType( expressibleType );
|
||||
}
|
||||
|
@ -35,22 +37,22 @@ public abstract class AbstractJpaTupleElement<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
public @Nullable String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected access to set the alias.
|
||||
*/
|
||||
protected void setAlias(String alias) {
|
||||
protected void setAlias(@Nullable String alias) {
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
public SqmExpressible<T> getNodeType() {
|
||||
public @Nullable SqmExpressible<T> getNodeType() {
|
||||
return expressibleType;
|
||||
}
|
||||
|
||||
protected final void setExpressibleType(SqmExpressible<?> expressibleType) {
|
||||
protected final void setExpressibleType(@Nullable SqmExpressible<?> expressibleType) {
|
||||
//noinspection unchecked
|
||||
this.expressibleType = (SqmExpressible<T>) expressibleType;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ import jakarta.persistence.criteria.Predicate;
|
|||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Selection;
|
||||
import jakarta.persistence.criteria.SetJoin;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -600,12 +601,12 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressible<T> getNodeType() {
|
||||
public @Nullable SqmExpressible<T> getNodeType() {
|
||||
return expressibleType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressible<?> type) {
|
||||
public void applyInferableType(@Nullable SqmExpressible<?> type) {
|
||||
//noinspection unchecked
|
||||
expressibleType = (SqmExpressible<T>) type;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.collection.spi.MapSemantics;
|
|||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
|
||||
import org.hibernate.type.descriptor.java.ArrayJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -58,9 +59,14 @@ public class CollectionJavaType<C> extends AbstractClassJavaType<C> {
|
|||
TypeConfiguration typeConfiguration) {
|
||||
final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
final JavaTypeRegistry javaTypeRegistry = typeConfiguration.getJavaTypeRegistry();
|
||||
final JavaType<Object> valueDescriptor = javaTypeRegistry.resolveDescriptor( actualTypeArguments[actualTypeArguments.length - 1] );
|
||||
switch ( semantics.getCollectionClassification() ) {
|
||||
case ARRAY:
|
||||
//noinspection unchecked
|
||||
return (JavaType<C>) new ArrayJavaType<>(
|
||||
javaTypeRegistry.resolveDescriptor(
|
||||
( (Class<?>) parameterizedType.getRawType() ).getComponentType()
|
||||
)
|
||||
);
|
||||
case BAG:
|
||||
case ID_BAG:
|
||||
case LIST:
|
||||
|
@ -70,7 +76,7 @@ public class CollectionJavaType<C> extends AbstractClassJavaType<C> {
|
|||
//noinspection unchecked,rawtypes
|
||||
return new BasicCollectionJavaType(
|
||||
parameterizedType,
|
||||
valueDescriptor,
|
||||
javaTypeRegistry.resolveDescriptor( actualTypeArguments[actualTypeArguments.length - 1] ),
|
||||
semantics
|
||||
);
|
||||
|
||||
|
@ -82,7 +88,7 @@ public class CollectionJavaType<C> extends AbstractClassJavaType<C> {
|
|||
new MapMutabilityPlan<>(
|
||||
(MapSemantics<Map<Object, Object>, Object, Object>) semantics,
|
||||
javaTypeRegistry.resolveDescriptor( actualTypeArguments[0] ),
|
||||
valueDescriptor
|
||||
javaTypeRegistry.resolveDescriptor( actualTypeArguments[actualTypeArguments.length - 1] )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ public class JdbcTypeJavaClassMappings {
|
|||
workMap.put( SqlTypes.ARRAY, Array.class );
|
||||
workMap.put( SqlTypes.STRUCT, Struct.class );
|
||||
workMap.put( SqlTypes.REF, Ref.class );
|
||||
workMap.put( SqlTypes.JAVA_OBJECT, Class.class );
|
||||
workMap.put( SqlTypes.JAVA_OBJECT, Object.class );
|
||||
workMap.put( SqlTypes.ROWID, RowId.class );
|
||||
workMap.put( SqlTypes.SQLXML, SQLXML.class );
|
||||
workMap.put( SqlTypes.UUID, UUID.class );
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry;
|
||||
|
@ -48,6 +49,8 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
|
@ -137,15 +140,7 @@ public class DynamicParameterizedTypeTest {
|
|||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return resolveFunctionReturnType( impliedType, null, arguments, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnableType<?> resolveFunctionReturnType(
|
||||
ReturnableType<?> impliedType,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeSupplier,
|
||||
@Nullable SqmToSqlAstConverter converter,
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
SqmTypedNode<?> sqmTypedNode = arguments.get(0);
|
||||
|
|
|
@ -138,7 +138,7 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
|||
QueryEngine queryEngine) {
|
||||
super(
|
||||
orderByFragmentFunction,
|
||||
null,
|
||||
(sqlAppender, sqlAstArguments, returnType, walker) -> {},
|
||||
arguments,
|
||||
impliedResultType,
|
||||
orderByFragmentFunction.getArgumentsValidator(),
|
||||
|
|
|
@ -2558,9 +2558,14 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
// TODO: anything more we can do here? e.g. check constructor
|
||||
try {
|
||||
final Class<?> javaResultType = selection.getJavaType();
|
||||
final TypeElement typeElement = context.getTypeElementForFullyQualifiedName( javaResultType.getName() );
|
||||
final Types types = context.getTypeUtils();
|
||||
returnTypeCorrect = types.isAssignable( returnType, types.erasure( typeElement.asType() ) );
|
||||
if ( javaResultType == null ) {
|
||||
returnTypeCorrect = true;
|
||||
}
|
||||
else {
|
||||
final TypeElement typeElement = context.getTypeElementForFullyQualifiedName( javaResultType.getName() );
|
||||
final Types types = context.getTypeUtils();
|
||||
returnTypeCorrect = context.getTypeUtils().isAssignable( returnType, types.erasure( typeElement.asType() ) );
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
//ignore
|
||||
|
@ -2670,7 +2675,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
|
||||
private static boolean parameterMatches(VariableElement parameter, JpaSelection<?> item) {
|
||||
return parameterMatches( parameter.asType(), item.getJavaType() );
|
||||
final Class<?> javaType = item.getJavaType();
|
||||
return javaType != null && parameterMatches( parameter.asType(), javaType );
|
||||
}
|
||||
|
||||
private static boolean parameterMatches(TypeMirror parameterType, Class<?> itemType) {
|
||||
|
|
|
@ -104,8 +104,9 @@ class NamedQueryMethod implements MetaAttribute {
|
|||
else {
|
||||
final List<SqmSelectableNode<?>> items =
|
||||
select.getQuerySpec().getSelectClause().getSelectionItems();
|
||||
if ( items.size() == 1 ) {
|
||||
final String typeName = items.get(0).getExpressible().getTypeName();
|
||||
final SqmExpressible<?> expressible;
|
||||
if ( items.size() == 1 && ( expressible = items.get( 0 ).getExpressible() ) != null ) {
|
||||
final String typeName = expressible.getTypeName();
|
||||
final TypeElement entityType = entityType( typeName );
|
||||
return entityType == null ? typeName : entityType.getQualifiedName().toString();
|
||||
|
||||
|
|
Loading…
Reference in New Issue