HHH-17729 move validation of constructors in HQL instantiations to SemanticQueryBuilder
report SemanticExceptions with the query string fix some warnings in ReflectHelper
This commit is contained in:
parent
0bce456e3a
commit
24937b4e67
|
@ -9,14 +9,13 @@ package org.hibernate.boot.model;
|
|||
import org.hibernate.InstantiationException;
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
|
||||
import org.hibernate.type.spi.TypeBootstrapContext;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.internal.util.ReflectHelper.getConstructor;
|
||||
|
||||
/**
|
||||
* {@link BeanInstanceProducer} implementation for building beans related to custom types.
|
||||
*
|
||||
|
@ -33,7 +32,7 @@ public class TypeBeanInstanceProducer implements BeanInstanceProducer, TypeBoots
|
|||
@Override
|
||||
public <B> B produceBeanInstance(Class<B> beanType) {
|
||||
final Constructor<B> bootstrapContextAwareConstructor =
|
||||
getConstructor( beanType, TypeBootstrapContext.class );
|
||||
ReflectHelper.getConstructorOrNull( beanType, TypeBootstrapContext.class );
|
||||
if ( bootstrapContextAwareConstructor != null ) {
|
||||
try {
|
||||
return bootstrapContextAwareConstructor.newInstance( this );
|
||||
|
@ -43,7 +42,7 @@ public class TypeBeanInstanceProducer implements BeanInstanceProducer, TypeBoots
|
|||
}
|
||||
}
|
||||
else {
|
||||
final Constructor<B> constructor = getConstructor( beanType );
|
||||
final Constructor<B> constructor = ReflectHelper.getConstructorOrNull( beanType );
|
||||
if ( constructor != null ) {
|
||||
try {
|
||||
return constructor.newInstance();
|
||||
|
|
|
@ -27,8 +27,8 @@ public class CustomOptimizerDescriptor implements OptimizerDescriptor {
|
|||
return className;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public Class<? extends Optimizer> getOptimizerClass() throws ClassNotFoundException {
|
||||
return ReflectHelper.classForName( className );
|
||||
return (Class<? extends Optimizer>) ReflectHelper.classForName( className );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ import jakarta.persistence.Transient;
|
|||
@SuppressWarnings("unchecked")
|
||||
public final class ReflectHelper {
|
||||
|
||||
public static final Class[] NO_PARAM_SIGNATURE = ArrayHelper.EMPTY_CLASS_ARRAY;
|
||||
public static final Class<?>[] NO_PARAM_SIGNATURE = ArrayHelper.EMPTY_CLASS_ARRAY;
|
||||
|
||||
public static final Class[] SINGLE_OBJECT_PARAM_SIGNATURE = new Class[] { Object.class };
|
||||
public static final Class<?>[] SINGLE_OBJECT_PARAM_SIGNATURE = new Class[] { Object.class };
|
||||
|
||||
private static final Method OBJECT_EQUALS;
|
||||
private static final Method OBJECT_HASHCODE;
|
||||
|
@ -99,7 +99,7 @@ public final class ReflectHelper {
|
|||
* @return The equals method reference
|
||||
* @throws NoSuchMethodException Should indicate an attempt to extract equals method from interface.
|
||||
*/
|
||||
public static Method extractEqualsMethod(Class clazz) throws NoSuchMethodException {
|
||||
public static Method extractEqualsMethod(Class<?> clazz) throws NoSuchMethodException {
|
||||
return clazz.getMethod( "equals", SINGLE_OBJECT_PARAM_SIGNATURE );
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ public final class ReflectHelper {
|
|||
* @return The hashCode method reference
|
||||
* @throws NoSuchMethodException Should indicate an attempt to extract hashCode method from interface.
|
||||
*/
|
||||
public static Method extractHashCodeMethod(Class clazz) throws NoSuchMethodException {
|
||||
public static Method extractHashCodeMethod(Class<?> clazz) throws NoSuchMethodException {
|
||||
return clazz.getMethod( "hashCode", NO_PARAM_SIGNATURE );
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ public final class ReflectHelper {
|
|||
* @param clazz The class to check
|
||||
* @return True if clazz defines an equals override.
|
||||
*/
|
||||
public static boolean overridesEquals(Class clazz) {
|
||||
public static boolean overridesEquals(Class<?> clazz) {
|
||||
Method equals;
|
||||
try {
|
||||
equals = extractEqualsMethod( clazz );
|
||||
|
@ -137,7 +137,7 @@ public final class ReflectHelper {
|
|||
* @param clazz The class to check
|
||||
* @return True if clazz defines an hashCode override.
|
||||
*/
|
||||
public static boolean overridesHashCode(Class clazz) {
|
||||
public static boolean overridesHashCode(Class<?> clazz) {
|
||||
Method hashCode;
|
||||
try {
|
||||
hashCode = extractHashCodeMethod( clazz );
|
||||
|
@ -155,7 +155,7 @@ public final class ReflectHelper {
|
|||
* @param intf The interface to check it against.
|
||||
* @return True if the class does implement the interface, false otherwise.
|
||||
*/
|
||||
public static boolean implementsInterface(Class clazz, Class intf) {
|
||||
public static boolean implementsInterface(Class<?> clazz, Class<?> intf) {
|
||||
assert intf.isInterface() : "Interface to check was not an interface";
|
||||
return intf.isAssignableFrom( clazz );
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ public final class ReflectHelper {
|
|||
* @return The class reference.
|
||||
* @throws ClassNotFoundException From {@link Class#forName(String, boolean, ClassLoader)}.
|
||||
*/
|
||||
public static Class classForName(String name, Class caller) throws ClassNotFoundException {
|
||||
public static Class<?> classForName(String name, Class<?> caller) throws ClassNotFoundException {
|
||||
try {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
if ( classLoader != null ) {
|
||||
|
@ -198,7 +198,7 @@ public final class ReflectHelper {
|
|||
* or {@link org.hibernate.boot.spi.ClassLoaderAccess} should be preferred
|
||||
*/
|
||||
@Deprecated
|
||||
public static Class classForName(String name) throws ClassNotFoundException {
|
||||
public static Class<?> classForName(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
if ( classLoader != null ) {
|
||||
|
@ -217,7 +217,7 @@ public final class ReflectHelper {
|
|||
* @param member The member.
|
||||
* @return True if the member is publicly accessible, false otherwise.
|
||||
*/
|
||||
public static boolean isPublic(Class clazz, Member member) {
|
||||
public static boolean isPublic(Class<?> clazz, Member member) {
|
||||
return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() );
|
||||
}
|
||||
|
||||
|
@ -232,12 +232,12 @@ public final class ReflectHelper {
|
|||
*
|
||||
* @throws MappingException Indicates we were unable to locate the property.
|
||||
*/
|
||||
public static Class reflectedPropertyClass(
|
||||
public static Class<?> reflectedPropertyClass(
|
||||
String className,
|
||||
String name,
|
||||
ClassLoaderService classLoaderService) throws MappingException {
|
||||
try {
|
||||
Class clazz = classLoaderService.classForName( className );
|
||||
Class<?> clazz = classLoaderService.classForName( className );
|
||||
return getter( clazz, name ).getReturnTypeClass();
|
||||
}
|
||||
catch ( ClassLoadingException e ) {
|
||||
|
@ -266,11 +266,11 @@ public final class ReflectHelper {
|
|||
* @return The type of the property.
|
||||
* @throws MappingException Indicates we were unable to locate the property.
|
||||
*/
|
||||
public static Class reflectedPropertyClass(Class clazz, String name) throws MappingException {
|
||||
public static Class<?> reflectedPropertyClass(Class<?> clazz, String name) throws MappingException {
|
||||
return getter( clazz, name ).getReturnTypeClass();
|
||||
}
|
||||
|
||||
private static Getter getter(Class clazz, String name) throws MappingException {
|
||||
private static Getter getter(Class<?> clazz, String name) throws MappingException {
|
||||
return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( clazz, name, true ).getGetter();
|
||||
}
|
||||
|
||||
|
@ -304,7 +304,7 @@ public final class ReflectHelper {
|
|||
* @param clazz The class to check.
|
||||
* @return True if the class is abstract, false otherwise.
|
||||
*/
|
||||
public static boolean isAbstractClass(Class clazz) {
|
||||
public static boolean isAbstractClass(Class<?> clazz) {
|
||||
int modifier = clazz.getModifiers();
|
||||
return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier);
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ public final class ReflectHelper {
|
|||
* @param clazz The class to check.
|
||||
* @return True if the class is final, false otherwise.
|
||||
*/
|
||||
public static boolean isFinalClass(Class clazz) {
|
||||
public static boolean isFinalClass(Class<?> clazz) {
|
||||
return Modifier.isFinal( clazz.getModifiers() );
|
||||
}
|
||||
|
||||
|
@ -325,15 +325,19 @@ public final class ReflectHelper {
|
|||
*
|
||||
* @param clazz The class needing instantiation
|
||||
* @param types The types representing the required ctor param signature
|
||||
* @return The matching constructor.
|
||||
* @throws PropertyNotFoundException Indicates we could not locate an appropriate constructor (todo : again with PropertyNotFoundException???)
|
||||
* @return The matching constructor
|
||||
* @throws PropertyNotFoundException Indicates we could not locate an appropriate constructor
|
||||
*
|
||||
* @deprecated no longer used, since we moved away from the {@link Type} interface
|
||||
*/
|
||||
public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
|
||||
final Constructor[] candidates = clazz.getConstructors();
|
||||
Constructor constructor = null;
|
||||
// todo : again with PropertyNotFoundException???
|
||||
@Deprecated(since = "6", forRemoval = true)
|
||||
public static Constructor<?> getConstructor(Class<?> clazz, Type[] types) throws PropertyNotFoundException {
|
||||
final Constructor<?>[] candidates = clazz.getConstructors();
|
||||
Constructor<?> constructor = null;
|
||||
int numberOfMatchingConstructors = 0;
|
||||
for ( final Constructor candidate : candidates ) {
|
||||
final Class[] params = candidate.getParameterTypes();
|
||||
for ( final Constructor<?> candidate : candidates ) {
|
||||
final Class<?>[] params = candidate.getParameterTypes();
|
||||
if ( params.length == types.length ) {
|
||||
boolean found = true;
|
||||
for ( int j = 0; j < params.length; j++ ) {
|
||||
|
@ -361,9 +365,18 @@ public final class ReflectHelper {
|
|||
|
||||
}
|
||||
|
||||
public static <T> Constructor<T> getConstructor(
|
||||
/**
|
||||
* Retrieve a constructor for the given class, with arguments matching
|
||||
* the specified Java {@linkplain Class types}, or return {@code null}
|
||||
* if no such constructor exists.
|
||||
*
|
||||
* @param clazz The class needing instantiation
|
||||
* @param constructorArgs The types representing the required ctor param signature
|
||||
* @return The matching constructor, or {@code null}
|
||||
*/
|
||||
public static <T> Constructor<T> getConstructorOrNull(
|
||||
Class<T> clazz,
|
||||
Class... constructorArgs) {
|
||||
Class<?>... constructorArgs) {
|
||||
Constructor<T> constructor = null;
|
||||
try {
|
||||
constructor = clazz.getDeclaredConstructor( constructorArgs );
|
||||
|
@ -380,7 +393,7 @@ public final class ReflectHelper {
|
|||
return constructor;
|
||||
}
|
||||
|
||||
public static Method getMethod(Class clazz, Method method) {
|
||||
public static Method getMethod(Class<?> clazz, Method method) {
|
||||
try {
|
||||
return clazz.getMethod( method.getName(), method.getParameterTypes() );
|
||||
}
|
||||
|
@ -389,7 +402,7 @@ public final class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Method getMethod(Class clazz, String methodName, Class... paramTypes) {
|
||||
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
|
||||
try {
|
||||
return clazz.getMethod( methodName, paramTypes );
|
||||
}
|
||||
|
@ -398,9 +411,9 @@ public final class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Field findField(Class containerClass, String propertyName) {
|
||||
public static Field findField(Class<?> containerClass, String propertyName) {
|
||||
if ( containerClass == null ) {
|
||||
throw new IllegalArgumentException( "Class on which to find field [" + propertyName + "] cannot be null" );
|
||||
throw new IllegalArgumentException( "Class<?> on which to find field [" + propertyName + "] cannot be null" );
|
||||
}
|
||||
else if ( containerClass == Object.class ) {
|
||||
throw new IllegalArgumentException( "Illegal attempt to locate field [" + propertyName + "] on Object.class" );
|
||||
|
@ -430,7 +443,7 @@ public final class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private static Field locateField(Class clazz, String propertyName) {
|
||||
private static Field locateField(Class<?> clazz, String propertyName) {
|
||||
if ( clazz == null || Object.class.equals( clazz ) ) {
|
||||
return null;
|
||||
}
|
||||
|
@ -451,8 +464,8 @@ public final class ReflectHelper {
|
|||
return field != null && ( field.getModifiers() & Modifier.STATIC ) == Modifier.STATIC;
|
||||
}
|
||||
|
||||
public static Method findGetterMethod(Class containerClass, String propertyName) {
|
||||
Class checkClass = containerClass;
|
||||
public static Method findGetterMethod(Class<?> containerClass, String propertyName) {
|
||||
Class<?> checkClass = containerClass;
|
||||
Method getter = null;
|
||||
|
||||
if ( isRecord( containerClass ) ) {
|
||||
|
@ -497,10 +510,10 @@ public final class ReflectHelper {
|
|||
return getter;
|
||||
}
|
||||
|
||||
private static Method getGetterOrNull(Class[] interfaces, String propertyName) {
|
||||
private static Method getGetterOrNull(Class<?>[] interfaces, String propertyName) {
|
||||
Method getter = null;
|
||||
for ( int i = 0; getter == null && i < interfaces.length; ++i ) {
|
||||
final Class anInterface = interfaces[i];
|
||||
final Class<?> anInterface = interfaces[i];
|
||||
getter = getGetterOrNull( anInterface, propertyName );
|
||||
if ( getter == null ) {
|
||||
// if no getter found yet, check all implemented interfaces of interface
|
||||
|
@ -513,14 +526,14 @@ public final class ReflectHelper {
|
|||
/**
|
||||
* Find the method that can be used as the getter for this property.
|
||||
*
|
||||
* @param containerClass The Class which contains the property
|
||||
* @param containerClass The Class<?> which contains the property
|
||||
* @param propertyName The name of the property
|
||||
*
|
||||
* @return The getter method, or {@code null} if there is none.
|
||||
*
|
||||
* @throws MappingException If the {@code containerClass} has both a get- and an is- form.
|
||||
*/
|
||||
public static Method getGetterOrNull(Class containerClass, String propertyName) {
|
||||
public static Method getGetterOrNull(Class<?> containerClass, String propertyName) {
|
||||
if ( isRecord( containerClass ) ) {
|
||||
try {
|
||||
return containerClass.getMethod( propertyName, NO_PARAM_SIGNATURE );
|
||||
|
@ -583,7 +596,7 @@ public final class ReflectHelper {
|
|||
String propertyName,
|
||||
Method getMethod,
|
||||
String stemName) {
|
||||
// verify that the Class does not also define a method with the same stem name with 'is'
|
||||
// verify that the Class<?> does not also define a method with the same stem name with 'is'
|
||||
try {
|
||||
final Method isMethod = containerClass.getDeclaredMethod( "is" + stemName );
|
||||
if ( !Modifier.isStatic( isMethod.getModifiers() ) && isMethod.getAnnotation( Transient.class ) == null ) {
|
||||
|
@ -598,7 +611,7 @@ public final class ReflectHelper {
|
|||
|
||||
|
||||
public static void checkGetAndIsVariants(
|
||||
Class containerClass,
|
||||
Class<?> containerClass,
|
||||
String propertyName,
|
||||
Method getMethod,
|
||||
Method isMethod) {
|
||||
|
@ -608,7 +621,7 @@ public final class ReflectHelper {
|
|||
throw new MappingException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Class '%s' declares both 'get' [%s] and 'is' [%s] variants of getter for property '%s'",
|
||||
"Class<?> '%s' declares both 'get' [%s] and 'is' [%s] variants of getter for property '%s'",
|
||||
containerClass.getName(),
|
||||
getMethod,
|
||||
isMethod,
|
||||
|
@ -619,11 +632,11 @@ public final class ReflectHelper {
|
|||
}
|
||||
|
||||
public static void verifyNoGetVariantExists(
|
||||
Class containerClass,
|
||||
Class<?> containerClass,
|
||||
String propertyName,
|
||||
Method isMethod,
|
||||
String stemName) {
|
||||
// verify that the Class does not also define a method with the same stem name with 'is'
|
||||
// verify that the Class<?> does not also define a method with the same stem name with 'is'
|
||||
try {
|
||||
final Method getMethod = containerClass.getDeclaredMethod( "get" + stemName );
|
||||
// No such method should throw the caught exception. So if we get here, there was
|
||||
|
@ -636,7 +649,7 @@ public final class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Method getterMethodOrNull(Class containerJavaType, String propertyName) {
|
||||
public static Method getterMethodOrNull(Class<?> containerJavaType, String propertyName) {
|
||||
try {
|
||||
return findGetterMethod( containerJavaType, propertyName );
|
||||
}
|
||||
|
@ -645,8 +658,8 @@ public final class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Method setterMethodOrNull(final Class containerClass, final String propertyName, final Class propertyType) {
|
||||
Class checkClass = containerClass;
|
||||
public static Method setterMethodOrNull(final Class<?> containerClass, final String propertyName, final Class<?> propertyType) {
|
||||
Class<?> checkClass = containerClass;
|
||||
Method setter = null;
|
||||
|
||||
// check containerClass, and then its super types (if any)
|
||||
|
@ -670,8 +683,8 @@ public final class ReflectHelper {
|
|||
return setter; // might be null
|
||||
}
|
||||
|
||||
public static Method setterMethodOrNullBySetterName(final Class containerClass, final String setterName, final Class propertyType) {
|
||||
Class checkClass = containerClass;
|
||||
public static Method setterMethodOrNullBySetterName(final Class<?> containerClass, final String setterName, final Class<?> propertyType) {
|
||||
Class<?> checkClass = containerClass;
|
||||
Method setter = null;
|
||||
|
||||
// check containerClass, and then its super types (if any)
|
||||
|
@ -695,10 +708,10 @@ public final class ReflectHelper {
|
|||
return setter; // might be null
|
||||
}
|
||||
|
||||
private static Method setterOrNullBySetterName(Class[] interfaces, String setterName, Class propertyType) {
|
||||
private static Method setterOrNullBySetterName(Class<?>[] interfaces, String setterName, Class<?> propertyType) {
|
||||
Method setter = null;
|
||||
for ( int i = 0; setter == null && i < interfaces.length; ++i ) {
|
||||
final Class anInterface = interfaces[i];
|
||||
final Class<?> anInterface = interfaces[i];
|
||||
setter = setterOrNullBySetterName( anInterface, setterName, propertyType );
|
||||
if ( setter == null ) {
|
||||
// if no setter found yet, check all implemented interfaces of interface
|
||||
|
@ -708,7 +721,7 @@ public final class ReflectHelper {
|
|||
return setter;
|
||||
}
|
||||
|
||||
private static Method setterOrNullBySetterName(Class theClass, String setterName, Class propertyType) {
|
||||
private static Method setterOrNullBySetterName(Class<?> theClass, String setterName, Class<?> propertyType) {
|
||||
Method potentialSetter = null;
|
||||
|
||||
for ( Method method : theClass.getDeclaredMethods() ) {
|
||||
|
@ -724,7 +737,7 @@ public final class ReflectHelper {
|
|||
return potentialSetter;
|
||||
}
|
||||
|
||||
public static Method findSetterMethod(final Class containerClass, final String propertyName, final Class propertyType) {
|
||||
public static Method findSetterMethod(final Class<?> containerClass, final String propertyName, final Class<?> propertyType) {
|
||||
final Method setter = setterMethodOrNull( containerClass, propertyName, propertyType );
|
||||
if ( setter == null ) {
|
||||
throw new PropertyNotFoundException(
|
||||
|
@ -739,10 +752,10 @@ public final class ReflectHelper {
|
|||
return setter;
|
||||
}
|
||||
|
||||
private static Method setterOrNull(Class[] interfaces, String propertyName, Class propertyType) {
|
||||
private static Method setterOrNull(Class<?>[] interfaces, String propertyName, Class<?> propertyType) {
|
||||
Method setter = null;
|
||||
for ( int i = 0; setter == null && i < interfaces.length; ++i ) {
|
||||
final Class anInterface = interfaces[i];
|
||||
final Class<?> anInterface = interfaces[i];
|
||||
setter = setterOrNull( anInterface, propertyName, propertyType );
|
||||
if ( setter == null ) {
|
||||
// if no setter found yet, check all implemented interfaces of interface
|
||||
|
@ -752,7 +765,7 @@ public final class ReflectHelper {
|
|||
return setter;
|
||||
}
|
||||
|
||||
private static Method setterOrNull(Class theClass, String propertyName, Class propertyType) {
|
||||
private static Method setterOrNull(Class<?> theClass, String propertyName, Class<?> propertyType) {
|
||||
Method potentialSetter = null;
|
||||
|
||||
for ( Method method : theClass.getDeclaredMethods() ) {
|
||||
|
@ -775,7 +788,7 @@ public final class ReflectHelper {
|
|||
/**
|
||||
* Similar to {@link #getterMethodOrNull}, except that here we are just looking for the
|
||||
* corresponding getter for a field (defined as field access) if one exists.
|
||||
*
|
||||
* <p>
|
||||
* We do not look at supers, although conceivably the super could declare the method
|
||||
* as an abstract - but again, that is such an edge case...
|
||||
*/
|
||||
|
@ -876,7 +889,7 @@ public final class ReflectHelper {
|
|||
return (Class<T>) ( (ParameterizedType) type ).getRawType();
|
||||
}
|
||||
else if ( type instanceof TypeVariable ) {
|
||||
return getClass( ( (TypeVariable) type ).getBounds()[0] );
|
||||
return getClass( ( (TypeVariable<?>) type ).getBounds()[0] );
|
||||
}
|
||||
else if ( type instanceof WildcardType ) {
|
||||
return getClass( ( (WildcardType) type ).getUpperBounds()[0] );
|
||||
|
|
|
@ -25,7 +25,7 @@ public class EmbeddableInstantiatorRecordStandard extends AbstractPojoInstantiat
|
|||
super( javaType );
|
||||
|
||||
final Class<?>[] componentTypes = ReflectHelper.getRecordComponentTypes( javaType );
|
||||
this.constructor = ReflectHelper.getConstructor( javaType, componentTypes );
|
||||
this.constructor = ReflectHelper.getConstructorOrNull( javaType, componentTypes );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.time.ZonedDateTime;
|
|||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -88,7 +87,6 @@ import org.hibernate.query.sqm.ParsingException;
|
|||
import org.hibernate.query.sqm.SetOperator;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.SqmTreeCreationLogger;
|
||||
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
|
||||
import org.hibernate.query.sqm.TemporalUnit;
|
||||
|
@ -108,7 +106,6 @@ import org.hibernate.query.sqm.produce.function.FunctionArgumentException;
|
|||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.spi.ParameterDeclarationContext;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.SqmQuery;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
|
@ -214,9 +211,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelection;
|
|||
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
import org.hibernate.query.sqm.tree.update.SqmAssignment;
|
||||
import org.hibernate.query.sqm.tree.update.SqmSetClause;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
import org.hibernate.sql.ast.tree.cte.CteMaterialization;
|
||||
import org.hibernate.sql.ast.tree.cte.CteSearchClauseKind;
|
||||
|
@ -316,14 +311,17 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
HqlParser.StatementContext hqlParseTree,
|
||||
Class<R> expectedResultType,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext) {
|
||||
return new SemanticQueryBuilder<>( expectedResultType, creationOptions, creationContext ).visitStatement( hqlParseTree );
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
return new SemanticQueryBuilder<>( expectedResultType, creationOptions, creationContext, query )
|
||||
.visitStatement( hqlParseTree );
|
||||
}
|
||||
|
||||
private final Class<R> expectedResultType;
|
||||
private final String expectedResultEntity;
|
||||
private final SqmCreationOptions creationOptions;
|
||||
private final SqmCreationContext creationContext;
|
||||
private final String query;
|
||||
|
||||
private final Stack<DotIdentifierConsumer> dotIdentifierConsumerStack;
|
||||
|
||||
|
@ -347,26 +345,30 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SemanticQueryBuilder(
|
||||
Class<R> expectedResultType,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext) {
|
||||
this( expectedResultType, null, creationOptions, creationContext );
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this( expectedResultType, null, creationOptions, creationContext, query );
|
||||
}
|
||||
|
||||
public SemanticQueryBuilder(
|
||||
String expectedResultEntity,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext) {
|
||||
this( null, expectedResultEntity, creationOptions, creationContext );
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this( null, expectedResultEntity, creationOptions, creationContext, query );
|
||||
}
|
||||
|
||||
private SemanticQueryBuilder(
|
||||
Class<R> expectedResultType,
|
||||
String expectedResultEntity,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext) {
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this.expectedResultType = expectedResultType;
|
||||
this.expectedResultEntity = expectedResultEntity;
|
||||
this.creationOptions = creationOptions;
|
||||
this.creationContext = creationContext;
|
||||
this.query = query;
|
||||
this.dotIdentifierConsumerStack = new StandardStack<>(
|
||||
DotIdentifierConsumer.class,
|
||||
new BasicDotIdentifierConsumer( this )
|
||||
|
@ -476,10 +478,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final SqmRoot<R> root = visitTargetEntity( dmlTargetContext );
|
||||
if ( root.getModel() instanceof SqmPolymorphicRootDescriptor<?> ) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
"Target type '%s' in 'insert' statement is not an entity",
|
||||
root.getModel().getHibernateEntityName()
|
||||
)
|
||||
"Target type '" + root.getModel().getHibernateEntityName()
|
||||
+ "' in 'insert' statement is not an entity",
|
||||
query
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -587,6 +588,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
return null;
|
||||
}
|
||||
final SqmCreationProcessingState processingState = processingStateStack.getCurrent();
|
||||
@SuppressWarnings("unchecked")
|
||||
final SqmInsertStatement<R> statement = (SqmInsertStatement<R>) processingState.getProcessingQuery();
|
||||
final SqmConflictClause<R> conflictClause = new SqmConflictClause<>( statement );
|
||||
final HqlParser.ConflictTargetContext conflictTargetContext = ctx.conflictTarget();
|
||||
|
@ -869,7 +871,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
"Cycle attribute '%s' not found in the CTE %s",
|
||||
attributeName,
|
||||
cteDefinition.getName()
|
||||
)
|
||||
),
|
||||
query
|
||||
);
|
||||
}
|
||||
cycleAttributes.add( attribute );
|
||||
|
@ -929,7 +932,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
"Search attribute '%s' not found in the CTE %s",
|
||||
attributeName,
|
||||
cteDefinition.getName()
|
||||
)
|
||||
),
|
||||
query
|
||||
);
|
||||
}
|
||||
SortDirection sortOrder = SortDirection.ASCENDING;
|
||||
|
@ -946,7 +950,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
sortOrder = SortDirection.DESCENDING;
|
||||
break;
|
||||
default:
|
||||
throw new SemanticException( "Unrecognized sort ordering: " + sortCtx.getText() );
|
||||
throw new UnsupportedOperationException( "Unrecognized sort ordering: " + sortCtx.getText() );
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
@ -960,7 +964,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
nullPrecedence = NullPrecedence.LAST;
|
||||
break;
|
||||
default:
|
||||
throw new SemanticException( "Unrecognized null precedence: " + nullsPrecedenceContext.getText() );
|
||||
throw new UnsupportedOperationException( "Unrecognized null precedence: " + nullsPrecedenceContext.getText() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1169,7 +1173,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
if ( processingStateStack.depth() > 1 && orderByClause == null ) {
|
||||
throw new SemanticException(
|
||||
"A 'limit', 'offset', or 'fetch' clause requires an 'order by' clause when used in a subquery"
|
||||
"A 'limit', 'offset', or 'fetch' clause requires an 'order by' clause when used in a subquery",
|
||||
query
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1191,7 +1196,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
sqmQueryPart.setFetchExpression( (SqmExpression<? extends Number>) visitLimitClause(limitClauseContext) );
|
||||
}
|
||||
else {
|
||||
throw new SemanticException("The 'limit' and 'fetch' clauses may not be used together" );
|
||||
throw new SemanticException("The 'limit' and 'fetch' clauses may not be used together", query );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1258,16 +1263,16 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
if ( expectedResultEntity != null ) {
|
||||
final EntityDomainType<R> entityDescriptor = jpaMetamodel.entity( expectedResultEntity );
|
||||
if ( entityDescriptor == null ) {
|
||||
throw new SemanticException("Query has no 'from' clause, and the result type '"
|
||||
+ expectedResultEntity + "' is not an entity type");
|
||||
throw new SemanticException( "Query has no 'from' clause, and the result type '"
|
||||
+ expectedResultEntity + "' is not an entity type", query );
|
||||
}
|
||||
return entityDescriptor;
|
||||
}
|
||||
else if ( expectedResultType != null ) {
|
||||
final EntityDomainType<R> entityDescriptor = jpaMetamodel.findEntityType( expectedResultType );
|
||||
if ( entityDescriptor == null ) {
|
||||
throw new SemanticException("Query has no 'from' clause, and the result type '"
|
||||
+ expectedResultType.getSimpleName() + "' is not an entity type");
|
||||
throw new SemanticException( "Query has no 'from' clause, and the result type '"
|
||||
+ expectedResultType.getSimpleName() + "' is not an entity type", query );
|
||||
}
|
||||
return entityDescriptor;
|
||||
}
|
||||
|
@ -1286,7 +1291,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
if ( fromClause.getNumberOfRoots() == 0 ) {
|
||||
throw new SemanticException( "query has no 'select' clause, and no root entities"
|
||||
+ " (every selection query must have an explicit 'select', an explicit 'from', or an explicit entity result type)");
|
||||
+ " (every selection query must have an explicit 'select', an explicit 'from', or an explicit entity result type)",
|
||||
query );
|
||||
}
|
||||
|
||||
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
||||
|
@ -1309,13 +1315,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
if ( fromClause.getNumberOfRoots() > 1 ) {
|
||||
// multiple root entities
|
||||
throw new SemanticException( "Query has no 'select' clause, and multiple root entities, but query result type is an entity class"
|
||||
+ " (specify an explicit 'select' list, or a different result type, for example, 'Object[].class')");
|
||||
+ " (specify an explicit 'select' list, or a different result type, for example, 'Object[].class')",
|
||||
query );
|
||||
}
|
||||
else {
|
||||
final SqmRoot<?> sqmRoot = fromClause.getRoots().get(0);
|
||||
if ( sqmRoot instanceof SqmCteRoot ) {
|
||||
throw new SemanticException( "Query has no 'select' clause, and the 'from' clause refers to a CTE, but query result type is an entity class"
|
||||
+ " (specify an explicit 'select' list)");
|
||||
+ " (specify an explicit 'select' list)",
|
||||
query );
|
||||
}
|
||||
else {
|
||||
// exactly one root entity, return it
|
||||
|
@ -1429,7 +1437,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
);
|
||||
}
|
||||
catch (ClassLoadingException e) {
|
||||
throw new SemanticException( "Could not resolve class '" + className + "' named for instantiation" );
|
||||
throw new SemanticException( "Could not resolve class '" + className + "' named for instantiation",
|
||||
query );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1456,6 +1465,12 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
dynamicInstantiation.addArgument( visitInstantiationArgument( arg ) );
|
||||
}
|
||||
|
||||
if ( !dynamicInstantiation.checkInstantiation( creationContext.getTypeConfiguration() ) ) {
|
||||
throw new SemanticException( "No matching constructor for type '"
|
||||
+ dynamicInstantiation.getJavaType().getSimpleName() + "'",
|
||||
query );
|
||||
}
|
||||
|
||||
return dynamicInstantiation;
|
||||
}
|
||||
|
||||
|
@ -1468,20 +1483,16 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
|
||||
private Class<?> classForName(String className) {
|
||||
return creationContext.getServiceRegistry().getService( ClassLoaderService.class ).classForName( className );
|
||||
return creationContext.getServiceRegistry().requireService( ClassLoaderService.class ).classForName( className );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDynamicInstantiationArgument<?> visitInstantiationArgument(HqlParser.InstantiationArgumentContext ctx) {
|
||||
final String alias;
|
||||
if ( ctx.getChildCount() > 1 ) {
|
||||
alias = extractAlias( (HqlParser.VariableContext) ctx.getChild( ctx.getChildCount() - 1 ) );
|
||||
}
|
||||
else {
|
||||
alias = null;
|
||||
}
|
||||
final HqlParser.VariableContext variable = ctx.variable();
|
||||
final String alias = variable == null ? null : extractAlias( variable );
|
||||
|
||||
final SqmSelectableNode<?> argExpression = (SqmSelectableNode<?>) ctx.getChild( 0 ).accept( this );
|
||||
final SqmSelectableNode<?> argExpression =
|
||||
(SqmSelectableNode<?>) ctx.instantiationArgumentExpression().accept( this );
|
||||
|
||||
final SqmDynamicInstantiationArgument<?> argument = new SqmDynamicInstantiationArgument<>(
|
||||
argExpression,
|
||||
|
@ -1504,7 +1515,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
true
|
||||
);
|
||||
if ( sqmFromByAlias == null ) {
|
||||
throw new SemanticException( "Could not resolve alias '" + alias + "' in selection [" + ctx.getText() + "]" );
|
||||
throw new SemanticException( "Could not resolve alias '" + alias
|
||||
+ "' in selection [" + ctx.getText() + "]",
|
||||
query );
|
||||
}
|
||||
return sqmFromByAlias;
|
||||
}
|
||||
|
@ -1563,7 +1576,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
nodeByPosition = processingState.getPathRegistry().findAliasedNodeByPosition( position );
|
||||
}
|
||||
if ( nodeByPosition == null ) {
|
||||
throw new SemanticException( "Numeric literal '" + position + "' used in 'group by' does not match a registered select item" );
|
||||
throw new SemanticException( "Numeric literal '" + position
|
||||
+ "' used in 'group by' does not match a registered select item",
|
||||
query );
|
||||
}
|
||||
|
||||
return new SqmAliasedNodeRef( position, integerDomainType, nodeBuilder);
|
||||
|
@ -1701,7 +1716,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
allowPositionalOrAliases
|
||||
);
|
||||
if ( sortExpression == null ) {
|
||||
throw new SemanticException( "Could not resolve sort expression: '" + ctx.sortExpression().getText() + "'" );
|
||||
throw new SemanticException( "Could not resolve sort expression: '" + ctx.sortExpression().getText() + "'",
|
||||
query );
|
||||
}
|
||||
if ( sortExpression instanceof SqmLiteral || sortExpression instanceof SqmParameter ) {
|
||||
HqlLogging.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression );
|
||||
|
@ -2014,7 +2030,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
if ( processingStateStack.depth() > 1 ) {
|
||||
throw new SemanticException(
|
||||
"Implicitly-polymorphic domain path in subquery '" + entityDescriptor.getName() +"'"
|
||||
"Implicitly-polymorphic domain path in subquery '" + entityDescriptor.getName() + "'",
|
||||
query
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2060,7 +2077,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
);
|
||||
return ((SqmCorrelation<?, ?>) correlation).getCorrelatedRoot();
|
||||
}
|
||||
throw new SemanticException( "Could not resolve entity or correlation path '" + name + "'" );
|
||||
throw new SemanticException( "Could not resolve entity or correlation path '" + name + "'", query );
|
||||
}
|
||||
final SqmCteStatement<?> cteStatement = findCteStatement( name );
|
||||
if ( cteStatement != null ) {
|
||||
|
@ -2131,7 +2148,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
.resolveHqlEntityReference( name );
|
||||
|
||||
if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) {
|
||||
throw new SemanticException( "Unmapped polymorphic reference cannot be used as a target of 'cross join'" );
|
||||
throw new SemanticException( "Unmapped polymorphic reference cannot be used as a target of 'cross join'",
|
||||
query );
|
||||
}
|
||||
final SqmCrossJoin<T> join = new SqmCrossJoin<>(
|
||||
entityDescriptor,
|
||||
|
@ -2157,7 +2175,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final boolean fetch = parserJoin.FETCH() != null;
|
||||
|
||||
if ( fetch && processingStateStack.depth() > 1 ) {
|
||||
throw new SemanticException( "The 'from' clause of a subquery has a 'fetch'" );
|
||||
throw new SemanticException( "The 'from' clause of a subquery has a 'fetch'", query );
|
||||
}
|
||||
|
||||
dotIdentifierConsumerStack.push( new QualifiedJoinPathConsumer( sqmRoot, joinType, fetch, alias, this ) );
|
||||
|
@ -2178,7 +2196,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
}
|
||||
if ( joinRestrictionContext != null && attributeJoin.isFetched() ) {
|
||||
throw new SemanticException( "Fetch join has a 'with' clause (use a filter instead)" );
|
||||
throw new SemanticException( "Fetch join has a 'with' clause (use a filter instead)", query );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2222,7 +2240,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
else if ( joinTargetContext instanceof HqlParser.JoinSubqueryContext ) {
|
||||
if ( fetch ) {
|
||||
throw new SemanticException( "The 'from' clause of a subquery has a 'fetch' join" );
|
||||
throw new SemanticException( "The 'from' clause of a subquery has a 'fetch' join", query );
|
||||
}
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation(
|
||||
|
@ -2397,7 +2415,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
);
|
||||
}
|
||||
else {
|
||||
throw new SemanticException( "Operand of 'is empty' operator must be a plural path" );
|
||||
throw new SemanticException( "Operand of 'is empty' operator must be a plural path", query );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2598,7 +2616,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final String escape = unquoteStringLiteral( terminalNode.getText() );
|
||||
if ( escape.length() != 1 ) {
|
||||
throw new SemanticException(
|
||||
"Escape character literals must have exactly a single character, but found: " + escape
|
||||
"Escape character literals must have exactly a single character, but found: " + escape,
|
||||
query
|
||||
);
|
||||
}
|
||||
return new SqmLiteral<>(
|
||||
|
@ -2622,7 +2641,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
);
|
||||
}
|
||||
else {
|
||||
throw new SemanticException( "Operand of 'member of' operator must be a plural path" );
|
||||
throw new SemanticException( "Operand of 'member of' operator must be a plural path", query );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2740,7 +2759,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPredicate visitBooleanExpressionPredicate(HqlParser.BooleanExpressionPredicateContext ctx) {
|
||||
final SqmExpression<?> expression = (SqmExpression<?>) ctx.expression().accept( this );
|
||||
if ( expression.getJavaType() != Boolean.class ) {
|
||||
throw new SemanticException( "Non-boolean expression used in predicate context: " + ctx.getText() );
|
||||
throw new SemanticException( "Non-boolean expression used in predicate context: " + ctx.getText(), query );
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
final SqmExpression<Boolean> booleanExpression = (SqmExpression<Boolean>) expression;
|
||||
|
@ -3971,20 +3990,30 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
else {
|
||||
final FunctionKind functionKind = functionTemplate.getFunctionKind();
|
||||
if ( ctx.filterClause() != null && functionKind == FunctionKind.NORMAL ) {
|
||||
throw new SemanticException( "'FILTER' clause is illegal for non-aggregate function: " + functionName );
|
||||
throw new SemanticException( "'FILTER' clause is illegal for non-aggregate function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
if ( ctx.overClause() != null && functionKind == FunctionKind.NORMAL ) {
|
||||
throw new SemanticException( "'OVER' clause is illegal for non-aggregate function: " + functionName);
|
||||
throw new SemanticException( "'OVER' clause is illegal for non-aggregate function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
if ( ctx.withinGroupClause() != null && functionKind == FunctionKind.NORMAL ) {
|
||||
throw new SemanticException( "'WITHIN' GROUP clause is illegal for non-aggregate function: " + functionName);
|
||||
throw new SemanticException( "'WITHIN' GROUP clause is illegal for non-aggregate function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
if ( ctx.overClause() == null && functionKind == FunctionKind.WINDOW ) {
|
||||
throw new SemanticException( "'OVER' clause is mandatory for window-only function: " + functionName );
|
||||
throw new SemanticException( "'OVER' clause is mandatory for window-only function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
if ( ctx.withinGroupClause() == null && ctx.overClause() == null
|
||||
&& functionKind == FunctionKind.ORDERED_SET_AGGREGATE ) {
|
||||
throw new SemanticException( "'WITHIN GROUP' or 'OVER' clause is mandatory for ordered set aggregate function: " + functionName );
|
||||
throw new SemanticException( "'WITHIN GROUP' or 'OVER' clause is mandatory for ordered set aggregate function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
|
||||
if ( ctx.nullsClause() != null ) {
|
||||
|
@ -3996,11 +4025,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
case "nth_value":
|
||||
break;
|
||||
default:
|
||||
throw new SemanticException( "'RESPECT NULLS' or 'IGNORE NULLS' are illegal for function: " + functionName );
|
||||
throw new SemanticException( "'RESPECT NULLS' or 'IGNORE NULLS' are illegal for function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
}
|
||||
if ( ctx.nthSideClause() != null && !"nth_value".equals( functionName ) ) {
|
||||
throw new SemanticException( "'FROM FIRST' or 'FROM LAST' are illegal for function: " + functionName );
|
||||
throw new SemanticException( "'FROM FIRST' or 'FROM LAST' are illegal for function: "
|
||||
+ functionName,
|
||||
query );
|
||||
}
|
||||
return functionTemplate;
|
||||
}
|
||||
|
@ -4049,7 +4082,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
final SqmFunctionDescriptor functionTemplate = getFunctionDescriptor( "listagg" );
|
||||
if ( functionTemplate == null ) {
|
||||
throw new SemanticException( "The listagg() function was not registered for the dialect" );
|
||||
throw new SemanticException( "The listagg() function was not registered for the dialect", query );
|
||||
}
|
||||
|
||||
return applyOverClause(
|
||||
|
@ -4510,8 +4543,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
if ( !(referencedPathSource instanceof PluralPersistentAttribute ) ) {
|
||||
//TODO: improve this message
|
||||
throw new SemanticException( "Path is not a plural path '"
|
||||
+ pluralAttributePath.getNavigablePath() + "'" );
|
||||
throw new SemanticException( "Path is not a plural path '" + pluralAttributePath.getNavigablePath() + "'",
|
||||
query );
|
||||
}
|
||||
final SqmSubQuery<?> subQuery = new SqmSubQuery<>(
|
||||
processingStateStack.getCurrent().getProcessingQuery(),
|
||||
|
@ -4768,7 +4801,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final String padCharText = ctx.STRING_LITERAL().getText();
|
||||
|
||||
if ( padCharText.length() != 3 ) {
|
||||
throw new SemanticException( "Pad character for pad() function must be single character, found '" + padCharText + "'" );
|
||||
throw new SemanticException( "Pad character for pad() function must be single character, found '"
|
||||
+ padCharText + "'",
|
||||
query );
|
||||
}
|
||||
|
||||
return new SqmLiteral<>(
|
||||
|
@ -4831,7 +4866,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
else {
|
||||
trimCharText = unquoteStringLiteral( ctx.getText() );
|
||||
if ( trimCharText.length() != 1 ) {
|
||||
throw new SemanticException( "Trim character for trim() function must be single character, found '" + trimCharText + "'" );
|
||||
throw new SemanticException( "Trim character for trim() function must be single character, found '"
|
||||
+ trimCharText + "'",
|
||||
query );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5145,7 +5182,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final String treatTargetEntityName =
|
||||
getCreationContext().getJpaMetamodel().qualifyImportableName( treatTargetName );
|
||||
if ( treatTargetEntityName == null ) {
|
||||
throw new SemanticException( "Could not resolve treat target type '" + treatTargetName + "'" );
|
||||
throw new SemanticException( "Could not resolve treat target type '" + treatTargetName + "'", query );
|
||||
}
|
||||
|
||||
final boolean hasContinuation = ctx.getChildCount() == 7;
|
||||
|
|
|
@ -72,7 +72,8 @@ public class StandardHqlTranslator implements HqlTranslator {
|
|||
hqlParseTree,
|
||||
expectedResultType,
|
||||
sqmCreationOptions,
|
||||
sqmCreationContext
|
||||
sqmCreationContext,
|
||||
query
|
||||
);
|
||||
|
||||
// Log the SQM tree (if enabled)
|
||||
|
|
|
@ -9,8 +9,6 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -18,8 +16,8 @@ public class Compatibility {
|
|||
private Compatibility() {
|
||||
}
|
||||
|
||||
private static final Map<Class,Class> primitiveToWrapper;
|
||||
private static final Map<Class,Class> wrapperToPrimitive;
|
||||
private static final Map<Class<?>,Class<?>> primitiveToWrapper;
|
||||
private static final Map<Class<?>,Class<?>> wrapperToPrimitive;
|
||||
static {
|
||||
primitiveToWrapper = new ConcurrentHashMap<>();
|
||||
wrapperToPrimitive = new ConcurrentHashMap<>();
|
||||
|
@ -33,27 +31,26 @@ public class Compatibility {
|
|||
map( double.class, Double.class );
|
||||
}
|
||||
|
||||
private static void map(Class primitive, Class wrapper) {
|
||||
private static void map(Class<?> primitive, Class<?> wrapper) {
|
||||
primitiveToWrapper.put( primitive, wrapper );
|
||||
wrapperToPrimitive.put( wrapper, primitive );
|
||||
}
|
||||
|
||||
public static boolean isWrapper(Class potentialWrapper) {
|
||||
public static boolean isWrapper(Class<?> potentialWrapper) {
|
||||
return wrapperToPrimitive.containsKey( potentialWrapper );
|
||||
}
|
||||
|
||||
public static Class primitiveEquivalent(Class potentialWrapper) {
|
||||
public static Class<?> primitiveEquivalent(Class<?> potentialWrapper) {
|
||||
assert isWrapper( potentialWrapper );
|
||||
return wrapperToPrimitive.get( potentialWrapper );
|
||||
}
|
||||
|
||||
public static Class wrapperEquivalent(Class primitive) {
|
||||
public static Class<?> wrapperEquivalent(Class<?> primitive) {
|
||||
assert primitive.isPrimitive();
|
||||
return primitiveToWrapper.get( primitive );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean areAssignmentCompatible(Class to, Class from) {
|
||||
public static boolean areAssignmentCompatible(Class<?> to, Class<?> from) {
|
||||
assert to != null;
|
||||
assert from != null;
|
||||
|
||||
|
@ -79,7 +76,7 @@ public class Compatibility {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static boolean areAssignmentCompatiblePrimitive(Class to, Class from) {
|
||||
private static boolean areAssignmentCompatiblePrimitive(Class<?> to, Class<?> from) {
|
||||
assert to != null;
|
||||
assert from != null;
|
||||
|
||||
|
@ -112,7 +109,7 @@ public class Compatibility {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean isIntegralType(Class potentialIntegral) {
|
||||
public static boolean isIntegralType(Class<?> potentialIntegral) {
|
||||
if ( potentialIntegral.isPrimitive() ) {
|
||||
return isIntegralTypePrimitive( potentialIntegral );
|
||||
}
|
||||
|
@ -122,7 +119,7 @@ public class Compatibility {
|
|||
|
||||
}
|
||||
|
||||
private static boolean isIntegralTypePrimitive(Class potentialIntegral) {
|
||||
private static boolean isIntegralTypePrimitive(Class<?> potentialIntegral) {
|
||||
assert potentialIntegral.isPrimitive();
|
||||
|
||||
return potentialIntegral == short.class
|
||||
|
@ -130,7 +127,7 @@ public class Compatibility {
|
|||
|| potentialIntegral == long.class;
|
||||
}
|
||||
|
||||
private static boolean isCompatibleIntegralTypePrimitive(Class to, Class from) {
|
||||
private static boolean isCompatibleIntegralTypePrimitive(Class<?> to, Class<?> from) {
|
||||
assert isIntegralTypePrimitive( to );
|
||||
assert from.isPrimitive();
|
||||
|
||||
|
@ -146,7 +143,7 @@ public class Compatibility {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isFloatingType(Class potentialFloating) {
|
||||
public static boolean isFloatingType(Class<?> potentialFloating) {
|
||||
if ( potentialFloating.isPrimitive() ) {
|
||||
return isFloatingTypePrimitive( potentialFloating );
|
||||
}
|
||||
|
@ -156,33 +153,17 @@ public class Compatibility {
|
|||
|
||||
}
|
||||
|
||||
private static boolean isFloatingTypePrimitive(Class potentialFloating) {
|
||||
private static boolean isFloatingTypePrimitive(Class<?> potentialFloating) {
|
||||
assert potentialFloating.isPrimitive();
|
||||
|
||||
return potentialFloating == float.class
|
||||
|| potentialFloating == double.class;
|
||||
}
|
||||
|
||||
private static boolean isCompatibleFloatingTypePrimitive(Class to, Class from) {
|
||||
private static boolean isCompatibleFloatingTypePrimitive(Class<?> to, Class<?> from) {
|
||||
assert isFloatingTypePrimitive( to );
|
||||
assert from.isPrimitive();
|
||||
|
||||
if ( to == float.class ) {
|
||||
return from == float.class;
|
||||
}
|
||||
else {
|
||||
return isFloatingTypePrimitive( from );
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean areAssignmentCompatible(
|
||||
JavaType to,
|
||||
JavaType from) {
|
||||
|
||||
// todo (6.0) - base this in the descriptor.
|
||||
// `JavaType#assignableFrom` ?
|
||||
// Note from Christian: I think this is a good idea to allow honoring parameterized types
|
||||
|
||||
return areAssignmentCompatible( to.getJavaTypeClass(), from.getJavaTypeClass() );
|
||||
return to == float.class ? from == float.class : isFloatingTypePrimitive( from );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.select;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -22,11 +23,14 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
|||
import org.hibernate.query.sqm.tree.jpa.AbstractJpaSelection;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.hibernate.query.sqm.DynamicInstantiationNature.CLASS;
|
||||
import static org.hibernate.query.sqm.DynamicInstantiationNature.LIST;
|
||||
import static org.hibernate.query.sqm.DynamicInstantiationNature.MAP;
|
||||
import static org.hibernate.sql.results.graph.instantiation.internal.InstantiationHelper.isConstructorCompatible;
|
||||
|
||||
/**
|
||||
* Represents a dynamic instantiation ({@code select new XYZ(...) ...}) as part of the SQM.
|
||||
|
@ -111,6 +115,30 @@ public class SqmDynamicInstantiation<T>
|
|||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public boolean checkInstantiation(TypeConfiguration typeConfiguration) {
|
||||
if ( getInstantiationTarget().getNature() == CLASS) {
|
||||
if ( getArguments().stream().allMatch(arg -> arg.getAlias() != null ) ) {
|
||||
// it's probably a bean injection-type instantiator, don't check it now
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
final List<Class<?>> argTypes =
|
||||
getArguments().stream()
|
||||
.map(arg -> arg.getNodeJavaType().getJavaTypeClass())
|
||||
.collect(toList());
|
||||
for ( Constructor<?> constructor : getJavaType().getDeclaredConstructors() ) {
|
||||
if ( isConstructorCompatible( constructor, argTypes, typeConfiguration ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDynamicInstantiation<T> copy(SqmCopyContext context) {
|
||||
final SqmDynamicInstantiation<T> existing = context.getCopy( this );
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.sql.results.graph.instantiation.internal;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashSet;
|
||||
|
@ -23,10 +22,11 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
|||
import org.hibernate.sql.results.graph.instantiation.DynamicInstantiationResult;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.hibernate.query.sqm.tree.expression.Compatibility.areAssignmentCompatible;
|
||||
import static org.hibernate.sql.results.graph.instantiation.internal.InstantiationHelper.isConstructorCompatible;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -150,49 +150,30 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
|
|||
new DynamicInstantiationAssemblerMapImpl( (JavaType<Map<?,?>>) javaType, argumentReaders );
|
||||
}
|
||||
else {
|
||||
// find a constructor matching argument types
|
||||
constructor_loop:
|
||||
for ( Constructor<?> constructor : javaType.getJavaTypeClass().getDeclaredConstructors() ) {
|
||||
final Type[] genericParameterTypes = constructor.getGenericParameterTypes();
|
||||
if ( genericParameterTypes.length == argumentReaders.size() ) {
|
||||
for ( int i = 0; i < argumentReaders.size(); i++ ) {
|
||||
final Type parameterType = genericParameterTypes[i];
|
||||
final ArgumentReader<?> argumentReader = argumentReaders.get( i );
|
||||
final boolean assignmentCompatible;
|
||||
if ( parameterType instanceof Class<?> ) {
|
||||
assignmentCompatible = areAssignmentCompatible(
|
||||
(Class<?>) parameterType,
|
||||
argumentReader.getAssembledJavaType().getJavaTypeClass()
|
||||
);
|
||||
return assembler( areAllArgumentsAliased, duplicatedAliases, argumentReaders, creationState );
|
||||
}
|
||||
else {
|
||||
final JavaType<?> argumentTypeDescriptor = creationState.getSqlAstCreationContext()
|
||||
}
|
||||
|
||||
private DomainResultAssembler<R> assembler(
|
||||
boolean areAllArgumentsAliased,
|
||||
List<String> duplicatedAliases,
|
||||
List<ArgumentReader<?>> argumentReaders,
|
||||
AssemblerCreationState creationState) {
|
||||
final List<Class<?>> argumentTypes =
|
||||
argumentReaders.stream()
|
||||
.map(reader -> reader.getAssembledJavaType().getJavaTypeClass())
|
||||
.collect(toList());
|
||||
final TypeConfiguration typeConfiguration =
|
||||
creationState.getSqlAstCreationContext()
|
||||
.getMappingMetamodel()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeRegistry()
|
||||
.resolveDescriptor( parameterType );
|
||||
assignmentCompatible = areAssignmentCompatible(
|
||||
argumentTypeDescriptor,
|
||||
argumentReader.getAssembledJavaType()
|
||||
);
|
||||
}
|
||||
|
||||
if ( !assignmentCompatible ) {
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Skipping constructor for dynamic-instantiation match due to argument mismatch [%s] : %s -> %s",
|
||||
i,
|
||||
argumentReader.getAssembledJavaType().getTypeName(),
|
||||
parameterType.getTypeName()
|
||||
);
|
||||
}
|
||||
continue constructor_loop;
|
||||
}
|
||||
}
|
||||
|
||||
.getTypeConfiguration();
|
||||
// find a constructor matching argument types
|
||||
for ( Constructor<?> constructor : javaType.getJavaTypeClass().getDeclaredConstructors() ) {
|
||||
if ( isConstructorCompatible( constructor, argumentTypes, typeConfiguration ) ) {
|
||||
constructor.setAccessible( true );
|
||||
//noinspection rawtypes
|
||||
return new DynamicInstantiationAssemblerConstructorImpl( constructor, javaType, argumentReaders );
|
||||
@SuppressWarnings("unchecked")
|
||||
final Constructor<R> construct = (Constructor<R>) constructor;
|
||||
return new DynamicInstantiationAssemblerConstructorImpl<>( construct, javaType, argumentReaders );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +184,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
|
|||
);
|
||||
}
|
||||
|
||||
if ( ! areAllArgumentsAliased ) {
|
||||
if ( !areAllArgumentsAliased) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot instantiate class '" + javaType.getJavaType().getTypeName() + "'"
|
||||
+ " (it has no constructor with signature " + signature()
|
||||
|
@ -215,13 +196,12 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
|
|||
"Cannot instantiate class '" + javaType.getJavaType().getTypeName() + "'"
|
||||
+ " (it has no constructor with signature " + signature()
|
||||
+ ", and has arguments with duplicate aliases ["
|
||||
+ StringHelper.join( ",", duplicatedAliases ) + "])"
|
||||
+ StringHelper.join( ",", duplicatedAliases) + "])"
|
||||
);
|
||||
}
|
||||
|
||||
return new DynamicInstantiationAssemblerInjectionImpl<>( javaType, argumentReaders );
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> signature() {
|
||||
return argumentResults.stream()
|
||||
|
|
|
@ -6,12 +6,56 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph.instantiation.internal;
|
||||
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hibernate.query.sqm.tree.expression.Compatibility.areAssignmentCompatible;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class InstantiationHelper {
|
||||
|
||||
private static final Logger log = Logger.getLogger( InstantiationHelper.class );
|
||||
|
||||
private InstantiationHelper() {
|
||||
// disallow direct instantiation
|
||||
}
|
||||
|
||||
public static boolean isConstructorCompatible(
|
||||
Constructor<?> constructor,
|
||||
List<Class<?>> argumentTypes,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final Type[] genericParameterTypes = constructor.getGenericParameterTypes();
|
||||
if ( genericParameterTypes.length == argumentTypes.size() ) {
|
||||
for (int i = 0; i < argumentTypes.size(); i++ ) {
|
||||
final Type parameterType = genericParameterTypes[i];
|
||||
final Class<?> argumentType = argumentTypes.get( i );
|
||||
final Class<?> argType = parameterType instanceof Class<?>
|
||||
? (Class<?>) parameterType
|
||||
: typeConfiguration.getJavaTypeRegistry().resolveDescriptor( parameterType ).getJavaTypeClass();
|
||||
|
||||
if ( !areAssignmentCompatible( argType, argumentType ) ) {
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Skipping constructor for dynamic-instantiation match due to argument mismatch [%s] : %s -> %s",
|
||||
i,
|
||||
argumentType.getTypeName(),
|
||||
parameterType.getTypeName()
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ public class EnumType<T extends Enum<T>>
|
|||
if ( parameters.containsKey( ENUM ) ) {
|
||||
final String enumClassName = (String) parameters.get( ENUM );
|
||||
try {
|
||||
enumClass = ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class );
|
||||
enumClass = (Class<T>) ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class );
|
||||
}
|
||||
catch ( ClassNotFoundException exception ) {
|
||||
throw new HibernateException("Enum class not found: " + enumClassName, exception);
|
||||
|
|
|
@ -83,7 +83,7 @@ public class SerializableToBlobType<T extends Serializable> implements BasicType
|
|||
}
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> classForName = ReflectHelper.classForName(className);
|
||||
Class<T> classForName = (Class<T>) ReflectHelper.classForName(className);
|
||||
setJavaTypeDescriptor( new SerializableJavaType<>(classForName) );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
|
|
|
@ -3071,7 +3071,8 @@ public abstract class AbstractQueryCacheResultTransformerTest {
|
|||
|
||||
private Constructor getConstructor() {
|
||||
Type studentNametype =
|
||||
scope.getSessionFactory().getMappingMetamodel().getEntityDescriptor( Student.class.getName() )
|
||||
scope.getSessionFactory().getMappingMetamodel()
|
||||
.getEntityDescriptor( Student.class.getName() )
|
||||
.getPropertyType( "name" );
|
||||
return ReflectHelper.getConstructor(
|
||||
Student.class,
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.lang.reflect.Constructor;
|
|||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -42,7 +41,7 @@ public final class DialectContext {
|
|||
final Constructor<? extends Dialect> constructor;
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends Dialect> dialectClass = ReflectHelper.classForName( dialectName );
|
||||
final Class<? extends Dialect> dialectClass = (Class<? extends Dialect>) ReflectHelper.classForName( dialectName );
|
||||
constructor = dialectClass.getConstructor( DialectResolutionInfo.class );
|
||||
}
|
||||
catch (ClassNotFoundException cnfe) {
|
||||
|
|
|
@ -84,7 +84,7 @@ public class Validation {
|
|||
int errorOffset,
|
||||
HqlParser.StatementContext statementContext) {
|
||||
try {
|
||||
return createSemanticQueryBuilder( returnType, factory ).visitStatement( statementContext );
|
||||
return createSemanticQueryBuilder( returnType, hql, factory ).visitStatement( statementContext );
|
||||
}
|
||||
catch ( JdbcTypeRecommendationException ignored ) {
|
||||
// just squash these for now
|
||||
|
@ -100,15 +100,15 @@ public class Validation {
|
|||
}
|
||||
|
||||
private static SemanticQueryBuilder<?> createSemanticQueryBuilder(
|
||||
@Nullable TypeMirror returnType, SessionFactoryImplementor factory) {
|
||||
@Nullable TypeMirror returnType, String hql, SessionFactoryImplementor factory) {
|
||||
if ( returnType != null && returnType.getKind() == TypeKind.DECLARED ) {
|
||||
final DeclaredType declaredType = (DeclaredType) returnType;
|
||||
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
||||
if ( isEntity( typeElement ) ) {
|
||||
return new SemanticQueryBuilder<>( getEntityName( typeElement ), () -> false, factory );
|
||||
return new SemanticQueryBuilder<>( getEntityName( typeElement ), () -> false, factory, hql );
|
||||
}
|
||||
}
|
||||
return new SemanticQueryBuilder<>( Object[].class, () -> false, factory );
|
||||
return new SemanticQueryBuilder<>( Object[].class, () -> false, factory, hql );
|
||||
}
|
||||
|
||||
private static HqlParser.StatementContext parseAndCheckSyntax(String hql, Handler handler) {
|
||||
|
|
Loading…
Reference in New Issue