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:
parent
cd354f1e2b
commit
35860baad6
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
*
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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...
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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) {
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue