From fffc9e7786488a28faa328d6be58ed91fa9b2441 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Fri, 30 Aug 2019 13:40:14 +0100 Subject: [PATCH] 6 - SQM based on JPA type system Fix compilation errors, imports, and amend deleted files after rebasing. --- .../org/hibernate/dialect/DB2Dialect.java | 4 - .../java/org/hibernate/dialect/Dialect.java | 2 - .../engine/query/spi/QueryPlanCache.java | 448 ------ .../internal/DefaultRefreshEventListener.java | 5 +- .../ast/tree/AbstractMapComponentNode.java | 143 -- .../tree/BinaryArithmeticOperatorNode.java | 217 --- .../hql/internal/ast/tree/FromElement.java | 730 --------- .../internal/ast/tree/FromElementType.java | 0 .../hql/internal/ast/tree/MapEntryNode.java | 313 ---- .../ast/util/ASTReferencedTablesPrinter.java | 72 - .../ast/util/SyntheticAndFactory.java | 191 --- .../internal/classic/QueryTranslatorImpl.java | 1376 ----------------- .../AbstractInlineIdsUpdateHandlerImpl.java | 141 -- .../AbstractSharedSessionContract.java | 2 - .../internal/SessionFactoryImpl.java | 2 - .../java/org/hibernate/loader/Loader.java | 4 + .../internal/ResultSetProcessorImpl.java | 2 + .../AbstractManipulationCriteriaQuery.java | 172 --- .../ParameterizedFunctionExpression.java | 128 -- .../internal/predicate/CompoundPredicate.java | 174 --- .../query/internal/AbstractProducedQuery.java | 2 +- .../tuple/entity/AbstractEntityTuplizer.java | 1 + .../org/hibernate/test/join/JoinTest.java | 3 - .../OmitAncestorJoinTest.java | 167 -- ...inWhenCommonSecondaryTablePresentTest.java | 262 ---- ...storJoinWhenSecondaryTablePresentTest.java | 107 -- .../OmitAncestorTestCase.java | 48 - .../stat/ConcurrentQueryStatisticsTest.java | 0 28 files changed, 11 insertions(+), 4705 deletions(-) delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractMapComponentNode.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryArithmeticOperatorNode.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MapEntryNode.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTReferencedTablesPrinter.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/SyntheticAndFactory.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/hql/spi/id/inline/AbstractInlineIdsUpdateHandlerImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/query/criteria/internal/AbstractManipulationCriteriaQuery.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/function/ParameterizedFunctionExpression.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/query/criteria/internal/predicate/CompoundPredicate.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenCommonSecondaryTablePresentTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenSecondaryTablePresentTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorTestCase.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/stat/ConcurrentQueryStatisticsTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index 1e1021256f..bc6059b54f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -32,10 +32,6 @@ import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; -import org.hibernate.hql.spi.id.IdTableSupportStandardImpl; -import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy; -import org.hibernate.hql.spi.id.local.AfterUseAction; -import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index db498ae350..be24a4c41b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -29,7 +29,6 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.LockMode; @@ -37,7 +36,6 @@ import org.hibernate.LockOptions; import org.hibernate.MappingException; import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NullPrecedence; -import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java deleted file mode 100644 index cf521026a7..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.query.spi; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.hibernate.Filter; -import org.hibernate.MappingException; -import org.hibernate.QueryException; -import org.hibernate.cfg.Environment; -import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.CoreLogging; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.FilterImpl; -import org.hibernate.internal.util.collections.BoundedConcurrentHashMap; -import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.query.ParameterMetadata; -import org.hibernate.query.internal.ParameterMetadataImpl; -import org.hibernate.stat.spi.StatisticsImplementor; - -/** - * Acts as a cache for compiled query plans, as well as query-parameter metadata. - * - * @see Environment#QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE - * @see Environment#QUERY_PLAN_CACHE_MAX_SIZE - * - * @author Steve Ebersole - */ -public class QueryPlanCache implements Serializable { - private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryPlanCache.class ); - - /** - * The default strong reference count. - */ - public static final int DEFAULT_PARAMETER_METADATA_MAX_COUNT = 128; - /** - * The default soft reference count. - */ - public static final int DEFAULT_QUERY_PLAN_MAX_COUNT = 2048; - - private final SessionFactoryImplementor factory; - - /** - * the cache of the actual plans... - */ - private final BoundedConcurrentHashMap queryPlanCache; - - /** - * simple cache of param metadata based on query string. Ideally, the original "user-supplied query" - * string should be used to obtain this metadata (i.e., not the para-list-expanded query string) to avoid - * unnecessary cache entries. - *

- * Used solely for caching param metadata for native-sql queries, see {@link #getSQLParameterMetadata} for a - * discussion as to why... - */ - private final BoundedConcurrentHashMap parameterMetadataCache; - - - private NativeQueryInterpreter nativeQueryInterpreter; - - /** - * Constructs the QueryPlanCache to be used by the given SessionFactory - * - * @param factory The SessionFactory - */ - @SuppressWarnings("deprecation") - public QueryPlanCache(final SessionFactoryImplementor factory) { - this.factory = factory; - - Integer maxParameterMetadataCount = ConfigurationHelper.getInteger( - Environment.QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE, - factory.getProperties() - ); - if ( maxParameterMetadataCount == null ) { - maxParameterMetadataCount = ConfigurationHelper.getInt( - Environment.QUERY_PLAN_CACHE_MAX_STRONG_REFERENCES, - factory.getProperties(), - DEFAULT_PARAMETER_METADATA_MAX_COUNT - ); - } - Integer maxQueryPlanCount = ConfigurationHelper.getInteger( - Environment.QUERY_PLAN_CACHE_MAX_SIZE, - factory.getProperties() - ); - if ( maxQueryPlanCount == null ) { - maxQueryPlanCount = ConfigurationHelper.getInt( - Environment.QUERY_PLAN_CACHE_MAX_SOFT_REFERENCES, - factory.getProperties(), - DEFAULT_QUERY_PLAN_MAX_COUNT - ); - } - - queryPlanCache = new BoundedConcurrentHashMap( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS ); - parameterMetadataCache = new BoundedConcurrentHashMap<>( - maxParameterMetadataCount, - 20, - BoundedConcurrentHashMap.Eviction.LIRS - ); - - nativeQueryInterpreter = factory.getServiceRegistry().getService( NativeQueryInterpreter.class ); - } - - /** - * Obtain the parameter metadata for given native-sql query. - *

- * for native-sql queries, the param metadata is determined outside any relation to a query plan, because - * query plan creation and/or retrieval for a native-sql query depends on all of the return types having been - * set, which might not be the case up-front when param metadata would be most useful - * - * @param query The query - * @return The parameter metadata - */ - public ParameterMetadata getSQLParameterMetadata(final String query, boolean isOrdinalParameterZeroBased) { - final ParameterMetadataKey key = new ParameterMetadataKey( query, isOrdinalParameterZeroBased ); - return parameterMetadataCache.computeIfAbsent( key, k -> nativeQueryInterpreter.getParameterMetadata( query ) ); - } - - /** - * Get the query plan for the given HQL query, creating it and caching it if not already cached - * - * @param queryString The HQL query string - * @param shallow Whether the execution will be shallow - * @param enabledFilters The filters enabled on the Session - * - * @return The query plan - * - * @throws QueryException Indicates a problem translating the query - * @throws MappingException Indicates a problem translating the query - */ - @SuppressWarnings("unchecked") - public HQLQueryPlan getHQLQueryPlan(String queryString, boolean shallow, Map enabledFilters) - throws QueryException, MappingException { - final HQLQueryPlanKey key = new HQLQueryPlanKey( queryString, shallow, enabledFilters ); - HQLQueryPlan value = (HQLQueryPlan) queryPlanCache.get( key ); - final StatisticsImplementor statistics = factory.getStatistics(); - boolean stats = statistics.isStatisticsEnabled(); - - if ( value == null ) { - final long startTime = ( stats ) ? System.nanoTime() : 0L; - - LOG.tracev( "Unable to locate HQL query plan in cache; generating ({0})", queryString ); - value = new HQLQueryPlan( queryString, shallow, enabledFilters, factory ); - - if ( stats ) { - final long endTime = System.nanoTime(); - final long microseconds = TimeUnit.MICROSECONDS.convert( endTime - startTime, TimeUnit.NANOSECONDS ); - statistics.queryCompiled( queryString, microseconds ); - } - - queryPlanCache.putIfAbsent( key, value ); - } - else { - LOG.tracev( "Located HQL query plan in cache ({0})", queryString ); - - if ( stats ) { - statistics.queryPlanCacheHit( queryString ); - } - } - return value; - } - - /** - * Get the query plan for the given collection HQL filter fragment, creating it and caching it if not already cached - * - * @param filterString The HQL filter fragment - * @param collectionRole The collection being filtered - * @param shallow Whether the execution will be shallow - * @param enabledFilters The filters enabled on the Session - * - * @return The query plan - * - * @throws QueryException Indicates a problem translating the query - * @throws MappingException Indicates a problem translating the query - */ - @SuppressWarnings("unchecked") - public FilterQueryPlan getFilterQueryPlan( - String filterString, - String collectionRole, - boolean shallow, - Map enabledFilters) throws QueryException, MappingException { - final FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters ); - FilterQueryPlan value = (FilterQueryPlan) queryPlanCache.get( key ); - if ( value == null ) { - LOG.tracev( - "Unable to locate collection-filter query plan in cache; generating ({0} : {1} )", - collectionRole, - filterString - ); - value = new FilterQueryPlan( filterString, collectionRole, shallow, enabledFilters,factory ); - queryPlanCache.putIfAbsent( key, value ); - } - else { - LOG.tracev( "Located collection-filter query plan in cache ({0} : {1})", collectionRole, filterString ); - } - return value; - } - - /** - * Get the query plan for a native SQL query, creating it and caching it if not already cached - * - * @param spec The native SQL query specification - * - * @return The query plan - * - * @throws QueryException Indicates a problem translating the query - * @throws MappingException Indicates a problem translating the query - */ - @SuppressWarnings("unchecked") - public NativeSQLQueryPlan getNativeSQLQueryPlan(final NativeSQLQuerySpecification spec) { - NativeSQLQueryPlan value = (NativeSQLQueryPlan) queryPlanCache.get( spec ); - if ( value == null ) { - LOG.tracev( "Unable to locate native-sql query plan in cache; generating ({0})", spec.getQueryString() ); - value = nativeQueryInterpreter.createQueryPlan( spec, factory ); - queryPlanCache.putIfAbsent( spec, value ); - } - else { - LOG.tracev( "Located native-sql query plan in cache ({0})", spec.getQueryString() ); - } - return value; - } - - /** - * Clean up the caches when the SessionFactory is closed. - *

- * Note that depending on the cache strategy implementation chosen, clearing the cache might not reclaim all the - * memory. - *

- * Typically, when using LIRS, clearing the cache only invalidates the entries but the outdated entries are kept in - * memory until they are replaced by others. It is not considered a memory leak as the cache is bounded. - */ - public void cleanup() { - LOG.trace( "Cleaning QueryPlan Cache" ); - queryPlanCache.clear(); - parameterMetadataCache.clear(); - } - - public NativeQueryInterpreter getNativeQueryInterpreter() { - return nativeQueryInterpreter; - } - - private static class ParameterMetadataKey implements Serializable { - private final String query; - private final boolean isOrdinalParameterZeroBased; - private final int hashCode; - - public ParameterMetadataKey(String query, boolean isOrdinalParameterZeroBased) { - this.query = query; - this.isOrdinalParameterZeroBased = isOrdinalParameterZeroBased; - int hash = query.hashCode(); - hash = 29 * hash + ( isOrdinalParameterZeroBased ? 1 : 0 ); - this.hashCode = hash; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - final ParameterMetadataKey that = (ParameterMetadataKey) o; - - return isOrdinalParameterZeroBased == that.isOrdinalParameterZeroBased - && query.equals( that.query ); - - } - - @Override - public int hashCode() { - return hashCode; - } - } - - private static class HQLQueryPlanKey implements Serializable { - private final String query; - private final boolean shallow; - private final Set filterKeys; - private final int hashCode; - - public HQLQueryPlanKey(String query, boolean shallow, Map enabledFilters) { - this.query = query; - this.shallow = shallow; - if ( CollectionHelper.isEmpty( enabledFilters ) ) { - filterKeys = Collections.emptySet(); - } - else { - final Set tmp = new HashSet( - CollectionHelper.determineProperSizing( enabledFilters ), - CollectionHelper.LOAD_FACTOR - ); - for ( Object o : enabledFilters.values() ) { - tmp.add( new DynamicFilterKey( (FilterImpl) o ) ); - } - this.filterKeys = Collections.unmodifiableSet( tmp ); - } - - int hash = query.hashCode(); - hash = 29 * hash + ( shallow ? 1 : 0 ); - hash = 29 * hash + filterKeys.hashCode(); - this.hashCode = hash; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - final HQLQueryPlanKey that = (HQLQueryPlanKey) o; - - return shallow == that.shallow - && filterKeys.equals( that.filterKeys ) - && query.equals( that.query ); - - } - - @Override - public int hashCode() { - return hashCode; - } - } - - private static class DynamicFilterKey implements Serializable { - private final String filterName; - private final Map parameterMetadata; - private final int hashCode; - - private DynamicFilterKey(FilterImpl filter) { - this.filterName = filter.getName(); - final Map parameters = filter.getParameters(); - if ( parameters.isEmpty() ) { - parameterMetadata = Collections.emptyMap(); - } - else { - parameterMetadata = new HashMap( - CollectionHelper.determineProperSizing( parameters ), - CollectionHelper.LOAD_FACTOR - ); - for ( Object o : parameters.entrySet() ) { - final Map.Entry entry = (Map.Entry) o; - final String key = (String) entry.getKey(); - final Integer valueCount; - if ( Collection.class.isInstance( entry.getValue() ) ) { - valueCount = ( (Collection) entry.getValue() ).size(); - } - else { - valueCount = 1; - } - parameterMetadata.put( key, valueCount ); - } - } - - int hash = filterName.hashCode(); - hash = 31 * hash + parameterMetadata.hashCode(); - this.hashCode = hash; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - final DynamicFilterKey that = (DynamicFilterKey) o; - return filterName.equals( that.filterName ) - && parameterMetadata.equals( that.parameterMetadata ); - - } - - @Override - public int hashCode() { - return hashCode; - } - } - - private static class FilterQueryPlanKey implements Serializable { - private final String query; - private final String collectionRole; - private final boolean shallow; - private final Set filterNames; - private final int hashCode; - - @SuppressWarnings({ "unchecked" }) - public FilterQueryPlanKey(String query, String collectionRole, boolean shallow, Map enabledFilters) { - this.query = query; - this.collectionRole = collectionRole; - this.shallow = shallow; - - if ( CollectionHelper.isEmpty( enabledFilters ) ) { - this.filterNames = Collections.emptySet(); - } - else { - final Set tmp = new HashSet( enabledFilters.keySet() ); - this.filterNames = Collections.unmodifiableSet( tmp ); - - } - - int hash = query.hashCode(); - hash = 29 * hash + collectionRole.hashCode(); - hash = 29 * hash + ( shallow ? 1 : 0 ); - hash = 29 * hash + filterNames.hashCode(); - this.hashCode = hash; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - final FilterQueryPlanKey that = (FilterQueryPlanKey) o; - return shallow == that.shallow - && filterNames.equals( that.filterNames ) - && query.equals( that.query ) - && collectionRole.equals( that.collectionRole ); - - } - - @Override - public int hashCode() { - return hashCode; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java index 1cdd0843c2..48fb894359 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java @@ -174,7 +174,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener { final Object result = source.getLoadQueryInfluencers().fromInternalFetchProfile( InternalFetchProfile.REFRESH, - () -> doRefresh( event, source, object, e, persister, id ) + () -> doRefresh( event, source, object, e, persister, id, persistenceContext ) ); UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() ); @@ -187,7 +187,8 @@ public class DefaultRefreshEventListener implements RefreshEventListener { Object object, EntityEntry e, EntityPersister persister, - Serializable id) { + Serializable id, + PersistenceContext persistenceContext) { // Handle the requested lock-mode (if one) in relation to the entry's (if one) current lock-mode diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractMapComponentNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractMapComponentNode.java deleted file mode 100644 index 48ee9f35e2..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractMapComponentNode.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.ast.tree; - -import java.util.Map; - -import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; -import org.hibernate.hql.internal.ast.util.ColumnHelper; -import org.hibernate.persister.collection.QueryableCollection; -import org.hibernate.persister.entity.AbstractEntityPersister; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.type.CollectionType; -import org.hibernate.type.Type; - -import antlr.SemanticException; -import antlr.collections.AST; - -/** - * Basic support for KEY, VALUE and ENTRY based "qualified identification variables". - * - * @author Steve Ebersole - */ -public abstract class AbstractMapComponentNode extends FromReferenceNode implements HqlSqlTokenTypes { - private FromElement mapFromElement; - private String[] columns; - - public FromReferenceNode getMapReference() { - return (FromReferenceNode) getFirstChild(); - } - - public String[] getColumns() { - return columns; - } - - @Override - public void setScalarColumnText(int i) { - ColumnHelper.generateScalarColumns( this, getColumns(), i ); - } - - @Override - public void resolve( - boolean generateJoin, - boolean implicitJoin, - String classAlias, - AST parent, - AST parentPredicate) throws SemanticException { - if ( mapFromElement == null ) { - final FromReferenceNode mapReference = getMapReference(); - mapReference.resolve( true, true ); - - FromElement sourceFromElement = null; - if ( isAliasRef( mapReference ) ) { - final QueryableCollection collectionPersister = mapReference.getFromElement().getQueryableCollection(); - if ( Map.class.isAssignableFrom( collectionPersister.getCollectionType().getReturnedClass() ) ) { - sourceFromElement = mapReference.getFromElement(); - } - } - else { - if ( mapReference.getDataType().isCollectionType() ) { - final CollectionType collectionType = (CollectionType) mapReference.getDataType(); - if ( Map.class.isAssignableFrom( collectionType.getReturnedClass() ) ) { - sourceFromElement = mapReference.getFromElement(); - } - } - } - - if ( sourceFromElement == null ) { - throw nonMap(); - } - - mapFromElement = sourceFromElement; - } - - setFromElement( mapFromElement ); - setDataType( resolveType( mapFromElement.getQueryableCollection() ) ); - this.columns = resolveColumns( mapFromElement.getQueryableCollection() ); - initText( this.columns ); - setFirstChild( null ); - } - - public FromElement getMapFromElement() { - return mapFromElement; - } - - private boolean isAliasRef(FromReferenceNode mapReference) { - return ALIAS_REF == mapReference.getType(); - } - - private void initText(String[] columns) { - String text = String.join( ", ", columns ); - if ( columns.length > 1 && getWalker().isComparativeExpressionClause() ) { - text = "(" + text + ")"; - } - setText( text ); - } - - protected abstract String expressionDescription(); - protected abstract String[] resolveColumns(QueryableCollection collectionPersister); - protected abstract Type resolveType(QueryableCollection collectionPersister); - - protected SemanticException nonMap() { - return new SemanticException( expressionDescription() + " expression did not reference map property" ); - } - - @Override - public void resolveIndex(AST parent) { - throw new UnsupportedOperationException( expressionDescription() + " expression cannot be the source for an index operation" ); - } - - protected MapKeyEntityFromElement findOrAddMapKeyEntityFromElement(QueryableCollection collectionPersister) { - if ( !collectionPersister.getIndexType().isEntityType() ) { - return null; - } - - - for ( FromElement destination : getFromElement().getDestinations() ) { - if ( destination instanceof MapKeyEntityFromElement ) { - return (MapKeyEntityFromElement) destination; - } - } - - return MapKeyEntityFromElement.buildKeyJoin( getFromElement() ); - } - - @Override - public String[] getReferencedTables() { - String[] referencedTables = null; - FromElement fromElement = getFromElement(); - if ( fromElement != null ) { - EntityPersister entityPersister = fromElement.getEntityPersister(); - if ( entityPersister != null && entityPersister instanceof AbstractEntityPersister ) { - AbstractEntityPersister abstractEntityPersister = (AbstractEntityPersister) entityPersister; - referencedTables = abstractEntityPersister.getTableNames(); - } - } - return referencedTables; - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryArithmeticOperatorNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryArithmeticOperatorNode.java deleted file mode 100644 index a9182fec78..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryArithmeticOperatorNode.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.ast.tree; - -import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; -import org.hibernate.hql.internal.ast.util.ColumnHelper; -import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.Type; - -import antlr.SemanticException; - -/** - * Nodes which represent binary arithmetic operators. - * - * @author Gavin King - */ -public class BinaryArithmeticOperatorNode extends AbstractSelectExpression - implements BinaryOperatorNode, DisplayableNode { - - @Override - public void initialize() throws SemanticException { - final Node lhs = getLeftHandOperand(); - if ( lhs == null ) { - throw new SemanticException( "left-hand operand of a binary operator was null" ); - } - - final Node rhs = getRightHandOperand(); - if ( rhs == null ) { - throw new SemanticException( "right-hand operand of a binary operator was null" ); - } - - final Type lhType = ( lhs instanceof SqlNode ) ? ( (SqlNode) lhs ).getDataType() : null; - final Type rhType = ( rhs instanceof SqlNode ) ? ( (SqlNode) rhs ).getDataType() : null; - - if ( ExpectedTypeAwareNode.class.isAssignableFrom( lhs.getClass() ) && rhType != null ) { - final Type expectedType; - // we have something like : "? [op] rhs" - if ( isDateTimeType( rhType ) ) { - // more specifically : "? [op] datetime" - // 1) if the operator is MINUS, the param needs to be of - // some datetime type - // 2) if the operator is PLUS, the param needs to be of - // some numeric type - expectedType = getType() == HqlSqlTokenTypes.PLUS ? StandardBasicTypes.DOUBLE : rhType; - } - else { - expectedType = rhType; - } - ( (ExpectedTypeAwareNode) lhs ).setExpectedType( expectedType ); - } - else if ( ParameterNode.class.isAssignableFrom( rhs.getClass() ) && lhType != null ) { - Type expectedType = null; - // we have something like : "lhs [op] ?" - if ( isDateTimeType( lhType ) ) { - // more specifically : "datetime [op] ?" - // 1) if the operator is MINUS, we really cannot determine - // the expected type as either another datetime or - // numeric would be valid - // 2) if the operator is PLUS, the param needs to be of - // some numeric type - if ( getType() == HqlSqlTokenTypes.PLUS ) { - expectedType = StandardBasicTypes.DOUBLE; - } - } - else { - expectedType = lhType; - } - ( (ExpectedTypeAwareNode) rhs ).setExpectedType( expectedType ); - } - } - - /** - * Figure out the type of the binary expression by looking at - * the types of the operands. Sometimes we don't know both types, - * if, for example, one is a parameter. - */ - @Override - public Type getDataType() { - if ( super.getDataType() == null ) { - super.setDataType( resolveDataType() ); - } - return super.getDataType(); - } - - private Type resolveDataType() { - // TODO : we may also want to check that the types here map to exactly one column/JDBC-type - // can't think of a situation where arithmetic expression between multi-column mappings - // makes any sense. - final Node lhs = getLeftHandOperand(); - final Node rhs = getRightHandOperand(); - - final Type lhType = ( lhs instanceof SqlNode ) ? ( (SqlNode) lhs ).getDataType() : null; - final Type rhType = ( rhs instanceof SqlNode ) ? ( (SqlNode) rhs ).getDataType() : null; - - if ( isDateTimeType( lhType ) || isDateTimeType( rhType ) ) { - return resolveDateTimeArithmeticResultType( lhType, rhType ); - } - else { - if ( lhType == null ) { - if ( rhType == null ) { - // we do not know either type - // BLIND GUESS! - return StandardBasicTypes.DOUBLE; - } - else { - // we know only the rhs-hand type, so use that - return rhType; - } - } - else { - if ( rhType == null ) { - // we know only the lhs-hand type, so use that - return lhType; - } - else { - if ( lhType == StandardBasicTypes.DOUBLE || rhType == StandardBasicTypes.DOUBLE ) { - return StandardBasicTypes.DOUBLE; - } - if ( lhType == StandardBasicTypes.FLOAT || rhType == StandardBasicTypes.FLOAT ) { - return StandardBasicTypes.FLOAT; - } - if ( lhType == StandardBasicTypes.BIG_DECIMAL || rhType == StandardBasicTypes.BIG_DECIMAL ) { - return StandardBasicTypes.BIG_DECIMAL; - } - if ( lhType == StandardBasicTypes.BIG_INTEGER || rhType == StandardBasicTypes.BIG_INTEGER ) { - return StandardBasicTypes.BIG_INTEGER; - } - if ( lhType == StandardBasicTypes.LONG || rhType == StandardBasicTypes.LONG ) { - return StandardBasicTypes.LONG; - } - if ( lhType == StandardBasicTypes.INTEGER || rhType == StandardBasicTypes.INTEGER ) { - return StandardBasicTypes.INTEGER; - } - return lhType; - } - } - } - } - - private boolean isDateTimeType(Type type) { - return type != null - && ( java.util.Date.class.isAssignableFrom( type.getReturnedClass() ) - || java.util.Calendar.class.isAssignableFrom( type.getReturnedClass() ) ); - } - - private Type resolveDateTimeArithmeticResultType(Type lhType, Type rhType) { - // here, we work under the following assumptions: - // ------------ valid cases -------------------------------------- - // 1) datetime + {something other than datetime} : always results - // in a datetime ( db will catch invalid conversions ) - // 2) datetime - datetime : always results in a DOUBLE - // 3) datetime - {something other than datetime} : always results - // in a datetime ( db will catch invalid conversions ) - // ------------ invalid cases ------------------------------------ - // 4) datetime + datetime - // 5) {something other than datetime} - datetime - // 6) datetime * {any type} - // 7) datetime / {any type} - // 8) {any type} / datetime - // doing so allows us to properly handle parameters as either the left - // or right side here in the majority of cases - boolean lhsIsDateTime = isDateTimeType( lhType ); - boolean rhsIsDateTime = isDateTimeType( rhType ); - - // handle the (assumed) valid cases: - // #1 - the only valid datetime addition synatx is one or the other is a datetime (but not both) - if ( getType() == HqlSqlTokenTypes.PLUS ) { - // one or the other needs to be a datetime for us to get into this method in the first place... - return lhsIsDateTime ? lhType : rhType; - } - else if ( getType() == HqlSqlTokenTypes.MINUS ) { - // #3 - note that this is also true of "datetime - :param"... - if ( lhsIsDateTime && !rhsIsDateTime ) { - return lhType; - } - // #2 - if ( lhsIsDateTime && rhsIsDateTime ) { - return StandardBasicTypes.DOUBLE; - } - } - return null; - } - - @Override - public void setScalarColumnText(int i) throws SemanticException { - ColumnHelper.generateSingleScalarColumn( this, i ); - } - - /** - * Retrieves the left-hand operand of the operator. - * - * @return The left-hand operand - */ - @Override - public Node getLeftHandOperand() { - return (Node) getFirstChild(); - } - - /** - * Retrieves the right-hand operand of the operator. - * - * @return The right-hand operand - */ - @Override - public Node getRightHandOperand() { - return (Node) getFirstChild().getNextSibling(); - } - - @Override - public String getDisplayText() { - return "{dataType=" + getDataType() + "}"; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java deleted file mode 100644 index 6470c33d99..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java +++ /dev/null @@ -1,730 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.ast.tree; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.hibernate.QueryException; -import org.hibernate.engine.internal.JoinSequence; -import org.hibernate.hql.internal.CollectionProperties; -import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; -import org.hibernate.hql.internal.antlr.SqlTokenTypes; -import org.hibernate.hql.internal.ast.TypeDiscriminatorMetadata; -import org.hibernate.hql.internal.ast.util.ASTUtil; -import org.hibernate.hql.spi.QueryTranslator; -import org.hibernate.internal.CoreLogging; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.param.DynamicFilterParameterSpecification; -import org.hibernate.param.ParameterSpecification; -import org.hibernate.persister.collection.QueryableCollection; -import org.hibernate.persister.entity.DiscriminatorMetadata; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.persister.entity.Queryable; -import org.hibernate.type.EntityType; -import org.hibernate.type.Type; - -/** - * Represents a single mapped class mentioned in an HQL FROM clause. Each - * class reference will have the following symbols: - *

    - *
  • A class name - This is the name of the Java class that is mapped by Hibernate.
  • - *
  • [optional] an HQL alias for the mapped class.
  • - *
  • A table name - The name of the table that is mapped to the Java class.
  • - *
  • A table alias - The alias for the table that will be used in the resulting SQL.
  • - *
- * - * @author josh - */ -public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, ParameterContainer { - private static final CoreMessageLogger LOG = CoreLogging.messageLogger( FromElement.class ); - - private String className; - private String classAlias; - private String tableAlias; - private String collectionTableAlias; - private FromClause fromClause; - private boolean includeSubclasses = true; - private boolean collectionJoin; - private FromElement origin; - private String[] columns; - private String role; - private boolean fetch; - private boolean isAllPropertyFetch; - private boolean filter; - private int sequence = -1; - private boolean useFromFragment; - private boolean initialized; - private FromElementType elementType; - private boolean useWhereFragment = true; - private List destinations; - private boolean manyToMany; - private String withClauseFragment; - private boolean dereferencedBySuperclassProperty; - private boolean dereferencedBySubclassProperty; - - public FromElement() { - } - - /** - * Constructor form used to initialize {@link ComponentJoin} - * - * @param fromClause The FROM clause to which this element belongs - * @param origin The origin (LHS) of this element - * @param alias The alias applied to this element - */ - protected FromElement( - FromClause fromClause, - FromElement origin, - String alias) { - this.fromClause = fromClause; - this.origin = origin; - this.classAlias = alias; - this.tableAlias = origin.getTableAlias(); - super.initialize( fromClause.getWalker() ); - - } - - protected void initializeComponentJoin(FromElementType elementType) { - fromClause.registerFromElement( this ); - elementType.applyTreatAsDeclarations( getWalker().getTreatAsDeclarationsByPath( classAlias ) ); - this.elementType = elementType; - initialized = true; - } - - public String getCollectionSuffix() { - return elementType.getCollectionSuffix(); - } - - public void setCollectionSuffix(String suffix) { - elementType.setCollectionSuffix(suffix); - } - - public void initializeCollection(FromClause fromClause, String classAlias, String tableAlias) { - doInitialize( fromClause, tableAlias, null, classAlias, null, null ); - initialized = true; - } - - public void initializeEntity( - FromClause fromClause, - String className, - EntityPersister persister, - EntityType type, - String classAlias, - String tableAlias) { - doInitialize( fromClause, tableAlias, className, classAlias, persister, type ); - this.sequence = fromClause.nextFromElementCounter(); - initialized = true; - } - - protected void doInitialize( - FromClause fromClause, - String tableAlias, - String className, - String classAlias, - EntityPersister persister, - EntityType type) { - if ( initialized ) { - throw new IllegalStateException( "Already initialized!!" ); - } - this.fromClause = fromClause; - this.tableAlias = tableAlias; - this.className = className; - this.classAlias = classAlias; - this.elementType = new FromElementType( this, persister, type ); - // Register the FromElement with the FROM clause, now that we have the names and aliases. - fromClause.registerFromElement( this ); - LOG.debugf( "%s : %s (%s) -> %s", fromClause, className, classAlias == null ? "" : classAlias, tableAlias ); - } - - public EntityPersister getEntityPersister() { - return elementType.getEntityPersister(); - } - - @Override - public Type getDataType() { - return elementType.getDataType(); - } - - public Type getSelectType() { - return elementType.getSelectType(); - } - - public Queryable getQueryable() { - return elementType.getQueryable(); - } - - public String getClassName() { - return className; - } - - public String getClassAlias() { - return classAlias; - //return classAlias == null ? className : classAlias; - } - - public String getTableName() { - Queryable queryable = getQueryable(); - return ( queryable != null ) ? queryable.getTableName() : "{none}"; - } - - public String getTableAlias() { - return tableAlias; - } - - /** - * Render the identifier select, but in a 'scalar' context (i.e. generate the column alias). - * - * @param i the sequence of the returned type - * @return the identifier select with the column alias. - */ - String renderScalarIdentifierSelect(int i) { - return elementType.renderScalarIdentifierSelect( i ); - } - - void checkInitialized() { - if ( !initialized ) { - throw new IllegalStateException( "FromElement has not been initialized!" ); - } - } - - /** - * Returns the identifier select SQL fragment. - * - * @param size The total number of returned types. - * @param k The sequence of the current returned type. - * @return the identifier select SQL fragment. - */ - String renderIdentifierSelect(int size, int k) { - return elementType.renderIdentifierSelect( size, k ); - } - - /** - * Returns the property select SQL fragment. - * - * @param size The total number of returned types. - * @param k The sequence of the current returned type. - * @return the property select SQL fragment. - */ - String renderPropertySelect(int size, int k) { - return elementType.renderPropertySelect( size, k, isAllPropertyFetch ); - } - - public String renderMapKeyPropertySelectFragment(int size, int k) { - return elementType.renderMapKeyPropertySelectFragment( size, k ); - } - - public String renderMapEntryPropertySelectFragment(int size, int k) { - return elementType.renderMapEntryPropertySelectFragment( size, k ); - } - - String renderCollectionSelectFragment(int size, int k) { - return elementType.renderCollectionSelectFragment( size, k ); - } - - String renderValueCollectionSelectFragment(int size, int k) { - return elementType.renderValueCollectionSelectFragment( size, k ); - } - - public FromClause getFromClause() { - return fromClause; - } - - /** - * Returns true if this FromElement was implied by a path, or false if this FROM element is explicitly declared in - * the FROM clause. - * - * @return true if this FromElement was implied by a path, or false if this FROM element is explicitly declared - */ - public boolean isImplied() { - return false; // This is an explicit FROM element. - } - - /** - * Returns additional display text for the AST node. - * - * @return String - The additional display text. - */ - public String getDisplayText() { - StringBuilder buf = new StringBuilder(); - buf.append( "FromElement{" ); - appendDisplayText( buf ); - buf.append( "}" ); - return buf.toString(); - } - - protected void appendDisplayText(StringBuilder buf) { - buf.append( isImplied() ? ( - isImpliedInFromClause() ? "implied in FROM clause" : "implied" ) - : "explicit" ); - buf.append( "," ).append( isCollectionJoin() ? "collection join" : "not a collection join" ); - buf.append( "," ).append( fetch ? "fetch join" : "not a fetch join" ); - buf.append( "," ).append( isAllPropertyFetch ? "fetch all properties" : "fetch non-lazy properties" ); - buf.append( ",classAlias=" ).append( getClassAlias() ); - buf.append( ",role=" ).append( role ); - buf.append( ",tableName=" ).append( getTableName() ); - buf.append( ",tableAlias=" ).append( getTableAlias() ); - FromElement origin = getRealOrigin(); - buf.append( ",origin=" ).append( origin == null ? "null" : origin.getText() ); - buf.append( ",columns={" ); - if ( columns != null ) { - for ( int i = 0; i < columns.length; i++ ) { - buf.append( columns[i] ); - if ( i < columns.length - 1 ) { - buf.append( " " ); - } - } - } - buf.append( ",className=" ).append( className ); - buf.append( "}" ); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return super.equals( obj ); - } - - - public void setJoinSequence(JoinSequence joinSequence) { - elementType.setJoinSequence( joinSequence ); - } - - public JoinSequence getJoinSequence() { - return elementType.getJoinSequence(); - } - - public void setIncludeSubclasses(boolean includeSubclasses) { - if ( !includeSubclasses && isDereferencedBySuperclassOrSubclassProperty() && LOG.isTraceEnabled() ) { - LOG.trace( "Attempt to disable subclass-inclusions : ", new Exception( "Stack-trace source" ) ); - } - this.includeSubclasses = includeSubclasses; - } - - public boolean isIncludeSubclasses() { - return includeSubclasses; - } - - public boolean isDereferencedBySuperclassOrSubclassProperty() { - return dereferencedBySubclassProperty || dereferencedBySuperclassProperty; - } - - public String getIdentityColumn() { - final String[] cols = getIdentityColumns(); - if ( cols.length == 1 ) { - return cols[0]; - } - else { - return "(" + String.join( ", ", cols ) + ")"; - } - } - - public String[] getIdentityColumns() { - checkInitialized(); - final String table = getTableAlias(); - if ( table == null ) { - throw new IllegalStateException( "No table alias for node " + this ); - } - - final String[] propertyNames = getIdentifierPropertyNames(); - List columns = new ArrayList<>(); - final boolean inSelect = getWalker().getStatementType() == HqlSqlTokenTypes.SELECT; - for ( String propertyName : propertyNames ) { - String[] propertyNameColumns = toColumns( table, propertyName, inSelect ); - for ( String propertyNameColumn : propertyNameColumns ) { - columns.add( propertyNameColumn ); - } - } - return columns.toArray( new String[columns.size()] ); - } - - public void setCollectionJoin(boolean collectionJoin) { - this.collectionJoin = collectionJoin; - } - - public boolean isCollectionJoin() { - return collectionJoin; - } - - public void setRole(String role) { - this.role = role; - applyTreatAsDeclarations( getWalker().getTreatAsDeclarationsByPath( role ) ); - } - - public void applyTreatAsDeclarations(Set treatAsDeclarationsByPath) { - elementType.applyTreatAsDeclarations( treatAsDeclarationsByPath ); - } - - public String getRole() { - return role; - } - - public void setQueryableCollection(QueryableCollection queryableCollection) { - elementType.setQueryableCollection( queryableCollection ); - } - - public QueryableCollection getQueryableCollection() { - return elementType.getQueryableCollection(); - } - - public void setColumns(String[] columns) { - this.columns = columns; - } - - public void setOrigin(FromElement origin, boolean manyToMany) { - this.origin = origin; - this.manyToMany = manyToMany; - origin.addDestination( this ); - if ( origin.getFromClause() == this.getFromClause() ) { - // TODO: Figure out a better way to get the FROM elements in a proper tree structure. - // If this is not the destination of a many-to-many, add it as a child of the origin. - if ( manyToMany ) { - ASTUtil.appendSibling( origin, this ); - } - else { - if ( !getWalker().isInFrom() && !getWalker().isInSelect() && !getWalker().isInEntityGraph() ) { - getFromClause().addChild( this ); - } - else { - origin.addChild( this ); - } - } - } - else if ( !getWalker().isInFrom() ) { - // HHH-276 : implied joins in a subselect where clause - The destination needs to be added - // to the destination's from clause. - getFromClause().addChild( this ); // Not sure if this is will fix everything, but it works. - } - else { - // Otherwise, the destination node was implied by the FROM clause and the FROM clause processor - // will automatically add it in the right place. - } - } - - public boolean isManyToMany() { - return manyToMany; - } - - private void addDestination(FromElement fromElement) { - if ( destinations == null ) { - destinations = new LinkedList(); - } - destinations.add( fromElement ); - } - - public List getDestinations() { - if ( destinations == null ) { - return Collections.emptyList(); - } - else { - return destinations; - } - } - - public FromElement getOrigin() { - return origin; - } - - public FromElement getRealOrigin() { - if ( origin == null ) { - return null; - } - if ( StringHelper.isEmpty( origin.getText() ) ) { - return origin.getRealOrigin(); - } - return origin; - } - - public FromElement getFetchOrigin() { - if ( origin == null ) { - return null; - } - if ( !origin.isFetch() ) { - return origin; - } - if ( StringHelper.isEmpty( origin.getText() ) ) { - return origin.getFetchOrigin(); - } - return origin; - } - - public static final String DISCRIMINATOR_PROPERTY_NAME = "class"; - private TypeDiscriminatorMetadata typeDiscriminatorMetadata; - - private static class TypeDiscriminatorMetadataImpl implements TypeDiscriminatorMetadata { - private final DiscriminatorMetadata persisterDiscriminatorMetadata; - private final String alias; - - private TypeDiscriminatorMetadataImpl( - DiscriminatorMetadata persisterDiscriminatorMetadata, - String alias) { - this.persisterDiscriminatorMetadata = persisterDiscriminatorMetadata; - this.alias = alias; - } - - @Override - public String getSqlFragment() { - return persisterDiscriminatorMetadata.getSqlFragment( alias ); - } - - @Override - public Type getResolutionType() { - return persisterDiscriminatorMetadata.getResolutionType(); - } - } - - public TypeDiscriminatorMetadata getTypeDiscriminatorMetadata() { - if ( typeDiscriminatorMetadata == null ) { - typeDiscriminatorMetadata = buildTypeDiscriminatorMetadata(); - } - return typeDiscriminatorMetadata; - } - - private TypeDiscriminatorMetadata buildTypeDiscriminatorMetadata() { - final String aliasToUse = getTableAlias(); - Queryable queryable = getQueryable(); - if ( queryable == null ) { - QueryableCollection collection = getQueryableCollection(); - if ( ! collection.getElementType().isEntityType() ) { - throw new QueryException( "type discrimination cannot be applied to value collection [" + collection.getRole() + "]" ); - } - queryable = (Queryable) collection.getElementPersister(); - } - - handlePropertyBeingDereferenced( getDataType(), DISCRIMINATOR_PROPERTY_NAME ); - - return new TypeDiscriminatorMetadataImpl( queryable.getTypeDiscriminatorMetadata(), aliasToUse ); - } - - public Type getPropertyType(String propertyName, String propertyPath) { - return elementType.getPropertyType( propertyName, propertyPath ); - } - - public String getPropertyTableName(String propertyName) { - return elementType.getPropertyTableName( propertyName ); - } - - public String[] toColumns(String tableAlias, String path, boolean inSelect) { - return elementType.toColumns( tableAlias, path, inSelect ); - } - - public String[] toColumns(String tableAlias, String path, boolean inSelect, boolean forceAlias) { - return elementType.toColumns( tableAlias, path, inSelect, forceAlias ); - } - - public PropertyMapping getPropertyMapping(String propertyName) { - return elementType.getPropertyMapping( propertyName ); - } - - public CollectionPropertyReference getCollectionPropertyReference(String propertyName) { - return elementType.getCollectionPropertyReference( propertyName ); - } - - public String[] getIdentifierPropertyNames() { - return elementType.getIdentifierPropertyNames(); - } - - public void setFetch(boolean fetch) { - this.fetch = fetch; - // Fetch can't be used with scroll() or iterate(). - if ( fetch && getWalker().isShallowQuery() ) { - throw new QueryException( QueryTranslator.ERROR_CANNOT_FETCH_WITH_ITERATE ); - } - } - - public boolean isFetch() { - return fetch; - } - - public int getSequence() { - return sequence; - } - - public void setFilter(boolean b) { - filter = b; - } - - public boolean isFilter() { - return filter; - } - - public boolean useFromFragment() { - checkInitialized(); - // If it's not implied or it is implied and it's a many to many join where the target wasn't found. - return !isImplied() || this.useFromFragment; - } - - public void setUseFromFragment(boolean useFromFragment) { - this.useFromFragment = useFromFragment; - } - - public boolean useWhereFragment() { - return useWhereFragment; - } - - public void setUseWhereFragment(boolean b) { - useWhereFragment = b; - } - - - public void setCollectionTableAlias(String collectionTableAlias) { - this.collectionTableAlias = collectionTableAlias; - } - - public String getCollectionTableAlias() { - return collectionTableAlias; - } - - public boolean isCollectionOfValuesOrComponents() { - return elementType.isCollectionOfValuesOrComponents(); - } - - public boolean isEntity() { - return elementType.isEntity(); - } - - public void setImpliedInFromClause(boolean flag) { - throw new UnsupportedOperationException( "Explicit FROM elements can't be implied in the FROM clause!" ); - } - - public boolean isImpliedInFromClause() { - return false; // Since this is an explicit FROM element, it can't be implied in the FROM clause. - } - - public void setInProjectionList(boolean inProjectionList) { - // Do nothing, eplicit from elements are *always* in the projection list. - } - - public boolean inProjectionList() { - return !isImplied() && isFromOrJoinFragment(); - } - - public boolean isFromOrJoinFragment() { - return getType() == SqlTokenTypes.FROM_FRAGMENT - || getType() == SqlTokenTypes.JOIN_FRAGMENT - || getType() == SqlTokenTypes.ENTITY_JOIN; - } - - public boolean isAllPropertyFetch() { - return isAllPropertyFetch; - } - - public void setAllPropertyFetch(boolean fetch) { - isAllPropertyFetch = fetch; - } - - public String getWithClauseFragment() { - return withClauseFragment; - } - - public void setWithClauseFragment(String withClauseFragment) { - this.withClauseFragment = withClauseFragment; - } - - public void handlePropertyBeingDereferenced(Type propertySource, String propertyName) { - if ( getQueryableCollection() != null && CollectionProperties.isCollectionProperty( propertyName ) ) { - // propertyName refers to something like collection.size... - return; - } - if ( propertySource.isComponentType() ) { - // property name is a sub-path of a component... - return; - } - - Queryable persister = getQueryable(); - if ( persister != null ) { - try { - Queryable.Declarer propertyDeclarer = persister.getSubclassPropertyDeclarer( propertyName ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Handling property dereference [{0} ({1}) -> {2} ({3})]", - persister.getEntityName(), getClassAlias(), propertyName, propertyDeclarer ); - } - if ( propertyDeclarer == Queryable.Declarer.SUBCLASS ) { - dereferencedBySubclassProperty = true; - includeSubclasses = true; - } - else if ( propertyDeclarer == Queryable.Declarer.SUPERCLASS ) { - dereferencedBySuperclassProperty = true; - } - } - catch( QueryException ignore ) { - // ignore it; the incoming property could not be found so we - // cannot be sure what to do here. At the very least, the - // safest is to simply not apply any dereference toggling... - - } - } - } - - public boolean isDereferencedBySuperclassProperty() { - return dereferencedBySuperclassProperty; - } - - public boolean isDereferencedBySubclassProperty() { - return dereferencedBySubclassProperty; - } - - - // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private List embeddedParameters = new ArrayList<>( ); - - @Override - public void addEmbeddedParameter(ParameterSpecification specification) { - embeddedParameters.add( specification ); - } - - @Override - public boolean hasEmbeddedParameters() { - return !embeddedParameters.isEmpty(); - } - - @Override - public ParameterSpecification[] getEmbeddedParameters() { - final List parameterSpecification = getParameterSpecification(); - return parameterSpecification.toArray( new ParameterSpecification[ parameterSpecification.size() ] ); - } - - private List getParameterSpecification() { - List parameterSpecifications = - embeddedParameters.stream() - .filter( o -> o instanceof DynamicFilterParameterSpecification ) - .collect( Collectors.toList() ); - - parameterSpecifications.addAll( - embeddedParameters.stream() - .filter( o -> ! (o instanceof DynamicFilterParameterSpecification ) ) - .collect( Collectors.toList() ) ); - return parameterSpecifications; - } - - public ParameterSpecification getIndexCollectionSelectorParamSpec() { - return elementType.getIndexCollectionSelectorParamSpec(); - } - - public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) { - if ( indexCollectionSelectorParamSpec == null ) { - if ( elementType.getIndexCollectionSelectorParamSpec() != null ) { - embeddedParameters.remove( elementType.getIndexCollectionSelectorParamSpec() ); - elementType.setIndexCollectionSelectorParamSpec( null ); - } - } - else { - elementType.setIndexCollectionSelectorParamSpec( indexCollectionSelectorParamSpec ); - addEmbeddedParameter( indexCollectionSelectorParamSpec ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MapEntryNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MapEntryNode.java deleted file mode 100644 index 6b8e21284c..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MapEntryNode.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.ast.tree; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import antlr.collections.AST; -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.hql.internal.NameGenerator; -import org.hibernate.persister.collection.QueryableCollection; -import org.hibernate.persister.entity.Queryable; -import org.hibernate.sql.AliasGenerator; -import org.hibernate.sql.SelectExpression; -import org.hibernate.sql.SelectFragment; -import org.hibernate.transform.BasicTransformerAdapter; -import org.hibernate.transform.ResultTransformer; -import org.hibernate.type.EntityType; -import org.hibernate.type.Type; - -import antlr.SemanticException; - -/** - * Tree node representing reference to the entry ({@link Map.Entry}) of a Map association. - * - * @author Steve Ebersole - */ -public class MapEntryNode extends AbstractMapComponentNode implements AggregatedSelectExpression { - private static class LocalAliasGenerator implements AliasGenerator { - private final int base; - private int counter; - - private LocalAliasGenerator(int base) { - this.base = base; - } - - @Override - public String generateAlias(String sqlExpression) { - return NameGenerator.scalarName( base, counter++ ); - } - } - - private int scalarColumnIndex = -1; - - @Override - protected String expressionDescription() { - return "entry(*)"; - } - - @Override - public Class getAggregationResultType() { - return Map.Entry.class; - } - - - @Override - public void resolve( - boolean generateJoin, - boolean implicitJoin, - String classAlias, - AST parent, - AST parentPredicate) throws SemanticException { - if (parent != null) { - throw new SemanticException( expressionDescription() + " expression cannot be further de-referenced" ); - } - super.resolve(generateJoin, implicitJoin, classAlias, parent, parentPredicate); - } - - @Override - @SuppressWarnings("unchecked") - protected Type resolveType(QueryableCollection collectionPersister) { - final Type keyType = collectionPersister.getIndexType(); - final Type valueType = collectionPersister.getElementType(); - types.add( keyType ); - types.add( valueType ); - mapEntryBuilder = new MapEntryBuilder(); - - // an entry (as an aggregated select expression) does not have a type... - return null; - } - - @Override - protected String[] resolveColumns(QueryableCollection collectionPersister) { - List selections = new ArrayList(); - determineKeySelectExpressions( collectionPersister, selections ); - determineValueSelectExpressions( collectionPersister, selections ); - - final int columnNumber = selections.size(); - StringBuilder text = new StringBuilder( columnNumber * 12 ); //Some guess - String[] columns = new String[columnNumber]; - for ( int i = 0; i < columnNumber; i++ ) { - SelectExpression selectExpression = (SelectExpression) selections.get( i ); - if ( i != 0 ) { - text.append( ", " ); - } - text.append( selectExpression.getExpression() ); - text.append( " as " ); - text.append( selectExpression.getAlias() ); - columns[i] = selectExpression.getExpression(); - } - setText( text.toString() ); - setResolved(); - return columns; - } - - private void determineKeySelectExpressions(QueryableCollection collectionPersister, List selections) { - AliasGenerator aliasGenerator = new LocalAliasGenerator( 0 ); - appendSelectExpressions( collectionPersister.getIndexColumnNames(), selections, aliasGenerator ); - Type keyType = collectionPersister.getIndexType(); - if ( keyType.isEntityType() ) { - MapKeyEntityFromElement mapKeyEntityFromElement = findOrAddMapKeyEntityFromElement( collectionPersister ); - Queryable keyEntityPersister = mapKeyEntityFromElement.getQueryable(); - SelectFragment fragment = keyEntityPersister.propertySelectFragmentFragment( - mapKeyEntityFromElement.getTableAlias(), - null, - false - ); - appendSelectExpressions( fragment, selections, aliasGenerator ); - } - } - - @SuppressWarnings({"unchecked", "ForLoopReplaceableByForEach"}) - private void appendSelectExpressions(String[] columnNames, List selections, AliasGenerator aliasGenerator) { - for ( int i = 0; i < columnNames.length; i++ ) { - selections.add( - new BasicSelectExpression( - collectionTableAlias() + '.' + columnNames[i], - aliasGenerator.generateAlias( columnNames[i] ) - ) - ); - } - } - - @SuppressWarnings({"unchecked", "WhileLoopReplaceableByForEach"}) - private void appendSelectExpressions(SelectFragment fragment, List selections, AliasGenerator aliasGenerator) { - Iterator itr = fragment.getColumns().iterator(); - while ( itr.hasNext() ) { - final String column = (String) itr.next(); - selections.add( - new BasicSelectExpression( column, aliasGenerator.generateAlias( column ) ) - ); - } - } - - private void determineValueSelectExpressions(QueryableCollection collectionPersister, List selections) { - AliasGenerator aliasGenerator = new LocalAliasGenerator( 1 ); - appendSelectExpressions( collectionPersister.getElementColumnNames(), selections, aliasGenerator ); - Type valueType = collectionPersister.getElementType(); - if ( valueType.isAssociationType() ) { - EntityType valueEntityType = (EntityType) valueType; - Queryable valueEntityPersister = (Queryable) sfi().getEntityPersister( - valueEntityType.getAssociatedEntityName( sfi() ) - ); - SelectFragment fragment = valueEntityPersister.propertySelectFragmentFragment( - elementTableAlias(), - null, - false - ); - appendSelectExpressions( fragment, selections, aliasGenerator ); - } - } - - private String collectionTableAlias() { - return getFromElement().getCollectionTableAlias() != null - ? getFromElement().getCollectionTableAlias() - : getFromElement().getTableAlias(); - } - - private String elementTableAlias() { - return getFromElement().getTableAlias(); - } - - private static class BasicSelectExpression implements SelectExpression { - private final String expression; - private final String alias; - - private BasicSelectExpression(String expression, String alias) { - this.expression = expression; - this.alias = alias; - } - - @Override - public String getExpression() { - return expression; - } - - @Override - public String getAlias() { - return alias; - } - } - - public SessionFactoryImplementor sfi() { - return getSessionFactoryHelper().getFactory(); - } - - @Override - public void setText(String s) { - if ( isResolved() ) { - return; - } - super.setText( s ); - } - - @Override - public void setScalarColumn(int i) { - this.scalarColumnIndex = i; - } - - @Override - public int getScalarColumnIndex() { - return scalarColumnIndex; - } - - @Override - public void setScalarColumnText(int i) { - } - - @Override - public boolean isScalar() { - // Constructors are always considered scalar results. - return true; - } - - private List types = new ArrayList( 4 ); // size=4 to prevent resizing - - @Override - public List getAggregatedSelectionTypeList() { - return types; - } - - private static final String[] ALIASES = {null, null}; - - @Override - public String[] getAggregatedAliases() { - return ALIASES; - } - - private MapEntryBuilder mapEntryBuilder; - - @Override - public ResultTransformer getResultTransformer() { - return mapEntryBuilder; - } - - private static class MapEntryBuilder extends BasicTransformerAdapter { - @Override - public Object transformTuple(Object[] tuple, String[] aliases) { - if ( tuple.length != 2 ) { - throw new HibernateException( "Expecting exactly 2 tuples to transform into Map.Entry" ); - } - return new EntryAdapter( tuple[0], tuple[1] ); - } - } - - private static class EntryAdapter implements Map.Entry { - private final Object key; - private Object value; - - private EntryAdapter(Object key, Object value) { - this.key = key; - this.value = value; - } - - @Override - public Object getValue() { - return value; - } - - @Override - public Object getKey() { - return key; - } - - @Override - public Object setValue(Object value) { - Object old = this.value; - this.value = value; - return old; - } - - @Override - public boolean equals(Object o) { - // IMPL NOTE : nulls are considered equal for keys and values according to Map.Entry contract - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - EntryAdapter that = (EntryAdapter) o; - - // make sure we have the same types... - return ( key == null ? that.key == null : key.equals( that.key ) ) - && ( value == null ? that.value == null : value.equals( that.value ) ); - - } - - @Override - public int hashCode() { - int keyHash = key == null ? 0 : key.hashCode(); - int valueHash = value == null ? 0 : value.hashCode(); - return keyHash ^ valueHash; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTReferencedTablesPrinter.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTReferencedTablesPrinter.java deleted file mode 100644 index 1999881f1d..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTReferencedTablesPrinter.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.ast.util; - -import java.util.Arrays; -import java.util.LinkedHashMap; - -import org.hibernate.hql.internal.ast.tree.DotNode; -import org.hibernate.hql.internal.ast.tree.FromElement; -import org.hibernate.hql.internal.ast.tree.FromReferenceNode; -import org.hibernate.hql.internal.ast.tree.IdentNode; -import org.hibernate.hql.internal.ast.tree.SelectClause; -import org.hibernate.persister.entity.AbstractEntityPersister; -import org.hibernate.persister.entity.EntityPersister; - -import antlr.collections.AST; - -public class ASTReferencedTablesPrinter extends ASTPrinter { - - public ASTReferencedTablesPrinter(Class tokenTypeConstants) { - super( tokenTypeConstants ); - } - - @Override - public String nodeToString(AST ast) { - if ( ast == null ) { - return "{node:null}"; - } - return ast.getClass().getSimpleName(); - } - - @Override - public LinkedHashMap createNodeProperties(AST node) { - LinkedHashMap props = new LinkedHashMap<>(); - if ( node instanceof FromReferenceNode ) { - FromReferenceNode frn = (FromReferenceNode) node; - FromElement fromElement = frn.getFromElement(); - EntityPersister entityPersister = fromElement != null ? fromElement.getEntityPersister() : null; - String entityPersisterStr = entityPersister != null ? entityPersister.toString() : null; - props.put( "persister", entityPersisterStr ); - String referencedTablesStr = Arrays.toString( frn.getReferencedTables() ); - props.put( "referencedTables", referencedTablesStr ); - } - if ( node instanceof DotNode ) { - DotNode dn = (DotNode) node; - props.put( "path", dn.getPath() ); - props.put( "originalPropertyName", dn.getOriginalPropertyName() ); - } - if ( node instanceof IdentNode ) { - IdentNode in = (IdentNode) node; - props.put( "originalText", in.getOriginalText() ); - } - if ( node instanceof SelectClause ) { - SelectClause sc = (SelectClause) node; - for ( Object element : sc.getFromElementsForLoad() ) { - FromElement fromElement = (FromElement) element; - EntityPersister entityPersister = fromElement.getEntityPersister(); - if ( entityPersister != null && entityPersister instanceof AbstractEntityPersister ) { - AbstractEntityPersister aep = (AbstractEntityPersister) entityPersister; - String entityClass = aep.getMappedClass().getSimpleName(); - String tables = Arrays.toString( aep.getTableNames() ); - props.put( String.format( "referencedTables(entity %s)", entityClass ), tables ); - } - } - } - return props; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/SyntheticAndFactory.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/SyntheticAndFactory.java deleted file mode 100644 index 19d3d9f26f..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/SyntheticAndFactory.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.ast.util; - -import java.util.Map; - -import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; -import org.hibernate.hql.internal.ast.HqlSqlWalker; -import org.hibernate.hql.internal.ast.tree.FromElement; -import org.hibernate.hql.internal.ast.tree.Node; -import org.hibernate.hql.internal.ast.tree.QueryNode; -import org.hibernate.hql.internal.ast.tree.RestrictableStatement; -import org.hibernate.hql.internal.ast.tree.SqlFragment; -import org.hibernate.internal.CoreLogging; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.param.CollectionFilterKeyParameterSpecification; -import org.hibernate.persister.entity.Queryable; -import org.hibernate.sql.JoinFragment; -import org.hibernate.type.Type; - -import antlr.collections.AST; - -/** - * Creates synthetic and nodes based on the where fragment part of a JoinSequence. - * - * @author josh - */ -public class SyntheticAndFactory implements HqlSqlTokenTypes { - private static final CoreMessageLogger LOG = CoreLogging.messageLogger( SyntheticAndFactory.class ); - - private HqlSqlWalker hqlSqlWalker; - private AST thetaJoins; - private AST filters; - - public SyntheticAndFactory(HqlSqlWalker hqlSqlWalker) { - this.hqlSqlWalker = hqlSqlWalker; - } - - private Node create(int tokenType, String text) { - return (Node) hqlSqlWalker.getASTFactory().create( tokenType, text ); - } - - public void addWhereFragment( - JoinFragment joinFragment, - String whereFragment, - QueryNode query, - FromElement fromElement, - HqlSqlWalker hqlSqlWalker) { - if ( whereFragment == null ) { - return; - } - - if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) { - return; - } - - whereFragment = whereFragment.trim(); - if ( whereFragment.isEmpty() ) { - return; - } - - // Forcefully remove leading ands from where fragments; the grammar will - // handle adding them - if ( whereFragment.startsWith( "and" ) ) { - whereFragment = whereFragment.substring( 4 ); - } - - LOG.debugf( "Using unprocessed WHERE-fragment [%s]", whereFragment ); - - SqlFragment fragment = (SqlFragment) create( SQL_TOKEN, whereFragment ); - fragment.setJoinFragment( joinFragment ); - fragment.setFromElement( fromElement ); - - if ( fromElement.getIndexCollectionSelectorParamSpec() != null ) { - fragment.addEmbeddedParameter( fromElement.getIndexCollectionSelectorParamSpec() ); - fromElement.setIndexCollectionSelectorParamSpec( null ); - } - - if ( hqlSqlWalker.isFilter() ) { - if ( whereFragment.indexOf( '?' ) >= 0 ) { - Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper() - .requireQueryableCollection( hqlSqlWalker.getCollectionFilterRole() ) - .getKeyType(); - CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification( - hqlSqlWalker.getCollectionFilterRole(), - collectionFilterKeyType - ); - fragment.addEmbeddedParameter( paramSpec ); - } - } - - JoinProcessor.processDynamicFilterParameters( - whereFragment, - fragment, - hqlSqlWalker - ); - - if ( LOG.isDebugEnabled() ) { - LOG.debugf( "Using processed WHERE-fragment [%s]", fragment.getText() ); - } - - // Filter conditions need to be inserted before the HQL where condition and the - // theta join node. This is because org.hibernate.loader.Loader binds the filter parameters first, - // then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters(). - if ( fragment.getFromElement().isFilter() || fragment.hasFilterCondition() ) { - if ( filters == null ) { - // Find or create the WHERE clause - AST where = query.getWhereClause(); - // Create a new FILTERS node as a parent of all filters - filters = create( FILTERS, "{filter conditions}" ); - // Put the FILTERS node before the HQL condition and theta joins - ASTUtil.insertChild( where, filters ); - } - - // add the current fragment to the FILTERS node - filters.addChild( fragment ); - } - else { - if ( thetaJoins == null ) { - // Find or create the WHERE clause - AST where = query.getWhereClause(); - // Create a new THETA_JOINS node as a parent of all filters - thetaJoins = create( THETA_JOINS, "{theta joins}" ); - // Put the THETA_JOINS node before the HQL condition, after the filters. - if ( filters == null ) { - ASTUtil.insertChild( where, thetaJoins ); - } - else { - ASTUtil.insertSibling( thetaJoins, filters ); - } - } - - // add the current fragment to the THETA_JOINS node - thetaJoins.addChild( fragment ); - } - - } - - public void addDiscriminatorWhereFragment( - RestrictableStatement statement, - Queryable persister, - Map enabledFilters, - String alias) { - String whereFragment = persister.filterFragment( alias, enabledFilters ).trim(); - if ( "".equals( whereFragment ) ) { - return; - } - if ( whereFragment.startsWith( "and" ) ) { - whereFragment = whereFragment.substring( 4 ); - } - - // Need to parse off the column qualifiers; this is assuming (which is true as of now) - // that this is only used from update and delete HQL statement parsing - whereFragment = StringHelper.replace( - whereFragment, - persister.generateFilterConditionAlias( alias ) + '.', - "" - ); - - // Note: this simply constructs a "raw" SQL_TOKEN representing the - // where fragment and injects this into the tree. This "works"; - // however it is probably not the best long-term solution. - // - // At some point we probably want to apply an additional grammar to - // properly tokenize this where fragment into constituent parts - // focused on the operators embedded within the fragment. - SqlFragment discrimNode = (SqlFragment) create( SQL_TOKEN, whereFragment ); - - JoinProcessor.processDynamicFilterParameters( - whereFragment, - discrimNode, - hqlSqlWalker - ); - - if ( statement.getWhereClause().getNumberOfChildren() == 0 ) { - statement.getWhereClause().setFirstChild( discrimNode ); - } - else { - AST and = create( AND, "{and}" ); - AST currentFirstChild = statement.getWhereClause().getFirstChild(); - and.setFirstChild( discrimNode ); - and.addChild( currentFirstChild ); - statement.getWhereClause().setFirstChild( and ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java deleted file mode 100644 index a29a096d53..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java +++ /dev/null @@ -1,1376 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.internal.classic; - -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.MappingException; -import org.hibernate.QueryException; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.internal.JoinSequence; -import org.hibernate.engine.spi.QueryParameters; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.event.spi.EventSource; -import org.hibernate.hql.internal.HolderInstantiator; -import org.hibernate.hql.internal.NameGenerator; -import org.hibernate.hql.internal.ast.tree.FromElement; -import org.hibernate.hql.spi.FilterTranslator; -import org.hibernate.hql.spi.NamedParameterInformation; -import org.hibernate.hql.spi.ParameterTranslations; -import org.hibernate.hql.spi.PositionalParameterInformation; -import org.hibernate.internal.CoreLogging; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.IteratorImpl; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.loader.BasicLoader; -import org.hibernate.loader.internal.AliasConstantsHelper; -import org.hibernate.loader.spi.AfterLoadAction; -import org.hibernate.param.CollectionFilterKeyParameterSpecification; -import org.hibernate.param.ParameterBinder; -import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.persister.collection.QueryableCollection; -import org.hibernate.persister.entity.Loadable; -import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.persister.entity.Queryable; -import org.hibernate.query.spi.ScrollableResultsImplementor; -import org.hibernate.sql.JoinFragment; -import org.hibernate.sql.JoinType; -import org.hibernate.sql.QuerySelect; -import org.hibernate.stat.spi.StatisticsImplementor; -import org.hibernate.transform.ResultTransformer; -import org.hibernate.type.AssociationType; -import org.hibernate.type.EntityType; -import org.hibernate.type.Type; - -/** - * An instance of QueryTranslator translates a Hibernate - * query string to SQL. - */ -public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator { - private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryTranslatorImpl.class ); - - private static final String[] NO_RETURN_ALIASES = new String[] {}; - - private final String queryIdentifier; - private final String queryString; - - private final Map typeMap = new LinkedHashMap(); - private final Map collections = new LinkedHashMap(); - private List returnedTypes = new ArrayList(); - private final List fromTypes = new ArrayList(); - private final List scalarTypes = new ArrayList(); - private final Map aliasNames = new HashMap(); - private final Map oneToOneOwnerNames = new HashMap(); - private final Map uniqueKeyOwnerReferences = new HashMap(); - private final Map decoratedPropertyMappings = new HashMap(); - - private final Map namedParameters = new HashMap<>(); - private final Map ordinalParameters = new HashMap<>(); - private final List paramValueBinders = new ArrayList<>(); - - private final List scalarSelectTokens = new ArrayList(); - private final List whereTokens = new ArrayList(); - private final List havingTokens = new ArrayList(); - private final Map joins = new LinkedHashMap(); - private final List orderByTokens = new ArrayList(); - private final List groupByTokens = new ArrayList(); - private final Set querySpaces = new HashSet(); - private final Set entitiesToFetch = new HashSet(); - - private final Map pathAliases = new HashMap(); - private final Map pathJoins = new HashMap(); - - private Queryable[] persisters; - private int[] owners; - private EntityType[] ownerAssociationTypes; - private String[] names; - private boolean[] includeInSelect; - private int selectLength; - private Type[] returnTypes; - private Type[] actualReturnTypes; - private String[][] scalarColumnNames; - private Map tokenReplacements; - private int nameCount; - private int parameterCount; - private boolean distinct; - private boolean compiled; - private String sqlString; - private Class holderClass; - private Constructor holderConstructor; - private boolean hasScalars; - private boolean shallowQuery; - private QueryTranslatorImpl superQuery; - - private QueryableCollection collectionPersister; - private int collectionOwnerColumn = -1; - private String collectionOwnerName; - private String fetchName; - - private String[] suffixes; - - private Map enabledFilters; - - /** - * Construct a query translator - * - * @param queryIdentifier A unique identifier for the query of which this - * translation is part; typically this is the original, user-supplied query string. - * @param queryString The "preprocessed" query string; at the very least - * already processed by {@link org.hibernate.hql.internal.QuerySplitter}. - * @param enabledFilters Any enabled filters. - * @param factory The session factory. - */ - public QueryTranslatorImpl( - String queryIdentifier, - String queryString, - Map enabledFilters, - SessionFactoryImplementor factory) { - super( factory ); - this.queryIdentifier = queryIdentifier; - this.queryString = queryString; - this.enabledFilters = enabledFilters; - } - - /** - * Construct a query translator; this form used internally. - * - * @param queryString The query string to process. - * @param enabledFilters Any enabled filters. - * @param factory The session factory. - */ - public QueryTranslatorImpl( - String queryString, - Map enabledFilters, - SessionFactoryImplementor factory) { - this( queryString, queryString, enabledFilters, factory ); - } - - /** - * Compile a subquery. - * - * @param superquery The containing query of the query to be compiled. - * - * @throws org.hibernate.MappingException Indicates problems resolving - * things referenced in the query. - * @throws org.hibernate.QueryException Generally some form of syntatic - * failure. - */ - void compile(QueryTranslatorImpl superquery) throws QueryException, MappingException { - this.tokenReplacements = superquery.tokenReplacements; - this.superQuery = superquery; - this.shallowQuery = true; - this.enabledFilters = superquery.getEnabledFilters(); - compile(); - } - - - /** - * Compile a "normal" query. This method may be called multiple - * times. Subsequent invocations are no-ops. - */ - public synchronized void compile( - Map replacements, - boolean scalar) throws QueryException, MappingException { - if ( !compiled ) { - this.tokenReplacements = replacements; - this.shallowQuery = scalar; - compile(); - } - } - - /** - * Compile a filter. This method may be called multiple - * times. Subsequent invocations are no-ops. - */ - public synchronized void compile( - String collectionRole, - Map replacements, - boolean scalar) throws QueryException, MappingException { - - if ( !isCompiled() ) { - addFromAssociation( "this", collectionRole ); - paramValueBinders.add( - new CollectionFilterKeyParameterSpecification( - collectionRole, - getFactory().getMetamodel().collectionPersister( collectionRole ).getKeyType() - ) - ); - compile( replacements, scalar ); - } - } - - /** - * Compile the query (generate the SQL). - * - * @throws org.hibernate.MappingException Indicates problems resolving - * things referenced in the query. - * @throws org.hibernate.QueryException Generally some form of syntatic - * failure. - */ - private void compile() throws QueryException, MappingException { - LOG.trace( "Compiling query" ); - try { - ParserHelper.parse( - new PreprocessingParser( tokenReplacements ), - queryString, - ParserHelper.HQL_SEPARATORS, - this - ); - renderSQL(); - } - catch (QueryException qe) { - if ( qe.getQueryString() == null ) { - throw qe.wrapWithQueryString( queryString ); - } - else { - throw qe; - } - } - catch (MappingException me) { - throw me; - } - catch (Exception e) { - LOG.debug( "Unexpected query compilation problem", e ); - throw new QueryException( "Incorrect query syntax", queryString, e ); - } - - postInstantiate(); - - compiled = true; - - } - - @Override - public String getSQLString() { - return sqlString; - } - - @Override - public List collectSqlStrings() { - return Collections.singletonList( sqlString ); - } - - @Override - public String getQueryString() { - return queryString; - } - - /** - * Persisters for the return values of a find() style query. - * - * @return an array of EntityPersisters. - */ - @Override - protected Loadable[] getEntityPersisters() { - return persisters; - } - - /** - * Types of the return values of an iterate() style query. - * - * @return an array of Types. - */ - @Override - public Type[] getReturnTypes() { - return actualReturnTypes; - } - - @Override - public String[] getReturnAliases() { - // return aliases not supported in classic translator! - return NO_RETURN_ALIASES; - } - - @Override - public String[][] getColumnNames() { - return scalarColumnNames; - } - - private static void logQuery(String hql, String sql) { - if ( LOG.isDebugEnabled() ) { - LOG.debugf( "HQL: %s", hql ); - LOG.debugf( "SQL: %s", sql ); - } - } - - void setAliasName(String alias, String name) { - aliasNames.put( alias, name ); - } - - public String getAliasName(String alias) { - String name = (String) aliasNames.get( alias ); - if ( name == null ) { - if ( superQuery != null ) { - name = superQuery.getAliasName( alias ); - } - else { - name = alias; - } - } - return name; - } - - String unalias(String path) { - String alias = StringHelper.root( path ); - String name = getAliasName( alias ); - if ( name != null ) { - return name + path.substring( alias.length() ); - } - return path; - } - - void addEntityToFetch(String name, String oneToOneOwnerName, AssociationType ownerAssociationType) { - addEntityToFetch( name ); - if ( oneToOneOwnerName != null ) { - oneToOneOwnerNames.put( name, oneToOneOwnerName ); - } - if ( ownerAssociationType != null ) { - uniqueKeyOwnerReferences.put( name, ownerAssociationType ); - } - } - - private void addEntityToFetch(String name) { - entitiesToFetch.add( name ); - } - - private int nextCount() { - return ( superQuery == null ) ? nameCount++ : superQuery.nameCount++; - } - - String createNameFor(String type) { - return StringHelper.generateAlias( type, nextCount() ); - } - - String createNameForCollection(String role) { - return StringHelper.generateAlias( role, nextCount() ); - } - - private String getType(String name) { - String type = (String) typeMap.get( name ); - if ( type == null && superQuery != null ) { - type = superQuery.getType( name ); - } - return type; - } - - private String getRole(String name) { - String role = (String) collections.get( name ); - if ( role == null && superQuery != null ) { - role = superQuery.getRole( name ); - } - return role; - } - - boolean isName(String name) { - return aliasNames.containsKey( name ) || - typeMap.containsKey( name ) || - collections.containsKey( name ) || ( - superQuery != null && superQuery.isName( name ) - ); - } - - PropertyMapping getPropertyMapping(String name) throws QueryException { - PropertyMapping decorator = getDecoratedPropertyMapping( name ); - if ( decorator != null ) { - return decorator; - } - - String type = getType( name ); - if ( type == null ) { - String role = getRole( name ); - if ( role == null ) { - throw new QueryException( "alias not found: " + name ); - } - return getCollectionPersister( role ); //.getElementPropertyMapping(); - } - else { - Queryable persister = getEntityPersister( type ); - if ( persister == null ) { - throw new QueryException( "persistent class not found: " + type ); - } - return persister; - } - } - - private PropertyMapping getDecoratedPropertyMapping(String name) { - return (PropertyMapping) decoratedPropertyMappings.get( name ); - } - - void decoratePropertyMapping(String name, PropertyMapping mapping) { - decoratedPropertyMappings.put( name, mapping ); - } - - private Queryable getEntityPersisterForName(String name) throws QueryException { - String type = getType( name ); - Queryable persister = getEntityPersister( type ); - if ( persister == null ) { - throw new QueryException( "persistent class not found: " + type ); - } - return persister; - } - - Queryable getEntityPersisterUsingImports(String className) { - final String importedClassName = getFactory().getMetamodel().getImportedClassName( className ); - if ( importedClassName == null ) { - return null; - } - try { - return (Queryable) getFactory().getMetamodel().entityPersister( importedClassName ); - } - catch (MappingException me) { - return null; - } - } - - Queryable getEntityPersister(String entityName) throws QueryException { - try { - return (Queryable) getFactory().getMetamodel().entityPersister( entityName ); - } - catch (Exception e) { - throw new QueryException( "persistent class not found: " + entityName ); - } - } - - QueryableCollection getCollectionPersister(String role) throws QueryException { - try { - return (QueryableCollection) getFactory().getMetamodel().collectionPersister( role ); - } - catch (ClassCastException cce) { - throw new QueryException( "collection role is not queryable: " + role ); - } - catch (Exception e) { - throw new QueryException( "collection role not found: " + role ); - } - } - - void addType(String name, String type) { - typeMap.put( name, type ); - } - - void addCollection(String name, String role) { - collections.put( name, role ); - } - - void addFrom(String name, String type, JoinSequence joinSequence) - throws QueryException { - addType( name, type ); - addFrom( name, joinSequence ); - } - - void addFromCollection(String name, String collectionRole, JoinSequence joinSequence) - throws QueryException { - //register collection role - addCollection( name, collectionRole ); - addJoin( name, joinSequence ); - } - - void addFrom(String name, JoinSequence joinSequence) - throws QueryException { - fromTypes.add( name ); - addJoin( name, joinSequence ); - } - - void addFromClass(String name, Queryable classPersister) - throws QueryException { - JoinSequence joinSequence = new JoinSequence( getFactory() ) - .setRoot( classPersister, name ); - //crossJoins.add(name); - addFrom( name, classPersister.getEntityName(), joinSequence ); - } - - void addSelectClass(String name) { - returnedTypes.add( name ); - } - - void addSelectScalar(Type type) { - scalarTypes.add( type ); - } - - void appendWhereToken(String token) { - whereTokens.add( token ); - } - - void appendHavingToken(String token) { - havingTokens.add( token ); - } - - void appendOrderByToken(String token) { - orderByTokens.add( token ); - } - - void appendGroupByToken(String token) { - groupByTokens.add( token ); - } - - void appendScalarSelectToken(String token) { - scalarSelectTokens.add( token ); - } - - void appendScalarSelectTokens(String[] tokens) { - scalarSelectTokens.add( tokens ); - } - - void addFromJoinOnly(String name, JoinSequence joinSequence) throws QueryException { - addJoin( name, joinSequence.getFromPart() ); - } - - void addJoin(String name, JoinSequence joinSequence) throws QueryException { - if ( !joins.containsKey( name ) ) { - joins.put( name, joinSequence ); - } - } - - void addNamedParameter(String name) { - if ( superQuery != null ) { - superQuery.addNamedParameter( name ); - } - - final int loc = parameterCount++; - - final NamedParameterInformationImpl info = namedParameters.computeIfAbsent( - name, - k -> new NamedParameterInformationImpl( name ) - ); - paramValueBinders.add( info ); - info.addSourceLocation( loc ); - } - - private enum OrdinalParameterStyle { LABELED, LEGACY } - - private OrdinalParameterStyle ordinalParameterStyle; - - private int legacyPositionalParameterCount = 0; - - void addLegacyPositionalParameter() { - if ( superQuery != null ) { - superQuery.addLegacyPositionalParameter(); - } - - if ( ordinalParameterStyle == null ) { - ordinalParameterStyle = OrdinalParameterStyle.LEGACY; - } - else if ( ordinalParameterStyle != OrdinalParameterStyle.LEGACY ) { - throw new QueryException( "Cannot mix legacy and labeled positional parameters" ); - } - - final int label = legacyPositionalParameterCount++; - final PositionalParameterInformationImpl paramInfo = new PositionalParameterInformationImpl( label ); - ordinalParameters.put( label, paramInfo ); - paramValueBinders.add( paramInfo ); - - final int loc = parameterCount++; - paramInfo.addSourceLocation( loc ); - - } - - void addOrdinalParameter(int label) { - if ( superQuery != null ) { - superQuery.addOrdinalParameter( label ); - } - - if ( ordinalParameterStyle == null ) { - ordinalParameterStyle = OrdinalParameterStyle.LABELED; - } - else if ( ordinalParameterStyle != OrdinalParameterStyle.LABELED ) { - throw new QueryException( "Cannot mix legacy and labeled positional parameters" ); - } - - final int loc = parameterCount++; - - final PositionalParameterInformationImpl info = ordinalParameters.computeIfAbsent( - label, - k -> new PositionalParameterInformationImpl( label ) - ); - - paramValueBinders.add( info ); - - info.addSourceLocation( loc ); - } - - @Override - protected int bindParameterValues( - PreparedStatement statement, - QueryParameters queryParameters, - int startIndex, - SharedSessionContractImplementor session) throws SQLException { - - int span = 0; - for ( ParameterBinder binder : paramValueBinders ) { - span += binder.bind( statement, queryParameters, session, startIndex + span ); - } - return span; - } - - @Override - public int[] getNamedParameterLocs(String name) throws QueryException { - Object o = namedParameters.get( name ); - if ( o == null ) { - throw new QueryException( ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name, queryString ); - } - if ( o instanceof Integer ) { - return new int[] {(Integer) o}; - } - else { - return ArrayHelper.toIntArray( (ArrayList) o ); - } - } - - private void renderSQL() throws QueryException, MappingException { - final int rtsize; - if ( returnedTypes.size() == 0 && scalarTypes.size() == 0 ) { - //ie no select clause in HQL - returnedTypes = fromTypes; - rtsize = returnedTypes.size(); - } - else { - rtsize = returnedTypes.size(); - returnedTypes.addAll( entitiesToFetch ); - } - int size = returnedTypes.size(); - persisters = new Queryable[size]; - names = new String[size]; - owners = new int[size]; - ownerAssociationTypes = new EntityType[size]; - suffixes = new String[size]; - includeInSelect = new boolean[size]; - for ( int i = 0; i < size; i++ ) { - String name = (String) returnedTypes.get( i ); - //if ( !isName(name) ) throw new QueryException("unknown type: " + name); - persisters[i] = getEntityPersisterForName( name ); - // TODO: cannot use generateSuffixes() - it handles the initial suffix differently. - suffixes[i] = ( size == 1 ) ? "" : AliasConstantsHelper.get( i ); - names[i] = name; - includeInSelect[i] = !entitiesToFetch.contains( name ); - if ( includeInSelect[i] ) { - selectLength++; - } - if ( name.equals( collectionOwnerName ) ) { - collectionOwnerColumn = i; - } - String oneToOneOwner = (String) oneToOneOwnerNames.get( name ); - owners[i] = ( oneToOneOwner == null ) ? -1 : returnedTypes.indexOf( oneToOneOwner ); - ownerAssociationTypes[i] = (EntityType) uniqueKeyOwnerReferences.get( name ); - } - - if ( ArrayHelper.isAllNegative( owners ) ) { - owners = null; - } - - String scalarSelect = renderScalarSelect(); //Must be done here because of side-effect! yuck... - - int scalarSize = scalarTypes.size(); - hasScalars = scalarTypes.size() != rtsize; - - returnTypes = new Type[scalarSize]; - for ( int i = 0; i < scalarSize; i++ ) { - returnTypes[i] = (Type) scalarTypes.get( i ); - } - - QuerySelect sql = new QuerySelect( getFactory().getDialect() ); - sql.setDistinct( distinct ); - - if ( !shallowQuery ) { - renderIdentifierSelect( sql ); - renderPropertiesSelect( sql ); - } - - if ( collectionPersister != null ) { - sql.addSelectFragmentString( collectionPersister.selectFragment( fetchName, "__" ) ); - } - - if ( hasScalars || shallowQuery ) { - sql.addSelectFragmentString( scalarSelect ); - } - - //TODO: for some dialects it would be appropriate to add the renderOrderByPropertiesSelect() to other select strings - mergeJoins( sql.getJoinFragment() ); - - sql.setWhereTokens( whereTokens.iterator() ); - - sql.setGroupByTokens( groupByTokens.iterator() ); - sql.setHavingTokens( havingTokens.iterator() ); - sql.setOrderByTokens( orderByTokens.iterator() ); - - if ( collectionPersister != null && collectionPersister.hasOrdering() ) { - sql.addOrderBy( collectionPersister.getSQLOrderByString( fetchName ) ); - } - - scalarColumnNames = NameGenerator.generateColumnNames( returnTypes, getFactory() ); - - // initialize the Set of queried identifier spaces (ie. tables) - Iterator iter = collections.values().iterator(); - while ( iter.hasNext() ) { - CollectionPersister p = getCollectionPersister( (String) iter.next() ); - addQuerySpaces( p.getCollectionSpaces() ); - } - iter = typeMap.keySet().iterator(); - while ( iter.hasNext() ) { - Queryable p = getEntityPersisterForName( (String) iter.next() ); - addQuerySpaces( p.getQuerySpaces() ); - } - - sqlString = sql.toQueryString(); - - if ( holderClass != null ) { - holderConstructor = ReflectHelper.getConstructor( holderClass, returnTypes ); - } - - if ( hasScalars ) { - actualReturnTypes = returnTypes; - } - else { - actualReturnTypes = new Type[selectLength]; - int j = 0; - for ( int i = 0; i < persisters.length; i++ ) { - if ( includeInSelect[i] ) { - actualReturnTypes[j++] = getFactory().getTypeResolver() - .getTypeFactory() - .manyToOne( persisters[i].getEntityName(), shallowQuery ); - } - } - } - - } - - private void renderIdentifierSelect(QuerySelect sql) { - int size = returnedTypes.size(); - - for ( int k = 0; k < size; k++ ) { - String name = (String) returnedTypes.get( k ); - String suffix = size == 1 ? "" : AliasConstantsHelper.get( k ); - sql.addSelectFragmentString( persisters[k].identifierSelectFragment( name, suffix ) ); - } - - } - - /*private String renderOrderByPropertiesSelect() { - StringBuffer buf = new StringBuffer(10); - - //add the columns we are ordering by to the select ID select clause - Iterator iter = orderByTokens.iterator(); - while ( iter.hasNext() ) { - String token = (String) iter.next(); - if ( token.lastIndexOf(".") > 0 ) { - //ie. it is of form "foo.bar", not of form "asc" or "desc" - buf.append(StringHelper.COMMA_SPACE).append(token); - } - } - - return buf.toString(); - }*/ - - private void renderPropertiesSelect(QuerySelect sql) { - int size = returnedTypes.size(); - for ( int k = 0; k < size; k++ ) { - String suffix = size == 1 ? "" : AliasConstantsHelper.get( k ); - String name = (String) returnedTypes.get( k ); - sql.addSelectFragmentString( persisters[k].propertySelectFragment( name, suffix, false ) ); - } - } - - /** - * WARNING: side-effecty - */ - private String renderScalarSelect() { - - boolean isSubselect = superQuery != null; - - StringBuilder buf = new StringBuilder( 20 ); - - if ( scalarTypes.size() == 0 ) { - //ie. no select clause - int size = returnedTypes.size(); - for ( int k = 0; k < size; k++ ) { - - scalarTypes.add( - getFactory().getTypeResolver().getTypeFactory().manyToOne( - persisters[k].getEntityName(), - shallowQuery - ) - ); - - String[] idColumnNames = persisters[k].getIdentifierColumnNames(); - for ( int i = 0; i < idColumnNames.length; i++ ) { - buf.append( returnedTypes.get( k ) ).append( '.' ).append( idColumnNames[i] ); - if ( !isSubselect ) { - buf.append( " as " ).append( NameGenerator.scalarName( k, i ) ); - } - if ( i != idColumnNames.length - 1 || k != size - 1 ) { - buf.append( ", " ); - } - } - - } - - } - else { - //there _was_ a select clause - Iterator iter = scalarSelectTokens.iterator(); - int c = 0; - boolean nolast = false; //real hacky... - int parenCount = 0; // used to count the nesting of parentheses - while ( iter.hasNext() ) { - Object next = iter.next(); - if ( next instanceof String ) { - String token = (String) next; - - if ( "(".equals( token ) ) { - parenCount++; - } - else if ( ")".equals( token ) ) { - parenCount--; - } - - String lc = token.toLowerCase( Locale.ROOT ); - if ( lc.equals( ", " ) ) { - if ( nolast ) { - nolast = false; - } - else { - if ( !isSubselect && parenCount == 0 ) { - int x = c++; - buf.append( " as " ).append( NameGenerator.scalarName( x, 0 ) ); - } - } - } - buf.append( token ); - if ( lc.equals( "distinct" ) || lc.equals( "all" ) ) { - buf.append( ' ' ); - } - } - else { - nolast = true; - String[] tokens = (String[]) next; - for ( int i = 0; i < tokens.length; i++ ) { - buf.append( tokens[i] ); - if ( !isSubselect ) { - buf.append( " as " ).append( NameGenerator.scalarName( c, i ) ); - } - if ( i != tokens.length - 1 ) { - buf.append( ", " ); - } - } - c++; - } - } - if ( !isSubselect && !nolast ) { - int x = c++; - buf.append( " as " ).append( NameGenerator.scalarName( x, 0 ) ); - } - - } - - return buf.toString(); - } - - private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException { - - Iterator iter = joins.entrySet().iterator(); - while ( iter.hasNext() ) { - Map.Entry me = (Map.Entry) iter.next(); - String name = (String) me.getKey(); - JoinSequence join = (JoinSequence) me.getValue(); - join.setSelector( - new JoinSequence.Selector() { - @Override - public boolean includeSubclasses(String alias) { - return returnedTypes.contains( alias ) && !isShallowQuery(); - } - } - ); - - if ( typeMap.containsKey( name ) ) { - ojf.addFragment( join.toJoinFragment( enabledFilters, true ) ); - } - else if ( collections.containsKey( name ) ) { - ojf.addFragment( join.toJoinFragment( enabledFilters, true ) ); - } - } - - } - - @Override - public final Set getQuerySpaces() { - return querySpaces; - } - - /** - * Is this query called by scroll() or iterate()? - * - * @return true if it is, false if it is called by find() or list() - */ - boolean isShallowQuery() { - return shallowQuery; - } - - void addQuerySpaces(Serializable[] spaces) { - Collections.addAll( querySpaces, spaces ); - if ( superQuery != null ) { - superQuery.addQuerySpaces( spaces ); - } - } - - void setDistinct(boolean distinct) { - this.distinct = distinct; - } - - boolean isSubquery() { - return superQuery != null; - } - - @Override - public CollectionPersister[] getCollectionPersisters() { - return collectionPersister == null ? null : new CollectionPersister[] {collectionPersister}; - } - - @Override - protected String[] getCollectionSuffixes() { - return collectionPersister == null ? null : new String[] {"__"}; - } - - void setCollectionToFetch(String role, String name, String ownerName, String entityName) - throws QueryException { - fetchName = name; - collectionPersister = getCollectionPersister( role ); - collectionOwnerName = ownerName; - if ( collectionPersister.getElementType().isEntityType() ) { - addEntityToFetch( entityName ); - } - } - - @Override - protected String[] getSuffixes() { - return suffixes; - } - - @Override - protected String[] getAliases() { - return names; - } - - /** - * Used for collection filters - */ - private void addFromAssociation(final String elementName, final String collectionRole) - throws QueryException { - //q.addCollection(collectionName, collectionRole); - QueryableCollection persister = getCollectionPersister( collectionRole ); - Type collectionElementType = persister.getElementType(); - if ( !collectionElementType.isEntityType() ) { - throw new QueryException( "collection of values in filter: " + elementName ); - } - - String[] keyColumnNames = persister.getKeyColumnNames(); - //if (keyColumnNames.length!=1) throw new QueryException("composite-key collection in filter: " + collectionRole); - - String collectionName; - JoinSequence join = new JoinSequence( getFactory() ); - collectionName = persister.isOneToMany() ? - elementName : - createNameForCollection( collectionRole ); - join.setRoot( persister, collectionName ); - if ( !persister.isOneToMany() ) { - //many-to-many - addCollection( collectionName, collectionRole ); - try { - join.addJoin( - (AssociationType) persister.getElementType(), - elementName, - JoinType.INNER_JOIN, - persister.getElementColumnNames( collectionName ) - ); - } - catch (MappingException me) { - throw new QueryException( me ); - } - } - join.addCondition( collectionName, keyColumnNames, " = ?" ); - //if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(collectionName) ); - EntityType elemType = (EntityType) collectionElementType; - addFrom( elementName, elemType.getAssociatedEntityName(), join ); - - } - - String getPathAlias(String path) { - return (String) pathAliases.get( path ); - } - - JoinSequence getPathJoin(String path) { - return (JoinSequence) pathJoins.get( path ); - } - - void addPathAliasAndJoin(String path, String alias, JoinSequence joinSequence) { - pathAliases.put( path, alias ); - pathJoins.put( path, joinSequence ); - } - - @Override - public List list(SharedSessionContractImplementor session, QueryParameters queryParameters) - throws HibernateException { - return list( session, queryParameters, getQuerySpaces(), actualReturnTypes ); - } - - /** - * Return the query results as an iterator - */ - @Override - public Iterator iterate(QueryParameters queryParameters, EventSource session) - throws HibernateException { - - final StatisticsImplementor statistics = session.getFactory().getStatistics(); - boolean stats = statistics.isStatisticsEnabled(); - long startTime = 0; - if ( stats ) { - startTime = System.nanoTime(); - } - - try { - final List afterLoadActions = new ArrayList<>(); - final SqlStatementWrapper wrapper = executeQueryStatement( - queryParameters, - false, - afterLoadActions, - session - ); - final ResultSet rs = wrapper.getResultSet(); - final PreparedStatement st = (PreparedStatement) wrapper.getStatement(); - HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator( - holderConstructor, - queryParameters.getResultTransformer() - ); - Iterator result = new IteratorImpl( - rs, - st, - session, - queryParameters.isReadOnly( session ), - returnTypes, - getColumnNames(), - hi - ); - - if ( stats ) { - final long endTime = System.nanoTime(); - final long milliseconds = TimeUnit.MILLISECONDS.convert( endTime - startTime, TimeUnit.NANOSECONDS ); - statistics.queryExecuted( - "HQL: " + queryString, - 0, - milliseconds - ); - } - - return result; - - } - catch (SQLException sqle) { - throw getFactory().getJdbcServices().getSqlExceptionHelper().convert( - sqle, - "could not execute query using iterate", - getSQLString() - ); - } - - } - - @Override - public int executeUpdate(QueryParameters queryParameters, SharedSessionContractImplementor session) throws HibernateException { - throw new UnsupportedOperationException( "Not supported! Use the AST translator..." ); - } - - @Override - protected boolean[] includeInResultRow() { - boolean[] isResultReturned = includeInSelect; - if ( hasScalars ) { - isResultReturned = new boolean[returnedTypes.size()]; - Arrays.fill( isResultReturned, true ); - } - return isResultReturned; - } - - - @Override - protected ResultTransformer resolveResultTransformer(ResultTransformer resultTransformer) { - return HolderInstantiator.resolveClassicResultTransformer( - holderConstructor, - resultTransformer - ); - } - - @Override - protected Object getResultColumnOrRow( - Object[] row, - ResultTransformer transformer, - ResultSet rs, - SharedSessionContractImplementor session) - throws SQLException, HibernateException { - Object[] resultRow = getResultRow( row, rs, session ); - return ( holderClass == null && resultRow.length == 1 ? - resultRow[0] : - resultRow - ); - } - - @Override - protected Object[] getResultRow(Object[] row, ResultSet rs, SharedSessionContractImplementor session) - throws SQLException, HibernateException { - Object[] resultRow; - if ( hasScalars ) { - String[][] scalarColumns = getColumnNames(); - int queryCols = returnTypes.length; - resultRow = new Object[queryCols]; - for ( int i = 0; i < queryCols; i++ ) { - resultRow[i] = returnTypes[i].nullSafeGet( rs, scalarColumns[i], session, null ); - } - } - else { - resultRow = toResultRow( row ); - } - return resultRow; - } - - @Override - protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException { - if ( holderClass != null ) { - for ( int i = 0; i < results.size(); i++ ) { - Object[] row = (Object[]) results.get( i ); - try { - results.set( i, holderConstructor.newInstance( row ) ); - } - catch (Exception e) { - throw new QueryException( "could not instantiate: " + holderClass, e ); - } - } - } - return results; - } - - private Object[] toResultRow(Object[] row) { - if ( selectLength == row.length ) { - return row; - } - else { - Object[] result = new Object[selectLength]; - int j = 0; - for ( int i = 0; i < row.length; i++ ) { - if ( includeInSelect[i] ) { - result[j++] = row[i]; - } - } - return result; - } - } - - void setHolderClass(Class clazz) { - holderClass = clazz; - } - - @Override - protected LockMode[] getLockModes(LockOptions lockOptions) { - - // unfortunately this stuff can't be cached because - // it is per-invocation, not constant for the - // QueryTranslator instance - HashMap nameLockOptions = new HashMap(); - if ( lockOptions == null ) { - lockOptions = LockOptions.NONE; - } - - if ( lockOptions.getAliasLockCount() > 0 ) { - Iterator iter = lockOptions.getAliasLockIterator(); - while ( iter.hasNext() ) { - Map.Entry me = (Map.Entry) iter.next(); - nameLockOptions.put( - getAliasName( (String) me.getKey() ), - me.getValue() - ); - } - } - LockMode[] lockModesArray = new LockMode[names.length]; - for ( int i = 0; i < names.length; i++ ) { - LockMode lm = (LockMode) nameLockOptions.get( names[i] ); - //if ( lm == null ) lm = LockOptions.NONE; - if ( lm == null ) { - lm = lockOptions.getLockMode(); - } - lockModesArray[i] = lm; - } - return lockModesArray; - } - - @Override - protected String applyLocks( - String sql, - QueryParameters parameters, - Dialect dialect, - List afterLoadActions) throws QueryException { - // can't cache this stuff either (per-invocation) - final LockOptions lockOptions = parameters.getLockOptions(); - final String result; - if ( lockOptions == null || - ( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) { - return sql; - } - else { - LockOptions locks = new LockOptions(); - locks.setLockMode( lockOptions.getLockMode() ); - locks.setTimeOut( lockOptions.getTimeOut() ); - locks.setScope( lockOptions.getScope() ); - Iterator iter = lockOptions.getAliasLockIterator(); - while ( iter.hasNext() ) { - Map.Entry me = (Map.Entry) iter.next(); - locks.setAliasSpecificLockMode( getAliasName( (String) me.getKey() ), (LockMode) me.getValue() ); - } - Map keyColumnNames = null; - if ( dialect.forUpdateOfColumns() ) { - keyColumnNames = new HashMap(); - for ( int i = 0; i < names.length; i++ ) { - keyColumnNames.put( names[i], persisters[i].getIdentifierColumnNames() ); - } - } - result = dialect.applyLocksToSql( sql, locks, keyColumnNames ); - } - logQuery( queryString, result ); - return result; - } - - @Override - protected boolean upgradeLocks() { - return true; - } - - @Override - protected int[] getCollectionOwners() { - return new int[] {collectionOwnerColumn}; - } - - protected boolean isCompiled() { - return compiled; - } - - @Override - public String toString() { - return queryString; - } - - @Override - protected int[] getOwners() { - return owners; - } - - @Override - protected EntityType[] getOwnerAssociationTypes() { - return ownerAssociationTypes; - } - - public Class getHolderClass() { - return holderClass; - } - - @Override - public Map getEnabledFilters() { - return enabledFilters; - } - - @Override - public ScrollableResultsImplementor scroll( - final QueryParameters queryParameters, - final SharedSessionContractImplementor session) throws HibernateException { - HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator( - holderConstructor, - queryParameters.getResultTransformer() - ); - return scroll( queryParameters, returnTypes, hi, session ); - } - - @Override - public String getQueryIdentifier() { - return queryIdentifier; - } - - @Override - protected boolean isSubselectLoadingEnabled() { - return hasSubselectLoadableCollections(); - } - - @Override - public List getPrimaryFromClauseTables() { - throw new UnsupportedOperationException( "The classic mode does not support UPDATE statements via createQuery!" ); - } - - @Override - public void validateScrollability() throws HibernateException { - // This is the legacy behaviour for HQL queries... - if ( getCollectionPersisters() != null ) { - throw new HibernateException( "Cannot scroll queries which initialize collections" ); - } - } - - @Override - public boolean containsCollectionFetches() { - return false; - } - - @Override - public boolean isManipulationStatement() { - // classic parser does not support bulk manipulation statements - return false; - } - - @Override - public Class getDynamicInstantiationResultType() { - return holderClass; - } - - @Override - public ParameterTranslations getParameterTranslations() { - return new ParameterTranslations() { - @Override - @SuppressWarnings("unchecked") - public Map getNamedParameterInformationMap() { - return namedParameters; - } - - @Override - @SuppressWarnings("unchecked") - public Map getPositionalParameterInformationMap() { - return ordinalParameters; - } - - @Override - public PositionalParameterInformation getPositionalParameterInformation(int position) { - return ordinalParameters.get( position ); - } - - @Override - public NamedParameterInformation getNamedParameterInformation(String name) { - return namedParameters.get( name ); - } - }; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/inline/AbstractInlineIdsUpdateHandlerImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/inline/AbstractInlineIdsUpdateHandlerImpl.java deleted file mode 100644 index 8db4752a96..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/inline/AbstractInlineIdsUpdateHandlerImpl.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.hql.spi.id.inline; - -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.engine.jdbc.spi.JdbcCoordinator; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.spi.QueryParameters; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.hql.internal.ast.HqlSqlWalker; -import org.hibernate.hql.internal.ast.tree.AssignmentSpecification; -import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy; -import org.hibernate.param.ParameterSpecification; -import org.hibernate.persister.entity.Queryable; -import org.hibernate.sql.Update; - -/** - * Inline bulk-id delete handler that selects the identifiers of the rows to be deleted. - * - * @author Vlad Mihalcea - */ -public abstract class AbstractInlineIdsUpdateHandlerImpl - extends AbstractInlineIdsBulkIdHandler - implements MultiTableBulkIdStrategy.UpdateHandler { - - private final Map updates = new LinkedHashMap<>(); - - private ParameterSpecification[][] assignmentParameterSpecifications; - - public AbstractInlineIdsUpdateHandlerImpl( - SessionFactoryImplementor factory, - HqlSqlWalker walker) { - super( factory, walker ); - } - - @Override - public String[] getSqlStatements() { - return updates.values().toArray( new String[updates.values().size()] ); - } - - @Override - public int execute( - SharedSessionContractImplementor session, - QueryParameters queryParameters) { - - IdsClauseBuilder values = prepareInlineStatement( session, queryParameters ); - - if ( !values.getIds().isEmpty() ) { - - final Queryable targetedQueryable = getTargetedQueryable(); - String[] tableNames = targetedQueryable.getConstraintOrderedTableNameClosure(); - String[][] columnNames = targetedQueryable.getContraintOrderedTableKeyColumnClosure(); - - String idSubselect = values.toStatement(); - - assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][]; - for ( int tableIndex = 0; tableIndex < tableNames.length; tableIndex++ ) { - boolean affected = false; - final List parameterList = new ArrayList<>(); - - Update update = generateUpdate( tableNames[tableIndex], columnNames[tableIndex], idSubselect, "bulk update" ); - - final List assignmentSpecifications = walker().getAssignmentSpecifications(); - for ( AssignmentSpecification assignmentSpecification : assignmentSpecifications ) { - if ( assignmentSpecification.affectsTable( tableNames[tableIndex] ) ) { - affected = true; - update.appendAssignmentFragment( assignmentSpecification.getSqlAssignmentFragment() ); - if ( assignmentSpecification.getParameters() != null ) { - Collections.addAll( parameterList, assignmentSpecification.getParameters() ); - } - } - } - if ( affected ) { - updates.put( tableIndex, update.toStatementString() ); - assignmentParameterSpecifications[tableIndex] = parameterList.toArray( new ParameterSpecification[parameterList.size()] ); - } - } - - final JdbcCoordinator jdbcCoordinator = session - .getJdbcCoordinator(); - // Start performing the updates - for ( Map.Entry updateEntry: updates.entrySet()) { - int i = updateEntry.getKey(); - String update = updateEntry.getValue(); - - if ( update == null) { - continue; - } - try { - try (PreparedStatement ps = jdbcCoordinator.getStatementPreparer() - .prepareStatement( update, false )) { - int position = 1; // jdbc params are 1-based - if ( assignmentParameterSpecifications[i] != null ) { - for ( ParameterSpecification assignmentParameterSpecification : assignmentParameterSpecifications[i] ) { - position += assignmentParameterSpecification - .bind( ps, queryParameters, session, position ); - } - } - jdbcCoordinator.getResultSetReturn() - .executeUpdate( ps ); - } - } - catch ( SQLException e ) { - throw convert( - e, - "error performing bulk update", - update - ); - } - } - } - - return values.getIds().size(); - } - - protected Update generateUpdate( - String tableName, - String[] columnNames, - String idSubselect, - String comment) { - final Update update = new Update( factory().getServiceRegistry().getService( JdbcServices.class ).getDialect() ) - .setTableName( tableName ) - .setWhere( "(" + String.join( ", ", (CharSequence[]) columnNames ) + ") in (" + idSubselect + ")" ); - if ( factory().getSessionFactoryOptions().isCommentsEnabled() ) { - update.setComment( comment ); - } - return update; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java index 327a2c3e55..012cc9fbc9 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java @@ -56,8 +56,6 @@ import org.hibernate.engine.transaction.internal.TransactionImpl; import org.hibernate.engine.transaction.spi.TransactionImplementor; import org.hibernate.id.uuid.StandardRandomStrategy; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; -import org.hibernate.jpa.spi.NativeQueryTupleTransformer; -import org.hibernate.jpa.spi.TupleBuilderTransformer; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.internal.ProcedureCallImpl; 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 d1999774cf..b0313e6365 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -119,8 +119,6 @@ import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.sql.spi.NativeQueryImplementor; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; -import org.hibernate.query.NativeQuery; -import org.hibernate.query.spi.NamedQueryRepository; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.resource.jdbc.spi.StatementInspector; import org.hibernate.resource.transaction.backend.jta.internal.synchronization.AfterCompletionAction; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java index 46f7a512f3..179eda570c 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java @@ -46,7 +46,9 @@ import org.hibernate.dialect.pagination.NoopLimitHandler; import org.hibernate.engine.internal.CacheHelper; import org.hibernate.engine.internal.TwoPhaseLoad; import org.hibernate.engine.jdbc.ColumnNameCache; +import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.spi.BatchFetchQueue; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityUniqueKey; @@ -82,6 +84,8 @@ import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.HibernateProxy; import org.hibernate.query.spi.ScrollableResultsImplementor; +import org.hibernate.sql.results.spi.RowReader; +import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.transform.CacheableResultTransformer; import org.hibernate.transform.ResultTransformer; import org.hibernate.type.AssociationType; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/ResultSetProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/ResultSetProcessorImpl.java index ab94213c6c..f8dc2e72b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/ResultSetProcessorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/ResultSetProcessorImpl.java @@ -14,6 +14,8 @@ import java.util.List; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.CollectionKey; +import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.SharedSessionContractImplementor; diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/AbstractManipulationCriteriaQuery.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/AbstractManipulationCriteriaQuery.java deleted file mode 100644 index 6a0379f219..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/AbstractManipulationCriteriaQuery.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.query.criteria.internal; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.persistence.criteria.CommonAbstractCriteria; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; -import javax.persistence.criteria.Subquery; -import javax.persistence.metamodel.EntityType; - -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.jpa.spi.HibernateEntityManagerImplementor; -import org.hibernate.query.criteria.internal.compile.CompilableCriteria; -import org.hibernate.query.criteria.internal.compile.CriteriaInterpretation; -import org.hibernate.query.criteria.internal.compile.ImplicitParameterBinding; -import org.hibernate.query.criteria.internal.compile.InterpretedParameterMetadata; -import org.hibernate.query.criteria.internal.compile.RenderingContext; -import org.hibernate.query.criteria.internal.path.RootImpl; -import org.hibernate.query.spi.QueryImplementor; -import org.hibernate.sql.ast.Clause; - -/** - * Base class for commonality between {@link javax.persistence.criteria.CriteriaUpdate} and - * {@link javax.persistence.criteria.CriteriaDelete} - * - * @author Steve Ebersole - */ -public abstract class AbstractManipulationCriteriaQuery implements CompilableCriteria, CommonAbstractCriteria { - private final CriteriaBuilderImpl criteriaBuilder; - - private RootImpl root; - private Predicate restriction; - - protected AbstractManipulationCriteriaQuery(CriteriaBuilderImpl criteriaBuilder) { - this.criteriaBuilder = criteriaBuilder; - } - - protected CriteriaBuilderImpl criteriaBuilder() { - return criteriaBuilder; - } - - - // Root ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public Root from(Class entityClass) { - EntityType entityType = criteriaBuilder.getEntityManagerFactory() - .getMetamodel() - .entity( entityClass ); - if ( entityType == null ) { - throw new IllegalArgumentException( entityClass + " is not an entity" ); - } - return from( entityType ); - } - - public Root from(EntityType entityType) { - root = new RootImpl( criteriaBuilder, entityType, false ); - return root; - } - - public Root getRoot() { - return root; - } - - - // Restriction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - protected void setRestriction(Expression restriction) { - this.restriction = criteriaBuilder.wrap( restriction ); - } - - public void setRestriction(Predicate... restrictions) { - this.restriction = criteriaBuilder.and( restrictions ); - } - - public Predicate getRestriction() { - return restriction; - } - - public Subquery subquery(Class type) { - return new CriteriaSubqueryImpl( criteriaBuilder(), type, this ); - } - - - // compiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public void validate() { - if ( root == null ) { - throw new IllegalStateException( "UPDATE/DELETE criteria must name root entity" ); - } - } - - @Override - public CriteriaInterpretation interpret(RenderingContext renderingContext) { - final String jpaqlString = renderQuery( renderingContext ); - return new CriteriaInterpretation() { - @Override - @SuppressWarnings("unchecked") - public QueryImplementor buildCompiledQuery( - SharedSessionContractImplementor entityManager, - final InterpretedParameterMetadata interpretedParameterMetadata) { - - final Map implicitParameterTypes = extractTypeMap( interpretedParameterMetadata.implicitParameterBindings() ); - - QueryImplementor query = entityManager.createQuery( - jpaqlString, - null, - null, - new HibernateEntityManagerImplementor.QueryOptions() { - @Override - public List getValueHandlers() { - return null; - } - - @Override - public Map getNamedParameterExplicitTypes() { - return implicitParameterTypes; - } - - @Override - public ResultMetadataValidator getResultMetadataValidator() { - return null; - } - } - ); - - for ( ImplicitParameterBinding implicitParameterBinding : interpretedParameterMetadata.implicitParameterBindings() ) { - implicitParameterBinding.bind( query ); - } - - return query; - } - - private Map extractTypeMap(List implicitParameterBindings) { - final HashMap map = new HashMap<>(); - for ( ImplicitParameterBinding implicitParameter : implicitParameterBindings ) { - map.put( implicitParameter.getParameterName(), implicitParameter.getJavaType() ); - } - return map; - } - }; - } - - protected abstract String renderQuery(RenderingContext renderingContext); - - protected void renderRoot(StringBuilder jpaql, RenderingContext renderingContext) { - jpaql.append( ( (FromImplementor) root ).renderTableExpression( renderingContext ) ); - } - - protected void renderRestrictions(StringBuilder jpaql, RenderingContext renderingContext) { - if ( getRestriction() == null ) { - return; - } - - renderingContext.getClauseStack().push( Clause.WHERE ); - try { - jpaql.append( " where " ) - .append( ( (Renderable) getRestriction() ).render( renderingContext ) ); - } - finally { - renderingContext.getClauseStack().pop(); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/function/ParameterizedFunctionExpression.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/function/ParameterizedFunctionExpression.java deleted file mode 100644 index de2297b264..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/function/ParameterizedFunctionExpression.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.query.criteria.internal.expression.function; - -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import javax.persistence.criteria.Expression; - -import org.hibernate.query.criteria.internal.CriteriaBuilderImpl; -import org.hibernate.query.criteria.internal.ParameterContainer; -import org.hibernate.query.criteria.internal.ParameterRegistry; -import org.hibernate.query.criteria.internal.Renderable; -import org.hibernate.query.criteria.internal.compile.RenderingContext; - -/** - * Support for functions with parameters. - * - * @author Steve Ebersole - */ -public class ParameterizedFunctionExpression - extends BasicFunctionExpression - implements FunctionExpression { - - public static final List STANDARD_JPA_FUNCTION_NAMES = Arrays.asList( - // 4.6.17.2.1 - "CONCAT", - "SUBSTRING", - "TRIM", - "UPPER", - "LOWER", - "LOCATE", - "LENGTH", - //4.6.17.2.2 - "ABS", - "SQRT", - "MOD", - "SIZE", - "INDEX", - // 4.6.17.2.3 - "CURRENT_DATE", - "CURRENT_TIME", - "CURRENT_TIMESTAMP" - ); - - private final List> argumentExpressions; - private final boolean isStandardJpaFunction; - - public ParameterizedFunctionExpression( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - String functionName, - List> argumentExpressions) { - super( criteriaBuilder, javaType, functionName ); - this.argumentExpressions = argumentExpressions; - this.isStandardJpaFunction = STANDARD_JPA_FUNCTION_NAMES.contains( functionName.toUpperCase(Locale.ROOT) ); - } - - public ParameterizedFunctionExpression( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - String functionName, - Expression... argumentExpressions) { - super( criteriaBuilder, javaType, functionName ); - this.argumentExpressions = Arrays.asList( argumentExpressions ); - this.isStandardJpaFunction = STANDARD_JPA_FUNCTION_NAMES.contains( functionName.toUpperCase(Locale.ROOT) ); - } - - protected boolean isStandardJpaFunction() { - return isStandardJpaFunction; - } - - protected static int properSize(int number) { - return number + (int)( number*.75 ) + 1; - } - - public List> getArgumentExpressions() { - return argumentExpressions; - } - - @Override - public void registerParameters(ParameterRegistry registry) { - for ( Expression argument : getArgumentExpressions() ) { - if ( ParameterContainer.class.isInstance( argument ) ) { - ( (ParameterContainer) argument ).registerParameters(registry); - } - } - } - - @Override - public String render(RenderingContext renderingContext) { - renderingContext.getFunctionStack().push( this ); - - try { - final StringBuilder buffer = new StringBuilder(); - if ( isStandardJpaFunction() ) { - buffer.append( getFunctionName() ).append( "(" ); - } - else { - buffer.append( "function('" ) - .append( getFunctionName() ) - .append( "', " ); - } - - renderArguments( buffer, renderingContext ); - - return buffer.append( ')' ).toString(); - } - finally { - renderingContext.getFunctionStack().pop(); - } - } - - protected void renderArguments(StringBuilder buffer, RenderingContext renderingContext) { - String sep = ""; - for ( Expression argument : argumentExpressions ) { - buffer.append( sep ).append( ( (Renderable) argument ).render( renderingContext ) ); - sep = ", "; - } - } - - - -} diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/predicate/CompoundPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/predicate/CompoundPredicate.java deleted file mode 100644 index 00840a7c47..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/predicate/CompoundPredicate.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.query.criteria.internal.predicate; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Predicate; - -import org.hibernate.query.criteria.internal.CriteriaBuilderImpl; -import org.hibernate.query.criteria.internal.ParameterRegistry; -import org.hibernate.query.criteria.internal.Renderable; -import org.hibernate.query.criteria.internal.compile.RenderingContext; - -/** - * A compound {@link Predicate predicate} is a grouping of other {@link Predicate predicates} in order to convert - * either a conjunction (logical AND) or a disjunction (logical OR). - * - * @author Steve Ebersole - */ -public class CompoundPredicate - extends AbstractPredicateImpl - implements Serializable { - private BooleanOperator operator; - private final List> expressions = new ArrayList>(); - - /** - * Constructs an empty conjunction or disjunction. - * - * @param criteriaBuilder The query builder from which this originates. - * @param operator Indicates whether this predicate will function - * as a conjunction or disjunction. - */ - public CompoundPredicate(CriteriaBuilderImpl criteriaBuilder, BooleanOperator operator) { - super( criteriaBuilder ); - this.operator = operator; - } - - /** - * Constructs a conjunction or disjunction over the given expressions. - * - * @param criteriaBuilder The query builder from which this originates. - * @param operator Indicates whether this predicate will function - * as a conjunction or disjunction. - * @param expressions The expressions to be grouped. - */ - public CompoundPredicate( - CriteriaBuilderImpl criteriaBuilder, - BooleanOperator operator, - Expression... expressions) { - this( criteriaBuilder, operator ); - applyExpressions( expressions ); - } - - /** - * Constructs a conjunction or disjunction over the given expressions. - * - * @param criteriaBuilder The query builder from which this originates. - * @param operator Indicates whether this predicate will function - * as a conjunction or disjunction. - * @param expressions The expressions to be grouped. - */ - public CompoundPredicate( - CriteriaBuilderImpl criteriaBuilder, - BooleanOperator operator, - List> expressions) { - this( criteriaBuilder, operator ); - applyExpressions( expressions ); - } - - private void applyExpressions(Expression... expressions) { - applyExpressions( Arrays.asList( expressions ) ); - } - - private void applyExpressions(List> expressions) { - this.expressions.clear(); - this.expressions.addAll( expressions ); - } - - @Override - public BooleanOperator getOperator() { - return operator; - } - - @Override - public List> getExpressions() { - return expressions; - } - - @Override - public void registerParameters(ParameterRegistry registry) { - for ( Expression expression : getExpressions() ) { - Helper.possibleParameter( expression, registry ); - } - } - - @Override - public String render(RenderingContext renderingContext) { - return render( isNegated(), renderingContext ); - } - - @Override - public boolean isJunction() { - return true; - } - - @Override - public String render(boolean isNegated, RenderingContext renderingContext) { - return render( this, renderingContext ); - } - - /** - * Create negation of compound predicate by using logic rules: - * 1. not (x || y) is (not x && not y) - * 2. not (x && y) is (not x || not y) - */ - @Override - public Predicate not() { - return new NegatedPredicateWrapper( this ); - } - - private void toggleOperator() { - this.operator = reverseOperator( this.operator ); - } - - public static BooleanOperator reverseOperator(BooleanOperator operator) { - return operator == BooleanOperator.AND - ? BooleanOperator.OR - : BooleanOperator.AND; - } - - public static String render(PredicateImplementor predicate, RenderingContext renderingContext) { - if ( ! predicate.isJunction() ) { - throw new IllegalStateException( "CompoundPredicate.render should only be used to render junctions" ); - } - - // for junctions, the negation is already cooked into the expressions and operator; we just need to render - // them as is - - if ( predicate.getExpressions().isEmpty() ) { - boolean implicitTrue = predicate.getOperator() == BooleanOperator.AND; - // AND is always true for empty; OR is always false - return implicitTrue ? "1=1" : "0=1"; - } - - // single valued junction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ( predicate.getExpressions().size() == 1 ) { - return ( (Renderable) predicate.getExpressions().get( 0 ) ).render( renderingContext ); - } - - final StringBuilder buffer = new StringBuilder(); - String sep = ""; - for ( Expression expression : predicate.getExpressions() ) { - buffer.append( sep ) - .append( "( " ) - .append( ( (Renderable) expression ).render( renderingContext ) ) - .append( " )" ); - sep = operatorTextWithSeparator( predicate.getOperator() ); - } - return buffer.toString(); - } - - private static String operatorTextWithSeparator(BooleanOperator operator) { - return operator == BooleanOperator.AND - ? " and " - : " or "; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java index 376cbe38f0..58a9ac2ae9 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java @@ -899,7 +899,7 @@ public abstract class AbstractProducedQuery implements QueryImplementor { } protected void collectHints(Map hints) { - final RowSelection queryOptions = getQueryOptions(); + final MutableQueryOptions queryOptions = getQueryOptions(); final Integer queryTimeout = queryOptions.getTimeout(); if ( queryTimeout != null ) { hints.put( HINT_TIMEOUT, queryTimeout ); diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java index 30350665c4..a8c3c00a3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java @@ -34,6 +34,7 @@ import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Setter; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.ProxyFactory; +import org.hibernate.tuple.IdentifierProperty; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.NonIdentifierAttribute; import org.hibernate.type.AssociationType; diff --git a/hibernate-core/src/test/java/org/hibernate/test/join/JoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/join/JoinTest.java index a33e0ccfd2..56ae5f2eb0 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/join/JoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/join/JoinTest.java @@ -12,15 +12,12 @@ import java.sql.SQLException; import java.util.Iterator; import java.util.List; -import javax.jws.soap.SOAPBinding; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.hibernate.Hibernate; import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.jdbc.AbstractWork; diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinTest.java deleted file mode 100644 index fee912f180..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.joinwithoutancestor; - -import java.util.List; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Table; - -import org.hibernate.testing.TestForIssue; -import org.junit.Test; - -@TestForIssue( jiraKey = "HHH-12993") -public class OmitAncestorJoinTest extends OmitAncestorTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { A.class, SubA.class, SubSubA.class, B.class }; - } - - @Test - public void test() { - // Should not join any parent table - assertFromTables("select valSubA from SubA", SubA.TABLE); - - // Should not join any parent table - assertFromTables("select sa.valSubA from SubA sa", SubA.TABLE); - - // Should omit middle table from inheritance hierarchy - assertFromTables("select ssa.valA from SubSubA ssa", SubSubA.TABLE, A.TABLE); - - // Should omit middle table from inheritance hierarchy - assertFromTables( "select ssa.valA, ssa.valSubSubA from SubSubA ssa", SubSubA.TABLE, A.TABLE ); - - // Should join parent table, because it is used in "where" part - assertFromTables("select valSubA from SubA where valA = 'foo'", SubA.TABLE, A.TABLE); - - // Should join parent table, because it is used in "order by" part - assertFromTables("select valSubSubA from SubSubA order by valA", SubSubA.TABLE, A.TABLE); - - // Should other tables from hierarchye, because it returns whole entity - assertFromTables("select suba from SubA suba", SubA.TABLE, A.TABLE, SubSubA.TABLE); - assertFromTables("from SubA", SubA.TABLE, A.TABLE, SubSubA.TABLE); - - // Should join A table, because it has the reference to B table - assertFromTables( "select suba.b from SubA suba", SubA.TABLE, A.TABLE, B.TABLE ); - assertFromTables( "select suba.b.id from SubA suba", SubA.TABLE, A.TABLE ); - } - - @Entity(name = "A") - @Table(name = A.TABLE) - @Inheritance(strategy = InheritanceType.JOINED) - static class A { - - public static final String TABLE = "A_Table"; - - @Id - @GeneratedValue - private Long id; - - private String valA; - - @ManyToOne - private B b; - - public Long getId() { - return id; - } - - public String getValA() { - return valA; - } - - public void setValA(String valA) { - this.valA = valA; - } - - public B getB() { - return b; - } - - public void setB(B b) { - this.b = b; - } - } - - @Entity(name = "SubA") - @Table(name = SubA.TABLE) - static class SubA extends A { - - public static final String TABLE = "SubA_Table"; - - private String valSubA; - - public String getValSubA() { - return valSubA; - } - - public void setValSubA(String valSubA) { - this.valSubA = valSubA; - } - } - - @Entity(name = "SubSubA") - @Table(name = SubSubA.TABLE) - static class SubSubA extends SubA { - - public static final String TABLE = "SubSubA_Table"; - - private String valSubSubA; - - public String getValSubSubA() { - return valSubSubA; - } - - public void setValSubSubA(String valSubSubA) { - this.valSubSubA = valSubSubA; - } - } - - @Entity(name = "B") - @Table(name = B.TABLE) - static class B { - - public static final String TABLE = "B_table"; - - @Id - @GeneratedValue - private Long id; - - private String valB; - - @OneToMany(mappedBy = "b") - private List aList; - - public Long getId() { - return id; - } - - public String getValB() { - return valB; - } - - public void setValB(String valB) { - this.valB = valB; - } - - public List getaList() { - return aList; - } - - public void setaList(List aList) { - this.aList = aList; - } - - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenCommonSecondaryTablePresentTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenCommonSecondaryTablePresentTest.java deleted file mode 100644 index 70f284e02d..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenCommonSecondaryTablePresentTest.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.joinwithoutancestor; - -import java.util.List; -import javax.persistence.Column; -import javax.persistence.ConstraintMode; -import javax.persistence.Entity; -import javax.persistence.ForeignKey; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.ManyToOne; -import javax.persistence.SecondaryTable; -import javax.persistence.Table; - -import org.hibernate.query.Query; - -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.transaction.TransactionUtil; -import org.junit.Assert; -import org.junit.Test; - -@TestForIssue(jiraKey = "HHH-12993") -public class OmitAncestorJoinWhenCommonSecondaryTablePresentTest extends OmitAncestorTestCase { - - private static final String SECONDARY_TABLE_NAME = "secondary_table"; - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { A.class, SubA.class, B.class, SubB.class, C.class }; - } - - @Override - protected boolean isCleanupTestDataRequired() { - return true; - } - - @Override - protected void cleanupTestData() throws Exception { - TransactionUtil.doInHibernate( this::sessionFactory, s -> { - s.createQuery( "from A", A.class ).list().forEach( s::remove ); - s.createQuery( "from B", B.class ).list().forEach( s::remove ); - s.createQuery( "from C", C.class ).list().forEach( s::remove ); - } ); - super.cleanupTestData(); - } - - @Test - public void shouldNotReturnSecondaryTableValueForSubB() { - TransactionUtil.doInHibernate( this::sessionFactory, session -> { - SubA subA = new SubA( 1L ); - subA.setValSubA( "valSubA" ); - subA.setValSecondaryTable( "valSecondaryTableFromSubA" ); - session.persist( subA ); - - SubB subB = new SubB( 2L ); - subB.setValSubB( "valSubB" ); - subB.setValSecondaryTable( "valSecondaryTableFromSubB" ); - session.persist( subB ); - - Query query = session.createQuery( "select suba.valSecondaryTable from SubA suba", String.class ); - List resultList = query.getResultList(); - Assert.assertEquals( 1, resultList.size() ); - Assert.assertEquals( "valSecondaryTableFromSubA", resultList.get( 0 ) ); - } ); - } - - @Test - public void shouldNotReturnSecondaryTableValueForSubB_implicitJoin() { - TransactionUtil.doInHibernate( this::sessionFactory, session -> { - SubA subA = new SubA( 1L ); - subA.setValSubA( "valSubA" ); - subA.setValSecondaryTable( "valSecondaryTableFromSubA" ); - session.persist( subA ); - - SubB subB = new SubB( 2L ); - subB.setValSubB( "valSubB" ); - subB.setValSecondaryTable( "valSecondaryTableFromSubB" ); - session.persist( subB ); - - C c = new C(); - c.setSubA( subA ); - session.persist( c ); - - Query query = session.createQuery( "select c.subA.valSecondaryTable from C c", String.class ); - List resultList = query.getResultList(); - Assert.assertEquals( 1, resultList.size() ); - Assert.assertEquals( "valSecondaryTableFromSubA", resultList.get( 0 ) ); - } ); - } - - @Entity(name = "A") - @Table(name = A.TABLE) - @Inheritance(strategy = InheritanceType.JOINED) - static class A { - - public static final String TABLE = "A_Table"; - - public A() { - } - - public A(Long id) { - this.id = id; - } - - @Id - private Long id; - - private String valA; - - public Long getId() { - return id; - } - - public String getValA() { - return valA; - } - - public void setValA(String valA) { - this.valA = valA; - } - - } - - @Entity(name = "SubA") - @Table(name = SubA.TABLE) - @SecondaryTable(name = SECONDARY_TABLE_NAME, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT)) - static class SubA extends A { - - public static final String TABLE = "SubA_table"; - - public SubA() { - } - - public SubA(Long id) { - super( id ); - } - - private String valSubA; - - @Column(table = SECONDARY_TABLE_NAME) - private String valSecondaryTable; - - public String getValSubA() { - return valSubA; - } - - public void setValSubA(String valSubA) { - this.valSubA = valSubA; - } - - public String getValSecondaryTable() { - return valSecondaryTable; - } - - public void setValSecondaryTable(String valSecondaryTable) { - this.valSecondaryTable = valSecondaryTable; - } - } - - @Entity(name = "B") - @Table(name = B.TABLE) - @Inheritance(strategy = InheritanceType.JOINED) - static class B { - - public static final String TABLE = "B_Table"; - - public B() { - } - - public B(Long id) { - this.id = id; - } - - @Id - private Long id; - - private String valB; - - public Long getId() { - return id; - } - - public String getValB() { - return valB; - } - - public void setValB(String valB) { - this.valB = valB; - } - - } - - @Entity(name = "SubB") - @Table(name = SubB.TABLE) - @SecondaryTable(name = SECONDARY_TABLE_NAME, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT)) - static class SubB extends B { - - public static final String TABLE = "SubB_table"; - - public SubB() { - } - - public SubB(Long id) { - super( id ); - } - - private String valSubB; - - @Column(table = SECONDARY_TABLE_NAME) - private String valSecondaryTable; - - public String getValSubB() { - return valSubB; - } - - public void setValSubB(String valSubB) { - this.valSubB = valSubB; - } - - public String getValSecondaryTable() { - return valSecondaryTable; - } - - public void setValSecondaryTable(String valSecondaryTable) { - this.valSecondaryTable = valSecondaryTable; - } - } - - @Entity(name = "C") - @Table(name = C.TABLE) - static class C { - - public static final String TABLE = "C_table"; - - @Id - @GeneratedValue - private Long id; - - @ManyToOne - private SubA subA; - - public Long getId() { - return id; - } - - public SubA getSubA() { - return subA; - } - - public void setSubA(SubA subA) { - this.subA = subA; - } - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenSecondaryTablePresentTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenSecondaryTablePresentTest.java deleted file mode 100644 index 0a5c8a57cb..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorJoinWhenSecondaryTablePresentTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.joinwithoutancestor; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.SecondaryTable; -import javax.persistence.Table; - -import org.hibernate.testing.TestForIssue; -import org.junit.Test; - -@TestForIssue(jiraKey = "HHH-12993") -public class OmitAncestorJoinWhenSecondaryTablePresentTest extends OmitAncestorTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { A.class, SubA.class, SubSubA.class }; - } - - @Test - public void test() { - assertFromTables( "select valSubASecondaryTable from SubA", SubA.TABLE, SubSubA.TABLE, SubA.SECONDARY_TABLE ); - } - - @Entity(name = "A") - @Table(name = A.TABLE) - @Inheritance(strategy = InheritanceType.JOINED) - static class A { - - public static final String TABLE = "A_Table"; - - @Id - @GeneratedValue - private Long id; - - private String valA; - - public Long getId() { - return id; - } - - public String getValA() { - return valA; - } - - public void setValA(String valA) { - this.valA = valA; - } - } - - @Entity(name = "SubA") - @Table(name = SubA.TABLE) - @SecondaryTable(name = SubA.SECONDARY_TABLE) - static class SubA extends A { - - public static final String TABLE = "SubA_Table"; - public static final String SECONDARY_TABLE = "SubA_Table_Sec"; - - private String valSubA; - - @Column(table = SECONDARY_TABLE) - private String valSubASecondaryTable; - - public String getValSubA() { - return valSubA; - } - - public void setValSubA(String valSubA) { - this.valSubA = valSubA; - } - - public String getValSubASecondaryTable() { - return valSubASecondaryTable; - } - - public void setValSubASecondaryTable(String valSubASecondaryTable) { - this.valSubASecondaryTable = valSubASecondaryTable; - } - } - - @Entity(name = "SubSubA") - @Table(name = SubSubA.TABLE) - static class SubSubA extends SubA { - - public static final String TABLE = "SubSubA_Table"; - - private String valSubSubA; - - public String getValSubSubA() { - return valSubSubA; - } - - public void setValSubSubA(String valSubSubA) { - this.valSubSubA = valSubSubA; - } - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorTestCase.java deleted file mode 100644 index 5c6d310287..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/joinwithoutancestor/OmitAncestorTestCase.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.joinwithoutancestor; - -import org.hibernate.Session; -import org.hibernate.engine.query.spi.HQLQueryPlan; -import org.hibernate.engine.query.spi.QueryPlanCache; -import org.hibernate.hql.spi.QueryTranslator; -import org.hibernate.internal.SessionImpl; - -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.testing.transaction.TransactionUtil; - -public abstract class OmitAncestorTestCase extends BaseCoreFunctionalTestCase { - - protected void assertFromTables(String query, String... tables) { - try { - TransactionUtil.doInHibernate( this::sessionFactory, session -> { - String sql = getSql( session, query ); - SqlAsserts.assertFromTables( sql, tables ); - session.createQuery( query ).getResultList(); - } ); - } - catch (AssertionError e) { - throw e; - } - } - - protected String getSql(Session session, String hql) { - // Create query - session.createQuery( hql ); - - // Get plan from cache - QueryPlanCache queryPlanCache = sessionFactory().getQueryPlanCache(); - HQLQueryPlan hqlQueryPlan = queryPlanCache.getHQLQueryPlan( - hql, - false, - ( (SessionImpl) session ).getLoadQueryInfluencers().getEnabledFilters() - ); - QueryTranslator queryTranslator = hqlQueryPlan.getTranslators()[0]; - String sql = queryTranslator.getSQLString(); - return sql; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/stat/ConcurrentQueryStatisticsTest.java b/hibernate-core/src/test/java/org/hibernate/test/stat/ConcurrentQueryStatisticsTest.java deleted file mode 100644 index e69de29bb2..0000000000