Implement SQM copying for JPA Criteria API uses
This commit is contained in:
parent
5446291171
commit
0ad5796ffd
|
@ -79,6 +79,17 @@ Traditionally, Hibernate has considered the names locally scoped.
|
|||
If enabled, the names used by `@TableGenerator` and `@SequenceGenerator` will be considered global so configuring two different generators
|
||||
with the same name will cause a `java.lang.IllegalArgumentException` to be thrown at boot time.
|
||||
|
||||
`*hibernate.jpa.compliance.criteria_copy*` (e.g. `true` (default value) or `false` )::
|
||||
The Jakarta Persistence spec says that mutations done to `CriteriaQuery`, `CriteriaUpdate` and `CriteriaDelete`
|
||||
after such objects were used to create a `jakarta.persistence.Query` may not affect that query.
|
||||
This requirement makes it necessary to copy these objects because the APIs allow mutations.
|
||||
+
|
||||
If disabled, it is assumed that users do not mutate the criteria query afterwards
|
||||
and due to that, no copy will be created, which will improve performance.
|
||||
+
|
||||
By default, no copies are created to not hurt performance. When enabled,
|
||||
criteria query objects are copied, as required by the JPA specification.
|
||||
|
||||
[[configurations-database-connection]]
|
||||
=== Database connection properties
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ import org.hibernate.query.sqm.NullPrecedence;
|
|||
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
|
||||
import jakarta.persistence.criteria.CriteriaDelete;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.CriteriaUpdate;
|
||||
|
||||
/**
|
||||
* Enumerates the configuration properties supported by Hibernate, including
|
||||
* properties defined by the JPA specification.
|
||||
|
@ -2364,6 +2368,24 @@ public interface AvailableSettings {
|
|||
*/
|
||||
String JPA_LOAD_BY_ID_COMPLIANCE = "hibernate.jpa.compliance.load_by_id";
|
||||
|
||||
/**
|
||||
* When enabled, specifies that {@linkplain org.hibernate.query.Query queries}
|
||||
* created through {@link jakarta.persistence.EntityManager#createQuery(CriteriaQuery)},
|
||||
* {@link jakarta.persistence.EntityManager#createQuery(CriteriaUpdate)} or
|
||||
* {@link jakarta.persistence.EntityManager#createQuery(CriteriaDelete)}
|
||||
* must create a copy of the passed object such that the resulting {@link jakarta.persistence.Query}
|
||||
* is not affected by any mutations to the original criteria query.
|
||||
* <p>
|
||||
* If disabled, it is assumed that users do not mutate the criteria query afterwards
|
||||
* and due to that, no copy will be created, which will improve performance.
|
||||
* <p>
|
||||
* By default, no copies are created to not hurt performance. When enabled,
|
||||
* criteria query objects are copied, as required by the JPA specification.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
String JPA_CRITERIA_COPY_COMPLIANCE = "hibernate.jpa.compliance.criteria_copy";
|
||||
|
||||
/**
|
||||
* Determines if the identifier value stored in the database table backing a
|
||||
* {@linkplain jakarta.persistence.TableGenerator table generator} is the last
|
||||
|
|
|
@ -209,6 +209,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
|||
delegate.setCacheMode( cm );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJpaCriteriaCopyComplianceEnabled(boolean jpaCriteriaCopyComplianceEnabled) {
|
||||
delegate.setJpaCriteriaCopyComplianceEnabled( jpaCriteriaCopyComplianceEnabled );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaCriteriaCopyComplianceEnabled() {
|
||||
return delegate.isJpaCriteriaCopyComplianceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return delegate.isOpen();
|
||||
|
|
|
@ -332,6 +332,10 @@ public interface SharedSessionContractImplementor
|
|||
|
||||
void setCacheMode(CacheMode cm);
|
||||
|
||||
void setJpaCriteriaCopyComplianceEnabled(boolean jpaCriteriaCopyComplianceEnabled);
|
||||
|
||||
boolean isJpaCriteriaCopyComplianceEnabled();
|
||||
|
||||
/**
|
||||
* Set the flush mode for this session.
|
||||
* <p/>
|
||||
|
|
|
@ -81,6 +81,7 @@ import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
|||
import org.hibernate.query.sqm.SqmSelectionQuery;
|
||||
import org.hibernate.query.sqm.internal.QuerySqmImpl;
|
||||
import org.hibernate.query.sqm.internal.SqmSelectionQueryImpl;
|
||||
import org.hibernate.query.sqm.internal.SqmUtil;
|
||||
import org.hibernate.query.sqm.tree.SqmDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
|
@ -141,6 +142,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
private final PhysicalConnectionHandlingMode connectionHandlingMode;
|
||||
|
||||
private CacheMode cacheMode;
|
||||
private boolean jpaCriteriaCopyComplianceEnabled;
|
||||
|
||||
protected boolean closed;
|
||||
protected boolean waitingForAutoClose;
|
||||
|
@ -158,7 +160,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
this.factory = factory;
|
||||
this.fastSessionServices = factory.getFastSessionServices();
|
||||
this.cacheTransactionSync = factory.getCache().getRegionFactory().createTransactionContext( this );
|
||||
|
||||
setJpaCriteriaCopyComplianceEnabled( factory.getJpaMetamodel().getJpaCompliance().isJpaCriteriaCopyComplianceEnabled() );
|
||||
|
||||
this.flushMode = options.getInitialSessionFlushMode();
|
||||
|
||||
|
@ -643,6 +645,15 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
this.cacheMode = cacheMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJpaCriteriaCopyComplianceEnabled(boolean jpaCriteriaCopyComplianceEnabled) {
|
||||
this.jpaCriteriaCopyComplianceEnabled = jpaCriteriaCopyComplianceEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaCriteriaCopyComplianceEnabled() {
|
||||
return jpaCriteriaCopyComplianceEnabled;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// dynamic HQL handling
|
||||
|
@ -705,6 +716,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
@Override
|
||||
public <R> SelectionQuery<R> createSelectionQuery(CriteriaQuery<R> criteria) {
|
||||
SqmUtil.verifyIsSelectStatement( (SqmStatement<?>) criteria, null );
|
||||
return new SqmSelectionQueryImpl<>( (SqmSelectStatement<R>) criteria, this );
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ import static org.hibernate.cfg.AvailableSettings.JAKARTA_LOCK_SCOPE;
|
|||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_LOCK_TIMEOUT;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JPA_CRITERIA_COPY_COMPLIANCE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT;
|
||||
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
|
||||
|
@ -2599,6 +2600,9 @@ public class SessionImpl
|
|||
)
|
||||
);
|
||||
break;
|
||||
case JPA_CRITERIA_COPY_COMPLIANCE:
|
||||
setJpaCriteriaCopyComplianceEnabled( Boolean.parseBoolean( value.toString() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
private final boolean closedCompliance;
|
||||
private final boolean cachingCompliance;
|
||||
private final boolean loadByIdCompliance;
|
||||
private final boolean criteriaCopyCompliance;
|
||||
|
||||
public JpaComplianceImpl(
|
||||
boolean listCompliance,
|
||||
|
@ -31,7 +32,8 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
boolean transactionCompliance,
|
||||
boolean closedCompliance,
|
||||
boolean cachingCompliance,
|
||||
boolean loadByIdCompliance) {
|
||||
boolean loadByIdCompliance,
|
||||
boolean criteriaCopyCompliance) {
|
||||
this.queryCompliance = queryCompliance;
|
||||
this.transactionCompliance = transactionCompliance;
|
||||
this.listCompliance = listCompliance;
|
||||
|
@ -41,6 +43,7 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
this.globalGeneratorNameScopeCompliance = globalGeneratorNameScopeCompliance;
|
||||
this.orderByMappingCompliance = orderByMappingCompliance;
|
||||
this.loadByIdCompliance = loadByIdCompliance;
|
||||
this.criteriaCopyCompliance = criteriaCopyCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,6 +91,11 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
return loadByIdCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaCriteriaCopyComplianceEnabled() {
|
||||
return criteriaCopyCompliance;
|
||||
}
|
||||
|
||||
public static class JpaComplianceBuilder {
|
||||
private boolean queryCompliance;
|
||||
private boolean listCompliance;
|
||||
|
@ -98,6 +106,7 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
private boolean transactionCompliance;
|
||||
private boolean closedCompliance;
|
||||
private boolean loadByIdCompliance;
|
||||
private boolean criteriaCopyCompliance;
|
||||
|
||||
public JpaComplianceBuilder() {
|
||||
}
|
||||
|
@ -147,6 +156,11 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setJpaCriteriaCopyComplianceEnabled(boolean jpaCriteriaCopyComplianceEnabled) {
|
||||
this.criteriaCopyCompliance = jpaCriteriaCopyComplianceEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
JpaCompliance createJpaCompliance() {
|
||||
return new JpaComplianceImpl(
|
||||
listCompliance,
|
||||
|
@ -157,7 +171,8 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
transactionCompliance,
|
||||
closedCompliance,
|
||||
cachingCompliance,
|
||||
loadByIdCompliance
|
||||
loadByIdCompliance,
|
||||
criteriaCopyCompliance
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
|||
private boolean closedCompliance;
|
||||
private boolean cachingCompliance;
|
||||
private boolean loadByIdCompliance;
|
||||
private boolean criteriaCopyCompliance;
|
||||
|
||||
public MutableJpaComplianceImpl(Map configurationSettings) {
|
||||
this(
|
||||
|
@ -92,6 +93,12 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
|||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
|
||||
criteriaCopyCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_CRITERIA_COPY_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -134,6 +141,16 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
|||
return orderByMappingCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadByIdComplianceEnabled() {
|
||||
return loadByIdCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaCriteriaCopyComplianceEnabled() {
|
||||
return criteriaCopyCompliance;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Mutators
|
||||
|
||||
|
@ -182,8 +199,8 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadByIdComplianceEnabled() {
|
||||
return loadByIdCompliance;
|
||||
public void setJpaCriteriaCopyComplianceEnabled(boolean jpaCriteriaCopyComplianceEnabled) {
|
||||
this.criteriaCopyCompliance = jpaCriteriaCopyComplianceEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -197,7 +214,8 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
|||
.setTransactionCompliance( transactionCompliance )
|
||||
.setClosedCompliance( closedCompliance )
|
||||
.setCachingCompliance( cachingCompliance )
|
||||
.setLoadByIdCompliance( loadByIdCompliance );
|
||||
.setLoadByIdCompliance( loadByIdCompliance )
|
||||
.setJpaCriteriaCopyComplianceEnabled( criteriaCopyCompliance );
|
||||
return builder.createJpaCompliance();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,4 +154,22 @@ public interface JpaCompliance {
|
|||
* @since 6.0
|
||||
*/
|
||||
boolean isLoadByIdComplianceEnabled();
|
||||
|
||||
/**
|
||||
* JPA says that mutations done to {@link jakarta.persistence.criteria.CriteriaQuery},
|
||||
* {@link jakarta.persistence.criteria.CriteriaUpdate} and {@link jakarta.persistence.criteria.CriteriaDelete}
|
||||
* after such objects were used to create a {@link jakarta.persistence.Query} may not affect that query.
|
||||
* This requirement makes it necessary to copy these objects because the APIs allow mutations.
|
||||
*
|
||||
* If disabled, it is assumed that users do not mutate the criteria query afterwards
|
||||
* and due to that, no copy will be created, which will improve performance.
|
||||
*
|
||||
* By default, no copies are created to not hurt performance. When enabled,
|
||||
* criteria query objects are copied, as required by the JPA specification.
|
||||
*
|
||||
* @see org.hibernate.cfg.AvailableSettings#JPA_CRITERIA_COPY_COMPLIANCE
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
boolean isJpaCriteriaCopyComplianceEnabled();
|
||||
}
|
||||
|
|
|
@ -28,5 +28,7 @@ public interface MutableJpaCompliance extends JpaCompliance {
|
|||
|
||||
void setLoadByIdCompliance(boolean enabled);
|
||||
|
||||
void setJpaCriteriaCopyComplianceEnabled(boolean jpaCriteriaCopyComplianceEnabled);
|
||||
|
||||
JpaCompliance immutableCopy();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
import org.hibernate.query.sqm.sql.internal.DiscriminatorPathInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SelfInterpretingSqmPath;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.AbstractSqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
|
@ -50,6 +51,18 @@ public class DiscriminatorSqmPath extends AbstractSqmPath implements SelfInterpr
|
|||
this.entityDescriptor = entityDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscriminatorSqmPath copy(SqmCopyContext context) {
|
||||
final DiscriminatorSqmPath existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
return context.registerCopy(
|
||||
this,
|
||||
(DiscriminatorSqmPath) getLhs().copy( context ).type()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
if ( ! entityDescriptor.hasSubclasses() ) {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
|
||||
/**
|
||||
* Indicates an attempt to call {@link QueryProducer#createMutationQuery(String)},
|
||||
* {@link QueryProducer#createNamedMutationQuery(String)} or
|
||||
|
@ -16,8 +14,12 @@ import org.hibernate.QueryException;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IllegalMutationQueryException extends QueryException {
|
||||
public class IllegalMutationQueryException extends IllegalQueryOperationException {
|
||||
public IllegalMutationQueryException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public IllegalMutationQueryException(String message, String queryString) {
|
||||
super( message, queryString, null );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,20 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
|
||||
/**
|
||||
* Indicates an attempt to call {@link QueryProducer#createSelectionQuery(String)}
|
||||
* with a non-selection query (generally a mutation query)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IllegalSelectQueryException extends QueryException {
|
||||
public class IllegalSelectQueryException extends IllegalQueryOperationException {
|
||||
public IllegalSelectQueryException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public IllegalSelectQueryException(String message, String queryString) {
|
||||
super( message, queryString );
|
||||
super( message, queryString, null );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,17 +12,17 @@ import java.math.BigInteger;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.hql.HqlInterpretationException;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||
|
@ -31,6 +31,8 @@ import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
|||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -55,6 +57,11 @@ public class FullyQualifiedReflectivePathTerminal
|
|||
this.expressibleType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullyQualifiedReflectivePathTerminal copy(SqmCopyContext context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Function<SemanticQueryWalker, ?> resolveTerminalSemantic() {
|
||||
return semanticQueryWalker -> {
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.query.spi;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
@ -22,6 +24,9 @@ import jakarta.persistence.LockModeType;
|
|||
import jakarta.persistence.NoResultException;
|
||||
import jakarta.persistence.Parameter;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.TupleElement;
|
||||
import jakarta.persistence.criteria.CompoundSelection;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
|
@ -31,18 +36,36 @@ import org.hibernate.LockOptions;
|
|||
import org.hibernate.NonUniqueResultException;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.TypeMismatchException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.graph.spi.AppliedGraph;
|
||||
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.IllegalQueryOperationException;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.QueryTypeMismatchException;
|
||||
import org.hibernate.query.SelectionQuery;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.internal.ScrollableResultsIterator;
|
||||
import org.hibernate.query.named.NamedQueryMemento;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||
import org.hibernate.sql.exec.internal.CallbackImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
import org.hibernate.sql.results.internal.TupleMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE;
|
||||
|
@ -68,6 +91,64 @@ public abstract class AbstractSelectionQuery<R>
|
|||
super( session );
|
||||
}
|
||||
|
||||
protected TupleMetadata buildTupleMetadata(SqmStatement<?> statement, Class<R> resultType) {
|
||||
if ( resultType != null && Tuple.class.isAssignableFrom( resultType ) ) {
|
||||
final List<SqmSelection<?>> selections = ( (SqmSelectStatement<?>) statement ).getQueryPart()
|
||||
.getFirstQuerySpec()
|
||||
.getSelectClause()
|
||||
.getSelections();
|
||||
// resultType is Tuple..
|
||||
if ( getQueryOptions().getTupleTransformer() == null ) {
|
||||
final Map<TupleElement<?>, Integer> tupleElementMap;
|
||||
if ( selections.size() == 1 && selections.get( 0 ).getSelectableNode() instanceof CompoundSelection<?> ) {
|
||||
final List<? extends JpaSelection<?>> selectionItems = selections.get( 0 )
|
||||
.getSelectableNode()
|
||||
.getSelectionItems();
|
||||
tupleElementMap = new IdentityHashMap<>( selectionItems.size() );
|
||||
for ( int i = 0; i < selectionItems.size(); i++ ) {
|
||||
tupleElementMap.put( selectionItems.get( i ), i );
|
||||
}
|
||||
}
|
||||
else {
|
||||
tupleElementMap = new IdentityHashMap<>( selections.size() );
|
||||
for ( int i = 0; i < selections.size(); i++ ) {
|
||||
final SqmSelection<?> selection = selections.get( i );
|
||||
tupleElementMap.put( selection.getSelectableNode(), i );
|
||||
}
|
||||
}
|
||||
return new TupleMetadata( tupleElementMap );
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"Illegal combination of Tuple resultType and (non-JpaTupleBuilder) TupleTransformer : " +
|
||||
getQueryOptions().getTupleTransformer()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void applyOptions(NamedHqlQueryMemento memento) {
|
||||
applyOptions( (NamedQueryMemento) memento );
|
||||
|
||||
if ( memento.getFirstResult() != null ) {
|
||||
setFirstResult( memento.getFirstResult() );
|
||||
}
|
||||
|
||||
if ( memento.getMaxResults() != null ) {
|
||||
setMaxResults( memento.getMaxResults() );
|
||||
}
|
||||
|
||||
if ( memento.getParameterTypes() != null ) {
|
||||
for ( Map.Entry<String, String> entry : memento.getParameterTypes().entrySet() ) {
|
||||
final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( entry.getKey() );
|
||||
final BasicType<?> type = getSessionFactory().getTypeConfiguration()
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( entry.getValue() );
|
||||
parameter.applyAnticipatedType( type );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyOptions(NamedQueryMemento memento) {
|
||||
if ( memento.getHints() != null ) {
|
||||
memento.getHints().forEach( this::applyHint );
|
||||
|
@ -106,6 +187,143 @@ public abstract class AbstractSelectionQuery<R>
|
|||
}
|
||||
}
|
||||
|
||||
protected void visitQueryReturnType(
|
||||
SqmQueryPart<R> queryPart,
|
||||
Class<R> resultType,
|
||||
SessionFactoryImplementor factory) {
|
||||
if ( queryPart instanceof SqmQuerySpec<?> ) {
|
||||
final SqmQuerySpec<R> sqmQuerySpec = (SqmQuerySpec<R>) queryPart;
|
||||
final List<SqmSelection<?>> sqmSelections = sqmQuerySpec.getSelectClause().getSelections();
|
||||
|
||||
if ( sqmSelections == null || sqmSelections.isEmpty() ) {
|
||||
// make sure there is at least one root
|
||||
final List<SqmRoot<?>> sqmRoots = sqmQuerySpec.getFromClause().getRoots();
|
||||
if ( sqmRoots == null || sqmRoots.isEmpty() ) {
|
||||
throw new IllegalArgumentException( "Criteria did not define any query roots" );
|
||||
}
|
||||
// if there is a single root, use that as the selection
|
||||
if ( sqmRoots.size() == 1 ) {
|
||||
final SqmRoot<?> sqmRoot = sqmRoots.get( 0 );
|
||||
sqmQuerySpec.getSelectClause().add( sqmRoot, null );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( );
|
||||
}
|
||||
}
|
||||
|
||||
if ( resultType != null ) {
|
||||
checkQueryReturnType( sqmQuerySpec, resultType, factory );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final SqmQueryGroup<R> queryGroup = (SqmQueryGroup<R>) queryPart;
|
||||
for ( SqmQueryPart<R> sqmQueryPart : queryGroup.getQueryParts() ) {
|
||||
visitQueryReturnType( sqmQueryPart, resultType, factory );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static <T> void checkQueryReturnType(
|
||||
SqmQuerySpec<T> querySpec,
|
||||
Class<T> resultClass,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
if ( resultClass == null ) {
|
||||
// nothing to check
|
||||
return;
|
||||
}
|
||||
|
||||
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
|
||||
|
||||
if ( resultClass.isArray() ) {
|
||||
// todo (6.0) : implement
|
||||
}
|
||||
else if ( Tuple.class.isAssignableFrom( resultClass ) ) {
|
||||
// todo (6.0) : implement
|
||||
}
|
||||
else {
|
||||
final boolean jpaQueryComplianceEnabled = sessionFactory.getSessionFactoryOptions()
|
||||
.getJpaCompliance()
|
||||
.isJpaQueryComplianceEnabled();
|
||||
if ( selections.size() != 1 ) {
|
||||
final String errorMessage = "Query result-type error - multiple selections: use Tuple or array";
|
||||
|
||||
if ( jpaQueryComplianceEnabled ) {
|
||||
throw new IllegalArgumentException( errorMessage );
|
||||
}
|
||||
else {
|
||||
throw new QueryTypeMismatchException( errorMessage );
|
||||
}
|
||||
}
|
||||
|
||||
final SqmSelection<?> sqmSelection = selections.get( 0 );
|
||||
|
||||
if ( sqmSelection.getSelectableNode() instanceof SqmParameter ) {
|
||||
final SqmParameter<?> sqmParameter = (SqmParameter<?>) sqmSelection.getSelectableNode();
|
||||
|
||||
// we may not yet know a selection type
|
||||
if ( sqmParameter.getNodeType() == null || sqmParameter.getNodeType().getExpressibleJavaType() == null ) {
|
||||
// we can't verify the result type up front
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( jpaQueryComplianceEnabled ) {
|
||||
return;
|
||||
}
|
||||
verifyResultType( resultClass, sqmSelection.getNodeType(), sessionFactory );
|
||||
}
|
||||
}
|
||||
|
||||
protected static <T> void verifyResultType(
|
||||
Class<T> resultClass,
|
||||
SqmExpressible<?> sqmExpressible,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
assert sqmExpressible != null;
|
||||
assert sqmExpressible.getExpressibleJavaType() != null;
|
||||
final Class<?> javaTypeClass = sqmExpressible.getExpressibleJavaType().getJavaTypeClass();
|
||||
if ( !resultClass.isAssignableFrom( javaTypeClass ) ) {
|
||||
// Special case for date because we always report java.util.Date as expression type
|
||||
// But the expected resultClass could be a subtype of that, so we need to check the JdbcType
|
||||
if ( javaTypeClass == Date.class ) {
|
||||
JdbcType jdbcType = null;
|
||||
if ( sqmExpressible instanceof BasicDomainType<?> ) {
|
||||
jdbcType = ( (BasicDomainType<?>) sqmExpressible).getJdbcType();
|
||||
}
|
||||
else if ( sqmExpressible instanceof SqmPathSource<?> ) {
|
||||
final DomainType<?> domainType = ( (SqmPathSource<?>) sqmExpressible).getSqmPathType();
|
||||
if ( domainType instanceof BasicDomainType<?> ) {
|
||||
jdbcType = ( (BasicDomainType<?>) domainType ).getJdbcType();
|
||||
}
|
||||
}
|
||||
if ( jdbcType != null ) {
|
||||
switch ( jdbcType.getJdbcTypeCode() ) {
|
||||
case Types.DATE:
|
||||
if ( resultClass.isAssignableFrom( java.sql.Date.class ) ) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Types.TIME:
|
||||
if ( resultClass.isAssignableFrom( java.sql.Time.class ) ) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Types.TIMESTAMP:
|
||||
if ( resultClass.isAssignableFrom( java.sql.Timestamp.class ) ) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final String errorMessage = String.format(
|
||||
"Specified result type [%s] did not match Query selection type [%s] - multiple selections: use Tuple or array",
|
||||
resultClass.getName(),
|
||||
sqmExpressible.getExpressibleJavaType().getJavaType().getTypeName()
|
||||
);
|
||||
throw new QueryTypeMismatchException( errorMessage );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// execution
|
||||
|
@ -686,4 +904,8 @@ public abstract class AbstractSelectionQuery<R>
|
|||
super.setProperties( bean );
|
||||
return this;
|
||||
}
|
||||
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return getSession().getFactory();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.ReturnableType;
|
||||
|
@ -13,6 +14,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmAggregateFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
||||
|
@ -43,6 +45,34 @@ public class SelfRenderingSqmAggregateFunction<T> extends SelfRenderingSqmFuncti
|
|||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelfRenderingSqmAggregateFunction<T> copy(SqmCopyContext context) {
|
||||
final SelfRenderingSqmAggregateFunction<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final List<SqmTypedNode<?>> arguments = new ArrayList<>( getArguments().size() );
|
||||
for ( SqmTypedNode<?> argument : getArguments() ) {
|
||||
arguments.add( argument.copy( context ) );
|
||||
}
|
||||
final SelfRenderingSqmAggregateFunction<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SelfRenderingSqmAggregateFunction<>(
|
||||
getFunctionDescriptor(),
|
||||
getRenderingSupport(),
|
||||
arguments,
|
||||
filter == null ? null : filter.copy( context ),
|
||||
getImpliedResultType(),
|
||||
getArgumentsValidator(),
|
||||
getReturnTypeResolver(),
|
||||
nodeBuilder(),
|
||||
getFunctionName()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
|
||||
final ReturnableType<?> resultType = resolveResultType(
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.query.sqm.SqmExpressible;
|
|||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
|
@ -52,14 +53,49 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
this.returnTypeResolver = returnTypeResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelfRenderingSqmFunction<T> copy(SqmCopyContext context) {
|
||||
final SelfRenderingSqmFunction<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final List<SqmTypedNode<?>> arguments = new ArrayList<>( getArguments().size() );
|
||||
for ( SqmTypedNode<?> argument : getArguments() ) {
|
||||
arguments.add( argument.copy( context ) );
|
||||
}
|
||||
final SelfRenderingSqmFunction<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SelfRenderingSqmFunction<>(
|
||||
getFunctionDescriptor(),
|
||||
getRenderingSupport(),
|
||||
arguments,
|
||||
getImpliedResultType(),
|
||||
getArgumentsValidator(),
|
||||
getReturnTypeResolver(),
|
||||
nodeBuilder(),
|
||||
getFunctionName()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public FunctionRenderingSupport getRenderingSupport() {
|
||||
return renderingSupport;
|
||||
}
|
||||
|
||||
protected ReturnableType<T> getImpliedResultType() {
|
||||
return impliedResultType;
|
||||
}
|
||||
|
||||
protected ArgumentsValidator getArgumentsValidator() {
|
||||
return argumentsValidator;
|
||||
}
|
||||
|
||||
protected FunctionReturnTypeResolver getReturnTypeResolver() {
|
||||
return returnTypeResolver;
|
||||
}
|
||||
|
||||
protected static List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) {
|
||||
if ( sqmArguments == null || sqmArguments.isEmpty() ) {
|
||||
return emptyList();
|
||||
|
|
|
@ -85,12 +85,13 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
String hql,
|
||||
DomainParameterXref domainParameterXref,
|
||||
Class<R> resultType,
|
||||
TupleMetadata tupleMetadata,
|
||||
QueryOptions queryOptions) {
|
||||
this.sqm = sqm;
|
||||
this.hql = hql;
|
||||
this.domainParameterXref = domainParameterXref;
|
||||
|
||||
this.rowTransformer = determineRowTransformer( sqm, resultType, queryOptions );
|
||||
this.rowTransformer = determineRowTransformer( sqm, resultType, tupleMetadata, queryOptions );
|
||||
|
||||
this.listInterpreter = (unused, executionContext, sqmInterpretation, jdbcParameterBindings) -> {
|
||||
final SharedSessionContractImplementor session = executionContext.getSession();
|
||||
|
@ -178,6 +179,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
private RowTransformer<R> determineRowTransformer(
|
||||
SqmSelectStatement<?> sqm,
|
||||
Class<R> resultType,
|
||||
TupleMetadata tupleMetadata,
|
||||
QueryOptions queryOptions) {
|
||||
if ( resultType == null || resultType.isArray() ) {
|
||||
if ( queryOptions.getTupleTransformer() != null ) {
|
||||
|
@ -191,27 +193,10 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
// NOTE : if we get here, a result-type of some kind (other than Object[].class) was specified
|
||||
|
||||
final List<SqmSelection<?>> selections = sqm.getQueryPart().getFirstQuerySpec().getSelectClause().getSelections();
|
||||
if ( Tuple.class.isAssignableFrom( resultType ) ) {
|
||||
if ( tupleMetadata != null ) {
|
||||
// resultType is Tuple..
|
||||
if ( queryOptions.getTupleTransformer() == null ) {
|
||||
final Map<TupleElement<?>, Integer> tupleElementMap;
|
||||
if ( selections.size() == 1 && selections.get( 0 ).getSelectableNode() instanceof CompoundSelection<?> ) {
|
||||
final List<? extends JpaSelection<?>> selectionItems = selections.get( 0 )
|
||||
.getSelectableNode()
|
||||
.getSelectionItems();
|
||||
tupleElementMap = new IdentityHashMap<>( selectionItems.size() );
|
||||
for ( int i = 0; i < selectionItems.size(); i++ ) {
|
||||
tupleElementMap.put( selectionItems.get( i ), i );
|
||||
}
|
||||
}
|
||||
else {
|
||||
tupleElementMap = new IdentityHashMap<>( selections.size() );
|
||||
for ( int i = 0; i < selections.size(); i++ ) {
|
||||
final SqmSelection<?> selection = selections.get( i );
|
||||
tupleElementMap.put( selection.getSelectableNode(), i );
|
||||
}
|
||||
}
|
||||
return (RowTransformer<R>) new RowTransformerJpaTupleImpl( new TupleMetadata( tupleElementMap ) );
|
||||
return (RowTransformer<R>) new RowTransformerJpaTupleImpl( tupleMetadata );
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -77,7 +78,6 @@ import org.hibernate.query.spi.QueryEngine;
|
|||
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||
import org.hibernate.query.spi.SelectQueryPlan;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
|
@ -85,6 +85,7 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
|
@ -103,7 +104,7 @@ import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
|||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.sql.results.internal.TupleMetadata;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
|
||||
|
@ -135,7 +136,7 @@ public class QuerySqmImpl<R>
|
|||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QuerySqmImpl.class );
|
||||
|
||||
private final String hql;
|
||||
private final SqmStatement<?> sqm;
|
||||
private final SqmStatement<R> sqm;
|
||||
|
||||
private final ParameterMetadataImplementor parameterMetadata;
|
||||
private final DomainParameterXref domainParameterXref;
|
||||
|
@ -143,6 +144,7 @@ public class QuerySqmImpl<R>
|
|||
private final QueryParameterBindingsImpl parameterBindings;
|
||||
|
||||
private final Class<R> resultType;
|
||||
private final TupleMetadata tupleMetadata;
|
||||
|
||||
/**
|
||||
* Creates a Query instance from a named HQL memento
|
||||
|
@ -171,31 +173,11 @@ public class QuerySqmImpl<R>
|
|||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
|
||||
validateStatement( sqm, resultType );
|
||||
setComment( hql );
|
||||
|
||||
applyOptions( memento );
|
||||
}
|
||||
|
||||
protected void applyOptions(NamedHqlQueryMemento memento) {
|
||||
super.applyOptions( memento );
|
||||
|
||||
if ( memento.getFirstResult() != null ) {
|
||||
setFirstResult( memento.getFirstResult() );
|
||||
}
|
||||
|
||||
if ( memento.getMaxResults() != null ) {
|
||||
setMaxResults( memento.getMaxResults() );
|
||||
}
|
||||
|
||||
if ( memento.getParameterTypes() != null ) {
|
||||
for ( Map.Entry<String, String> entry : memento.getParameterTypes().entrySet() ) {
|
||||
final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( entry.getKey() );
|
||||
final BasicType<?> type = getSessionFactory().getTypeConfiguration()
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( entry.getValue() );
|
||||
parameter.applyAnticipatedType( type );
|
||||
}
|
||||
}
|
||||
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -218,24 +200,10 @@ public class QuerySqmImpl<R>
|
|||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
|
||||
validateStatement( sqm, resultType );
|
||||
setComment( hql );
|
||||
|
||||
//noinspection rawtypes
|
||||
final SqmStatement sqmStatement = hqlInterpretation.getSqmStatement();
|
||||
if ( resultType != null ) {
|
||||
SqmUtil.verifyIsSelectStatement( sqmStatement, hql );
|
||||
visitQueryReturnType(
|
||||
( (SqmSelectStatement<R>) sqmStatement ).getQueryPart(),
|
||||
resultType,
|
||||
session.getFactory()
|
||||
);
|
||||
}
|
||||
else if ( sqmStatement instanceof SqmUpdateStatement<?> ) {
|
||||
verifyImmutableEntityUpdate( hql, (SqmUpdateStatement<R>) sqmStatement, session.getFactory() );
|
||||
}
|
||||
else if ( sqmStatement instanceof SqmInsertStatement<?> ) {
|
||||
verifyInsertTypesMatch( hql, (SqmInsertStatement<R>) sqmStatement );
|
||||
}
|
||||
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,11 +215,16 @@ public class QuerySqmImpl<R>
|
|||
SharedSessionContractImplementor producer) {
|
||||
super( producer );
|
||||
this.hql = CRITERIA_HQL_STRING;
|
||||
this.sqm = criteria;
|
||||
if ( producer.isJpaCriteriaCopyComplianceEnabled() ) {
|
||||
this.sqm = criteria.copy( SqmCopyContext.simpleContext() );
|
||||
}
|
||||
else {
|
||||
this.sqm = criteria;
|
||||
}
|
||||
|
||||
setComment( hql );
|
||||
|
||||
this.domainParameterXref = DomainParameterXref.from( criteria );
|
||||
this.domainParameterXref = DomainParameterXref.from( this.sqm );
|
||||
if ( ! domainParameterXref.hasParameters() ) {
|
||||
this.parameterMetadata = ParameterMetadataImpl.EMPTY;
|
||||
}
|
||||
|
@ -275,7 +248,7 @@ public class QuerySqmImpl<R>
|
|||
}
|
||||
}
|
||||
|
||||
if ( resultType != null ) {
|
||||
if ( sqm instanceof SqmSelectStatement<?> ) {
|
||||
SqmUtil.verifyIsSelectStatement( sqm, null );
|
||||
final SqmQueryPart<R> queryPart = ( (SqmSelectStatement<R>) sqm ).getQueryPart();
|
||||
// For criteria queries, we have to validate the fetch structure here
|
||||
|
@ -286,154 +259,56 @@ public class QuerySqmImpl<R>
|
|||
producer.getFactory()
|
||||
);
|
||||
}
|
||||
else if ( sqm instanceof SqmUpdateStatement<?> ) {
|
||||
final SqmUpdateStatement<R> updateStatement = (SqmUpdateStatement<R>) sqm;
|
||||
verifyImmutableEntityUpdate( CRITERIA_HQL_STRING, updateStatement, producer.getFactory() );
|
||||
if ( updateStatement.getSetClause() == null || updateStatement.getSetClause().getAssignments().isEmpty() ) {
|
||||
throw new IllegalArgumentException( "No assignments specified as part of UPDATE criteria" );
|
||||
else {
|
||||
if ( resultType != null ) {
|
||||
throw new IllegalQueryOperationException(
|
||||
"Result type given for a non-SELECT Query",
|
||||
hql,
|
||||
null
|
||||
);
|
||||
}
|
||||
if ( sqm instanceof SqmUpdateStatement<?> ) {
|
||||
final SqmUpdateStatement<R> updateStatement = (SqmUpdateStatement<R>) sqm;
|
||||
verifyImmutableEntityUpdate( CRITERIA_HQL_STRING, updateStatement, producer.getFactory() );
|
||||
if ( updateStatement.getSetClause() == null || updateStatement.getSetClause()
|
||||
.getAssignments()
|
||||
.isEmpty() ) {
|
||||
throw new IllegalArgumentException( "No assignments specified as part of UPDATE criteria" );
|
||||
}
|
||||
}
|
||||
else if ( sqm instanceof SqmInsertStatement<?> ) {
|
||||
verifyInsertTypesMatch( CRITERIA_HQL_STRING, (SqmInsertStatement<R>) sqm );
|
||||
}
|
||||
}
|
||||
else if ( sqm instanceof SqmInsertStatement<?> ) {
|
||||
verifyInsertTypesMatch( CRITERIA_HQL_STRING, (SqmInsertStatement<R>) sqm );
|
||||
}
|
||||
|
||||
this.resultType = resultType;
|
||||
this.tupleMetadata = buildTupleMetadata( criteria, resultType );
|
||||
}
|
||||
|
||||
private void visitQueryReturnType(
|
||||
SqmQueryPart<R> queryPart,
|
||||
Class<R> resultType,
|
||||
SessionFactoryImplementor factory) {
|
||||
if ( queryPart instanceof SqmQuerySpec<?> ) {
|
||||
final SqmQuerySpec<R> sqmQuerySpec = (SqmQuerySpec<R>) queryPart;
|
||||
final List<SqmSelection<?>> sqmSelections = sqmQuerySpec.getSelectClause().getSelections();
|
||||
|
||||
if ( sqmSelections == null || sqmSelections.isEmpty() ) {
|
||||
// make sure there is at least one root
|
||||
final List<SqmRoot<?>> sqmRoots = sqmQuerySpec.getFromClause().getRoots();
|
||||
if ( sqmRoots == null || sqmRoots.isEmpty() ) {
|
||||
throw new IllegalArgumentException( "Criteria did not define any query roots" );
|
||||
}
|
||||
// if there is a single root, use that as the selection
|
||||
if ( sqmRoots.size() == 1 ) {
|
||||
final SqmRoot<?> sqmRoot = sqmRoots.get( 0 );
|
||||
sqmQuerySpec.getSelectClause().add( sqmRoot, null );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( );
|
||||
}
|
||||
}
|
||||
|
||||
if ( resultType != null ) {
|
||||
checkQueryReturnType( sqmQuerySpec, resultType, factory );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final SqmQueryGroup<R> queryGroup = (SqmQueryGroup<R>) queryPart;
|
||||
for ( SqmQueryPart<R> sqmQueryPart : queryGroup.getQueryParts() ) {
|
||||
visitQueryReturnType( sqmQueryPart, resultType, factory );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void checkQueryReturnType(
|
||||
SqmQuerySpec<T> querySpec,
|
||||
Class<T> resultClass,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
if ( resultClass == null ) {
|
||||
// nothing to check
|
||||
return;
|
||||
}
|
||||
|
||||
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
|
||||
|
||||
if ( resultClass.isArray() ) {
|
||||
// todo (6.0) : implement
|
||||
}
|
||||
else if ( Tuple.class.isAssignableFrom( resultClass ) ) {
|
||||
// todo (6.0) : implement
|
||||
}
|
||||
else {
|
||||
final boolean jpaQueryComplianceEnabled = sessionFactory.getSessionFactoryOptions()
|
||||
.getJpaCompliance()
|
||||
.isJpaQueryComplianceEnabled();
|
||||
if ( selections.size() != 1 ) {
|
||||
final String errorMessage = "Query result-type error - multiple selections: use Tuple or array";
|
||||
|
||||
if ( jpaQueryComplianceEnabled ) {
|
||||
throw new IllegalArgumentException( errorMessage );
|
||||
}
|
||||
else {
|
||||
throw new QueryTypeMismatchException( errorMessage );
|
||||
}
|
||||
}
|
||||
|
||||
final SqmSelection<?> sqmSelection = selections.get( 0 );
|
||||
|
||||
if ( sqmSelection.getSelectableNode() instanceof SqmParameter ) {
|
||||
final SqmParameter<?> sqmParameter = (SqmParameter<?>) sqmSelection.getSelectableNode();
|
||||
|
||||
// we may not yet know a selection type
|
||||
if ( sqmParameter.getNodeType() == null || sqmParameter.getNodeType().getExpressibleJavaType() == null ) {
|
||||
// we can't verify the result type up front
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( jpaQueryComplianceEnabled ) {
|
||||
return;
|
||||
}
|
||||
verifyResultType( resultClass, sqmSelection.getNodeType(), sessionFactory );
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void verifyResultType(
|
||||
Class<T> resultClass,
|
||||
SqmExpressible<?> sqmExpressible,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
assert sqmExpressible != null;
|
||||
assert sqmExpressible.getExpressibleJavaType() != null;
|
||||
final Class<?> javaTypeClass = sqmExpressible.getExpressibleJavaType().getJavaTypeClass();
|
||||
if ( !resultClass.isAssignableFrom( javaTypeClass ) ) {
|
||||
// Special case for date because we always report java.util.Date as expression type
|
||||
// But the expected resultClass could be a subtype of that, so we need to check the JdbcType
|
||||
if ( javaTypeClass == Date.class ) {
|
||||
JdbcType jdbcType = null;
|
||||
if ( sqmExpressible instanceof BasicDomainType<?> ) {
|
||||
jdbcType = ( (BasicDomainType<?>) sqmExpressible).getJdbcType();
|
||||
}
|
||||
else if ( sqmExpressible instanceof SqmPathSource<?> ) {
|
||||
final DomainType<?> domainType = ( (SqmPathSource<?>) sqmExpressible).getSqmPathType();
|
||||
if ( domainType instanceof BasicDomainType<?> ) {
|
||||
jdbcType = ( (BasicDomainType<?>) domainType ).getJdbcType();
|
||||
}
|
||||
}
|
||||
if ( jdbcType != null ) {
|
||||
switch ( jdbcType.getJdbcTypeCode() ) {
|
||||
case Types.DATE:
|
||||
if ( resultClass.isAssignableFrom( java.sql.Date.class ) ) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Types.TIME:
|
||||
if ( resultClass.isAssignableFrom( java.sql.Time.class ) ) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Types.TIMESTAMP:
|
||||
if ( resultClass.isAssignableFrom( java.sql.Timestamp.class ) ) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final String errorMessage = String.format(
|
||||
"Specified result type [%s] did not match Query selection type [%s] - multiple selections: use Tuple or array",
|
||||
resultClass.getName(),
|
||||
sqmExpressible.getExpressibleJavaType().getJavaType().getTypeName()
|
||||
private void validateStatement(SqmStatement<R> sqmStatement, Class<R> resultType) {
|
||||
if ( sqmStatement instanceof SqmSelectStatement<?> ) {
|
||||
SqmUtil.verifyIsSelectStatement( sqmStatement, hql );
|
||||
visitQueryReturnType(
|
||||
( (SqmSelectStatement<R>) sqmStatement ).getQueryPart(),
|
||||
resultType,
|
||||
getSessionFactory()
|
||||
);
|
||||
throw new QueryTypeMismatchException( errorMessage );
|
||||
}
|
||||
else {
|
||||
if ( resultType != null ) {
|
||||
throw new IllegalQueryOperationException(
|
||||
"Result type given for a non-SELECT Query",
|
||||
hql,
|
||||
null
|
||||
);
|
||||
}
|
||||
if ( sqmStatement instanceof SqmUpdateStatement<?> ) {
|
||||
SqmUpdateStatement<R> updateStatement = (SqmUpdateStatement<R>) sqmStatement;
|
||||
verifyImmutableEntityUpdate( hql, updateStatement, getSessionFactory() );
|
||||
}
|
||||
else if ( sqmStatement instanceof SqmInsertStatement<?> ) {
|
||||
verifyInsertTypesMatch( hql, (SqmInsertStatement<R>) sqmStatement );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,10 +423,6 @@ public class QuerySqmImpl<R>
|
|||
return parameterBindings;
|
||||
}
|
||||
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return getSession().getFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameterBindings getParameterBindings() {
|
||||
return getQueryParameterBindings();
|
||||
|
@ -739,6 +610,7 @@ public class QuerySqmImpl<R>
|
|||
getQueryString(),
|
||||
getDomainParameterXref(),
|
||||
resultType,
|
||||
tupleMetadata,
|
||||
queryOptions
|
||||
);
|
||||
}
|
||||
|
|
|
@ -56,11 +56,13 @@ import org.hibernate.query.spi.ScrollableResultsImplementor;
|
|||
import org.hibernate.query.spi.SelectQueryPlan;
|
||||
import org.hibernate.query.sqm.SqmSelectionQuery;
|
||||
import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||
import org.hibernate.sql.results.internal.TupleMetadata;
|
||||
|
||||
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
|
||||
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE;
|
||||
|
@ -81,13 +83,14 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
public static final String CRITERIA_HQL_STRING = "<criteria>";
|
||||
|
||||
private final String hql;
|
||||
private final SqmSelectStatement<?> sqm;
|
||||
private final SqmSelectStatement<R> sqm;
|
||||
|
||||
private final ParameterMetadataImplementor parameterMetadata;
|
||||
private final DomainParameterXref domainParameterXref;
|
||||
private final QueryParameterBindingsImpl parameterBindings;
|
||||
|
||||
private final Class<R> resultType;
|
||||
private final TupleMetadata tupleMetadata;
|
||||
|
||||
public SqmSelectionQueryImpl(
|
||||
String hql,
|
||||
|
@ -95,16 +98,19 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
SharedSessionContractImplementor session) {
|
||||
super( session );
|
||||
this.hql = hql;
|
||||
this.sqm = (SqmSelectStatement<?>) hqlInterpretation.getSqmStatement();
|
||||
//noinspection unchecked
|
||||
this.sqm = (SqmSelectStatement<R>) hqlInterpretation.getSqmStatement();
|
||||
|
||||
this.parameterMetadata = hqlInterpretation.getParameterMetadata();
|
||||
this.domainParameterXref = hqlInterpretation.getDomainParameterXref();
|
||||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
|
||||
this.resultType = determineResultType( sqm );
|
||||
visitQueryReturnType( sqm.getQueryPart(), null, getSessionFactory() );
|
||||
this.resultType = null;
|
||||
|
||||
setComment( hql );
|
||||
this.tupleMetadata = null;
|
||||
}
|
||||
|
||||
public SqmSelectionQueryImpl(
|
||||
|
@ -123,51 +129,33 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
(s) -> queryEngine.getHqlTranslator().translate( hql )
|
||||
);
|
||||
|
||||
if ( !( hqlInterpretation.getSqmStatement() instanceof SqmSelectStatement ) ) {
|
||||
throw new IllegalSelectQueryException( "Expecting a selection query, but found `" + hql + "`", hql );
|
||||
}
|
||||
|
||||
this.sqm = (SqmSelectStatement<?>) hqlInterpretation.getSqmStatement();
|
||||
SqmUtil.verifyIsSelectStatement( hqlInterpretation.getSqmStatement(), hql );
|
||||
//noinspection unchecked
|
||||
this.sqm = (SqmSelectStatement<R>) hqlInterpretation.getSqmStatement();
|
||||
|
||||
this.parameterMetadata = hqlInterpretation.getParameterMetadata();
|
||||
this.domainParameterXref = hqlInterpretation.getDomainParameterXref();
|
||||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
|
||||
visitQueryReturnType( sqm.getQueryPart(), resultType, getSessionFactory() );
|
||||
setComment( hql );
|
||||
|
||||
if ( resultType != null ) {
|
||||
final Class<R> determinedResultType = determineResultType( sqm );
|
||||
if ( !resultType.isAssignableFrom( determinedResultType ) ) {
|
||||
throw new QueryTypeMismatchException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"SelectionQuery result-type error - expecting `%s`, but found `%s`",
|
||||
resultType.getName(),
|
||||
determinedResultType.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Class<T> determineResultType(SqmSelectStatement<?> sqm) {
|
||||
final List<SqmSelection<?>> selections = sqm.getQuerySpec().getSelectClause().getSelections();
|
||||
if ( selections.size() == 1 ) {
|
||||
final SqmSelection<?> sqmSelection = selections.get( 0 );
|
||||
//noinspection unchecked
|
||||
return (Class<T>) sqmSelection.getNodeJavaType().getJavaTypeClass();
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (Class<T>) Object[].class;
|
||||
applyOptions( memento );
|
||||
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
|
||||
}
|
||||
|
||||
public SqmSelectionQueryImpl(
|
||||
SqmSelectStatement<R> sqm,
|
||||
SqmSelectStatement<R> criteria,
|
||||
SharedSessionContractImplementor session) {
|
||||
super( session );
|
||||
this.hql = CRITERIA_HQL_STRING;
|
||||
this.sqm = sqm;
|
||||
if ( session.isJpaCriteriaCopyComplianceEnabled() ) {
|
||||
this.sqm = criteria.copy( SqmCopyContext.simpleContext() );
|
||||
}
|
||||
else {
|
||||
this.sqm = criteria;
|
||||
}
|
||||
|
||||
this.domainParameterXref = DomainParameterXref.from( sqm );
|
||||
if ( ! domainParameterXref.hasParameters() ) {
|
||||
|
@ -195,7 +183,21 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
|
||||
this.resultType = determineResultType( sqm );
|
||||
|
||||
visitQueryReturnType( sqm.getQueryPart(), resultType, getSessionFactory() );
|
||||
setComment( hql );
|
||||
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
|
||||
}
|
||||
|
||||
private static <T> Class<T> determineResultType(SqmSelectStatement<?> sqm) {
|
||||
final List<SqmSelection<?>> selections = sqm.getQuerySpec().getSelectClause().getSelections();
|
||||
if ( selections.size() == 1 ) {
|
||||
final SqmSelection<?> sqmSelection = selections.get( 0 );
|
||||
//noinspection unchecked
|
||||
return (Class<T>) sqmSelection.getNodeJavaType().getJavaTypeClass();
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (Class<T>) Object[].class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -217,10 +219,6 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
return parameterBindings;
|
||||
}
|
||||
|
||||
protected SessionFactoryImplementor getSessionFactory() {
|
||||
return getSession().getSessionFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return hql;
|
||||
|
@ -373,6 +371,7 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
getQueryString(),
|
||||
getDomainParameterXref(),
|
||||
resultType,
|
||||
tupleMetadata,
|
||||
queryOptions
|
||||
);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
|||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.query.IllegalQueryOperationException;
|
||||
import org.hibernate.query.IllegalSelectQueryException;
|
||||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
|
@ -78,15 +79,14 @@ public class SqmUtil {
|
|||
|
||||
public static void verifyIsSelectStatement(SqmStatement<?> sqm, String hqlString) {
|
||||
if ( ! isSelect( sqm ) ) {
|
||||
throw new IllegalQueryOperationException(
|
||||
throw new IllegalSelectQueryException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Expecting a SELECT Query [%s], but found %s",
|
||||
SqmSelectStatement.class.getName(),
|
||||
sqm.getClass().getName()
|
||||
),
|
||||
hqlString,
|
||||
null
|
||||
hqlString
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,12 @@ package org.hibernate.query.sqm.tree;
|
|||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
|
@ -22,12 +24,13 @@ import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
|||
public abstract class AbstractSqmDmlStatement<E>
|
||||
extends AbstractSqmStatement<E>
|
||||
implements SqmDmlStatement<E> {
|
||||
private final Map<String, SqmCteStatement<?>> cteStatements = new LinkedHashMap<>();
|
||||
private final Map<String, SqmCteStatement<?>> cteStatements;
|
||||
private boolean withRecursiveCte;
|
||||
private SqmRoot<E> target;
|
||||
|
||||
public AbstractSqmDmlStatement(SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super( querySource, nodeBuilder );
|
||||
this.cteStatements = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public AbstractSqmDmlStatement(SqmRoot<E> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
|
@ -35,6 +38,27 @@ public abstract class AbstractSqmDmlStatement<E>
|
|||
this.target = target;
|
||||
}
|
||||
|
||||
public AbstractSqmDmlStatement(
|
||||
NodeBuilder builder,
|
||||
SqmQuerySource querySource,
|
||||
Set<SqmParameter<?>> parameters,
|
||||
Map<String, SqmCteStatement<?>> cteStatements,
|
||||
boolean withRecursiveCte,
|
||||
SqmRoot<E> target) {
|
||||
super( builder, querySource, parameters );
|
||||
this.cteStatements = cteStatements;
|
||||
this.withRecursiveCte = withRecursiveCte;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
protected Map<String, SqmCteStatement<?>> copyCteStatements(SqmCopyContext context) {
|
||||
final Map<String, SqmCteStatement<?>> cteStatements = new LinkedHashMap<>( this.cteStatements.size() );
|
||||
for ( Map.Entry<String, SqmCteStatement<?>> entry : this.cteStatements.entrySet() ) {
|
||||
cteStatements.put( entry.getKey(), entry.getValue().copy( context ) );
|
||||
}
|
||||
return cteStatements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithRecursive() {
|
||||
return withRecursiveCte;
|
||||
|
|
|
@ -6,20 +6,25 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.criteria.JpaCriteriaBase;
|
||||
import org.hibernate.query.criteria.JpaPredicate;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
|
@ -36,6 +41,27 @@ public abstract class AbstractSqmRestrictedDmlStatement<T> extends AbstractSqmDm
|
|||
super( target, querySource, nodeBuilder );
|
||||
}
|
||||
|
||||
public AbstractSqmRestrictedDmlStatement(
|
||||
NodeBuilder builder,
|
||||
SqmQuerySource querySource,
|
||||
Set<SqmParameter<?>> parameters,
|
||||
Map<String, SqmCteStatement<?>> cteStatements,
|
||||
boolean withRecursiveCte,
|
||||
SqmRoot<T> target) {
|
||||
super( builder, querySource, parameters, cteStatements, withRecursiveCte, target );
|
||||
}
|
||||
|
||||
protected SqmWhereClause copyWhereClause(SqmCopyContext context) {
|
||||
if ( getWhereClause() == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
final SqmWhereClause whereClause = new SqmWhereClause( nodeBuilder() );
|
||||
whereClause.setPredicate( getWhereClause().getPredicate().copy( context ) );
|
||||
return whereClause;
|
||||
}
|
||||
}
|
||||
|
||||
public Root<T> from(Class<T> entityClass) {
|
||||
final EntityDomainType<T> entity = nodeBuilder().getDomainModel().entity( entityClass );
|
||||
SqmRoot<T> root = new SqmRoot<>( entity, null, false, nodeBuilder() );
|
||||
|
|
|
@ -12,15 +12,16 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.internal.ParameterCollector;
|
||||
import org.hibernate.query.sqm.internal.SqmUtil;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.internal.ParameterCollector;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmStatement<T> extends AbstractSqmNode implements SqmStatement<T>, ParameterCollector {
|
||||
private final SqmQuerySource querySource;
|
||||
private Set<SqmParameter<?>> parameters;
|
||||
|
||||
public AbstractSqmStatement(
|
||||
SqmQuerySource querySource,
|
||||
|
@ -29,7 +30,27 @@ public abstract class AbstractSqmStatement<T> extends AbstractSqmNode implements
|
|||
this.querySource = querySource;
|
||||
}
|
||||
|
||||
private Set<SqmParameter<?>> parameters;
|
||||
protected AbstractSqmStatement(
|
||||
NodeBuilder builder,
|
||||
SqmQuerySource querySource,
|
||||
Set<SqmParameter<?>> parameters) {
|
||||
super( builder );
|
||||
this.querySource = querySource;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
protected Set<SqmParameter<?>> copyParameters(SqmCopyContext context) {
|
||||
if ( parameters == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
final Set<SqmParameter<?>> parameters = new HashSet<>( this.parameters.size() );
|
||||
for ( SqmParameter<?> parameter : this.parameters ) {
|
||||
parameters.add( parameter.copy( context ) );
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmQuerySource getQuerySource() {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.tree;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface SqmCopyContext {
|
||||
|
||||
<T> T getCopy(T original);
|
||||
|
||||
<T> T registerCopy(T original, T copy);
|
||||
|
||||
static SqmCopyContext simpleContext() {
|
||||
final IdentityHashMap<Object, Object> map = new IdentityHashMap<>();
|
||||
return new SqmCopyContext() {
|
||||
@Override
|
||||
public <T> T getCopy(T original) {
|
||||
//noinspection unchecked
|
||||
return (T) map.get( original );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T registerCopy(T original, T copy) {
|
||||
final Object old = map.put( original, copy );
|
||||
if ( old != null ) {
|
||||
throw new IllegalArgumentException( "Already registered a copy: " + old );
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -25,4 +25,6 @@ public interface SqmNode extends JpaCriteriaNode {
|
|||
}
|
||||
|
||||
NodeBuilder nodeBuilder();
|
||||
|
||||
SqmNode copy(SqmCopyContext context);
|
||||
}
|
||||
|
|
|
@ -14,4 +14,6 @@ import org.hibernate.query.criteria.JpaCriteriaBase;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmQuery<T> extends JpaCriteriaBase, SqmNode {
|
||||
@Override
|
||||
SqmQuery<T> copy(SqmCopyContext context);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ public interface SqmStatement<T> extends SqmQuery<T>, JpaQueryableCriteria<T>, S
|
|||
|
||||
ParameterResolutions resolveParameters();
|
||||
|
||||
@Override
|
||||
SqmStatement<T> copy(SqmCopyContext context);
|
||||
|
||||
interface ParameterResolutions {
|
||||
ParameterResolutions EMPTY = new ParameterResolutions() {
|
||||
@Override
|
||||
|
|
|
@ -30,4 +30,7 @@ public interface SqmTypedNode<T> extends SqmNode, SqmExpressibleAccessor<T> {
|
|||
}
|
||||
|
||||
SqmExpressible<T> getNodeType();
|
||||
|
||||
@Override
|
||||
SqmTypedNode<T> copy(SqmCopyContext context);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.sql.ast.tree.cte.CteSearchClauseKind;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
|
@ -70,6 +71,55 @@ public class SqmCteStatement<T> extends AbstractSqmNode implements SqmVisitableN
|
|||
this.noCycleValue = '\0';
|
||||
}
|
||||
|
||||
private SqmCteStatement(
|
||||
NodeBuilder builder,
|
||||
SqmCteContainer cteContainer,
|
||||
SqmCteTable cteTable,
|
||||
CteMaterialization materialization,
|
||||
SqmStatement<?> cteDefinition,
|
||||
CteSearchClauseKind searchClauseKind,
|
||||
List<SqmSearchClauseSpecification> searchBySpecifications,
|
||||
List<SqmCteTableColumn> cycleColumns,
|
||||
SqmCteTableColumn cycleMarkColumn,
|
||||
char cycleValue,
|
||||
char noCycleValue) {
|
||||
super( builder );
|
||||
this.cteContainer = cteContainer;
|
||||
this.cteTable = cteTable;
|
||||
this.materialization = materialization;
|
||||
this.cteDefinition = cteDefinition;
|
||||
this.searchClauseKind = searchClauseKind;
|
||||
this.searchBySpecifications = searchBySpecifications;
|
||||
this.cycleColumns = cycleColumns;
|
||||
this.cycleMarkColumn = cycleMarkColumn;
|
||||
this.cycleValue = cycleValue;
|
||||
this.noCycleValue = noCycleValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCteStatement<T> copy(SqmCopyContext context) {
|
||||
final SqmCteStatement<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
return context.registerCopy(
|
||||
this,
|
||||
new SqmCteStatement<>(
|
||||
nodeBuilder(),
|
||||
cteContainer,
|
||||
cteTable,
|
||||
materialization,
|
||||
cteDefinition.copy( context ),
|
||||
searchClauseKind,
|
||||
searchBySpecifications,
|
||||
cycleColumns,
|
||||
cycleMarkColumn,
|
||||
cycleValue,
|
||||
noCycleValue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public SqmCteTable getCteTable() {
|
||||
return cteTable;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.io.Serializable;
|
|||
|
||||
import org.hibernate.query.sqm.NullPrecedence;
|
||||
import org.hibernate.query.sqm.SortOrder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
|
@ -25,6 +26,14 @@ public class SqmSearchClauseSpecification implements Serializable {
|
|||
this.nullPrecedence = nullPrecedence;
|
||||
}
|
||||
|
||||
public SqmSearchClauseSpecification copy(SqmCopyContext context) {
|
||||
return new SqmSearchClauseSpecification(
|
||||
cteColumn,
|
||||
sortOrder,
|
||||
nullPrecedence
|
||||
);
|
||||
}
|
||||
|
||||
public SqmCteTableColumn getCteColumn() {
|
||||
return cteColumn;
|
||||
}
|
||||
|
|
|
@ -6,16 +6,23 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.delete;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.query.criteria.JpaCriteriaDelete;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmRestrictedDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -41,6 +48,37 @@ public class SqmDeleteStatement<T>
|
|||
);
|
||||
}
|
||||
|
||||
public SqmDeleteStatement(
|
||||
NodeBuilder builder,
|
||||
SqmQuerySource querySource,
|
||||
Set<SqmParameter<?>> parameters,
|
||||
Map<String, SqmCteStatement<?>> cteStatements,
|
||||
boolean withRecursiveCte,
|
||||
SqmRoot<T> target) {
|
||||
super( builder, querySource, parameters, cteStatements, withRecursiveCte, target );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDeleteStatement<T> copy(SqmCopyContext context) {
|
||||
final SqmDeleteStatement<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmDeleteStatement<T> statement = context.registerCopy(
|
||||
this,
|
||||
new SqmDeleteStatement<>(
|
||||
nodeBuilder(),
|
||||
getQuerySource(),
|
||||
copyParameters( context ),
|
||||
copyCteStatements( context ),
|
||||
isWithRecursive(),
|
||||
getTarget().copy( context )
|
||||
)
|
||||
);
|
||||
statement.setWhereClause( copyWhereClause( context ) );
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDeleteStatement<T> where(Expression<Boolean> restriction) {
|
||||
setWhere( restriction );
|
||||
|
|
|
@ -6,19 +6,16 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.criteria.JpaPredicate;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmJoinable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
@ -27,6 +24,10 @@ import org.hibernate.type.descriptor.java.JavaType;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* Models a join based on a mapped attribute reference.
|
||||
*
|
||||
|
@ -79,6 +80,11 @@ public abstract class AbstractSqmAttributeJoin<O,T>
|
|||
this.fetched = fetched;
|
||||
}
|
||||
|
||||
protected void copyTo(AbstractSqmAttributeJoin<O, T> target, SqmCopyContext context) {
|
||||
super.copyTo( target, context );
|
||||
this.onClausePredicate = onClausePredicate == null ? null : onClausePredicate.copy( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFrom<?, O> getLhs() {
|
||||
//noinspection unchecked
|
||||
|
|
|
@ -14,15 +14,6 @@ import java.util.Objects;
|
|||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import jakarta.persistence.criteria.Fetch;
|
||||
import jakarta.persistence.criteria.Join;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.metamodel.CollectionAttribute;
|
||||
import jakarta.persistence.metamodel.ListAttribute;
|
||||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.persistence.metamodel.PluralAttribute;
|
||||
import jakarta.persistence.metamodel.SetAttribute;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
||||
|
@ -34,14 +25,16 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.criteria.JpaEntityJoin;
|
||||
import org.hibernate.query.criteria.JpaPath;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
|
@ -50,6 +43,16 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
|
|||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
import jakarta.persistence.criteria.Fetch;
|
||||
import jakarta.persistence.criteria.Join;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.metamodel.CollectionAttribute;
|
||||
import jakarta.persistence.metamodel.ListAttribute;
|
||||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.persistence.metamodel.PluralAttribute;
|
||||
import jakarta.persistence.metamodel.SetAttribute;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
|
||||
/**
|
||||
* Convenience base class for SqmFrom implementations
|
||||
*
|
||||
|
@ -115,6 +118,22 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
super( navigablePath, referencedNavigable, null, nodeBuilder );
|
||||
}
|
||||
|
||||
protected void copyTo(AbstractSqmFrom<O, T> target, SqmCopyContext context) {
|
||||
super.copyTo( target, context );
|
||||
if ( joins != null ) {
|
||||
target.joins = new ArrayList<>( joins.size() );
|
||||
for ( SqmJoin<T, ?> join : joins ) {
|
||||
target.joins.add( join.copy( context ) );
|
||||
}
|
||||
}
|
||||
if ( treats != null ) {
|
||||
target.treats = new ArrayList<>( treats.size() );
|
||||
for ( SqmFrom<?, ?> treat : treats ) {
|
||||
target.treats.add( treat.copy( context ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitAlias() {
|
||||
return alias;
|
||||
|
|
|
@ -21,8 +21,11 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
|||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -48,6 +51,16 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
this.lhs = lhs;
|
||||
}
|
||||
|
||||
protected void copyTo(AbstractSqmPath<T> target, SqmCopyContext context) {
|
||||
super.copyTo( target, context );
|
||||
if ( reusablePaths != null ) {
|
||||
target.reusablePaths = new HashMap<>( reusablePaths.size() );
|
||||
for ( Map.Entry<String, SqmPath<?>> entry : reusablePaths.entrySet() ) {
|
||||
target.reusablePaths.put( entry.getKey(), entry.getValue().copy( context ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<T> getNodeType() {
|
||||
return (SqmPathSource<T>) super.getNodeType();
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.PathException;
|
||||
|
@ -15,6 +13,9 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
|
@ -30,7 +31,27 @@ public class NonAggregatedCompositeSimplePath<T> extends SqmEntityValuedSimplePa
|
|||
|
||||
assert referencedPathSource.getSqmPathType() instanceof EntityType;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NonAggregatedCompositeSimplePath<T> copy(SqmCopyContext context) {
|
||||
final NonAggregatedCompositeSimplePath<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final NonAggregatedCompositeSimplePath<T> path = context.registerCopy(
|
||||
this,
|
||||
new NonAggregatedCompositeSimplePath<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getLhs().copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> resolvePathPart(
|
||||
String name,
|
||||
|
|
|
@ -11,10 +11,11 @@ import org.hibernate.metamodel.model.domain.AnyMappingDomainType;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.PathException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -42,6 +43,27 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
assert referencedPathSource.getSqmPathType() instanceof AnyMappingDomainType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAnyValuedSimplePath<T> copy(SqmCopyContext context) {
|
||||
final SqmAnyValuedSimplePath<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmAnyValuedSimplePath<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmAnyValuedSimplePath<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getLhs().copy( context ),
|
||||
getExplicitAlias(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedPath<T, S> treatAs(Class<S> treatJavaType) throws PathException {
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
|
@ -18,10 +16,14 @@ import org.hibernate.query.criteria.JpaExpression;
|
|||
import org.hibernate.query.criteria.JpaPredicate;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -47,6 +49,28 @@ public class SqmBagJoin<O, E> extends AbstractSqmPluralJoin<O,Collection<E>, E>
|
|||
super( lhs, navigablePath, attribute, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmBagJoin<O, E> copy(SqmCopyContext context) {
|
||||
final SqmBagJoin<O, E> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmBagJoin<O, E> path = context.registerCopy(
|
||||
this,
|
||||
new SqmBagJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BagPersistentAttribute<O,E> getReferencedPathSource() {
|
||||
return (BagPersistentAttribute<O,E>) super.getReferencedPathSource();
|
||||
|
|
|
@ -1,57 +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 http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.spi.NavigablePath;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
|
||||
/**
|
||||
* A path that is wrapping an entity type literal.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
* @see SqmPath#type()
|
||||
*/
|
||||
public class SqmBasicValuedEntityTypePath<T> extends SqmBasicValuedSimplePath<T> {
|
||||
|
||||
private final SqmLiteralEntityType<T> literal;
|
||||
|
||||
public SqmBasicValuedEntityTypePath(
|
||||
NavigablePath navigablePath,
|
||||
EntityDomainType<T> referencedPathSource,
|
||||
SqmPath<?> lhs,
|
||||
NodeBuilder nodeBuilder) {
|
||||
this( navigablePath, referencedPathSource, lhs, null, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmBasicValuedEntityTypePath(
|
||||
NavigablePath navigablePath,
|
||||
EntityDomainType<T> referencedPathSource,
|
||||
SqmPath<?> lhs,
|
||||
String explicitAlias,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder );
|
||||
this.literal = new SqmLiteralEntityType<>( referencedPathSource, nodeBuilder );
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Visitation
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitEntityTypeLiteralExpression( literal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
sb.append( "type(" );
|
||||
super.appendHqlString( sb );
|
||||
sb.append( ')' );
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
|
@ -42,6 +43,27 @@ public class SqmBasicValuedSimplePath<T>
|
|||
super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmBasicValuedSimplePath<T> copy(SqmCopyContext context) {
|
||||
final SqmBasicValuedSimplePath<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmBasicValuedSimplePath<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmBasicValuedSimplePath<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getLhs().copy( context ),
|
||||
getExplicitAlias(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// SemanticPathPart
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -49,6 +50,29 @@ public class SqmCorrelatedBagJoin<O, T> extends SqmBagJoin<O, T> implements SqmC
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedBagJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedBagJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedBagJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedBagJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder(),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmBagJoin<O, T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
|
@ -41,6 +42,26 @@ public class SqmCorrelatedCrossJoin<T> extends SqmCrossJoin<T> implements SqmCor
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedCrossJoin<T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedCrossJoin<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedCrossJoin<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedCrossJoin<>(
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getRoot().copy( context ),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCrossJoin<T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -44,6 +45,27 @@ public class SqmCorrelatedEntityJoin<T> extends SqmEntityJoin<T> implements SqmC
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedEntityJoin<T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedEntityJoin<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedEntityJoin<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedEntityJoin<>(
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
getRoot().copy( context ),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEntityJoin<T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -49,6 +50,29 @@ public class SqmCorrelatedListJoin<O, T> extends SqmListJoin<O, T> implements Sq
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedListJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedListJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedListJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedListJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder(),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmListJoin<O, T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -49,6 +50,29 @@ public class SqmCorrelatedMapJoin<O, K, V> extends SqmMapJoin<O, K, V> implement
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedMapJoin<O, K, V> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedMapJoin<O, K, V> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedMapJoin<O, K, V> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedMapJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder(),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMapJoin<O, K, V> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -30,6 +31,20 @@ public class SqmCorrelatedPluralPartJoin<O, T> extends SqmPluralPartJoin<O, T> i
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedPluralPartJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedPluralPartJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedPluralPartJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedPluralPartJoin<>( correlationParent.copy( context ) )
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralPartJoin<O, T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
/**
|
||||
|
@ -27,6 +28,20 @@ public class SqmCorrelatedRoot<T> extends SqmRoot<T> implements SqmPathWrapper<T
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedRoot<T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedRoot<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedRoot<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedRoot<>( correlationParent.copy( context ) )
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmRoot<T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.query.spi.NavigablePath;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -26,6 +27,24 @@ public class SqmCorrelatedRootJoin<T> extends SqmRoot<T> implements SqmCorrelati
|
|||
super( navigablePath, referencedNavigable, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedRootJoin<T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedRootJoin<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedRootJoin<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedRootJoin<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <X, J extends SqmJoin<X, ?>> SqmCorrelatedRootJoin<X> create(J correlationParent, J correlatedJoin) {
|
||||
final SqmFrom<?, X> parentPath = (SqmFrom<?, X>) correlationParent.getParentPath();
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -49,6 +50,29 @@ public class SqmCorrelatedSetJoin<O, T> extends SqmSetJoin<O, T> implements SqmC
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedSetJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedSetJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedSetJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedSetJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder(),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSetJoin<O, T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -49,6 +50,29 @@ public class SqmCorrelatedSingularJoin<O, T> extends SqmSingularJoin<O, T> imple
|
|||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedSingularJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmCorrelatedSingularJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCorrelatedSingularJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmCorrelatedSingularJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder(),
|
||||
correlatedRootJoin.copy( context ),
|
||||
correlationParent.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSingularJoin<O, T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
|
|
|
@ -10,25 +10,42 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmElementAggregateFunction<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
||||
public static final String NAVIGABLE_NAME = "{max-element}";
|
||||
|
||||
private final String functionName;
|
||||
|
||||
public SqmElementAggregateFunction(SqmPath<?> pluralDomainPath, String functionName) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
pluralDomainPath.getNavigablePath().getParent().append( pluralDomainPath.getNavigablePath().getLocalName(), NAVIGABLE_NAME ),
|
||||
pluralDomainPath.getNavigablePath().getParent().append( pluralDomainPath.getNavigablePath().getLocalName(), "{" + functionName + "-element}" ),
|
||||
pluralDomainPath,
|
||||
(PluralPersistentAttribute<?, ?, T>) pluralDomainPath.getReferencedPathSource()
|
||||
);
|
||||
this.functionName = functionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmElementAggregateFunction<T> copy(SqmCopyContext context) {
|
||||
final SqmElementAggregateFunction<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmElementAggregateFunction<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmElementAggregateFunction<>(
|
||||
getLhs().copy( context ),
|
||||
functionName
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -46,6 +47,27 @@ public class SqmEmbeddedValuedSimplePath<T>
|
|||
assert referencedPathSource.getSqmPathType() instanceof EmbeddableDomainType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEmbeddedValuedSimplePath<T> copy(SqmCopyContext context) {
|
||||
final SqmEmbeddedValuedSimplePath<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmEmbeddedValuedSimplePath<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmEmbeddedValuedSimplePath<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getLhs().copy( context ),
|
||||
getExplicitAlias(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> resolvePathPart(
|
||||
String name,
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -26,6 +27,26 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
super( navigablePath, referencedPathSource, lhs, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEntityValuedSimplePath<T> copy(SqmCopyContext context) {
|
||||
final SqmEntityValuedSimplePath<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmEntityValuedSimplePath<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmEntityValuedSimplePath<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getLhs().copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> resolvePathPart(
|
||||
String name,
|
||||
|
|
|
@ -12,20 +12,19 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
|||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmIndexAggregateFunction<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
||||
public static final String NAVIGABLE_NAME = "{max-index}";
|
||||
|
||||
private final SqmPathSource<T> indexPathSource;
|
||||
private final String functionName;
|
||||
|
||||
public SqmIndexAggregateFunction(SqmPath<?> pluralDomainPath, String functionName) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
pluralDomainPath.getNavigablePath().getParent().append( pluralDomainPath.getNavigablePath().getLocalName(), NAVIGABLE_NAME ),
|
||||
pluralDomainPath.getNavigablePath().getParent().append( pluralDomainPath.getNavigablePath().getLocalName(), "{" + functionName + "-index}" ),
|
||||
pluralDomainPath,
|
||||
(PluralPersistentAttribute<?, ?, T>) pluralDomainPath.getReferencedPathSource()
|
||||
);
|
||||
|
@ -44,6 +43,24 @@ public class SqmIndexAggregateFunction<T> extends AbstractSqmSpecificPluralPartP
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmIndexAggregateFunction<T> copy(SqmCopyContext context) {
|
||||
final SqmIndexAggregateFunction<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmIndexAggregateFunction<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmIndexAggregateFunction<>(
|
||||
getLhs().copy( context ),
|
||||
functionName
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.hibernate.query.spi.NavigablePath;
|
|||
import org.hibernate.query.PathException;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +34,25 @@ public class SqmIndexedCollectionAccessPath<T> extends AbstractSqmPath<T> implem
|
|||
pluralDomainPath.nodeBuilder()
|
||||
);
|
||||
this.selectorExpression = selectorExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmIndexedCollectionAccessPath<T> copy(SqmCopyContext context) {
|
||||
final SqmIndexedCollectionAccessPath<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmIndexedCollectionAccessPath<T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmIndexedCollectionAccessPath<T>(
|
||||
getNavigablePath(),
|
||||
getLhs().copy( context ),
|
||||
selectorExpression.copy( context )
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
public SqmExpression<?> getSelectorExpression() {
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
||||
|
@ -19,10 +17,14 @@ import org.hibernate.query.criteria.JpaPredicate;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -50,6 +52,28 @@ public class SqmListJoin<O,E>
|
|||
super( lhs, navigablePath, listAttribute, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmListJoin<O, E> copy(SqmCopyContext context) {
|
||||
final SqmListJoin<O, E> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmListJoin<O, E> path = context.registerCopy(
|
||||
this,
|
||||
new SqmListJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListPersistentAttribute<O, E> getReferencedPathSource() {
|
||||
return (ListPersistentAttribute<O, E>) super.getReferencedPathSource();
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.query.criteria.JpaSelection;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
|
@ -52,6 +53,19 @@ public class SqmMapEntryReference<K,V>
|
|||
.getDescriptor( Map.Entry.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMapEntryReference<K, V> copy(SqmCopyContext context) {
|
||||
final SqmMapEntryReference<K, V> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmMapEntryReference<K, V> path = context.registerCopy(
|
||||
this,
|
||||
new SqmMapEntryReference<>( mapPath.copy( context ), nodeBuilder() )
|
||||
);
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
return explicitAlias;
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.query.criteria.JpaPredicate;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
|
@ -50,6 +51,28 @@ public class SqmMapJoin<O, K, V>
|
|||
super( lhs, navigablePath, pluralValuedNavigable, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMapJoin<O, K, V> copy(SqmCopyContext context) {
|
||||
final SqmMapJoin<O, K, V> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmMapJoin<O, K, V> path = context.registerCopy(
|
||||
this,
|
||||
new SqmMapJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapPersistentAttribute<O, K, V> getReferencedPathSource() {
|
||||
return(MapPersistentAttribute<O, K, V>) super.getReferencedPathSource();
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.ParsingException;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
@ -156,4 +158,7 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
|
|||
|
||||
@Override
|
||||
<Y> SqmPath<Y> get(String attributeName);
|
||||
|
||||
@Override
|
||||
SqmPath<T> copy(SqmCopyContext context);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
||||
|
@ -57,6 +58,27 @@ public class SqmPluralPartJoin<O,T> extends AbstractSqmJoin<O,T> implements SqmQ
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralPartJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmPluralPartJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmPluralPartJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmPluralPartJoin<>(
|
||||
(SqmFrom<?, O>) getLhs().copy( context ),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate getJoinPredicate() {
|
||||
return null;
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
@ -48,6 +49,27 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
|
|||
super( navigablePath, referencedNavigable, lhs, explicitAlias, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralValuedSimplePath<E> copy(SqmCopyContext context) {
|
||||
final SqmPluralValuedSimplePath<E> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmPluralValuedSimplePath<E> path = context.registerCopy(
|
||||
this,
|
||||
new SqmPluralValuedSimplePath<>(
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getLhs().copy( context ),
|
||||
getExplicitAlias(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralPersistentAttribute<?, ?, E> getReferencedPathSource() {
|
||||
return (PluralPersistentAttribute<?, ?, E>) super.getReferencedPathSource();
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import java.util.Set;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
||||
|
@ -19,10 +16,15 @@ import org.hibernate.query.criteria.JpaPredicate;
|
|||
import org.hibernate.query.criteria.JpaSetJoin;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -49,6 +51,28 @@ public class SqmSetJoin<O, E>
|
|||
super( lhs, navigablePath, pluralValuedNavigable, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSetJoin<O, E> copy(SqmCopyContext context) {
|
||||
final SqmSetJoin<O, E> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmSetJoin<O, E> path = context.registerCopy(
|
||||
this,
|
||||
new SqmSetJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetPersistentAttribute<O,E> getReferencedPathSource() {
|
||||
return (SetPersistentAttribute<O, E>) super.getReferencedPathSource();
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.query.spi.NavigablePath;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmJoinable;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
@ -53,6 +54,28 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
|||
super( lhs, navigablePath, joinedNavigable, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSingularJoin<O, T> copy(SqmCopyContext context) {
|
||||
final SqmSingularJoin<O, T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmSingularJoin<O, T> path = context.registerCopy(
|
||||
this,
|
||||
new SqmSingularJoin<>(
|
||||
getLhs().copy( context ),
|
||||
getNavigablePath(),
|
||||
getReferencedPathSource(),
|
||||
getExplicitAlias(),
|
||||
getSqmJoinType(),
|
||||
isFetched(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularPersistentAttribute<O, T> getReferencedPathSource() {
|
||||
return (SingularPersistentAttribute<O, T>) super.getReferencedPathSource();
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
|
@ -42,10 +43,21 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedBagJoin<O, T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedBagJoin<O, T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedBagJoin<O, T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedBagJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
|
@ -34,10 +35,21 @@ public class SqmTreatedCrossJoin<T, S extends T> extends SqmCrossJoin<S> impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedCrossJoin<T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedCrossJoin<T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedCrossJoin<T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedCrossJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
|
@ -37,10 +38,21 @@ public class SqmTreatedEntityJoin<T, S extends T> extends SqmEntityJoin<S> imple
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedEntityJoin<T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedEntityJoin<T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedEntityJoin<T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedEntityJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
@ -44,10 +45,21 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedListJoin<O, T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedListJoin<O, T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedListJoin<O, T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedListJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
/**
|
||||
|
@ -40,10 +41,21 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<V, ?>) join );
|
||||
public SqmTreatedMapJoin<O, K, V, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedMapJoin<O, K, V, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedMapJoin<O, K, V, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedMapJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.domain;
|
|||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
|
@ -39,10 +40,21 @@ public class SqmTreatedPluralPartJoin<O,T, S extends T> extends SqmPluralPartJoi
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedPluralPartJoin<O, T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedPluralPartJoin<O, T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedPluralPartJoin<O, T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedPluralPartJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
|
@ -37,10 +38,20 @@ public class SqmTreatedRoot<T, S extends T> extends SqmRoot<S> implements SqmTre
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmRoot<S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedRoot<T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedRoot<T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedRoot<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
|
@ -42,10 +43,21 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedSetJoin<O, T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedSetJoin<O, T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedSetJoin<O, T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedSetJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.query.PathException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -56,9 +57,22 @@ public class SqmTreatedSimplePath<T, S extends T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void registerReusablePath(SqmPath<?> path) {
|
||||
super.registerReusablePath( path );
|
||||
wrappedPath.registerReusablePath( path );
|
||||
public SqmTreatedSimplePath<T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedSimplePath<T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmTreatedSimplePath<T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedSimplePath<>(
|
||||
wrappedPath.copy( context ),
|
||||
getTreatTarget(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
|
@ -42,10 +43,21 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
public SqmTreatedSingularJoin<O, T, S> copy(SqmCopyContext context) {
|
||||
final SqmTreatedSingularJoin<O, T, S> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTreatedSingularJoin<O, T, S> path = context.registerCopy(
|
||||
this,
|
||||
new SqmTreatedSingularJoin<>(
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
|
@ -22,6 +21,8 @@ import org.hibernate.query.sqm.tree.predicate.SqmInPredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType;
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
||||
|
@ -45,6 +46,12 @@ public class JpaCriteriaParameter<T>
|
|||
this.allowsMultiValuedBinding = allowsMultiValuedBinding;
|
||||
}
|
||||
|
||||
protected JpaCriteriaParameter(JpaCriteriaParameter<T> original) {
|
||||
super( original.getNodeType(), original.nodeBuilder() );
|
||||
this.name = original.name;
|
||||
this.allowsMultiValuedBinding = original.allowsMultiValuedBinding;
|
||||
}
|
||||
|
||||
private static <T> SqmExpressible<T> toSqmType(BindableType<T> type, NodeBuilder nodeBuilder) {
|
||||
if ( type == null ) {
|
||||
return null;
|
||||
|
@ -54,6 +61,12 @@ public class JpaCriteriaParameter<T>
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaCriteriaParameter<T> copy(SqmCopyContext context) {
|
||||
// Don't create a copy of regular parameters because identity is important here
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* Models a reference to a {@link org.hibernate.query.sqm.tree.select.SqmAliasedNode}
|
||||
|
@ -23,6 +24,22 @@ public class SqmAliasedNodeRef extends AbstractSqmExpression<Integer> {
|
|||
this.position = position;
|
||||
}
|
||||
|
||||
private SqmAliasedNodeRef(SqmAliasedNodeRef original) {
|
||||
super( original.getNodeType(), original.nodeBuilder() );
|
||||
this.position = original.position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAliasedNodeRef copy(SqmCopyContext context) {
|
||||
final SqmAliasedNodeRef existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmAliasedNodeRef expression = context.registerCopy( this, new SqmAliasedNodeRef( this ) );
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
/**
|
||||
|
@ -22,6 +23,23 @@ public class SqmAny<T> extends AbstractSqmExpression<T> {
|
|||
this.subquery = subquery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAny<T> copy(SqmCopyContext context) {
|
||||
final SqmAny<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmAny<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmAny<>(
|
||||
subquery.copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public SqmSubQuery<T> getSubquery() {
|
||||
return subquery;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.query.sqm.BinaryArithmeticOperator;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
/**
|
||||
|
@ -61,6 +62,26 @@ public class SqmBinaryArithmetic<T> extends AbstractSqmExpression<T> implements
|
|||
applyInferableType( expressibleType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmBinaryArithmetic<T> copy(SqmCopyContext context) {
|
||||
final SqmBinaryArithmetic<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmBinaryArithmetic<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmBinaryArithmetic<>(
|
||||
operator,
|
||||
lhsOperand.copy( context ),
|
||||
rhsOperand.copy( context ),
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitBinaryArithmeticExpression( this );
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
|
@ -27,6 +28,25 @@ public class SqmByUnit extends AbstractSqmExpression<Long> {
|
|||
this.duration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmByUnit copy(SqmCopyContext context) {
|
||||
final SqmByUnit existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmByUnit expression = context.registerCopy(
|
||||
this,
|
||||
new SqmByUnit(
|
||||
unit.copy( context ),
|
||||
duration.copy( context ),
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public SqmDurationUnit<?> getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.query.internal.QueryHelper;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
@ -41,6 +42,35 @@ public class SqmCaseSearched<R>
|
|||
this.whenFragments = new ArrayList<>( estimateWhenSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCaseSearched<R> copy(SqmCopyContext context) {
|
||||
final SqmCaseSearched<R> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCaseSearched<R> caseSearched = context.registerCopy(
|
||||
this,
|
||||
new SqmCaseSearched<>(
|
||||
getNodeType(),
|
||||
whenFragments.size(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
for ( WhenFragment<R> whenFragment : whenFragments ) {
|
||||
caseSearched.whenFragments.add(
|
||||
new WhenFragment<>(
|
||||
whenFragment.predicate.copy( context ),
|
||||
whenFragment.result.copy( context )
|
||||
)
|
||||
);
|
||||
}
|
||||
if ( otherwise != null ) {
|
||||
caseSearched.otherwise = otherwise.copy( context );
|
||||
}
|
||||
copyTo( caseSearched, context );
|
||||
return caseSearched;
|
||||
}
|
||||
|
||||
public List<WhenFragment<R>> getWhenFragments() {
|
||||
return whenFragments;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.criteria.JpaSimpleCase;
|
||||
|
@ -19,9 +17,12 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -48,6 +49,36 @@ public class SqmCaseSimple<T, R>
|
|||
this.fixture = fixture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCaseSimple<T, R> copy(SqmCopyContext context) {
|
||||
final SqmCaseSimple<T, R> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCaseSimple<T, R> caseSearched = context.registerCopy(
|
||||
this,
|
||||
new SqmCaseSimple<>(
|
||||
fixture.copy( context ),
|
||||
getNodeType(),
|
||||
whenFragments.size(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
for ( SqmCaseSimple.WhenFragment<T, R> whenFragment : whenFragments ) {
|
||||
caseSearched.whenFragments.add(
|
||||
new SqmCaseSimple.WhenFragment<>(
|
||||
whenFragment.checkValue.copy( context ),
|
||||
whenFragment.result.copy( context )
|
||||
)
|
||||
);
|
||||
}
|
||||
if ( otherwise != null ) {
|
||||
caseSearched.otherwise = otherwise.copy( context );
|
||||
}
|
||||
copyTo( caseSearched, context );
|
||||
return caseSearched;
|
||||
}
|
||||
|
||||
public SqmExpression<T> getFixture() {
|
||||
return fixture;
|
||||
}
|
||||
|
@ -131,6 +162,11 @@ public class SqmCaseSimple<T, R>
|
|||
this.result = result;
|
||||
}
|
||||
|
||||
private WhenFragment(WhenFragment<T, R> original, SqmCopyContext context) {
|
||||
this.checkValue = original.checkValue.copy( context );
|
||||
this.result = original.result.copy( context );
|
||||
}
|
||||
|
||||
public SqmExpression<T> getCheckValue() {
|
||||
return checkValue;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
|
@ -70,6 +71,11 @@ public class SqmCastTarget<T> extends AbstractSqmNode implements SqmTypedNode<T>
|
|||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCastTarget<T> copy(SqmCopyContext context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReturnableType<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.query.criteria.JpaCoalesce;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
|
@ -13,10 +16,9 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -42,6 +44,27 @@ public class SqmCoalesce<T> extends AbstractSqmExpression<T> implements JpaCoale
|
|||
this.arguments = new ArrayList<>( numberOfArguments );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCoalesce<T> copy(SqmCopyContext context) {
|
||||
final SqmCoalesce<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCoalesce<T> coalesce = context.registerCopy(
|
||||
this,
|
||||
new SqmCoalesce<>(
|
||||
getNodeType(),
|
||||
arguments.size(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
for ( SqmExpression<? extends T> argument : arguments ) {
|
||||
coalesce.arguments.add( argument.copy( context ) );
|
||||
}
|
||||
copyTo( coalesce, context );
|
||||
return coalesce;
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor getFunctionDescriptor() {
|
||||
return functionDescriptor;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
|
@ -18,6 +19,20 @@ public class SqmCollation extends SqmLiteral<String> {
|
|||
super(value, inherentType, nodeBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCollation copy(SqmCopyContext context) {
|
||||
final SqmCollation existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCollation expression = context.registerCopy(
|
||||
this,
|
||||
new SqmCollation( getLiteralValue(), getNodeType(), nodeBuilder() )
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R accept(SemanticQueryWalker<R> walker) {
|
||||
return walker.visitCollation( this );
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
||||
/**
|
||||
|
@ -29,6 +30,24 @@ public class SqmCollectionSize extends AbstractSqmExpression<Integer> {
|
|||
this.pluralPath = pluralPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCollectionSize copy(SqmCopyContext context) {
|
||||
final SqmCollectionSize existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmCollectionSize expression = context.registerCopy(
|
||||
this,
|
||||
new SqmCollectionSize(
|
||||
pluralPath.copy( context ),
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public SqmPath<?> getPluralPath() {
|
||||
return pluralPath;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
|
@ -21,10 +22,25 @@ public class SqmDistinct<T> extends AbstractSqmNode implements SqmTypedNode<T>,
|
|||
private final SqmExpression<T> expression;
|
||||
|
||||
public SqmDistinct(SqmExpression<T> expression, NodeBuilder builder) {
|
||||
super(builder);
|
||||
super( builder );
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDistinct<T> copy(SqmCopyContext context) {
|
||||
final SqmDistinct<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
return context.registerCopy(
|
||||
this,
|
||||
new SqmDistinct<>(
|
||||
expression.copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public SqmExpression<T> getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
|
@ -28,6 +29,11 @@ public class SqmDurationUnit<T> extends AbstractSqmNode implements SqmTypedNode<
|
|||
this.unit = unit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDurationUnit<T> copy(SqmCopyContext context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReturnableType<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
|
||||
|
@ -42,6 +43,25 @@ public class SqmEnumLiteral<E extends Enum<E>> extends AbstractSqmExpression<E>
|
|||
setExpressibleType( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEnumLiteral<E> copy(SqmCopyContext context) {
|
||||
final SqmEnumLiteral<E> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmEnumLiteral<E> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmEnumLiteral<>(
|
||||
enumValue,
|
||||
referencedEnumTypeDescriptor,
|
||||
enumValueName,
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public E getEnumValue() {
|
||||
return enumValue;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
/**
|
||||
|
@ -22,6 +23,20 @@ public class SqmEvery<T> extends AbstractSqmExpression<T> {
|
|||
this.subquery = subquery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEvery<T> copy(SqmCopyContext context) {
|
||||
final SqmEvery<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmEvery<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmEvery<>( subquery.copy( context ), nodeBuilder() )
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public SqmSubQuery<T> getSubquery() {
|
||||
return subquery;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.metamodel.model.domain.DomainType;
|
|||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
|
@ -102,6 +103,9 @@ public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>
|
|||
@Override
|
||||
SqmPredicate in(Expression<Collection<?>> values);
|
||||
|
||||
@Override
|
||||
SqmExpression<T> copy(SqmCopyContext context);
|
||||
|
||||
default <X> SqmExpression<X> castAs(DomainType<X> type) {
|
||||
if ( getNodeType() == type ) {
|
||||
return (SqmExpression<X>) this;
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
|
@ -28,6 +29,11 @@ public class SqmExtractUnit<T> extends AbstractSqmNode implements SqmTypedNode<T
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExtractUnit<T> copy(SqmCopyContext context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporalUnit getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
@ -51,16 +52,6 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
|
|||
);
|
||||
}
|
||||
|
||||
private static <T> T extractValue(Field field) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return (T) field.get( null );
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new QueryException( "Could not access Field value for SqmFieldLiteral", e );
|
||||
}
|
||||
}
|
||||
|
||||
public SqmFieldLiteral(
|
||||
T value,
|
||||
JavaType<T> fieldJavaType,
|
||||
|
@ -74,6 +65,33 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
|
|||
this.expressible = this;
|
||||
}
|
||||
|
||||
private static <T> T extractValue(Field field) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return (T) field.get( null );
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new QueryException( "Could not access Field value for SqmFieldLiteral", e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFieldLiteral<T> copy(SqmCopyContext context) {
|
||||
final SqmFieldLiteral<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
return context.registerCopy(
|
||||
this,
|
||||
new SqmFieldLiteral<>(
|
||||
value,
|
||||
fieldJavaType,
|
||||
fieldName,
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.query.SemanticException;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* Effectively a query-literal but we want to handle it specially in the SQM -> SQL AST conversion
|
||||
|
@ -51,6 +52,24 @@ public class SqmFormat extends SqmLiteral<String> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFormat copy(SqmCopyContext context) {
|
||||
final SqmFormat existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmFormat expression = context.registerCopy(
|
||||
this,
|
||||
new SqmFormat(
|
||||
getLiteralValue(),
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R accept(SemanticQueryWalker<R> walker) {
|
||||
return walker.visitFormat( this );
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.criteria.JpaFunction;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
|
@ -19,8 +21,6 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
|||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A SQM function
|
||||
*
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.function.Consumer;
|
|||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
|
||||
|
@ -35,6 +36,22 @@ public class SqmJpaCriteriaParameterWrapper<T>
|
|||
this.jpaCriteriaParameter = jpaCriteriaParameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmJpaCriteriaParameterWrapper<T> copy(SqmCopyContext context) {
|
||||
final SqmJpaCriteriaParameterWrapper<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
return context.registerCopy(
|
||||
this,
|
||||
new SqmJpaCriteriaParameterWrapper<>(
|
||||
getNodeType(),
|
||||
jpaCriteriaParameter.copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return jpaCriteriaParameter.getName();
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.query.internal.QueryLiteralHelper;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -36,6 +37,24 @@ public class SqmLiteral<T> extends AbstractSqmExpression<T> {
|
|||
this.value = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmLiteral<T> copy(SqmCopyContext context) {
|
||||
final SqmLiteral<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmLiteral<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmLiteral<>(
|
||||
getLiteralValue(),
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public T getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
|
@ -35,6 +36,23 @@ public class SqmLiteralEntityType<T>
|
|||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmLiteralEntityType<T> copy(SqmCopyContext context) {
|
||||
final SqmLiteralEntityType<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmLiteralEntityType<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmLiteralEntityType<>(
|
||||
entityType,
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDomainType<T> getNodeType() {
|
||||
return entityType;
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -26,6 +27,23 @@ public class SqmLiteralNull<T> extends SqmLiteral<T> {
|
|||
super( expressibleType, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmLiteralNull<T> copy(SqmCopyContext context) {
|
||||
final SqmLiteralNull<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmLiteralNull<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmLiteralNull<>(
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitLiteral( this );
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
/**
|
||||
|
@ -49,6 +50,25 @@ public class SqmModifiedSubQueryExpression<T> extends AbstractSqmExpression<T> {
|
|||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmModifiedSubQueryExpression<T> copy(SqmCopyContext context) {
|
||||
final SqmModifiedSubQueryExpression<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmModifiedSubQueryExpression<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmModifiedSubQueryExpression<>(
|
||||
subQuery.copy( context ),
|
||||
modifier,
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
public Modifier getModifier() {
|
||||
return modifier;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
/**
|
||||
* Represents a named query parameter in the SQM tree.
|
||||
|
@ -31,6 +32,25 @@ public class SqmNamedParameter<T> extends AbstractSqmParameter<T> {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmNamedParameter<T> copy(SqmCopyContext context) {
|
||||
final SqmNamedParameter<T> existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmNamedParameter<T> expression = context.registerCopy(
|
||||
this,
|
||||
new SqmNamedParameter<>(
|
||||
name,
|
||||
allowMultiValuedBinding(),
|
||||
getNodeType(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( expression, context );
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitNamedParameterExpression( this );
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue