Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,16 @@
*/
public abstract class AbstractCommonQueryContract implements CommonQueryContract {
private final SharedSessionContractImplementor session;
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
private final QueryOptionsImpl queryOptions;

public AbstractCommonQueryContract(SharedSessionContractImplementor session) {
this.session = session;
this.queryOptions = new QueryOptionsImpl();
}

protected AbstractCommonQueryContract(AbstractCommonQueryContract original) {
this.session = original.session;
this.queryOptions = original.queryOptions;
}

public SharedSessionContractImplementor getSession() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.SelectionQuery;
import org.hibernate.query.internal.QueryOptionsImpl;
import org.hibernate.query.internal.ScrollableResultsIterator;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.sql.exec.internal.CallbackImpl;
Expand Down Expand Up @@ -81,6 +82,12 @@ public AbstractSelectionQuery(SharedSessionContractImplementor session) {
super( session );
}

protected AbstractSelectionQuery(AbstractSelectionQuery<?> original) {
super( original );
this.sessionFlushMode = original.sessionFlushMode;
this.sessionCacheMode = original.sessionCacheMode;
}

protected void applyOptions(NamedQueryMemento memento) {
if ( memento.getHints() != null ) {
memento.getHints().forEach( this::applyHint );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import java.util.Map;
import java.util.Set;

import org.hibernate.Internal;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.query.NullPrecedence;
Expand All @@ -33,7 +32,6 @@
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.criteria.JpaSimpleCase;
import org.hibernate.query.criteria.JpaWindow;
import org.hibernate.query.criteria.ValueHandlingMode;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
Expand Down Expand Up @@ -87,9 +85,6 @@ public interface NodeBuilder extends HibernateCriteriaBuilder {

QueryEngine getQueryEngine();

@Internal
ValueHandlingMode setCriteriaValueHandlingMode(ValueHandlingMode criteriaValueHandlingMode);

<R> SqmTuple<R> tuple(
Class<R> tupleType,
SqmExpression<?>... expressions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.from.SqmRoot;
Expand Down Expand Up @@ -69,6 +70,10 @@ abstract class AbstractSqmSelectionQuery<R> extends AbstractSelectionQuery<R> {
super(session);
}

AbstractSqmSelectionQuery(AbstractSqmSelectionQuery<?> original) {
super( original );
}

protected int max(boolean hasLimit, SqmSelectStatement<?> sqmStatement, List<R> list) {
return !hasLimit || getQueryOptions().getLimit().getMaxRows() == null
? getMaxRows( sqmStatement, list.size() )
Expand Down Expand Up @@ -158,46 +163,14 @@ public SelectionQuery<R> setPage(Page page) {
return this;
}

private SqmSelectStatement<KeyedResult<R>> paginateQuery(
List<Order<? super R>> keyDefinition, List<Comparable<?>> keyValues) {
@SuppressWarnings("unchecked")
final SqmSelectStatement<KeyedResult<R>> sqm =
(SqmSelectStatement<KeyedResult<R>>)
getSqmSelectStatement().copy( noParamCopyContext() );
final NodeBuilder builder = sqm.nodeBuilder();
//TODO: find a better way handle parameters
final ValueHandlingMode valueHandlingMode = builder.setCriteriaValueHandlingMode(ValueHandlingMode.INLINE);
try {
return paginate( keyDefinition, keyValues, sqm, builder );
}
finally {
builder.setCriteriaValueHandlingMode( valueHandlingMode );
}
}


@Override
public KeyedResultList<R> getKeyedResultList(KeyedPage<R> keyedPage) {
if ( keyedPage == null ) {
throw new IllegalArgumentException( "KeyedPage was null" );
}
final List<KeyedResult<R>> results = new SqmSelectionQueryImpl<KeyedResult<R>>( this, keyedPage )
.getResultList();
final Page page = keyedPage.getPage();
final List<Comparable<?>> key = keyedPage.getKey();
final List<Order<? super R>> keyDefinition = keyedPage.getKeyDefinition();
final List<Order<? super R>> appliedKeyDefinition =
keyedPage.getKeyInterpretation() == KEY_OF_FIRST_ON_NEXT_PAGE
? Order.reverse(keyDefinition) : keyDefinition;

setMaxResults( page.getMaxResults() + 1 );
if ( key == null ) {
setFirstResult( page.getFirstResult() );
}

// getQueryOptions().setQueryPlanCachingEnabled( false );
final List<KeyedResult<R>> results =
buildConcreteQueryPlan( paginateQuery( appliedKeyDefinition, key ), getQueryOptions() )
.performList(this);

return new KeyedResultList<>(
collectResults( results, page.getSize(), keyedPage.getKeyInterpretation() ),
collectKeys( results, page.getSize() ),
Expand Down Expand Up @@ -281,10 +254,6 @@ protected <T> ConcreteSqmSelectQueryPlan<T> buildConcreteQueryPlan(
);
}

private <T> SelectQueryPlan<T> buildConcreteQueryPlan(SqmSelectStatement<T> sqmStatement, QueryOptions options) {
return buildConcreteQueryPlan( sqmStatement, null, null, options );
}

protected void applyOptions(NamedSqmQueryMemento memento) {
applyOptions( (NamedQueryMemento) memento );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,6 @@ private static <C extends Comparable<? super C>> SqmPredicate keyPredicate(
Expression<? extends C> key, C keyValue, SortDirection direction,
List<SqmPath<?>> previousKeys, List<Comparable<?>> keyValues,
NodeBuilder builder) {
// TODO: use a parameter here and create a binding for it
// @SuppressWarnings("unchecked")
// final Class<C> valueClass = (Class<C>) keyValue.getClass();
// final JpaParameterExpression<C> parameter = builder.parameter(valueClass);
// setParameter( parameter, keyValue );
SqmPredicate predicate;
switch ( direction ) {
case ASCENDING:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.query.sqm.internal;

import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.tree.expression.SqmParameter;

import org.checkerframework.checker.nullness.qual.Nullable;
Expand All @@ -14,6 +15,13 @@
* @author Marco Belladelli
*/
public class NoParamSqmCopyContext extends SimpleSqmCopyContext {
public NoParamSqmCopyContext() {
}

public NoParamSqmCopyContext(@Nullable SqmQuerySource querySource) {
super( querySource );
}

@Override
public <T> @Nullable T getCopy(T original) {
if ( original instanceof SqmParameter<?> ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java.util.IdentityHashMap;

import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.tree.SqmCopyContext;

import org.checkerframework.checker.nullness.qual.Nullable;
Expand All @@ -17,6 +18,15 @@
*/
public class SimpleSqmCopyContext implements SqmCopyContext {
private final IdentityHashMap<Object, Object> map = new IdentityHashMap<>();
private final @Nullable SqmQuerySource querySource;

public SimpleSqmCopyContext() {
this( null );
}

public SimpleSqmCopyContext(@Nullable SqmQuerySource querySource) {
this.querySource = querySource;
}

@Override
@SuppressWarnings( "unchecked" )
Expand All @@ -32,4 +42,9 @@ public <T> T registerCopy(T original, T copy) {
}
return copy;
}

@Override
public @Nullable SqmQuerySource getQuerySource() {
return querySource;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl;
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.query.BindableType;
Expand Down Expand Up @@ -199,7 +198,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
private final transient boolean jpaComplianceEnabled;
private final transient QueryEngine queryEngine;
private final transient Supplier<SessionFactoryImplementor> sessionFactory;
private transient ValueHandlingMode criteriaValueHandlingMode;
private final transient ValueHandlingMode criteriaValueHandlingMode;
private transient BasicType<Boolean> booleanType;
private transient BasicType<Integer> integerType;
private transient BasicType<Long> longType;
Expand Down Expand Up @@ -228,13 +227,6 @@ public SqmCriteriaNodeBuilder(
}
}

@Override
public ValueHandlingMode setCriteriaValueHandlingMode(ValueHandlingMode criteriaValueHandlingMode) {
ValueHandlingMode current = this.criteriaValueHandlingMode;
this.criteriaValueHandlingMode = criteriaValueHandlingMode;
return current;
}

@Override
public JpaMetamodel getDomainModel() {
return getSessionFactory().getJpaMetamodel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.BindableType;
import org.hibernate.query.KeyedPage;
import org.hibernate.query.Order;
import org.hibernate.query.Page;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.criteria.internal.NamedCriteriaQueryMementoImpl;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
Expand All @@ -42,9 +46,11 @@
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
import org.hibernate.query.sqm.spi.SqmSelectionQueryImplementor;
Expand All @@ -69,9 +75,12 @@
import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_CACHE_STORE_MODE;
import static org.hibernate.jpa.SpecHints.HINT_SPEC_CACHE_RETRIEVE_MODE;
import static org.hibernate.jpa.SpecHints.HINT_SPEC_CACHE_STORE_MODE;
import static org.hibernate.query.KeyedPage.KeyInterpretation.KEY_OF_FIRST_ON_NEXT_PAGE;
import static org.hibernate.query.spi.SqlOmittingQueryOptions.omitSqlQueryOptions;
import static org.hibernate.query.sqm.internal.KeyBasedPagination.paginate;
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.createInterpretationsKey;
import static org.hibernate.query.sqm.internal.SqmUtil.isSelectionAssignableToResultType;
import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext;

/**
* @author Steve Ebersole
Expand Down Expand Up @@ -179,6 +188,87 @@ public SqmSelectionQueryImpl(
this.tupleMetadata = buildTupleMetadata( sqm, expectedResultType );
}

<E> SqmSelectionQueryImpl(AbstractSqmSelectionQuery<?> original, KeyedPage<E> keyedPage) {
super( original );

final Page page = keyedPage.getPage();
final List<Comparable<?>> key = keyedPage.getKey();
final List<Order<? super E>> keyDefinition = keyedPage.getKeyDefinition();
final List<Order<? super E>> appliedKeyDefinition =
keyedPage.getKeyInterpretation() == KEY_OF_FIRST_ON_NEXT_PAGE
? Order.reverse( keyDefinition ) : keyDefinition;

//noinspection unchecked
this.sqm = (SqmSelectStatement<R>) paginate(
appliedKeyDefinition,
key,
// Change the query source to CRITERIA, because we will change the query and introduce parameters
(SqmSelectStatement<KeyedResult<E>>) original.getSqmStatement()
.copy( noParamCopyContext( SqmQuerySource.CRITERIA ) ),
original.getSqmStatement().nodeBuilder()
);
this.hql = CRITERIA_HQL_STRING;

this.domainParameterXref = DomainParameterXref.from( sqm );
this.parameterMetadata = domainParameterXref.hasParameters()
? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() )
: ParameterMetadataImpl.EMPTY;

// Just use the original parameter bindings since this object is never going to be mutated
this.parameterBindings = parameterMetadata.createBindings( original.getSession().getSessionFactory() );
// Don't remove this cast. This is here to work around this bug: https://bugs.openjdk.org/browse/JDK-8340443
(( DomainQueryExecutionContext) original ).getQueryParameterBindings().visitBindings(
(parameter, binding) -> {
//noinspection unchecked
final QueryParameterBinding<Object> parameterBinding =
(QueryParameterBinding<Object>) this.parameterBindings.getBinding( parameter );
//noinspection unchecked
final BindableType<Object> bindType = (BindableType<Object>) binding.getBindType();
final TemporalType explicitTemporalPrecision = binding.getExplicitTemporalPrecision();
if ( explicitTemporalPrecision != null ) {
if ( binding.isMultiValued() ) {
parameterBinding.setBindValues(
binding.getBindValues(),
explicitTemporalPrecision,
getSessionFactory().getTypeConfiguration()
);
}
else {
parameterBinding.setBindValue( binding.getBindValue(), explicitTemporalPrecision );
}
}
else {
if ( binding.isMultiValued() ) {
parameterBinding.setBindValues( binding.getBindValues(), bindType );
}
else {
parameterBinding.setBindValue( binding.getBindValue(), bindType );
}
}
//noinspection unchecked
parameterBinding.setType( (MappingModelExpressible<Object>) binding.getType() );
}
);

// Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here
for ( SqmParameter<?> sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) {
if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper<?> ) {
bindCriteriaParameter( (SqmJpaCriteriaParameterWrapper<?>) sqmParameter );
}
}

//noinspection unchecked
this.expectedResultType = (Class<R>) KeyedResult.class;
this.resultType = determineResultType( sqm, expectedResultType );
this.tupleMetadata = null;

setMaxResults( page.getMaxResults() + 1 );
if ( key == null ) {
setFirstResult( page.getFirstResult() );
}
}


private static Class<?> determineResultType(SqmSelectStatement<?> sqm, Class<?> expectedResultType) {
final List<SqmSelection<?>> selections = sqm.getQuerySpec().getSelectClause().getSelections();
if ( selections.size() == 1 ) {
Expand Down
Loading
Loading