diff --git a/hibernate-core/src/main/java/org/hibernate/Metamodel.java b/hibernate-core/src/main/java/org/hibernate/Metamodel.java index b0fdbdcf44..923c64f876 100644 --- a/hibernate-core/src/main/java/org/hibernate/Metamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/Metamodel.java @@ -14,12 +14,12 @@ import org.hibernate.metamodel.model.domain.JpaMetamodel; /** * @author Steve Ebersole * - * @deprecated (since 6.0) Access to JPA's type system and Hibernate's type - * system has been separated into {@link JpaMetamodel} - * and {@link org.hibernate.metamodel.spi.RuntimeModel} respectively. + * @deprecated (since 6.0) Prefer {@link JpaMetamodel} + * + * @see JpaMetamodel */ @Deprecated -public interface Metamodel extends JpaMetamodel { +public interface Metamodel extends javax.persistence.metamodel.Metamodel { /** * Access to the SessionFactory that this Metamodel instance is bound to. * diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 46c9fe05b0..f36a873c6a 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -103,7 +103,7 @@ import org.hibernate.jpa.internal.PersistenceUnitUtilImpl; import org.hibernate.mapping.RootClass; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.metamodel.internal.MetamodelImpl; +import org.hibernate.metamodel.internal.DomainMetamodelImpl; import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; @@ -302,7 +302,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor { LOG.debug( "Instantiated session factory" ); this.metamodel = metadata.getTypeConfiguration().scope( this ); - ( (MetamodelImpl) this.metamodel ).initialize( + ( (DomainMetamodelImpl) this.metamodel ).initialize( metadata, determineJpaMetaModelPopulationSetting( properties ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/DomainMetamodelImpl.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/DomainMetamodelImpl.java index 6f8af313de..6c047a7bd5 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/DomainMetamodelImpl.java @@ -65,6 +65,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; +import org.hibernate.metamodel.spi.DomainMetamodel; import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; @@ -82,27 +83,43 @@ import org.hibernate.type.spi.TypeConfiguration; * * @author Steve Ebersole * @author Emmanuel Bernard + * @author Andrea Boriero */ -public class MetamodelImpl implements MetamodelImplementor, Serializable { +public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplementor, Serializable { // todo : Integrate EntityManagerLogger into CoreMessageLogger - private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( MetamodelImpl.class ); + private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( DomainMetamodelImpl.class ); + private static final Object ENTITY_NAME_RESOLVER_MAP_VALUE = new Object(); private static final String INVALID_IMPORT = ""; private static final String[] EMPTY_IMPLEMENTORS = new String[0]; private final SessionFactoryImplementor sessionFactory; - private final Map imports = new ConcurrentHashMap<>(); - private final Map entityPersisterMap = new ConcurrentHashMap<>(); - private final Map entityProxyInterfaceMap = new ConcurrentHashMap<>(); - private final Map collectionPersisterMap = new ConcurrentHashMap<>(); - private final Map> collectionRolesByEntityParticipant = new ConcurrentHashMap<>(); - private final ConcurrentMap entityNameResolvers = new ConcurrentHashMap<>(); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // JpaMetamodel + private final Map, EntityDomainType> jpaEntityTypeMap = new ConcurrentHashMap<>(); private final Map> jpaEntityTypesByEntityName = new ConcurrentHashMap<>(); - private final Map, MappedSuperclassType> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>(); + private final Set> jpaEmbeddableTypes = new CopyOnWriteArraySet<>(); + private final Map entityProxyInterfaceMap = new ConcurrentHashMap<>(); + private final Map imports = new ConcurrentHashMap<>(); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // RuntimeModel + + private final Map entityPersisterMap = new ConcurrentHashMap<>(); + private final Map collectionPersisterMap = new ConcurrentHashMap<>(); + private final Map> collectionRolesByEntityParticipant = new ConcurrentHashMap<>(); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // DomainMetamodel + + private final ConcurrentMap entityNameResolvers = new ConcurrentHashMap<>(); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NOTE : Relational/mapping information is not part of the JPA metamodel @@ -124,7 +141,6 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable { /** * There can be multiple instances of an Embeddable type, each one being relative to its parent entity. */ - private final Set> jpaEmbeddableTypes = new CopyOnWriteArraySet<>(); /** * That's not strictly correct in the JPA standard since for a given Java type we could have @@ -143,7 +159,7 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable { private final Map implementorsCache = new ConcurrentHashMap<>(); - public MetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) { + public DomainMetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) { this.sessionFactory = sessionFactory; this.typeConfiguration = typeConfiguration; } @@ -353,7 +369,7 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable { final RootGraphImpl entityGraph = new RootGraphImpl( definition.getRegisteredName(), entityType, - this + getJpaMetamodel() ); final NamedEntityGraph namedEntityGraph = definition.getAnnotation(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java index 36cb90c9bb..921226dab6 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java @@ -48,7 +48,7 @@ import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry; /** - * Defines a context for storing information during the building of the {@link MetamodelImpl}. + * Defines a context for storing information during the building of the {@link DomainMetamodelImpl}. *

* This contextual information includes data needing to be processed in a second pass as well as * cross-references into the built metamodel classes. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java index 37f2760fe5..b39a510ec4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java @@ -12,13 +12,14 @@ import javax.persistence.metamodel.EmbeddableType; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; +import org.hibernate.metamodel.spi.DomainMetamodel; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.spi.TypeConfiguration; /** * Hibernate extension to the JPA {@link javax.persistence.metamodel.Metamodel} contract * - * @see org.hibernate.metamodel.spi.RuntimeModel + * @see DomainMetamodel * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java index 50436d68b7..e221678445 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java @@ -9,6 +9,7 @@ package org.hibernate.metamodel.model.domain; import javax.persistence.metamodel.PluralAttribute; import org.hibernate.metamodel.CollectionClassification; +import org.hibernate.query.NotIndexedCollectionException; import org.hibernate.query.sqm.SqmJoinable; import org.hibernate.query.sqm.SqmPathSource; @@ -29,9 +30,21 @@ public interface PluralPersistentAttribute SqmPathSource getElementPathSource(); + default SqmPathSource getIndexPathSource() { + throw new NotIndexedCollectionException( + "Plural attribute [" + getPathName() + "] is not indexed (list / map)" + ); + } + @Override SimpleDomainType getElementType(); @Override SimpleDomainType getValueGraphType(); + + default SimpleDomainType getKeyGraphType() { + throw new NotIndexedCollectionException( + "Plural attribute [" + getPathName() + "] is not indexed (list / map)" + ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/DomainMetamodel.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModel.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/DomainMetamodel.java index b64a1ed0f8..348dd774e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/DomainMetamodel.java @@ -11,6 +11,7 @@ import java.util.function.Consumer; import org.hibernate.graph.RootGraph; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; @@ -21,8 +22,15 @@ import org.hibernate.type.spi.TypeConfiguration; * * @author Steve Ebersole */ -public interface RuntimeModel { +public interface DomainMetamodel { TypeConfiguration getTypeConfiguration(); + JpaMetamodel getJpaMetamodel(); + + default EntityPersister resolveEntityPersister(EntityDomainType domainType) { + return findEntityDescriptor( domainType.getHibernateEntityName() ); + } + + EntityPersister resolveEntityPersister(Object entity); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetamodelImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetamodelImplementor.java index 8a18b6db5d..beac971f92 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetamodelImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetamodelImplementor.java @@ -29,6 +29,7 @@ import org.hibernate.type.spi.TypeConfiguration; * * @author Steve Ebersole */ +@Deprecated public interface MetamodelImplementor extends Metamodel { /** * Access to the TypeConfiguration in effect for this SessionFactory/Metamodel diff --git a/hibernate-core/src/main/java/org/hibernate/query/NotIndexedCollectionException.java b/hibernate-core/src/main/java/org/hibernate/query/NotIndexedCollectionException.java new file mode 100644 index 0000000000..ccdc17e0a8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/query/NotIndexedCollectionException.java @@ -0,0 +1,18 @@ +/* + * 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 an attempt to use a non-indexed collection as indexed. + * + * @author Steve Ebersole + */ +public class NotIndexedCollectionException extends SemanticException { + public NotIndexedCollectionException(String message) { + super( message ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SemanticException.java b/hibernate-core/src/main/java/org/hibernate/query/SemanticException.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/query/sqm/SemanticException.java rename to hibernate-core/src/main/java/org/hibernate/query/SemanticException.java index af7cafa7cd..66f67d0877 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SemanticException.java +++ b/hibernate-core/src/main/java/org/hibernate/query/SemanticException.java @@ -4,7 +4,7 @@ * 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; +package org.hibernate.query; /** * Represents an error in the semantics (meaning) of the passed query. Generally diff --git a/hibernate-core/src/main/java/org/hibernate/query/TrimSpec.java b/hibernate-core/src/main/java/org/hibernate/query/TrimSpec.java new file mode 100644 index 0000000000..0c07839a03 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/query/TrimSpec.java @@ -0,0 +1,22 @@ +/* + * 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; + +import java.util.Locale; + +/** + * @author Steve Ebersole + */ +public enum TrimSpec { + LEADING, + TRAILING, + BOTH; + + public String toSqlText() { + return name().toLowerCase( Locale.ROOT ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java index ddbc0cd7c6..65cb530b71 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java @@ -8,6 +8,7 @@ package org.hibernate.query.criteria; import javax.persistence.criteria.Path; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.NavigablePath; /** @@ -31,6 +32,11 @@ public interface JpaPath extends JpaExpression, Path { */ JpaPath treatAs(Class treatJavaType) throws PathException; + /** + * Support for JPA's explicit (TREAT) down-casting. + */ + JpaPath treatAs(EntityDomainType treatJavaType) throws PathException; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Covariant overrides diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index 8cd6e15479..09edaa8299 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -25,16 +25,22 @@ import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.StandardStack; import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; +import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.query.BinaryArithmeticOperator; import org.hibernate.query.ComparisonOperator; import org.hibernate.query.QueryLogger; +import org.hibernate.query.TrimSpec; import org.hibernate.query.UnaryArithmeticOperator; import org.hibernate.query.hql.DotIdentifierConsumer; import org.hibernate.query.sqm.LiteralNumberFormatException; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.ParsingException; -import org.hibernate.query.sqm.SemanticException; +import org.hibernate.query.SemanticException; +import org.hibernate.query.sqm.SqmExpressable; +import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.StrictJpaComplianceViolation; import org.hibernate.query.sqm.UnknownEntityException; import org.hibernate.query.sqm.produce.SqmCreationProcessingState; @@ -132,7 +138,6 @@ 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.SqmUpdateStatement; -import org.hibernate.sql.TrimSpec; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; @@ -1306,9 +1311,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmMapEntryReference visitMapEntrySelection(HqlParser.MapEntrySelectionContext ctx) { return new SqmMapEntryReference( consumePluralAttributeReference( ctx.path() ), - (BasicJavaDescriptor) creationContext.getDomainModel().getTypeConfiguration() - .getJavaTypeDescriptorRegistry() - .getDescriptor( Map.Entry.class ), creationContext.getNodeBuilder() ); } @@ -1379,7 +1381,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre throw new ParsingException( "Expecting 2 operands to the / operator" ); } - return new SqmBinaryArithmetic<>( + //noinspection unchecked + return new SqmBinaryArithmetic( BinaryArithmeticOperator.DIVIDE, (SqmExpression) ctx.expression( 0 ).accept( this ), (SqmExpression) ctx.expression( 1 ).accept( this ), @@ -1397,9 +1400,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre SqmExpression dividend = (SqmExpression) ctx.expression( 0).accept( this); SqmExpression divisor = (SqmExpression) ctx.expression( 1 ).accept( this ); + //noinspection unchecked return getFunctionTemplate("mod").makeSqmFunctionExpression( asList( dividend, divisor ), - (AllowableFunctionReturnType) dividend.getExpressableType(), + (AllowableFunctionReturnType) dividend.getNodeType(), creationContext.getQueryEngine() ); } @@ -1499,13 +1503,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public Object visitLeastFunction(HqlParser.LeastFunctionContext ctx) { final List> arguments = new ArrayList<>(); - ExpressableType type = null; + SqmExpressable type = null; for ( HqlParser.ExpressionContext argument : ctx.expression() ) { SqmTypedNode arg = (SqmTypedNode) argument.accept( this); arguments.add(arg); //TODO: do something better here! - type = arg.getExpressableType(); + type = arg.getNodeType(); } return getFunctionTemplate("least") @@ -1520,13 +1524,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public Object visitGreatestFunction(HqlParser.GreatestFunctionContext ctx) { final List> arguments = new ArrayList<>(); - ExpressableType type = null; + SqmExpressable type = null; for ( HqlParser.ExpressionContext argument : ctx.expression() ) { SqmTypedNode arg = (SqmTypedNode) argument.accept( this); arguments.add(arg); //TODO: do something better here! - type = arg.getExpressableType(); + type = arg.getNodeType(); } return getFunctionTemplate("greatest") @@ -1541,13 +1545,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitCoalesceExpression(HqlParser.CoalesceExpressionContext ctx) { final List> arguments = new ArrayList<>(); - ExpressableType type = null; + SqmExpressable type = null; for ( HqlParser.ExpressionContext argument : ctx.coalesce().expression() ) { SqmTypedNode arg = (SqmTypedNode) argument.accept( this); arguments.add(arg); //TODO: do something better here! - type = arg.getExpressableType(); + type = arg.getNodeType(); } return getFunctionTemplate("coalesce") @@ -1563,9 +1567,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre final SqmExpression arg1 = (SqmExpression) ctx.nullIf().expression( 0 ).accept( this ); final SqmExpression arg2 = (SqmExpression) ctx.nullIf().expression( 1 ).accept( this ); + //noinspection unchecked return getFunctionTemplate("nullif").makeSqmFunctionExpression( asList( arg1, arg2 ), - (AllowableFunctionReturnType) arg1.getExpressableType(), + (AllowableFunctionReturnType) arg1.getNodeType(), creationContext.getQueryEngine() ); } @@ -1638,7 +1643,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre } private SqmLiteral booleanLiteral(boolean value) { - final BasicValuedExpressableType expressionType = resolveExpressableTypeBasic( Boolean.class ); + final SqmExpressable expressionType = resolveExpressableTypeBasic( Boolean.class ); return new SqmLiteral<>( value, expressionType, creationContext.getQueryEngine().getCriteriaBuilder() ); } @@ -1778,8 +1783,9 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre } } - private BasicValuedExpressableType resolveExpressableTypeBasic(Class javaType) { - return creationContext.getDomainModel().getTypeConfiguration().standardExpressableTypeForJavaType( javaType ); + private SqmExpressable resolveExpressableTypeBasic(Class javaType) { + //noinspection unchecked + return creationContext.getDomainModel().getTypeConfiguration().standardBasicTypeForJavaType( javaType ); } @Override @@ -1889,9 +1895,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitCeilingFunction(HqlParser.CeilingFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("ceiling").makeSqmFunctionExpression( arg, - resolveExpressableTypeBasic( Long.class ), + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Long.class ), creationContext.getQueryEngine() ); } @@ -1900,9 +1907,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitFloorFunction(HqlParser.FloorFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("floor").makeSqmFunctionExpression( arg, - resolveExpressableTypeBasic( Long.class ), + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Long.class ), creationContext.getQueryEngine() ); } @@ -1915,9 +1923,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitAbsFunction(HqlParser.AbsFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("abs").makeSqmFunctionExpression( arg, - (AllowableFunctionReturnType) arg.getExpressableType(), + (AllowableFunctionReturnType) arg.getNodeType(), creationContext.getQueryEngine() ); } @@ -1926,9 +1935,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitSignFunction(HqlParser.SignFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("sign").makeSqmFunctionExpression( arg, - resolveExpressableTypeBasic( Integer.class ), + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), creationContext.getQueryEngine() ); } @@ -1938,9 +1948,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre final SqmExpression dividend = (SqmExpression) ctx.modDividendArgument().accept( this ); final SqmExpression divisor = (SqmExpression) ctx.modDivisorArgument().accept( this ); + //noinspection unchecked return getFunctionTemplate("mod").makeSqmFunctionExpression( asList( dividend, divisor ), - (AllowableFunctionReturnType) dividend.getExpressableType(), + (AllowableFunctionReturnType) dividend.getNodeType(), creationContext.getQueryEngine() ); } @@ -1950,9 +1961,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre final SqmExpression base = (SqmExpression) ctx.powerBaseArgument().accept( this ); final SqmExpression power = (SqmExpression) ctx.powerPowerArgument().accept( this ); + //noinspection unchecked return getFunctionTemplate("power").makeSqmFunctionExpression( asList( base, power ), - (AllowableFunctionReturnType) base.getExpressableType(), + (AllowableFunctionReturnType) base.getNodeType(), creationContext.getQueryEngine() ); } @@ -1963,7 +1975,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre return getFunctionTemplate( ctx.trigFunctionName().getText() ).makeSqmFunctionExpression( arg, - resolveExpressableTypeBasic( Double.class ), + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Double.class ), creationContext.getQueryEngine() ); } @@ -1972,9 +1984,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitSqrtFunction(HqlParser.SqrtFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("sqrt").makeSqmFunctionExpression( arg, - (AllowableFunctionReturnType) arg.getExpressableType(), + (AllowableFunctionReturnType) arg.getNodeType(), creationContext.getQueryEngine() ); } @@ -1984,9 +1997,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); final SqmExpression precision = (SqmExpression) ctx.roundFunctionPrecision().expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("round").makeSqmFunctionExpression( asList(arg, precision), - (AllowableFunctionReturnType) arg.getExpressableType(), + (AllowableFunctionReturnType) arg.getNodeType(), creationContext.getQueryEngine() ); } @@ -1996,9 +2010,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre final SqmExpression sin = (SqmExpression) ctx.expression().get( 0).accept( this ); final SqmExpression cos = (SqmExpression) ctx.expression().get( 1).accept( this ); + //noinspection unchecked return getFunctionTemplate("atan2").makeSqmFunctionExpression( asList(sin, cos), - (AllowableFunctionReturnType) sin.getExpressableType(), + (AllowableFunctionReturnType) sin.getNodeType(), creationContext.getQueryEngine() ); } @@ -2007,9 +2022,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitLnFunction(HqlParser.LnFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("ln").makeSqmFunctionExpression( arg, - (AllowableFunctionReturnType) arg.getExpressableType(), + (AllowableFunctionReturnType) arg.getNodeType(), creationContext.getQueryEngine() ); @@ -2019,9 +2035,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public SqmExpression visitExpFunction(HqlParser.ExpFunctionContext ctx) { final SqmExpression arg = (SqmExpression) ctx.expression().accept( this ); + //noinspection unchecked return getFunctionTemplate("exp").makeSqmFunctionExpression( arg, - (AllowableFunctionReturnType) arg.getExpressableType(), + (AllowableFunctionReturnType) arg.getNodeType(), creationContext.getQueryEngine() ); } @@ -2030,29 +2047,62 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public Object visitDatetimeField(HqlParser.DatetimeFieldContext ctx) { NodeBuilder nodeBuilder = creationContext.getNodeBuilder(); if (ctx.DAY()!=null) { - return new SqmExtractUnit<>( "day", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "day", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.MONTH()!=null) { - return new SqmExtractUnit<>( "month", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "month", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.YEAR()!=null) { - return new SqmExtractUnit<>( "year", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "year", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.HOUR()!=null) { - return new SqmExtractUnit<>( "hour", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "hour", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.MINUTE()!=null) { - return new SqmExtractUnit<>( "minute", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "minute", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.SECOND()!=null) { - return new SqmExtractUnit<>( "second", resolveExpressableTypeBasic( Float.class ), nodeBuilder); + return new SqmExtractUnit<>( + "second", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Float.class ), + nodeBuilder + ); } if (ctx.WEEK()!=null) { - return new SqmExtractUnit<>( "week", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "week", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.QUARTER()!=null) { - return new SqmExtractUnit<>( "quarter", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "quarter", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } + return super.visitDatetimeField(ctx); } @@ -2061,11 +2111,19 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre NodeBuilder nodeBuilder = creationContext.getNodeBuilder(); if (ctx.MICROSECOND()!=null) { //TODO: need to go back to the dialect, it's called "microseconds" on some - return new SqmExtractUnit<>( "microsecond", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "microsecond", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.MILLISECOND()!=null) { //TODO: need to go back to the dialect, it's called "milliseconds" on some - return new SqmExtractUnit<>( "millisecond", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "millisecond", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } return super.visitSecondsField(ctx); } @@ -2074,10 +2132,18 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre public Object visitTimeZoneField(HqlParser.TimeZoneFieldContext ctx) { NodeBuilder nodeBuilder = creationContext.getNodeBuilder(); if (ctx.TIMEZONE_HOUR()!=null) { - return new SqmExtractUnit<>( "timezone_hour", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "timezone_hour", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } if (ctx.TIMEZONE_MINUTE()!=null) { - return new SqmExtractUnit<>( "timezone_minute", resolveExpressableTypeBasic( Integer.class ), nodeBuilder); + return new SqmExtractUnit<>( + "timezone_minute", + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); } return super.visitTimeZoneField(ctx); } @@ -2097,6 +2163,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre return expressionToExtract; } + //noinspection unchecked return getFunctionTemplate("extract").makeSqmFunctionExpression( asList( extractFieldExpression, expressionToExtract ), extractFieldExpression.getType(), @@ -2136,24 +2203,66 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre String text = castTargetContext.identifier().getText(); NodeBuilder nodeBuilder = creationContext.getNodeBuilder(); switch (text.toLowerCase()) { - case "string": return new SqmCastTarget<>( resolveExpressableTypeBasic( String.class ), nodeBuilder ); - case "integer": return new SqmCastTarget<>( resolveExpressableTypeBasic( Integer.class ), nodeBuilder ); - case "long": return new SqmCastTarget<>( resolveExpressableTypeBasic( Long.class ), nodeBuilder ); - case "float": return new SqmCastTarget<>( resolveExpressableTypeBasic( Float.class ), nodeBuilder ); - case "double": return new SqmCastTarget<>( resolveExpressableTypeBasic( Double.class ), nodeBuilder ); - case "time": return new SqmCastTarget<>( resolveExpressableTypeBasic( Time.class ), nodeBuilder ); - case "date": return new SqmCastTarget<>( resolveExpressableTypeBasic( Date.class ), nodeBuilder ); - case "timestamp": return new SqmCastTarget<>( resolveExpressableTypeBasic( Timestamp.class ), nodeBuilder ); - default: throw new SqmProductionException( "unrecognized cast target type: " + text); + case "string": { + return new SqmCastTarget<>( + (AllowableFunctionReturnType) resolveExpressableTypeBasic( String.class ), + nodeBuilder + ); + } + case "integer": { + return new SqmCastTarget<>( + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ), + nodeBuilder + ); + } + case "long": { + return new SqmCastTarget<>( + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Long.class ), nodeBuilder + ); + } + case "float": { + return new SqmCastTarget<>( + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Float.class ), + nodeBuilder + ); + } + case "double": { + return new SqmCastTarget<>( + (AllowableFunctionReturnType) resolveExpressableTypeBasic( Double.class ), + nodeBuilder + ); + } + case "time": { + return new SqmCastTarget<>( + (AllowableFunctionReturnType