cosmetic improvements to HQL error reporting

makes the messages and exception types a bit more consistent
This commit is contained in:
Gavin King 2022-01-08 02:13:34 +01:00
parent 3103d84949
commit 6c83e1d0ec
8 changed files with 29 additions and 13 deletions

View File

@ -10,12 +10,12 @@ import java.lang.reflect.Field;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.DotIdentifierConsumer;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -252,7 +252,12 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
}
}
throw new ParsingException( "Could not interpret dot-ident : " + path );
throw new SemanticException(
String.format(
"Could not interpret path expression '%s'",
path
)
);
}
protected void validateAsRoot(SqmFrom<?, ?> pathRoot) {

View File

@ -1071,7 +1071,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
.getPathRegistry()
.findAliasedNodeByPosition( position );
if ( nodeByPosition == null ) {
throw new ParsingException( "Numeric literal `" + position + "` used in group-by does not match a registered select-item" );
throw new ParsingException( "Numeric literal '" + position + "' used in group-by does not match a registered select-item" );
}
return new SqmAliasedNodeRef( position, integerDomainType, creationContext.getNodeBuilder() );
@ -1474,9 +1474,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
);
return correlation.getCorrelatedRoot();
}
throw new SemanticException( "Could not resolve entity reference or correlation path: " + name );
throw new SemanticException( "Could not resolve entity or correlation path '" + name + "'" );
}
throw new SemanticException( "Could not resolve entity reference: " + name );
throw new SemanticException( "Could not resolve entity '" + name + "'" );
}
checkFQNEntityNameJpaComplianceViolationIfNeeded( name, entityDescriptor );

View File

@ -19,6 +19,7 @@ import jakarta.persistence.metamodel.SingularAttribute;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
@ -142,7 +143,12 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
final SqmPathSource<?> subNavigable = getReferencedPathSource().findSubPathSource( attributeName );
if ( subNavigable == null ) {
throw new IllegalArgumentException( "Could not resolve attribute named `" + attributeName + "` relative to `" + getNavigablePath() + "`" );
throw new SemanticException(
String.format(
"Could not resolve attribute '%s' of '%s'",
attributeName, getNavigablePath()
)
);
}
return resolvePath( attributeName, subNavigable );
}

View File

@ -11,7 +11,6 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.PathException;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
@ -50,7 +49,12 @@ public class SqmBasicValuedSimplePath<T>
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Basic-valued path [" + getNavigablePath() + "] cannot be de-referenced : " + name );
throw new SemanticException(
String.format(
"Could not interpret attribute '%s' of basic-valued path '%s'",
name, getNavigablePath()
)
);
}

View File

@ -43,8 +43,8 @@ public class LoaderWithInvalidQueryTest extends BaseEntityManagerFunctionalTestC
HibernateException rootCause = (HibernateException) ExceptionUtil.rootCause( expected );
Throwable[] suppressed = rootCause.getSuppressed();
assertEquals( 2, suppressed.length );
assertTrue( ExceptionUtil.rootCause( suppressed[0] ).getMessage().contains( "Could not resolve attribute named `valid`" ) );
assertTrue( ExceptionUtil.rootCause( suppressed[1] ).getMessage().contains( "Could not resolve entity reference: _Person" ) );
assertTrue( ExceptionUtil.rootCause( suppressed[0] ).getMessage().contains( "Could not resolve attribute 'valid'" ) );
assertTrue( ExceptionUtil.rootCause( suppressed[1] ).getMessage().contains( "Could not resolve entity '_Person'" ) );
}
}

View File

@ -72,7 +72,7 @@ public class JoinOnClauseTest extends BaseEntityManagerFunctionalTestCase {
fail( "Referring to a join alias in the on clause that is joined later should be invalid!" );
}
catch (IllegalArgumentException ex) {
assertTrue( ex.getCause().getCause().getMessage().endsWith( ": author2" ) );
assertTrue( ex.getCause().getMessage().contains( "'author2'" ) );
}
} );
}

View File

@ -76,7 +76,7 @@ public class MappedSuperclassInheritanceTest extends BaseEntityManagerFunctional
fail();
} catch (Exception expected) {
SemanticException rootException = (SemanticException) ExceptionUtil.rootCause( expected);
assertEquals("Could not resolve entity reference: Employee", rootException.getMessage());
assertEquals("Could not resolve entity 'Employee'", rootException.getMessage());
}
} );
}

View File

@ -17,6 +17,7 @@ import org.hibernate.orm.test.jpa.metamodel.Order;
import org.hibernate.orm.test.jpa.metamodel.Thing;
import org.hibernate.orm.test.jpa.metamodel.ThingWithQuantity;
import org.hibernate.query.SemanticException;
import org.hibernate.testing.orm.junit.ExpectedException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -66,7 +67,7 @@ public class AbstractPathImplTest extends AbstractMetamodelSpecificTest {
em.close();
}
@ExpectedException(value = IllegalArgumentException.class)
@ExpectedException(value = SemanticException.class)
@Test
public void testGetNonExistingAttributeViaName() {
EntityManager em = getOrCreateEntityManager();