support for pluggable HqlTranslator (renamed from SemanticQueryProducer);

support for pluggable SqmToSqlAstConverterFactory

- both allow a precedence of user-supplied > Dialect > standard
This commit is contained in:
Steve Ebersole 2019-09-23 11:53:14 -05:00
parent cd354f1e2b
commit 35860baad6
23 changed files with 283 additions and 71 deletions

View File

@ -58,9 +58,10 @@ import org.hibernate.loader.BatchFetchStyle;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.criteria.LiteralHandlingMode;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
@ -210,9 +211,10 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
// Queries
private SemanticQueryProducer semanticQueryProducer;
private HqlTranslator hqlTranslator;
private SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
private SqmFunctionRegistry sqmFunctionRegistry;
private SqmToSqlAstConverterFactory sqmTranslatorFactory;
private Boolean useOfJdbcNamedParametersEnabled;
private Map querySubstitutions;
private boolean namedQueryStartupCheckingEnabled;
@ -356,7 +358,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
this.jtaTrackByThread = cfgService.getSetting( JTA_TRACK_BY_THREAD, BOOLEAN, true );
final String semanticQueryProducerImplName = ConfigurationHelper.extractValue(
final String hqlTranslatorImplFqn = ConfigurationHelper.extractValue(
AvailableSettings.SEMANTIC_QUERY_PRODUCER,
configurationSettings,
() -> ConfigurationHelper.extractPropertyValue(
@ -364,12 +366,23 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
configurationSettings
)
);
this.semanticQueryProducer = resolveSemanticQueryProducer(
semanticQueryProducerImplName,
this.hqlTranslator = resolveHqlTranslator(
hqlTranslatorImplFqn,
serviceRegistry,
strategySelector
);
final String sqmTranslatorFactoryImplFqn = ConfigurationHelper.extractPropertyValue(
AvailableSettings.SEMANTIC_QUERY_TRANSLATOR,
configurationSettings
);
this.sqmTranslatorFactory = resolveSqmTranslator(
sqmTranslatorFactoryImplFqn,
serviceRegistry,
strategySelector
);
final String sqmMutationStrategyImplName = ConfigurationHelper.extractValue(
AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY,
configurationSettings,
@ -587,7 +600,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
);
}
private SemanticQueryProducer resolveSemanticQueryProducer(
private HqlTranslator resolveHqlTranslator(
String producerName,
StandardServiceRegistry serviceRegistry,
StrategySelector strategySelector) {
@ -597,18 +610,32 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
//noinspection Convert2Lambda
return strategySelector.resolveDefaultableStrategy(
SemanticQueryProducer.class,
HqlTranslator.class,
producerName,
new Callable<SemanticQueryProducer>() {
new Callable<HqlTranslator>() {
@Override
public SemanticQueryProducer call() throws Exception {
public HqlTranslator call() throws Exception {
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
return (SemanticQueryProducer) classLoaderService.classForName( producerName ).newInstance();
return (HqlTranslator) classLoaderService.classForName( producerName ).newInstance();
}
}
);
}
private SqmToSqlAstConverterFactory resolveSqmTranslator(
String translatorImplFqn,
StandardServiceRegistry serviceRegistry,
StrategySelector strategySelector) {
if ( StringHelper.isEmpty( translatorImplFqn ) ) {
return null;
}
return strategySelector.resolveStrategy(
SqmToSqlAstConverterFactory.class,
translatorImplFqn
);
}
@SuppressWarnings("deprecation")
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
Object setting = configurationSettings.get( INTERCEPTOR );
@ -831,8 +858,13 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
}
@Override
public SemanticQueryProducer getHqlTranslator() {
return semanticQueryProducer;
public HqlTranslator getHqlTranslator() {
return hqlTranslator;
}
@Override
public SqmToSqlAstConverterFactory getSqmTranslatorFactory() {
return sqmTranslatorFactory;
}
@Override

View File

@ -30,9 +30,10 @@ import org.hibernate.loader.BatchFetchStyle;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.criteria.LiteralHandlingMode;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
@ -40,6 +41,9 @@ import org.hibernate.tuple.entity.EntityTuplizerFactory;
/**
* Convenience base class for custom implementors of SessionFactoryOptions, using delegation
*
* @implNote non-abstract to ensure that all SessionFactoryOptions methods have at least
* a default implementation
*
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
@ -391,10 +395,15 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
}
@Override
public SemanticQueryProducer getHqlTranslator() {
public HqlTranslator getHqlTranslator() {
return delegate.getHqlTranslator();
}
@Override
public SqmToSqlAstConverterFactory getSqmTranslatorFactory() {
return delegate.getSqmTranslatorFactory();
}
@Override
public TimeZone getJdbcTimeZone() {
return delegate.getJdbcTimeZone();

View File

@ -33,9 +33,10 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.QueryLiteralRendering;
import org.hibernate.query.criteria.LiteralHandlingMode;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.stat.Statistics;
@ -143,7 +144,9 @@ public interface SessionFactoryOptions {
};
}
SemanticQueryProducer getHqlTranslator();
HqlTranslator getHqlTranslator();
SqmToSqlAstConverterFactory getSqmTranslatorFactory();
SqmMultiTableMutationStrategy getSqmMultiTableMutationStrategy();
@ -351,5 +354,4 @@ public interface SessionFactoryOptions {
boolean isUseOfJdbcNamedParametersEnabled();
boolean isOmitJoinOfSuperclassTablesEnabled();
}

View File

@ -17,9 +17,11 @@ import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.spi.TimestampsCacheFactory;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.resource.beans.container.spi.ExtendedBeanManager;
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
@ -924,10 +926,15 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
String QUERY_TRANSLATOR = "hibernate.query.factory_class";
/**
* Names the {@link org.hibernate.query.hql.SemanticQueryProducer} class to use.
* Names the {@link HqlTranslator} class to use.
*/
String SEMANTIC_QUERY_PRODUCER = "hibernate.query.hql.translator";
/**
* Names the {@link SqmToSqlAstConverterFactory} class to use.
*/
String SEMANTIC_QUERY_TRANSLATOR = "hibernate.query.sqm.translator";
/**
* @deprecated Use {@link #QUERY_MULTI_TABLE_MUTATION_STRATEGY} instead
*/

View File

@ -40,6 +40,7 @@ import org.hibernate.ScrollMode;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.model.relational.Sequence;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CastFunction;
@ -95,9 +96,11 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.ANSIJoinFragment;
@ -3072,4 +3075,31 @@ public abstract class Dialect implements ConversionContext {
protected String prependComment(String sql, String comment) {
return "/* " + comment + " */ " + sql;
}
/**
* Return an HqlTranslator specific for the Dialect. Return {@code null}
* to use Hibernate's standard translator.
*
* Note that {@link SessionFactoryOptions#getHqlTranslator()} has higher precedence
*
* @see org.hibernate.query.hql.internal.StandardHqlTranslator
* @see QueryEngine#getHqlTranslator()
*/
public HqlTranslator getHqlTranslator() {
return null;
}
/**
* Return an SqmToSqlAstConverterFactory specific for the Dialect. Return {@code null}
* to use Hibernate's standard translator.
*
* Note that {@link SessionFactoryOptions#getSqmTranslatorFactory()} has higher
* precedence as it comes directly from the user config
*
* @see org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter
* @see QueryEngine#getSqmTranslator()
*/
public SqmToSqlAstConverterFactory getSqmTranslatorFactory() {
return null;
}
}

View File

@ -615,7 +615,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
final QueryInterpretationCache interpretationCache = queryEngine.getInterpretationCache();
final SqmStatement sqm = interpretationCache.resolveSqmStatement(
queryString,
s -> queryEngine.getSemanticQueryProducer().interpret( queryString )
s -> queryEngine.getHqlTranslator().interpret( queryString )
);
final QuerySqmImpl query = new QuerySqmImpl(

View File

@ -15,21 +15,24 @@ import org.hibernate.query.sqm.tree.SqmStatement;
* Main entry point into building semantic queries.
*
* @see SessionFactoryImplementor#getQueryEngine()
* @see QueryEngine#getSemanticQueryProducer()
* @see QueryEngine#getHqlTranslator()
*
* @author Steve Ebersole
*/
@Incubating
public interface SemanticQueryProducer {
public interface HqlTranslator {
/**
* Performs the interpretation of a HQL/JPQL query string to SQM.
*
* @param query The HQL/JPQL query string to interpret
* @param hql The HQL/JPQL query string to interpret
*
* @return The semantic representation of the incoming query.
*/
SqmStatement interpret(String query);
SqmStatement interpret(String hql);
/**
* Give the translator a chance to "shut down" if it needs to
*/
default void close() {
// nothing to do generally speaking
}

View File

@ -124,7 +124,7 @@ public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implemen
@Override
public void validate(QueryEngine queryEngine) {
queryEngine.getSemanticQueryProducer().interpret( getHqlString() );
queryEngine.getHqlTranslator().interpret( getHqlString() );
}
@Override

View File

@ -8,7 +8,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.QueryException;
import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.internal.SqmTreePrinter;
import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.hql.spi.SqmCreationOptions;
@ -19,11 +19,11 @@ import org.hibernate.query.sqm.tree.SqmStatement;
*
* @author Steve Ebersole
*/
public class SemanticQueryProducerImpl implements SemanticQueryProducer {
public class StandardHqlTranslator implements HqlTranslator {
private final SqmCreationContext sqmCreationContext;
private final SqmCreationOptions sqmCreationOptions;
public SemanticQueryProducerImpl(
public StandardHqlTranslator(
SqmCreationContext sqmCreationContext,
SqmCreationOptions sqmCreationOptions) {
this.sqmCreationContext = sqmCreationContext;

View File

@ -12,7 +12,7 @@
* This includes transformation via Antlr, {@link org.hibernate.query.Query}
* manipulation and execution
*
* @see org.hibernate.query.hql.SemanticQueryProducer
* @see org.hibernate.query.hql.HqlTranslator
* @see org.hibernate.query.hql.spi.HqlQueryImplementor
* @see org.hibernate.query.hql.spi.NamedHqlQueryMemento
*/

View File

@ -12,7 +12,7 @@ import java.util.function.Consumer;
import org.hibernate.HibernateException;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.named.NamedQueryRepository;
import org.hibernate.query.named.NamedResultSetMappingMemento;
@ -127,7 +127,7 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
public Map<String, HibernateException> checkNamedQueries(QueryEngine queryEngine) {
Map<String,HibernateException> errors = new HashMap<>();
final SemanticQueryProducer sqmProducer = queryEngine.getSemanticQueryProducer();
final HqlTranslator sqmProducer = queryEngine.getHqlTranslator();
final QueryInterpretationCache interpretationCache = queryEngine.getInterpretationCache();
final boolean cachingEnabled = interpretationCache.isEnabled();

View File

@ -16,21 +16,27 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.query.QueryLogger;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.hql.internal.StandardHqlTranslator;
import org.hibernate.query.hql.spi.SqmCreationOptions;
import org.hibernate.query.internal.QueryInterpretationCacheDisabledImpl;
import org.hibernate.query.internal.QueryInterpretationCacheStandardImpl;
import org.hibernate.query.named.NamedQueryRepository;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
import org.hibernate.query.hql.internal.SemanticQueryProducerImpl ;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.internal.SqmCreationOptionsStandard;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.hql.spi.SqmCreationOptions;
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
/**
* Aggregation and encapsulation of the components Hibernate uses
@ -44,7 +50,7 @@ public class QueryEngine {
SessionFactoryImplementor sessionFactory,
MetadataImplementor metadata) {
return new QueryEngine(
sessionFactory.getMetamodel(),
sessionFactory.getJpaMetamodel(),
sessionFactory.getServiceRegistry(),
sessionFactory.getSessionFactoryOptions(),
sessionFactory,
@ -56,12 +62,13 @@ public class QueryEngine {
private final NamedQueryRepository namedQueryRepository;
private final SqmCriteriaNodeBuilder criteriaBuilder;
private final SemanticQueryProducer semanticQueryProducer;
private final HqlTranslator hqlTranslator;
private final SqmToSqlAstConverterFactory sqmToSqlAstConverterFactory;
private final QueryInterpretationCache interpretationCache;
private final SqmFunctionRegistry sqmFunctionRegistry;
public QueryEngine(
MetamodelImplementor domainModel,
JpaMetamodel domainModel,
ServiceRegistry serviceRegistry,
SessionFactoryOptions runtimeOptions,
SqmCreationContext sqmCreationContext,
@ -74,17 +81,27 @@ public class QueryEngine {
this.namedQueryRepository = namedQueryRepository;
// todo (6.0) : allow SemanticQueryProducer to be pluggable (see legacy `QueryTranslatorFactoryInitiator`)
// - also, allow for Dialect to specify producer to use (or defer to standard producer)
this.semanticQueryProducer = new SemanticQueryProducerImpl( sqmCreationContext, sqmCreationOptions );
this.hqlTranslator = resolveHqlTranslator(
runtimeOptions,
dialect,
sqmCreationContext,
sqmCreationOptions
);
this.sqmToSqlAstConverterFactory = resolveSqmToSqlAstConverterFactory(
runtimeOptions,
dialect,
sqmCreationContext,
sqmCreationOptions
);
this.criteriaBuilder = new SqmCriteriaNodeBuilder(
this,
domainModel.getJpaMetamodel(),
domainModel,
serviceRegistry
);
this.interpretationCache = buildQueryPlanCache( properties );
this.interpretationCache = buildInterpretationCache( properties );
this.sqmFunctionRegistry = new SqmFunctionRegistry();
dialect.initializeFunctionRegistry( this );
@ -93,7 +110,56 @@ public class QueryEngine {
}
}
private static QueryInterpretationCache buildQueryPlanCache(Map properties) {
private static HqlTranslator resolveHqlTranslator(
SessionFactoryOptions runtimeOptions,
Dialect dialect,
SqmCreationContext sqmCreationContext,
SqmCreationOptions sqmCreationOptions) {
if ( runtimeOptions.getHqlTranslator() != null ) {
return runtimeOptions.getHqlTranslator();
}
if ( dialect.getHqlTranslator() != null ) {
return dialect.getHqlTranslator();
}
return new StandardHqlTranslator( sqmCreationContext, sqmCreationOptions );
}
private SqmToSqlAstConverterFactory resolveSqmToSqlAstConverterFactory(
SessionFactoryOptions runtimeOptions,
Dialect dialect,
SqmCreationContext sqmCreationContext,
SqmCreationOptions sqmCreationOptions) {
if ( runtimeOptions.getSqmTranslatorFactory() != null ) {
return runtimeOptions.getSqmTranslatorFactory();
}
if ( dialect.getSqmTranslatorFactory() != null ) {
return dialect.getSqmTranslatorFactory();
}
//noinspection Convert2Lambda
return new SqmToSqlAstConverterFactory() {
@Override
public SqmSelectToSqlAstConverter createSelectConverter(
QueryOptions queryOptions,
DomainParameterXref domainParameterXref,
QueryParameterBindings domainParameterBindings,
LoadQueryInfluencers influencers,
SqlAstCreationContext creationContext) {
return new StandardSqmSelectToSqlAstConverter(
queryOptions,
domainParameterXref,
domainParameterBindings,
influencers,
creationContext
);
}
};
}
private static QueryInterpretationCache buildInterpretationCache(Map properties) {
final boolean explicitUseCache = ConfigurationHelper.getBoolean(
AvailableSettings.QUERY_PLAN_CACHE_ENABLED,
properties,
@ -144,8 +210,12 @@ public class QueryEngine {
return criteriaBuilder;
}
public SemanticQueryProducer getSemanticQueryProducer() {
return semanticQueryProducer;
public HqlTranslator getHqlTranslator() {
return hqlTranslator;
}
public SqmToSqlAstConverterFactory getSqmTranslatorFactory() {
return sqmToSqlAstConverterFactory;
}
public QueryInterpretationCache getInterpretationCache() {
@ -165,8 +235,8 @@ public class QueryEngine {
criteriaBuilder.close();
}
if ( semanticQueryProducer != null ) {
semanticQueryProducer.close();
if ( hqlTranslator != null ) {
hqlTranslator.close();
}
if ( interpretationCache != null ) {

View File

@ -14,14 +14,17 @@ import javax.persistence.TupleElement;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.streams.StingArrayCollector;
import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverterFactory;
import org.hibernate.query.sqm.sql.internal.SqmSelectInterpretation;
import org.hibernate.query.sqm.sql.internal.SqmSelectToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
@ -147,20 +150,30 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
@Override
public List<R> performList(ExecutionContext executionContext) {
final SharedSessionContractImplementor session = executionContext.getSession();
if ( jdbcSelect == null ) {
// todo (6.0) : for cases where we have no "load query influencers" we could use a cached SQL AST
// - this is similar to the plan for loaders
final SqmSelectToSqlAstConverter sqmConverter = new SqmSelectToSqlAstConverter(
final SessionFactoryImplementor sessionFactory = session.getFactory();
final SqmToSqlAstConverterFactory sqmTranslatorFactory = sessionFactory.getQueryEngine().getSqmTranslatorFactory();
final SqmSelectToSqlAstConverter sqmConverter = sqmTranslatorFactory.createSelectConverter(
executionContext.getQueryOptions(),
domainParameterXref,
executionContext.getDomainParameterBindingContext().getQueryParameterBindings(),
executionContext.getLoadQueryInfluencers(),
executionContext.getSession().getFactory()
sessionFactory
);
final SqmSelectInterpretation interpretation = sqmConverter.interpret( sqm );
// todo (6.0) : allow Dialect to specify SQL -> JdbcCall converter to use
jdbcSelect = SqlAstSelectToJdbcSelectConverter.interpret(
interpretation.getSqlAst(),
executionContext.getSession().getFactory()
sessionFactory
);
this.jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
@ -174,11 +187,11 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
executionContext.getDomainParameterBindingContext().getQueryParameterBindings(),
domainParameterXref,
jdbcParamsXref,
executionContext.getSession()
session
);
try {
return executionContext.getSession().getFactory().getJdbcServices().getJdbcSelectExecutor().list(
return session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect,
jdbcParameterBindings,
executionContext,

View File

@ -92,7 +92,7 @@ public class QuerySqmImpl<R>
final SessionFactoryImplementor factory = producer.getFactory();
this.sqmStatement = factory.getQueryEngine().getSemanticQueryProducer().interpret( hqlString );
this.sqmStatement = factory.getQueryEngine().getHqlTranslator().interpret( hqlString );
if ( resultType != null ) {
if ( sqmStatement instanceof SqmDmlStatement ) {

View File

@ -12,7 +12,7 @@
*
* This package defines support for producing SQM trees (see {@link org.hibernate.query.sqm.tree}).
* The main entry point into producing an SQM tree is
* {@link org.hibernate.query.hql.SemanticQueryProducer}, which
* {@link org.hibernate.query.hql.HqlTranslator}, which
* can be obtained via
* {@link org.hibernate.query.spi.QueryEngine} which in turn is obtained via
* {@link org.hibernate.engine.spi.SessionFactoryImplementor#getQueryEngine()}.
@ -21,7 +21,7 @@
* == From HQL/JPQL
*
* `SemanticQueryProducer` defines just a single method for producing SQM based on HQL:
* {@link org.hibernate.query.hql.SemanticQueryProducer#interpret}.
* {@link org.hibernate.query.hql.HqlTranslator#interpret}.
* See {@link org.hibernate.query.hql.internal} for details
*
*

View File

@ -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.sqm.sql;
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
import org.hibernate.query.sqm.sql.internal.SqmSelectInterpretation;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
/**
* @author Steve Ebersole
*/
public interface SqmSelectToSqlAstConverter extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
SqmSelectInterpretation interpret(SqmSelectStatement statement);
}

View File

@ -0,0 +1,28 @@
/*
* 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.sql;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
/**
* @author Steve Ebersole
*/
public interface SqmToSqlAstConverterFactory {
SqmSelectToSqlAstConverter createSelectConverter(
QueryOptions queryOptions,
DomainParameterXref domainParameterXref,
QueryParameterBindings domainParameterBindings,
LoadQueryInfluencers influencers,
SqlAstCreationContext creationContext);
// todo (6.0) : update, delete, etc converters...
}

View File

@ -17,7 +17,7 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
/**
* Details of the result of interpreting an SQM SELECT AST into a SQL SELECT AST
*
* @see SqmSelectToSqlAstConverter#interpret(org.hibernate.query.sqm.tree.select.SqmSelectStatement)
* @see StandardSqmSelectToSqlAstConverter#interpret(org.hibernate.query.sqm.tree.select.SqmSelectStatement)
*
* @author Steve Ebersole
*/

View File

@ -64,14 +64,14 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
* @author John O'Hara
*/
@SuppressWarnings("unchecked")
public class SqmSelectToSqlAstConverter
public class StandardSqmSelectToSqlAstConverter
extends BaseSqmToSqlAstConverter
implements DomainResultCreationState {
implements DomainResultCreationState, org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter {
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
private final List<DomainResult> domainResults = new ArrayList<>();
public SqmSelectToSqlAstConverter(
public StandardSqmSelectToSqlAstConverter(
QueryOptions queryOptions,
DomainParameterXref domainParameterXref,
QueryParameterBindings domainParameterBindings,
@ -82,6 +82,7 @@ public class SqmSelectToSqlAstConverter
super( creationContext, queryOptions, domainParameterXref, domainParameterBindings, influencers );
}
@Override
public SqmSelectInterpretation interpret(SqmSelectStatement statement) {
return new SqmSelectInterpretation(
visitSelectStatement( statement ),
@ -292,7 +293,7 @@ public class SqmSelectToSqlAstConverter
joined,
lockMode,
alias,
SqmSelectToSqlAstConverter.this
StandardSqmSelectToSqlAstConverter.this
);
}
catch (RuntimeException e) {

View File

@ -114,7 +114,7 @@ public class JpaStandardSqmInferenceTests extends SessionFactoryBasedFunctionalT
}
private void checkParameters(String query, Class<?>... expecteds) {
final SqmStatement sqmStatement = sessionFactory().getQueryEngine().getSemanticQueryProducer().interpret( query );
final SqmStatement sqmStatement = sessionFactory().getQueryEngine().getHqlTranslator().interpret( query );
checkParameterTypes( sqmStatement, expecteds );
}

View File

@ -56,7 +56,7 @@ public abstract class BaseSqmUnitTest
}
public static SqmSelectStatement interpretSelect(String hql, SessionFactoryImplementor sessionFactory) {
return (SqmSelectStatement) sessionFactory.getQueryEngine().getSemanticQueryProducer().interpret( hql );
return (SqmSelectStatement) sessionFactory.getQueryEngine().getHqlTranslator().interpret( hql );
}
@Override

View File

@ -12,7 +12,6 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Component;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
import org.hibernate.query.NavigablePath;
@ -20,7 +19,7 @@ import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sqm.internal.QuerySqmImpl;
import org.hibernate.query.sqm.sql.internal.SqmSelectInterpretation;
import org.hibernate.query.sqm.sql.internal.SqmSelectToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.sql.ast.spi.SqlAstSelectToJdbcSelectConverter;
import org.hibernate.sql.ast.spi.SqlSelection;
@ -78,7 +77,7 @@ public class SmokeTests {
//noinspection unchecked
final SqmSelectStatement<String> sqmStatement = (SqmSelectStatement<String>) hqlQuery.getSqmStatement();
final SqmSelectToSqlAstConverter sqmConverter = new SqmSelectToSqlAstConverter(
final StandardSqmSelectToSqlAstConverter sqmConverter = new StandardSqmSelectToSqlAstConverter(
hqlQuery.getQueryOptions(),
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
query.getParameterBindings(),
@ -134,7 +133,7 @@ public class SmokeTests {
//noinspection unchecked
final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
final SqmSelectToSqlAstConverter sqmConverter = new SqmSelectToSqlAstConverter(
final StandardSqmSelectToSqlAstConverter sqmConverter = new StandardSqmSelectToSqlAstConverter(
hqlQuery.getQueryOptions(),
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
query.getParameterBindings(),

View File

@ -17,7 +17,7 @@ import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@ -55,7 +55,7 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
super.configure( cfg );
cfg.setProperty( Environment.USE_QUERY_CACHE, "false" );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
cfg.setProperty( Environment.SEMANTIC_QUERY_PRODUCER, SemanticQueryProducer.class.getName() );
cfg.setProperty( Environment.SEMANTIC_QUERY_PRODUCER, HqlTranslator.class.getName() );
}
private void createData() {