further work on query parser exceptions

I missed a couple of things
This commit is contained in:
Gavin King 2023-06-13 21:29:06 +02:00
parent d859f43748
commit 9adffa4e4f
24 changed files with 198 additions and 100 deletions

View File

@ -7,8 +7,22 @@
package org.hibernate; package org.hibernate;
/** /**
* A problem occurred translating a Hibernate query to SQL * A problem occurred translating a Hibernate query to SQL due to illegal query
* due to invalid query syntax, or some similar problem. * syntax, an operation which is not well-typed, an unresolvable reference to
* an entity or attribute, an unknown named query, or any similar problem. This
* exception type is not used to represent failures that occur while executing
* a query or reading the result set of a query.
* <p>
* The two most important subtypes are:
* <ul>
* <li>{@link org.hibernate.query.SyntaxException}, which represents a syntax
* error in the HQL query, and
* <li>{@link org.hibernate.query.SemanticException}, which represents an error
* in the semantics of the query.
* </ul>
*
* @see org.hibernate.query.SemanticException
* @see org.hibernate.query.SyntaxException
*/ */
public class QueryException extends HibernateException { public class QueryException extends HibernateException {
private final String queryString; private final String queryString;

View File

@ -8,7 +8,7 @@ package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.TerminalPathException; import org.hibernate.query.sqm.TerminalPathException;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;

View File

@ -47,7 +47,7 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.EntityReferenceException; import org.hibernate.query.sqm.EntityTypeException;
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor; import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.EnumJavaType;
@ -164,7 +164,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) { public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
final EntityDomainType<X> hqlEntityReference = getHqlEntityReference( entityName ); final EntityDomainType<X> hqlEntityReference = getHqlEntityReference( entityName );
if ( hqlEntityReference == null ) { if ( hqlEntityReference == null ) {
throw new EntityReferenceException( "Could not resolve entity reference: " + entityName ); throw new EntityTypeException( "Could not resolve entity name '" + entityName + "'", entityName );
} }
return hqlEntityReference; return hqlEntityReference;
} }
@ -444,7 +444,8 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
// otherwise, try to handle it as a polymorphic reference // otherwise, try to handle it as a polymorphic reference
{ {
final EntityDomainType<T> polymorphicDomainType = (EntityDomainType<T>) polymorphicEntityReferenceMap.get( javaType ); final EntityDomainType<T> polymorphicDomainType =
(EntityDomainType<T>) polymorphicEntityReferenceMap.get( javaType );
if ( polymorphicDomainType != null ) { if ( polymorphicDomainType != null ) {
return polymorphicDomainType; return polymorphicDomainType;
} }
@ -495,7 +496,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
} }
} }
throw new EntityReferenceException( "Could not resolve entity reference : " + javaType.getName() ); throw new EntityTypeException( "Could not resolve entity class '" + javaType.getName() + "'", javaType.getName() );
} }
@Override @Override

View File

@ -1,25 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query;
/**
* Indicates that a reference to an entity did not resolve to
* a mapped entity class.
*
* @apiNote extends {@link IllegalArgumentException} to
* satisfy a questionable requirement of the JPA criteria
* query API
*
* @since 6.3
*
* @author Gavin King
*/
public class EntityReferenceException extends IllegalArgumentException {
public EntityReferenceException(String message) {
super(message);
}
}

View File

@ -13,7 +13,10 @@ import java.util.Map;
/** /**
* Indicates that validation and translation of one or more named * Indicates that validation and translation of one or more named
* queries failed at initialization time. * queries failed at initialization time. This exception packages
* every {@link org.hibernate.QueryException} that occurred for an
* invalid HQL/JPQL query, together with any exceptions that indicate
* problems with named native SQL queries.
* *
* @author Gavin King * @author Gavin King
*/ */

View File

@ -7,23 +7,22 @@
package org.hibernate.query; package org.hibernate.query;
/** /**
* Indicates an attempt to use a path in an unsupported way * Indicates a problem with a path expression in HQL/JPQL.
* *
* @author Steve Ebersole * @author Steve Ebersole
* *
* @see PathElementException * @see org.hibernate.query.sqm.UnknownPathException
* @see TerminalPathException
*/ */
public class PathException extends SemanticException { public class PathException extends SemanticException {
public PathException(String message) { public PathException(String message) {
super( message ); super( message );
} }
/**
* @deprecated This is currently unused
*/
@Deprecated(forRemoval = true, since = "6.3")
public PathException(String message, Exception cause) { public PathException(String message, Exception cause) {
super( message, cause ); super( message, cause );
} }
public PathException(String message, String hql, Exception cause) {
super(message, hql, cause);
}
} }

View File

@ -9,7 +9,7 @@ package org.hibernate.query;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
/** /**
* Indicates a mismatch between a Query's expected and actual result types * Indicates a mismatch between the expected and actual result types of a query.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */

View File

@ -9,10 +9,12 @@ package org.hibernate.query;
import org.hibernate.QueryException; import org.hibernate.QueryException;
/** /**
* Indicates a request for a named-query when no query is * Occurs when a named query is requested, and there is no known
* registered under that name * HQL or native SQL query registered under the given name.
* *
* @author Steve Ebersole * @author Steve Ebersole
*
* @see org.hibernate.query.named.NamedObjectRepository
*/ */
public class UnknownNamedQueryException extends QueryException { public class UnknownNamedQueryException extends QueryException {
public UnknownNamedQueryException(String queryName) { public UnknownNamedQueryException(String queryName) {

View File

@ -57,7 +57,7 @@ import org.hibernate.query.ParameterLabelException;
import org.hibernate.query.PathException; import org.hibernate.query.PathException;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.TerminalPathException; import org.hibernate.query.sqm.TerminalPathException;
import org.hibernate.query.criteria.JpaCteCriteria; import org.hibernate.query.criteria.JpaCteCriteria;
import org.hibernate.query.criteria.JpaCteCriteriaAttribute; import org.hibernate.query.criteria.JpaCteCriteriaAttribute;
import org.hibernate.query.criteria.JpaCteCriteriaType; import org.hibernate.query.criteria.JpaCteCriteriaType;

View File

@ -14,15 +14,17 @@ import org.antlr.v4.runtime.NoViableAltException;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.grammars.hql.HqlLexer; import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser; import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.EntityReferenceException; import org.hibernate.query.sqm.EntityTypeException;
import org.hibernate.query.PathElementException; import org.hibernate.query.sqm.PathElementException;
import org.hibernate.query.SyntaxException; import org.hibernate.query.SyntaxException;
import org.hibernate.query.TerminalPathException; import org.hibernate.query.sqm.TerminalPathException;
import org.hibernate.query.hql.HqlLogging; import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.hql.spi.SqmCreationOptions; import org.hibernate.query.hql.spi.SqmCreationOptions;
import org.hibernate.query.sqm.InterpretationException; import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.sqm.ParsingException; import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.UnknownEntityException;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.internal.SqmTreePrinter; import org.hibernate.query.sqm.internal.SqmTreePrinter;
import org.hibernate.query.sqm.spi.SqmCreationContext; import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
@ -78,9 +80,15 @@ public class StandardHqlTranslator implements HqlTranslator {
return sqmStatement; return sqmStatement;
} }
catch (QueryException | PathElementException | TerminalPathException | EntityReferenceException e) { catch (QueryException e) {
throw e; throw e;
} }
catch (PathElementException | TerminalPathException e) {
throw new UnknownPathException( e.getMessage(), query, e );
}
catch (EntityTypeException e) {
throw new UnknownEntityException( e.getMessage(), e.getReference(), e );
}
catch (Exception e) { catch (Exception e) {
// this is some sort of "unexpected" exception, i.e. something buglike // this is some sort of "unexpected" exception, i.e. something buglike
throw new InterpretationException( query, e ); throw new InterpretationException( query, e );

View File

@ -11,6 +11,7 @@ import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.query.NamedHqlQueryDefinition; import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition; import org.hibernate.boot.query.NamedNativeQueryDefinition;
@ -18,16 +19,18 @@ import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.EntityReferenceException; import org.hibernate.query.sqm.EntityTypeException;
import org.hibernate.query.NamedQueryValidationException; import org.hibernate.query.NamedQueryValidationException;
import org.hibernate.query.PathElementException; import org.hibernate.query.sqm.PathElementException;
import org.hibernate.query.TerminalPathException; import org.hibernate.query.sqm.TerminalPathException;
import org.hibernate.query.named.NamedObjectRepository; import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedQueryMemento; import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryInterpretationCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento; import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.UnknownEntityException;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento; import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -239,21 +242,24 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
// Check named HQL queries // Check named HQL queries
log.debugf( "Checking %s named HQL queries", sqmMementoMap.size() ); log.debugf( "Checking %s named HQL queries", sqmMementoMap.size() );
for ( NamedSqmQueryMemento hqlMemento : sqmMementoMap.values() ) { for ( NamedSqmQueryMemento hqlMemento : sqmMementoMap.values() ) {
final String queryString = hqlMemento.getHqlString();
final String registrationName = hqlMemento.getRegistrationName();
try { try {
log.debugf( "Checking named HQL query: %s", hqlMemento.getRegistrationName() ); log.debugf( "Checking named HQL query: %s", registrationName );
String queryString = hqlMemento.getHqlString();
interpretationCache.resolveHqlInterpretation( interpretationCache.resolveHqlInterpretation(
queryString, queryString,
null, null,
s -> queryEngine.getHqlTranslator().translate( queryString, null ) s -> queryEngine.getHqlTranslator().translate( queryString, null )
); );
} }
catch ( HibernateException e ) { catch ( QueryException e ) {
errors.put( hqlMemento.getRegistrationName(), e ); errors.put( registrationName, e );
} }
catch ( PathElementException | TerminalPathException | EntityReferenceException e ) { catch ( PathElementException | TerminalPathException e ) {
// JPA does not let these be HibernateExceptions in general errors.put( registrationName, new UnknownPathException( e.getMessage(), queryString, e ) );
errors.put( hqlMemento.getRegistrationName(), new HibernateException(e) ); }
catch ( EntityTypeException e ) {
errors.put( registrationName, new UnknownEntityException( e.getMessage(), e.getReference(), e ) );
} }
} }

View File

@ -0,0 +1,35 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sqm;
/**
* Indicates that a reference to an entity, that is, a given entity name
* or Java class object, did not resolve to a known mapped entity type.
*
* @apiNote extends {@link IllegalArgumentException} to
* satisfy a questionable requirement of the JPA
* criteria query API
*
* @since 6.3
*
* @author Gavin King
*/
public class EntityTypeException extends IllegalArgumentException {
private final String reference;
public EntityTypeException(String message, String reference) {
super(message);
this.reference = reference;
}
/**
* The entity name or the name of the Java class.
*/
public String getReference() {
return reference;
}
}

View File

@ -4,15 +4,15 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query; package org.hibernate.query.sqm;
/** /**
* Indicates that an element of a path did not resolve to * Indicates that an element of a path did not resolve to
* a mapped program element. * a mapped program element.
* *
* @apiNote extends {@link IllegalArgumentException} to * @apiNote extends {@link IllegalArgumentException} to
* satisfy a questionable requirement of the JPA criteria * satisfy a questionable requirement of the JPA
* query API * criteria query API
* *
* @since 6.3 * @since 6.3
* *

View File

@ -11,7 +11,6 @@ import java.util.Locale;
import jakarta.persistence.metamodel.Bindable; import jakarta.persistence.metamodel.Bindable;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.PathElementException;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.tree.SqmExpressibleAccessor; import org.hibernate.query.sqm.tree.SqmExpressibleAccessor;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;

View File

@ -4,15 +4,15 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query; package org.hibernate.query.sqm;
/** /**
* Indicates an attempt to dereference a terminal path * Indicates an attempt to dereference a terminal path
* (usually a path referring to something of basic type) * (usually a path referring to something of basic type)
* *
* @apiNote extends {@link IllegalStateException} to * @apiNote extends {@link IllegalStateException} to
* satisfy a questionable requirement of the JPA criteria * satisfy a questionable requirement of the JPA
* query API * criteria query API
* *
* @since 6.3 * @since 6.3
* *

View File

@ -9,14 +9,18 @@ package org.hibernate.query.sqm;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
/** /**
* Indicates we were not able to resolve a given "path structure" as an entity name. * Indicates a failure to resolve an entity name in HQL to a known mapped
* entity type.
* *
* @apiNote JPA generally requires this to be reported as the much less useful * @apiNote The JPA criteria API requires that this problem be reported
* {@link IllegalArgumentException}. * as an {@link IllegalArgumentException}, and so we usually
* * throw {@link EntityTypeException} from the SQM objects, and
* todo (6.0) : account for this in the "exception conversion" handling * then wrap as an instance of this exception type in the
* {@link org.hibernate.query.hql.HqlTranslator}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*
* @see EntityTypeException
*/ */
public class UnknownEntityException extends SemanticException { public class UnknownEntityException extends SemanticException {
private final String entityName; private final String entityName;
@ -30,6 +34,11 @@ public class UnknownEntityException extends SemanticException {
this.entityName = entityName; this.entityName = entityName;
} }
public UnknownEntityException(String message, String entityName, Exception cause) {
super( message, cause );
this.entityName = entityName;
}
public String getEntityName() { public String getEntityName() {
return entityName; return entityName;
} }

View File

@ -8,30 +8,44 @@ package org.hibernate.query.sqm;
import java.util.Locale; import java.util.Locale;
import org.hibernate.query.SemanticException; import org.hibernate.query.PathException;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
/** /**
* Indicates a failure to resolve an element of a path expression in HQL/JPQL.
* *
* * @apiNote The JPA criteria API requires that this sort of problem be reported
* todo (6.0) : account for this in the "exception conversion" handling * as an {@link IllegalArgumentException} or {@link IllegalStateException},
* and so we usually throw {@link PathElementException} or
* {@link TerminalPathException} from the SQM objects, and then wrap
* as an instance of this exception type in the
* {@link org.hibernate.query.hql.HqlTranslator}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*
* @see PathElementException
* @see TerminalPathException
*/ */
public class UnknownPathException extends SemanticException { public class UnknownPathException extends PathException {
public UnknownPathException(String message) {
super( message );
}
public UnknownPathException(String message, String hql, Exception cause) {
super( message, hql, cause );
}
public static UnknownPathException unknownSubPath(SqmPath base, String name) { public static UnknownPathException unknownSubPath(SqmPath base, String name) {
return new UnknownPathException( return new UnknownPathException(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"Could not resolve path `%s` relative to %s (%s)", "Could not resolve path element '%s' relative to '%s' (%s)",
name, name,
base.getReferencedPathSource().getSqmPathType().getTypeName(), base.getReferencedPathSource().getSqmPathType().getTypeName(),
base.getNavigablePath() base.getNavigablePath()
) )
); );
} }
private UnknownPathException(String message) {
super( message );
}
} }

View File

@ -19,6 +19,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException; import org.hibernate.query.PathException;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.from.SqmFrom;
@ -121,7 +122,7 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
} }
} }
throw new PathException( "Path '" + sqmPath.getNavigablePath() + "' did not reference a known model part" ); throw new UnknownPathException( "Path '" + sqmPath.getNavigablePath() + "' did not reference a known model part" );
} }
final TableReference tableReference = tableGroup.resolveTableReference( final TableReference tableReference = tableGroup.resolveTableReference(

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.tree.domain; package org.hibernate.query.sqm.tree.domain;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.PathException; import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
@ -70,7 +71,7 @@ public class SqmBasicValuedSimplePath<T>
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
throw new PathException( throw new UnknownPathException(
String.format( String.format(
"Could not interpret attribute '%s' of basic-valued path '%s'", "Could not interpret attribute '%s' of basic-valued path '%s'",
name, getNavigablePath() name, getNavigablePath()

View File

@ -16,7 +16,7 @@ import jakarta.persistence.metamodel.PluralAttribute;
import jakarta.persistence.metamodel.SingularAttribute; import jakarta.persistence.metamodel.SingularAttribute;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException; import org.hibernate.query.SemanticException;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.criteria.JpaPath; import org.hibernate.query.criteria.JpaPath;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
@ -138,7 +138,7 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
SqmExpression<?> selector, SqmExpression<?> selector,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
throw new PathException( "Index operator applied to non-plural path '" + getNavigablePath() + "'" ); throw new SemanticException( "Index operator applied to non-plural path '" + getNavigablePath() + "'" );
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Covariant overrides // Covariant overrides

View File

@ -90,7 +90,7 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
// this is a reference to a collection outside the from-clause... // this is a reference to a collection outside the from clause
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name ); final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
if ( nature == null ) { if ( nature == null ) {
throw new PathException( "Plural path '" + getNavigablePath() throw new PathException( "Plural path '" + getNavigablePath()

View File

@ -10,12 +10,12 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Locale; import java.util.Locale;
import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.EnumJavaType;
@ -85,7 +85,7 @@ public class SqmEnumLiteral<E extends Enum<E>> extends AbstractSqmExpression<E>
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
throw new PathException( throw new UnknownPathException(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"Static enum reference [%s#%s] cannot be de-referenced", "Static enum reference [%s#%s] cannot be de-referenced",
@ -100,7 +100,7 @@ public class SqmEnumLiteral<E extends Enum<E>> extends AbstractSqmExpression<E>
SqmExpression<?> selector, SqmExpression<?> selector,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
throw new PathException( throw new UnknownPathException(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"Static enum reference [%s#%s] cannot be de-referenced", "Static enum reference [%s#%s] cannot be de-referenced",

View File

@ -14,14 +14,13 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.query.PathException;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
@ -229,7 +228,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
throw new PathException( throw new UnknownPathException(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"Static field reference [%s#%s] cannot be de-referenced", "Static field reference [%s#%s] cannot be de-referenced",
@ -244,7 +243,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
SqmExpression<?> selector, SqmExpression<?> selector,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
throw new PathException( throw new UnknownPathException(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"Static field reference [%s#%s] cannot be de-referenced", "Static field reference [%s#%s] cannot be de-referenced",

View File

@ -6,13 +6,16 @@
*/ */
package org.hibernate.orm.test.hql; package org.hibernate.orm.test.hql;
import org.hibernate.HibernateException; import org.hibernate.Hibernate;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults; import org.hibernate.ScrollableResults;
import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.query.PathElementException; import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.RequiresDialectFeature;
@ -43,22 +46,51 @@ import static org.junit.jupiter.api.Assertions.fail;
public class ScrollableCollectionFetchingTest { public class ScrollableCollectionFetchingTest {
@Test @Test
public void testTupleReturnFails(SessionFactoryScope scope) { @SkipForDialect(dialectClass=DB2Dialect.class, matchSubTypes = true)
@SkipForDialect(dialectClass= DerbyDialect.class)
public void testTupleReturnWithFetch(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createMutationQuery("insert Mammal (description, bodyWeight, pregnant) values ('Human', 80.0, false)").executeUpdate();
assertEquals( 1L, session.createSelectionQuery("select count(*) from Mammal").getSingleResult() );
ScrollableResults results = session.createQuery("select a, a.bodyWeight from Animal a left join fetch a.offspring").scroll();
assertTrue( results.next() );
Object[] result = (Object[]) results.get();
assertTrue(Hibernate.isInitialized(((Animal) result[0]).getOffspring()));
session.createMutationQuery("delete Mammal").executeUpdate();
}
);
}
@Test
public void testTupleReturnWithFetchFailure(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
try {
session.createQuery( "select a.description, a.bodyWeight from Animal a inner join fetch a.offspring" ).scroll();
fail( "scroll allowed with fetch and projection result" );
}
catch (IllegalArgumentException e) {
assertTyping( SemanticException.class, e.getCause() );
}
}
);
}
@Test
public void testUknownPathFailure(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
try { try {
session.createQuery( "select a, a.weight from Animal a inner join fetch a.offspring" ).scroll(); session.createQuery( "select a, a.weight from Animal a inner join fetch a.offspring" ).scroll();
fail( "scroll allowed with collection fetch and reurning tuples" ); fail( "scroll allowed with unknown path" );
} }
catch (IllegalArgumentException e) { catch (IllegalArgumentException e) {
assertTyping( PathElementException.class, e ); assertTyping( UnknownPathException.class, e.getCause() );
}
catch (HibernateException e) {
// expected result...
} }
} }
); );
} }
@Test @Test