tests for JPQL

tests for JPA operations
This commit is contained in:
Steve Ebersole 2020-08-31 18:31:51 -05:00
parent 076a0aa25a
commit ca1692b86f
68 changed files with 740 additions and 407 deletions

View File

@ -151,7 +151,7 @@ public interface MappingModelCreationLogger extends BasicLogger {
|90003501 |90003501
|90004000 |90004000
|org.hibernate.orm.query.hql |org.hibernate.orm.query.hql
|org.hibernate.query.hql.HqlLogger |org.hibernate.query.hql.HqlLogging
|90004001 |90004001
|90005000 |90005000

View File

@ -35,6 +35,9 @@ import org.hibernate.engine.spi.ExceptionConverter;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.loader.MultipleBagFetchException; import org.hibernate.loader.MultipleBagFetchException;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.sqm.ParsingException;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
@ -134,9 +137,18 @@ public class ExceptionConverterImpl implements ExceptionConverter {
handlePersistenceException( converted ); handlePersistenceException( converted );
return converted; return converted;
} }
else if ( cause instanceof SemanticException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof QueryException ) { else if ( cause instanceof QueryException ) {
return new IllegalArgumentException( cause ); return new IllegalArgumentException( cause );
} }
else if ( cause instanceof InterpretationException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof ParsingException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof MultipleBagFetchException ) { else if ( cause instanceof MultipleBagFetchException ) {
return new IllegalArgumentException( cause ); return new IllegalArgumentException( cause );
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.internal.util; package org.hibernate.internal.util;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -43,6 +44,14 @@ public class MutableObject<T> {
this.reference = reference; this.reference = reference;
} }
public void set(T reference, BiConsumer<T,T> existingConsumer) {
if ( this.reference != null ) {
existingConsumer.accept( reference, this.reference );
}
this.reference = reference;
}
public void setIfNot(T reference) { public void setIfNot(T reference) {
if ( this.reference == null ) { if ( this.reference == null ) {
this.reference = reference; this.reference = reference;

View File

@ -13,6 +13,11 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
*/ */
public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValuedModelPart { public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValuedModelPart {
String ROLE_NAME = "{discriminator}"; String ROLE_NAME = "{discriminator}";
String LEGACY_HQL_ROLE_NAME = "class";
static boolean matchesRoleName(String name) {
return ROLE_NAME.equals( name ) || LEGACY_HQL_ROLE_NAME.equals( name );
}
@Override @Override
default String getPartName() { default String getPartName() {

View File

@ -15,6 +15,7 @@ import javax.persistence.metamodel.ManagedType;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -114,4 +115,6 @@ public interface JpaMetamodel extends javax.persistence.metamodel.Metamodel {
<T> RootGraphImplementor<T> findEntityGraphByName(String name); <T> RootGraphImplementor<T> findEntityGraphByName(String name);
<T> List<RootGraphImplementor<? super T>> findEntityGraphsByJavaType(Class<T> entityClass); <T> List<RootGraphImplementor<? super T>> findEntityGraphsByJavaType(Class<T> entityClass);
JpaCompliance getJpaCompliance();
} }

View File

@ -7,11 +7,8 @@
package org.hibernate.metamodel.model.domain.internal; package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -35,17 +32,7 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> {
@Override @Override
public SqmPathSource<?> findSubPathSource(String name) { public SqmPathSource<?> findSubPathSource(String name) {
final EntityDomainType<J> sqmPathType = getSqmPathType(); final EntityDomainType<J> sqmPathType = getSqmPathType();
final PersistentAttribute<?,?> attribute = sqmPathType.findAttribute( name ); return sqmPathType.findSubPathSource( name );
if ( attribute != null ) {
return (SqmPathSource<?>) attribute;
}
final SingularPersistentAttribute<J, ?> idAttribute = sqmPathType.findIdAttribute();
if ( idAttribute != null && idAttribute.getName().equals( name ) ) {
return idAttribute;
}
throw new SemanticException( "Unknown sub-path name : " + name );
} }
@Override @Override

View File

@ -12,15 +12,21 @@ import javax.persistence.metamodel.EntityType;
import org.hibernate.graph.internal.SubGraphImpl; import org.hibernate.graph.internal.SubGraphImpl;
import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.graph.spi.SubGraphImplementor;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
@ -33,6 +39,7 @@ public class EntityTypeImpl<J>
extends AbstractIdentifiableType<J> extends AbstractIdentifiableType<J>
implements EntityDomainType<J>, Serializable { implements EntityDomainType<J>, Serializable {
private final String jpaEntityName; private final String jpaEntityName;
private final SqmPathSource<?> discriminatorPathSource;
public EntityTypeImpl( public EntityTypeImpl(
JavaTypeDescriptor<J> javaTypeDescriptor, JavaTypeDescriptor<J> javaTypeDescriptor,
@ -50,6 +57,63 @@ public class EntityTypeImpl<J>
); );
this.jpaEntityName = persistentClass.getJpaEntityName(); this.jpaEntityName = persistentClass.getJpaEntityName();
if ( persistentClass.hasSubclasses() ) {
final Value discriminator = persistentClass.getDiscriminator();
final DomainType discriminatorType;
if ( discriminator != null ) {
discriminatorType = (DomainType) discriminator.getType();
}
else {
discriminatorType = StandardBasicTypes.STRING;
}
discriminatorPathSource = new SqmPathSource() {
@Override
public String getPathName() {
return EntityDiscriminatorMapping.ROLE_NAME;
}
@Override
public DomainType<?> getSqmPathType() {
// the BasicType for Class?
return discriminatorType;
}
@Override
public SqmPathSource<?> findSubPathSource(String name) {
throw new IllegalPathUsageException( "Entity discriminator cannot be de-referenced" );
}
@Override
public SqmPath<?> createSqmPath(SqmPath lhs, SqmCreationState creationState) {
return new SqmBasicValuedSimplePath(
lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
this,
lhs,
creationState.getCreationContext().getNodeBuilder()
);
}
@Override
public BindableType getBindableType() {
return BindableType.SINGULAR_ATTRIBUTE;
}
@Override
public Class<?> getBindableJavaType() {
return getExpressableJavaTypeDescriptor().getJavaType();
}
@Override
public JavaTypeDescriptor<?> getExpressableJavaTypeDescriptor() {
return discriminatorType.getExpressableJavaTypeDescriptor();
}
};
}
else {
discriminatorPathSource = null;
}
} }
@Override @Override
@ -83,6 +147,10 @@ public class EntityTypeImpl<J>
// todo (6.0) : probably need special handling here for non-aggregated composite ids // todo (6.0) : probably need special handling here for non-aggregated composite ids
} }
if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
return discriminatorPathSource;
}
return null; return null;
} }

View File

@ -36,9 +36,9 @@ import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging; import org.hibernate.internal.HEMLogging;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.internal.InflightRuntimeMetamodel;
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
import org.hibernate.metamodel.internal.MetadataContext; import org.hibernate.metamodel.internal.MetadataContext;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
@ -71,6 +71,7 @@ public class JpaMetamodelImpl implements JpaMetamodel {
} }
private final TypeConfiguration typeConfiguration; private final TypeConfiguration typeConfiguration;
private final JpaCompliance jpaCompliance;
private final Map<String, EntityDomainType<?>> jpaEntityTypeMap = new ConcurrentHashMap<>(); private final Map<String, EntityDomainType<?>> jpaEntityTypeMap = new ConcurrentHashMap<>();
private final Map<Class<?>, MappedSuperclassDomainType<?>> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>(); private final Map<Class<?>, MappedSuperclassDomainType<?>> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>();
@ -85,8 +86,9 @@ public class JpaMetamodelImpl implements JpaMetamodel {
private final Map<String, ImportInfo<?>> nameToImportMap = new ConcurrentHashMap<>(); private final Map<String, ImportInfo<?>> nameToImportMap = new ConcurrentHashMap<>();
public JpaMetamodelImpl(TypeConfiguration typeConfiguration) { public JpaMetamodelImpl(TypeConfiguration typeConfiguration, JpaCompliance jpaCompliance) {
this.typeConfiguration = typeConfiguration; this.typeConfiguration = typeConfiguration;
this.jpaCompliance = jpaCompliance;
} }
@Override @Override
@ -94,6 +96,11 @@ public class JpaMetamodelImpl implements JpaMetamodel {
return typeConfiguration; return typeConfiguration;
} }
@Override
public JpaCompliance getJpaCompliance() {
return jpaCompliance;
}
@Override @Override
public <X> EntityDomainType<X> entity(String entityName) { public <X> EntityDomainType<X> entity(String entityName) {
//noinspection unchecked //noinspection unchecked
@ -454,25 +461,6 @@ public class JpaMetamodelImpl implements JpaMetamodel {
throw new IllegalArgumentException( "Could not resolve entity reference : " + javaType.getName() ); throw new IllegalArgumentException( "Could not resolve entity reference : " + javaType.getName() );
} }
public static JpaMetamodel buildMetamodel(
RuntimeModelCreationContext runtimeModelCreationContext,
MetadataImplementor bootMetamodel,
InflightRuntimeMetamodel inflightRuntimeMetamodel,
JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting,
java.util.Collection<NamedEntityGraphDefinition> namedEntityGraphDefinitions) {
final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( inflightRuntimeMetamodel.getTypeConfiguration() );
jpaMetamodel.processJpa(
bootMetamodel,
inflightRuntimeMetamodel.getEntityProxyInterfaceMap(),
jpaStaticMetaModelPopulationSetting,
namedEntityGraphDefinitions,
runtimeModelCreationContext
);
return jpaMetamodel;
}
public void processJpa( public void processJpa(
MetadataImplementor bootMetamodel, MetadataImplementor bootMetamodel,
Map<Class, String> entityProxyInterfaceMap, Map<Class, String> entityProxyInterfaceMap,

View File

@ -149,7 +149,7 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
public MappingMetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) { public MappingMetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) {
this.sessionFactory = sessionFactory; this.sessionFactory = sessionFactory;
this.typeConfiguration = typeConfiguration; this.typeConfiguration = typeConfiguration;
this.jpaMetamodel = new JpaMetamodelImpl( typeConfiguration ); this.jpaMetamodel = new JpaMetamodelImpl( typeConfiguration, sessionFactory.getSessionFactoryOptions().getJpaCompliance() );
} }
public JpaMetamodel getJpaMetamodel() { public JpaMetamodel getJpaMetamodel() {

View File

@ -26,6 +26,7 @@ import javax.persistence.TemporalType;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -33,7 +34,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph; import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
@ -54,6 +54,7 @@ import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.results.ResultSetMappingImpl; import org.hibernate.query.results.ResultSetMappingImpl;
import org.hibernate.query.spi.AbstractQuery; import org.hibernate.query.spi.AbstractQuery;
import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.result.NoMoreReturnsException; import org.hibernate.result.NoMoreReturnsException;
@ -63,8 +64,6 @@ import org.hibernate.result.UpdateCountOutput;
import org.hibernate.result.spi.ResultContext; import org.hibernate.result.spi.ResultContext;
import org.hibernate.sql.results.NoMoreOutputsException; import org.hibernate.sql.results.NoMoreOutputsException;
import org.jboss.logging.Logger;
/** /**
* Standard implementation of {@link org.hibernate.procedure.ProcedureCall} * Standard implementation of {@link org.hibernate.procedure.ProcedureCall}
* *
@ -73,10 +72,6 @@ import org.jboss.logging.Logger;
public class ProcedureCallImpl<R> public class ProcedureCallImpl<R>
extends AbstractQuery<R> extends AbstractQuery<R>
implements ProcedureCallImplementor<R>, ResultContext { implements ProcedureCallImplementor<R>, ResultContext {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
ProcedureCallImpl.class.getName()
);
private final String procedureName; private final String procedureName;
@ -272,6 +267,11 @@ public class ProcedureCallImpl<R>
return queryOptions; return queryOptions;
} }
@Override
public QueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
throw new IllegalStateException( "Cannot set LockMode on a procedure-call" );
}
@Override @Override
public ProcedureParameterMetadataImpl getParameterMetadata() { public ProcedureParameterMetadataImpl getParameterMetadata() {
return parameterMetadata; return parameterMetadata;
@ -601,21 +601,6 @@ public class ProcedureCallImpl<R>
return mementos; return mementos;
} }
@Override
protected boolean canApplyAliasSpecificLockModes() {
return false;
}
@Override
protected void verifySettingLockMode() {
throw new IllegalStateException( "Illegal attempt to set lock mode on a ProcedureCall / StoredProcedureQuery" );
}
@Override
protected void verifySettingAliasSpecificLockModes() {
throw new IllegalStateException( "Illegal attempt to set lock mode on a ProcedureCall / StoredProcedureQuery" );
}
@Override @Override
protected void applyEntityGraphQueryHint(String hintName, RootGraphImplementor entityGraph) { protected void applyEntityGraphQueryHint(String hintName, RootGraphImplementor entityGraph) {
throw new IllegalStateException( "EntityGraph hints are not supported for ProcedureCall/StoredProcedureQuery" ); throw new IllegalStateException( "EntityGraph hints are not supported for ProcedureCall/StoredProcedureQuery" );

View File

@ -24,10 +24,10 @@ import static org.jboss.logging.Logger.Level.ERROR;
*/ */
@MessageLogger( projectCode = "HHH" ) @MessageLogger( projectCode = "HHH" )
@ValidIdRange( min = 90003501, max = 90004000 ) @ValidIdRange( min = 90003501, max = 90004000 )
public interface HqlLogger extends BasicLogger { public interface HqlLogging extends BasicLogger {
String LOGGER_NAME = QueryLogging.subLoggerName( "hql" ); String LOGGER_NAME = QueryLogging.subLoggerName( "hql" );
HqlLogger QUERY_LOGGER = Logger.getMessageLogger( HqlLogger.class, LOGGER_NAME ); HqlLogging QUERY_LOGGER = Logger.getMessageLogger( HqlLogging.class, LOGGER_NAME );
boolean TRACE_ENABLED = QUERY_LOGGER.isTraceEnabled(); boolean TRACE_ENABLED = QUERY_LOGGER.isTraceEnabled();
boolean DEBUG_ENABLED = QUERY_LOGGER.isDebugEnabled(); boolean DEBUG_ENABLED = QUERY_LOGGER.isDebugEnabled();

View File

@ -9,18 +9,22 @@ package org.hibernate.query.hql.internal;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.DotIdentifierConsumer; import org.hibernate.query.hql.spi.DotIdentifierConsumer;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.hql.spi.SqmPathRegistry; import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.ParsingException; import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.spi.SqmCreationContext; import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral; import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral; import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor; import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -45,8 +49,6 @@ import org.jboss.logging.Logger;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BasicDotIdentifierConsumer implements DotIdentifierConsumer { public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
private static final Logger log = Logger.getLogger( BasicDotIdentifierConsumer.class );
private final SqmCreationState creationState; private final SqmCreationState creationState;
private String pathSoFar; private String pathSoFar;
@ -84,7 +86,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
pathSoFar += ( '.' + identifier ); pathSoFar += ( '.' + identifier );
} }
log.tracef( HqlLogging.QUERY_LOGGER.tracef(
"BasicDotIdentifierHandler#consumeIdentifier( %s, %s, %s ) - %s", "BasicDotIdentifierHandler#consumeIdentifier( %s, %s, %s ) - %s",
identifier, identifier,
isBase, isBase,
@ -112,6 +114,14 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
String identifier, String identifier,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
HqlLogging.QUERY_LOGGER.tracef(
"BaseLocalSequencePart#consumeIdentifier( %s, %s, %s ) - %s",
identifier,
isBase,
isTerminal,
pathSoFar
);
if ( isBase ) { if ( isBase ) {
isBase = false; isBase = false;
@ -119,7 +129,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
.getCurrent() .getCurrent()
.getPathRegistry(); .getPathRegistry();
final SqmFrom pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier ); final SqmFrom<?,?> pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier );
if ( pathRootByAlias != null ) { if ( pathRootByAlias != null ) {
// identifier is an alias (identification variable) // identifier is an alias (identification variable)
validateAsRoot( pathRootByAlias ); validateAsRoot( pathRootByAlias );
@ -144,7 +154,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
} }
else { else {
pathRootByExposedNavigable.registerImplicitJoinPath( sqmPath ); pathRootByExposedNavigable.registerImplicitJoinPath( sqmPath );
return new DomainPathPart( pathRootByAlias ); return new DomainPathPart( pathRootByExposedNavigable );
} }
} }
} }
@ -161,11 +171,19 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
// //
// todo (6.0) : finish this logic. and see above note in `! isTerminal` block // todo (6.0) : finish this logic. and see above note in `! isTerminal` block
if ( !isTerminal ) { final SqmCreationContext creationContext = creationState.getCreationContext();
if ( ! isTerminal ) {
return this; return this;
} }
final SqmCreationContext creationContext = creationState.getCreationContext(); final String importableName = creationContext.getJpaMetamodel().qualifyImportableName( pathSoFar );
if ( importableName != null ) {
final EntityDomainType<?> entityDomainType = creationContext.getJpaMetamodel().entity( importableName );
if ( entityDomainType != null ) {
return new SqmLiteralEntityType( entityDomainType, creationContext.getNodeBuilder() );
}
}
final SqmFunctionDescriptor functionDescriptor = creationContext.getQueryEngine() final SqmFunctionDescriptor functionDescriptor = creationContext.getQueryEngine()
.getSqmFunctionRegistry() .getSqmFunctionRegistry()

View File

@ -8,6 +8,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
@ -25,6 +26,7 @@ public class DomainPathPart implements SemanticPathPart {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public DomainPathPart(SqmPath<?> basePath) { public DomainPathPart(SqmPath<?> basePath) {
this.currentPath = basePath; this.currentPath = basePath;
assert currentPath != null;
} }
@Override @Override
@ -32,6 +34,11 @@ public class DomainPathPart implements SemanticPathPart {
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
HqlLogging.QUERY_LOGGER.tracef(
"Resolving DomainPathPart(%s) sub-part : %s",
currentPath,
name
);
final SqmPath<?> lhs = currentPath; final SqmPath<?> lhs = currentPath;
final SqmPathSource subPathSource = lhs.getReferencedPathSource().findSubPathSource( name ); final SqmPathSource subPathSource = lhs.getReferencedPathSource().findSubPathSource( name );
if ( subPathSource == null ) { if ( subPathSource == null ) {

View File

@ -8,7 +8,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.grammars.hql.HqlLexer; import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser; import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.hql.HqlLogger; import org.hibernate.query.hql.HqlLogging;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -22,7 +22,7 @@ import org.antlr.v4.runtime.Token;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class HqlParseTreeBuilder { public class HqlParseTreeBuilder {
private static final Logger LOGGER = HqlLogger.subLogger( "reservedWordAsIdentifier" ); private static final Logger LOGGER = HqlLogging.subLogger( "reservedWordAsIdentifier" );
private static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled(); private static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
/** /**

View File

@ -474,7 +474,7 @@ public class QuerySplitter {
@Override @Override
public SqmEmptinessPredicate visitIsEmptyPredicate(SqmEmptinessPredicate predicate) { public SqmEmptinessPredicate visitIsEmptyPredicate(SqmEmptinessPredicate predicate) {
return new SqmEmptinessPredicate( return new SqmEmptinessPredicate(
(SqmPath) predicate.getPluralPath().accept( this ), (SqmPluralValuedSimplePath<?>) predicate.getPluralPath().accept( this ),
predicate.isNegated(), predicate.isNegated(),
predicate.nodeBuilder() predicate.nodeBuilder()
); );
@ -483,7 +483,7 @@ public class QuerySplitter {
@Override @Override
public SqmNullnessPredicate visitIsNullPredicate(SqmNullnessPredicate predicate) { public SqmNullnessPredicate visitIsNullPredicate(SqmNullnessPredicate predicate) {
return new SqmNullnessPredicate( return new SqmNullnessPredicate(
(SqmExpression) predicate.getExpression().accept( this ), (SqmExpression<?>) predicate.getExpression().accept( this ),
predicate.isNegated(), predicate.isNegated(),
predicate.nodeBuilder() predicate.nodeBuilder()
); );
@ -492,9 +492,9 @@ public class QuerySplitter {
@Override @Override
public SqmBetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) { public SqmBetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) {
return new SqmBetweenPredicate( return new SqmBetweenPredicate(
(SqmExpression) predicate.getExpression().accept( this ), (SqmExpression<?>) predicate.getExpression().accept( this ),
(SqmExpression) predicate.getLowerBound().accept( this ), (SqmExpression<?>) predicate.getLowerBound().accept( this ),
(SqmExpression) predicate.getUpperBound().accept( this ), (SqmExpression<?>) predicate.getUpperBound().accept( this ),
predicate.isNegated(), predicate.isNegated(),
predicate.nodeBuilder() predicate.nodeBuilder()
); );
@ -503,9 +503,9 @@ public class QuerySplitter {
@Override @Override
public SqmLikePredicate visitLikePredicate(SqmLikePredicate predicate) { public SqmLikePredicate visitLikePredicate(SqmLikePredicate predicate) {
return new SqmLikePredicate( return new SqmLikePredicate(
(SqmExpression) predicate.getMatchExpression().accept( this ), (SqmExpression<?>) predicate.getMatchExpression().accept( this ),
(SqmExpression) predicate.getPattern().accept( this ), (SqmExpression<?>) predicate.getPattern().accept( this ),
(SqmExpression) predicate.getEscapeCharacter().accept( this ), (SqmExpression<?>) predicate.getEscapeCharacter().accept( this ),
predicate.nodeBuilder() predicate.nodeBuilder()
); );
} }

View File

@ -30,7 +30,6 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.NullPrecedence; import org.hibernate.NullPrecedence;
import org.hibernate.QueryException; import org.hibernate.QueryException;
@ -58,7 +57,7 @@ import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.TrimSpec; import org.hibernate.query.TrimSpec;
import org.hibernate.query.UnaryArithmeticOperator; import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.hql.HqlLogger; import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.DotIdentifierConsumer; import org.hibernate.query.hql.spi.DotIdentifierConsumer;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationOptions; import org.hibernate.query.hql.spi.SqmCreationOptions;
@ -76,6 +75,7 @@ import org.hibernate.query.sqm.UnknownEntityException;
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor; import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.internal.ParameterCollector; import org.hibernate.query.sqm.internal.ParameterCollector;
import org.hibernate.query.sqm.internal.SqmCreationProcessingStateImpl;
import org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState; import org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState;
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl; import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
@ -92,6 +92,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMaxIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmMinElementPath; import org.hibernate.query.sqm.tree.domain.SqmMinElementPath;
import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath; import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor; import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.expression.SqmAny; import org.hibernate.query.sqm.tree.expression.SqmAny;
@ -164,6 +165,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE; import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME; import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;
@ -171,7 +173,17 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.hibernate.grammars.hql.HqlParser.IDENTIFIER; import static org.hibernate.grammars.hql.HqlParser.IDENTIFIER;
import static org.hibernate.query.TemporalUnit.*; import static org.hibernate.query.TemporalUnit.DATE;
import static org.hibernate.query.TemporalUnit.DAY_OF_MONTH;
import static org.hibernate.query.TemporalUnit.DAY_OF_WEEK;
import static org.hibernate.query.TemporalUnit.DAY_OF_YEAR;
import static org.hibernate.query.TemporalUnit.NANOSECOND;
import static org.hibernate.query.TemporalUnit.OFFSET;
import static org.hibernate.query.TemporalUnit.TIME;
import static org.hibernate.query.TemporalUnit.TIMEZONE_HOUR;
import static org.hibernate.query.TemporalUnit.TIMEZONE_MINUTE;
import static org.hibernate.query.TemporalUnit.WEEK_OF_MONTH;
import static org.hibernate.query.TemporalUnit.WEEK_OF_YEAR;
import static org.hibernate.type.descriptor.DateTimeUtils.DATE_TIME; import static org.hibernate.type.descriptor.DateTimeUtils.DATE_TIME;
import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType; import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType;
@ -310,7 +322,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
final SqmRoot<?> root = new SqmRoot<>( final SqmRoot<?> root = new SqmRoot<>(
visitEntityName( ctx.dmlTarget().entityName() ), visitEntityName( ctx.dmlTarget().entityName() ),
visitIdentificationVariableDef( ctx.dmlTarget().identificationVariableDef() ), applyJpaCompliance( visitIdentificationVariableDef( ctx.dmlTarget().identificationVariableDef() ) ),
creationContext.getNodeBuilder() creationContext.getNodeBuilder()
); );
@ -323,15 +335,26 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
); );
processingStateStack.push( processingState ); processingStateStack.push( processingState );
processingState.getPathRegistry().register( root );
try { try {
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) ); insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) { final SqmCreationProcessingState stateFieldsProcessingState = new SqmCreationProcessingStateImpl(
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx ); insertStatement,
// todo : validate each resolved stateField... this
insertStatement.addInsertTargetStateField( stateField ); );
stateFieldsProcessingState.getPathRegistry().register( root );
processingStateStack.push( stateFieldsProcessingState );
try {
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
// todo : validate each resolved stateField...
insertStatement.addInsertTargetStateField( stateField );
}
}
finally {
processingStateStack.pop();
} }
return insertStatement; return insertStatement;
@ -560,7 +583,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
@Override @Override
public SqmSelection visitSelection(HqlParser.SelectionContext ctx) { public SqmSelection visitSelection(HqlParser.SelectionContext ctx) {
final String resultIdentifier = visitResultIdentifier( ctx.resultIdentifier() ); final String resultIdentifier = applyJpaCompliance( visitResultIdentifier( ctx.resultIdentifier() ) );
final SqmSelectableNode selectableNode = visitSelectableNode( ctx ); final SqmSelectableNode selectableNode = visitSelectableNode( ctx );
//noinspection unchecked //noinspection unchecked
@ -746,7 +769,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
} }
if ( sortExpression instanceof SqmLiteral if ( sortExpression instanceof SqmLiteral
|| sortExpression instanceof SqmParameter ) { || sortExpression instanceof SqmParameter ) {
HqlLogger.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression ); HqlLogging.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression );
} }
final String collation; final String collation;
@ -903,8 +926,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
final SqmFromClause fromClause = new SqmFromClause( parserFromClause==null ? 0 : parserFromClause.fromClauseSpace().size() ); final SqmFromClause fromClause = new SqmFromClause( parserFromClause==null ? 0 : parserFromClause.fromClauseSpace().size() );
if ( parserFromClause!=null ) { if ( parserFromClause!=null ) {
for ( HqlParser.FromClauseSpaceContext parserSpace : parserFromClause.fromClauseSpace() ) { for ( HqlParser.FromClauseSpaceContext parserSpace : parserFromClause.fromClauseSpace() ) {
final SqmRoot sqmPathRoot = visitFromClauseSpace(parserSpace); final SqmRoot sqmPathRoot = visitFromClauseSpace( parserSpace );
fromClause.addRoot(sqmPathRoot); fromClause.addRoot( sqmPathRoot );
} }
} }
return fromClause; return fromClause;
@ -935,14 +958,15 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
} }
@Override @Override
@SuppressWarnings( { "rawtypes", "unchecked" } )
public SqmRoot visitPathRoot(HqlParser.PathRootContext ctx) { public SqmRoot visitPathRoot(HqlParser.PathRootContext ctx) {
final String name = ctx.entityName().fullNameText; final String name = ctx.entityName().fullNameText;
log.debugf( "Handling root path - %s", name ); log.debugf( "Handling root path - %s", name );
final EntityDomainType entityDescriptor = getCreationContext().getJpaMetamodel().resolveHqlEntityReference( final EntityDomainType entityDescriptor = getCreationContext()
name .getJpaMetamodel()
); .resolveHqlEntityReference( name );
checkFQNEntityNameJpaComplianceViolationIfNeeded( name, entityDescriptor ); checkFQNEntityNameJpaComplianceViolationIfNeeded( name, entityDescriptor );
@ -962,15 +986,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
} }
} }
final String alias = visitIdentificationVariableDef( ctx.identificationVariableDef() ); final String alias = applyJpaCompliance(
visitIdentificationVariableDef( ctx.identificationVariableDef() )
//noinspection unchecked
final SqmRoot sqmRoot = new SqmRoot(
entityDescriptor,
alias,
creationContext.getNodeBuilder()
); );
final SqmRoot sqmRoot = new SqmRoot( entityDescriptor, alias, creationContext.getNodeBuilder() );
processingStateStack.getCurrent().getPathRegistry().register( sqmRoot ); processingStateStack.getCurrent().getPathRegistry().register( sqmRoot );
return sqmRoot; return sqmRoot;
@ -1009,6 +1030,18 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
return null; return null;
} }
private String applyJpaCompliance(String text) {
if ( text == null ) {
return null;
}
if ( getCreationOptions().useStrictJpaCompliance() ) {
return text.toLowerCase( Locale.getDefault() );
}
return text;
}
@Override @Override
public final SqmCrossJoin visitCrossJoin(HqlParser.CrossJoinContext ctx) { public final SqmCrossJoin visitCrossJoin(HqlParser.CrossJoinContext ctx) {
throw new UnsupportedOperationException( "Unexpected call to #visitCrossJoin, see #consumeCrossJoin" ); throw new UnsupportedOperationException( "Unexpected call to #visitCrossJoin, see #consumeCrossJoin" );
@ -1217,7 +1250,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
@Override @Override
public SqmEmptinessPredicate visitIsEmptyPredicate(HqlParser.IsEmptyPredicateContext ctx) { public SqmEmptinessPredicate visitIsEmptyPredicate(HqlParser.IsEmptyPredicateContext ctx) {
return new SqmEmptinessPredicate( return new SqmEmptinessPredicate(
(SqmPath) ctx.expression().accept( this ), (SqmPluralValuedSimplePath<?>) ctx.expression().accept( this ),
ctx.NOT() != null, ctx.NOT() != null,
creationContext.getNodeBuilder() creationContext.getNodeBuilder()
); );

View File

@ -12,8 +12,9 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.hql.HqlLogger; import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.SqmCreationProcessingState; import org.hibernate.query.hql.spi.SqmCreationProcessingState;
import org.hibernate.query.hql.spi.SqmPathRegistry; import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.AliasCollisionException; import org.hibernate.query.sqm.AliasCollisionException;
@ -31,6 +32,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelection;
*/ */
public class SqmPathRegistryImpl implements SqmPathRegistry { public class SqmPathRegistryImpl implements SqmPathRegistry {
private final SqmCreationProcessingState associatedProcessingState; private final SqmCreationProcessingState associatedProcessingState;
private final JpaCompliance jpaCompliance;
private final Map<NavigablePath, SqmPath> sqmPathByPath = new HashMap<>(); private final Map<NavigablePath, SqmPath> sqmPathByPath = new HashMap<>();
private final Map<NavigablePath, SqmFrom> sqmFromByPath = new HashMap<>(); private final Map<NavigablePath, SqmFrom> sqmFromByPath = new HashMap<>();
@ -41,6 +43,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
public SqmPathRegistryImpl(SqmCreationProcessingState associatedProcessingState) { public SqmPathRegistryImpl(SqmCreationProcessingState associatedProcessingState) {
this.associatedProcessingState = associatedProcessingState; this.associatedProcessingState = associatedProcessingState;
this.jpaCompliance = associatedProcessingState.getCreationState().getCreationContext().getJpaMetamodel().getJpaCompliance();
} }
@Override @Override
@ -60,7 +63,12 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
final String alias = sqmPath.getExplicitAlias(); final String alias = sqmPath.getExplicitAlias();
if ( alias != null ) { if ( alias != null ) {
final SqmFrom previousFrom = sqmFromByAlias.put( alias, sqmFrom ); final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;
final SqmFrom previousFrom = sqmFromByAlias.put( aliasToUse, sqmFrom );
if ( previousFrom != null ) { if ( previousFrom != null ) {
throw new AliasCollisionException( throw new AliasCollisionException(
String.format( String.format(
@ -148,7 +156,12 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
@Override @Override
public SqmFrom findFromByAlias(String alias) { public SqmFrom findFromByAlias(String alias) {
final SqmFrom registered = sqmFromByAlias.get( alias ); final String localAlias = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;
final SqmFrom registered = sqmFromByAlias.get( localAlias );
if ( registered != null ) { if ( registered != null ) {
return registered; return registered;
} }
@ -167,10 +180,11 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
// (configurable?) option would be to simply pick the first one as a perf optimization // (configurable?) option would be to simply pick the first one as a perf optimization
SqmFrom found = null; SqmFrom found = null;
for ( SqmFrom fromElement : sqmFromByPath.values() ) { for ( Map.Entry<NavigablePath, SqmFrom> entry : sqmFromByPath.entrySet() ) {
final SqmFrom fromElement = entry.getValue();
if ( definesAttribute( fromElement.getReferencedPathSource(), navigableName ) ) { if ( definesAttribute( fromElement.getReferencedPathSource(), navigableName ) ) {
if ( found != null ) { if ( found != null ) {
// throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + navigableName ); throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + navigableName );
} }
found = fromElement; found = fromElement;
} }
@ -178,7 +192,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
if ( found == null ) { if ( found == null ) {
if ( associatedProcessingState.getParentProcessingState() != null ) { if ( associatedProcessingState.getParentProcessingState() != null ) {
HqlLogger.QUERY_LOGGER.debugf( HqlLogging.QUERY_LOGGER.debugf(
"Unable to resolve unqualified attribute [%s] in local from-clause; checking parent ", "Unable to resolve unqualified attribute [%s] in local from-clause; checking parent ",
navigableName navigableName
); );
@ -186,6 +200,11 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
} }
} }
HqlLogging.QUERY_LOGGER.debugf(
"Unable to resolve unqualified attribute [%s] in local from-clause",
navigableName
);
return found; return found;
} }

View File

@ -9,7 +9,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.grammars.hql.HqlLexer; import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser; import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.hql.HqlLogger; import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.sqm.InterpretationException; import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.internal.SqmTreePrinter; import org.hibernate.query.sqm.internal.SqmTreePrinter;
@ -42,7 +42,7 @@ public class StandardHqlTranslator implements HqlTranslator {
@Override @Override
public SqmStatement translate(String query) { public SqmStatement translate(String query) {
HqlLogger.QUERY_LOGGER.debugf( "HQL : " + query ); HqlLogging.QUERY_LOGGER.debugf( "HQL : " + query );
final HqlParser.StatementContext hqlParseTree = parseHql( query ); final HqlParser.StatementContext hqlParseTree = parseHql( query );

View File

@ -89,5 +89,4 @@ public interface SqmPathRegistry {
* Find an SqmSelection by its position in the SqmSelectClause * Find an SqmSelection by its position in the SqmSelectClause
*/ */
SqmSelection findSelectionByPosition(int position); SqmSelection findSelectionByPosition(int position);
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.query.results; package org.hibernate.query.results;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -50,6 +51,10 @@ public class ResultSetMappingImpl implements ResultSetMapping {
return resultBuilders == null ? 0 : resultBuilders.size(); return resultBuilders == null ? 0 : resultBuilders.size();
} }
public List<ResultBuilder> getResultBuilders() {
return Collections.unmodifiableList( resultBuilders );
}
@Override @Override
public void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer) { public void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer) {
if ( resultBuilders == null ) { if ( resultBuilders == null ) {

View File

@ -10,6 +10,7 @@ import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlExpressionAccess;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
@ -22,7 +23,7 @@ import org.hibernate.type.spi.TypeConfiguration;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqlSelectionImpl implements SqlSelection, Expression { public class SqlSelectionImpl implements SqlSelection, Expression, SqlExpressionAccess {
private final int valuesArrayPosition; private final int valuesArrayPosition;
private final BasicValuedMapping valueMapping; private final BasicValuedMapping valueMapping;
private final JdbcMapping jdbcMapping; private final JdbcMapping jdbcMapping;
@ -68,4 +69,9 @@ public class SqlSelectionImpl implements SqlSelection, Expression {
public void accept(SqlAstWalker sqlAstWalker) { public void accept(SqlAstWalker sqlAstWalker) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public Expression getSqlExpression() {
return this;
}
} }

View File

@ -58,6 +58,7 @@ import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.IllegalQueryOperationException; import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.ParameterMetadata; import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer; import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer; import org.hibernate.query.TupleTransformer;
@ -67,6 +68,9 @@ import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import static org.hibernate.LockMode.UPGRADE;
import static org.hibernate.LockOptions.NONE;
import static org.hibernate.LockOptions.READ;
import static org.hibernate.LockOptions.WAIT_FOREVER; import static org.hibernate.LockOptions.WAIT_FOREVER;
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; 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_LOCK_TIMEOUT;
@ -143,12 +147,6 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return session; return session;
} }
protected abstract boolean canApplyAliasSpecificLockModes();
protected abstract void verifySettingLockMode();
protected abstract void verifySettingAliasSpecificLockModes();
protected abstract QueryParameterBindings getQueryParameterBindings(); protected abstract QueryParameterBindings getQueryParameterBindings();
@Override @Override
@ -164,27 +162,44 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public int getMaxResults() { public int getMaxResults() {
getSession().checkOpen();
return getQueryOptions().getLimit().getMaxRowsJpa(); return getQueryOptions().getLimit().getMaxRowsJpa();
} }
@Override @Override
public QueryImplementor<R> setMaxResults(int maxResult) { public QueryImplementor<R> setMaxResults(int maxResult) {
if ( maxResult < 0 ) {
throw new IllegalArgumentException( "max-results cannot be negative" );
}
getSession().checkOpen();
getQueryOptions().getLimit().setMaxRows( maxResult ); getQueryOptions().getLimit().setMaxRows( maxResult );
return this; return this;
} }
@Override @Override
public int getFirstResult() { public int getFirstResult() {
getSession().checkOpen();
return getQueryOptions().getLimit().getFirstRowJpa(); return getQueryOptions().getLimit().getFirstRowJpa();
} }
@Override @Override
public QueryImplementor<R> setFirstResult(int startPosition) { public QueryImplementor<R> setFirstResult(int startPosition) {
getSession().checkOpen();
if ( startPosition < 0 ) {
throw new IllegalArgumentException( "first-result value cannot be negative : " + startPosition );
}
getQueryOptions().getLimit().setFirstRow( startPosition ); getQueryOptions().getLimit().setFirstRow( startPosition );
return this; return this;
} }
@Override @Override
@SuppressWarnings( "rawtypes" )
public QueryImplementor<R> setTupleTransformer(TupleTransformer transformer) { public QueryImplementor<R> setTupleTransformer(TupleTransformer transformer) {
getQueryOptions().setTupleTransformer( transformer ); getQueryOptions().setTupleTransformer( transformer );
return this; return this;
@ -196,25 +211,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this; return this;
} }
@Override
public LockModeType getLockMode() {
return LockModeTypeHelper.getLockModeType( getQueryOptions().getLockOptions().getLockMode() );
}
@Override @Override
public FlushMode getHibernateFlushMode() { public FlushMode getHibernateFlushMode() {
return getQueryOptions().getFlushMode(); return getQueryOptions().getFlushMode();
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setHibernateFlushMode(FlushMode flushMode) {
public QueryImplementor setHibernateFlushMode(FlushMode flushMode) {
getQueryOptions().setFlushMode( flushMode ); getQueryOptions().setFlushMode( flushMode );
return this; return this;
} }
@Override @Override
public FlushModeType getFlushMode() { public FlushModeType getFlushMode() {
getSession().checkOpen();
final FlushMode flushMode = getQueryOptions().getFlushMode() == null final FlushMode flushMode = getQueryOptions().getFlushMode() == null
? getSession().getHibernateFlushMode() ? getSession().getHibernateFlushMode()
: getQueryOptions().getFlushMode(); : getQueryOptions().getFlushMode();
@ -222,8 +232,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setFlushMode(FlushModeType flushModeType) {
public QueryImplementor setFlushMode(FlushModeType flushModeType) { getSession().checkOpen();
setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) ); setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) );
return this; return this;
} }
@ -234,8 +244,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setCacheMode(CacheMode cacheMode) {
public QueryImplementor setCacheMode(CacheMode cacheMode) {
getQueryOptions().setCacheMode( cacheMode ); getQueryOptions().setCacheMode( cacheMode );
return this; return this;
} }
@ -246,8 +255,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setCacheable(boolean cacheable) {
public QueryImplementor setCacheable(boolean cacheable) {
getQueryOptions().setResultCachingEnabled( cacheable ); getQueryOptions().setResultCachingEnabled( cacheable );
return this; return this;
} }
@ -258,8 +266,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setCacheRegion(String cacheRegion) {
public QueryImplementor setCacheRegion(String cacheRegion) {
getQueryOptions().setResultCacheRegionName( cacheRegion ); getQueryOptions().setResultCacheRegionName( cacheRegion );
return this; return this;
} }
@ -270,8 +277,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setTimeout(int timeout) {
public QueryImplementor setTimeout(int timeout) {
getQueryOptions().setTimeout( timeout ); getQueryOptions().setTimeout( timeout );
return this; return this;
} }
@ -282,8 +288,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setFetchSize(int fetchSize) {
public QueryImplementor setFetchSize(int fetchSize) {
getQueryOptions().setFetchSize( fetchSize ); getQueryOptions().setFetchSize( fetchSize );
return this; return this;
} }
@ -296,8 +301,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setReadOnly(boolean readOnly) {
public QueryImplementor setReadOnly(boolean readOnly) {
getQueryOptions().setReadOnly( readOnly ); getQueryOptions().setReadOnly( readOnly );
return this; return this;
} }
@ -308,8 +312,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public LockModeType getLockMode() {
public QueryImplementor setLockOptions(LockOptions lockOptions) { getSession().checkOpen( false );
return LockModeTypeHelper.getLockModeType( getQueryOptions().getLockOptions().getLockMode() );
}
@Override
public QueryImplementor<R> setLockOptions(LockOptions lockOptions) {
getQueryOptions().getLockOptions().setLockMode( lockOptions.getLockMode() ); getQueryOptions().getLockOptions().setLockMode( lockOptions.getLockMode() );
getQueryOptions().getLockOptions().setScope( lockOptions.getScope() ); getQueryOptions().getLockOptions().setScope( lockOptions.getScope() );
getQueryOptions().getLockOptions().setTimeOut( lockOptions.getTimeOut() ); getQueryOptions().getLockOptions().setTimeOut( lockOptions.getTimeOut() );
@ -318,23 +328,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
public QueryImplementor setLockMode(String alias, LockMode lockMode) {
if ( !LockMode.NONE.equals( lockMode ) ) {
verifySettingAliasSpecificLockModes();
}
getQueryOptions().getLockOptions().setAliasSpecificLockMode( alias, lockMode ); getQueryOptions().getLockOptions().setAliasSpecificLockMode( alias, lockMode );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setLockMode(LockModeType lockModeType) {
public QueryImplementor setLockMode(LockModeType lockModeType) { getSession().checkOpen();
if ( !LockModeType.NONE.equals( lockModeType ) ) {
verifySettingLockMode();
}
getQueryOptions().getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); getQueryOptions().getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
return this; return this;
} }
@ -345,15 +346,13 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> setComment(String comment) {
public QueryImplementor setComment(String comment) {
getQueryOptions().setComment( comment ); getQueryOptions().setComment( comment );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") public QueryImplementor<R> addQueryHint(String hint) {
public QueryImplementor addQueryHint(String hint) {
getQueryOptions().addDatabaseHint( hint ); getQueryOptions().addDatabaseHint( hint );
return this; return this;
} }
@ -375,16 +374,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
getSession().checkOpen( false ); getSession().checkOpen( false );
final Map<String,Object> hints = new HashMap<>(); final Map<String,Object> hints = new HashMap<>();
collectBaselineHints( hints );
collectHints( hints ); collectHints( hints );
return hints; return hints;
} }
@SuppressWarnings("WeakerAccess")
protected void collectBaselineHints(Map<String, Object> hints) {
// nothing to do in this form
}
protected void collectHints(Map<String, Object> hints) { protected void collectHints(Map<String, Object> hints) {
if ( getQueryOptions().getTimeout() != null ) { if ( getQueryOptions().getTimeout() != null ) {
hints.put( HINT_TIMEOUT, getQueryOptions().getTimeout() ); hints.put( HINT_TIMEOUT, getQueryOptions().getTimeout() );
@ -428,7 +421,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
} }
protected void putIfNotNull(Map<String, Object> hints, String hintName, Enum hintValue) { protected void putIfNotNull(Map<String, Object> hints, String hintName, Enum<?> hintValue) {
// centralized spot to handle the decision whether to put enums directly into the hints map // centralized spot to handle the decision whether to put enums directly into the hints map
// or whether to put the enum name // or whether to put the enum name
if ( hintValue != null ) { if ( hintValue != null ) {
@ -446,6 +439,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public QueryImplementor<R> setHint(String hintName, Object value) { public QueryImplementor<R> setHint(String hintName, Object value) {
getSession().checkOpen( true ); getSession().checkOpen( true );
boolean applied = false; boolean applied = false;
try { try {
if ( HINT_TIMEOUT.equals( hintName ) ) { if ( HINT_TIMEOUT.equals( hintName ) ) {
@ -492,27 +486,22 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
applied = applyNativeQueryLockMode( value ); applied = applyNativeQueryLockMode( value );
} }
else if ( hintName.startsWith( ALIAS_SPECIFIC_LOCK_MODE ) ) { else if ( hintName.startsWith( ALIAS_SPECIFIC_LOCK_MODE ) ) {
if ( canApplyAliasSpecificLockModes() ) { // extract the alias
// extract the alias final String alias = hintName.substring( ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
final String alias = hintName.substring( ALIAS_SPECIFIC_LOCK_MODE.length() + 1 ); // determine the LockMode
// determine the LockMode try {
try { final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value ); applyAliasSpecificLockModeHint( alias, lockMode );
applyAliasSpecificLockModeHint( alias, lockMode ); applied = true;
}
catch ( Exception e ) {
log.unableToDetermineLockModeValue( hintName, value );
applied = false;
}
} }
else { catch ( Exception e ) {
//noinspection ConstantConditions log.unableToDetermineLockModeValue( hintName, value );
applied = false; applied = false;
} }
} }
else if ( HINT_FETCHGRAPH.equals( hintName ) || HINT_LOADGRAPH.equals( hintName ) ) { else if ( HINT_FETCHGRAPH.equals( hintName ) || HINT_LOADGRAPH.equals( hintName ) ) {
if (value instanceof RootGraphImplementor ) { if (value instanceof RootGraphImplementor ) {
applyEntityGraphQueryHint( hintName, (RootGraphImplementor) value ); applyEntityGraphQueryHint( hintName, (RootGraphImplementor<?>) value );
} }
else { else {
log.warnf( "The %s hint was set, but the value was not an EntityGraph!", hintName ); log.warnf( "The %s hint was set, but the value was not an EntityGraph!", hintName );
@ -682,29 +671,34 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return true; return true;
} }
@SuppressWarnings( "UnusedReturnValue" )
protected boolean applyLockModeTypeHint(LockModeType lockModeType) { protected boolean applyLockModeTypeHint(LockModeType lockModeType) {
getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
return true; return true;
} }
@SuppressWarnings( "UnusedReturnValue" )
protected boolean applyHibernateLockModeHint(LockMode lockMode) { protected boolean applyHibernateLockModeHint(LockMode lockMode) {
getLockOptions().setLockMode( lockMode ); final LockOptions lockOptions;
if ( lockMode == LockMode.NONE ) {
lockOptions = NONE;
}
else if ( lockMode == LockMode.READ ) {
lockOptions = READ;
}
else if ( lockMode == UPGRADE || lockMode == LockMode.PESSIMISTIC_WRITE ) {
lockOptions = LockOptions.UPGRADE;
}
return true; return true;
} }
/**
* Apply the alias specific lock modes. Assumes {@link #canApplyAliasSpecificLockModes()} has already been
* called and returned {@code true}.
*
* @param alias The alias to apply the 'lockMode' to.
* @param lockMode The LockMode to apply.
*/
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected void applyAliasSpecificLockModeHint(String alias, LockMode lockMode) { protected void applyAliasSpecificLockModeHint(String alias, LockMode lockMode) {
getLockOptions().setAliasSpecificLockMode( alias, lockMode ); setLockMode( alias, lockMode );
} }
protected abstract void applyEntityGraphQueryHint(String hintName, RootGraphImplementor entityGraph); protected abstract void applyEntityGraphQueryHint(String hintName, RootGraphImplementor<?> entityGraph);
/** /**
* Apply the follow-on-locking hint. * Apply the follow-on-locking hint.
@ -719,19 +713,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// QueryParameter handling // QueryParameter handling
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public Set<Parameter<?>> getParameters() { public Set<Parameter<?>> getParameters() {
getSession().checkOpen( false );
return (Set) ( (ParameterMetadata) getParameterMetadata() ).getRegistrations(); return (Set) ( (ParameterMetadata) getParameterMetadata() ).getRegistrations();
} }
@Override @Override
public Parameter<?> getParameter(String name) { public Parameter<?> getParameter(String name) {
getSession().checkOpen( false );
try { try {
return getParameterMetadata().getQueryParameter( name ); return getParameterMetadata().getQueryParameter( name );
} }
@ -743,7 +738,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Parameter<T> getParameter(String name, Class<T> type) { public <T> Parameter<T> getParameter(String name, Class<T> type) {
getSession().checkOpen( false );
try { try {
//noinspection rawtypes
final QueryParameter parameter = getParameterMetadata().getQueryParameter( name ); final QueryParameter parameter = getParameterMetadata().getQueryParameter( name );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) { if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -761,6 +759,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public Parameter<?> getParameter(int position) { public Parameter<?> getParameter(int position) {
getSession().checkOpen( false );
try { try {
return getParameterMetadata().getQueryParameter( position ); return getParameterMetadata().getQueryParameter( position );
} }
@ -770,8 +770,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public <T> Parameter<T> getParameter(int position, Class<T> type) { public <T> Parameter<T> getParameter(int position, Class<T> type) {
getSession().checkOpen( false );
try { try {
final QueryParameter parameter = getParameterMetadata().getQueryParameter( position ); final QueryParameter parameter = getParameterMetadata().getQueryParameter( position );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) { if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
@ -790,14 +792,15 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public boolean isBound(Parameter<?> param) { public boolean isBound(Parameter<?> param) {
final QueryParameterImplementor qp = getParameterMetadata().resolve( param ); getSession().checkOpen();
final QueryParameterImplementor<?> qp = getParameterMetadata().resolve( param );
return qp != null && getQueryParameterBindings().isBound( qp ); return qp != null && getQueryParameterBindings().isBound( qp );
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings( {"WeakerAccess", "unchecked", "rawtypes"} )
protected <P> QueryParameterBinding<P> locateBinding(Parameter<P> parameter) { protected <P> QueryParameterBinding<P> locateBinding(Parameter<P> parameter) {
if ( parameter instanceof QueryParameterImplementor ) { if ( parameter instanceof QueryParameterImplementor ) {
//noinspection unchecked
return locateBinding( (QueryParameterImplementor) parameter ); return locateBinding( (QueryParameterImplementor) parameter );
} }
else if ( parameter.getName() != null ) { else if ( parameter.getName() != null ) {
@ -814,20 +817,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected <P> QueryParameterBinding<P> locateBinding(QueryParameterImplementor<P> parameter) { protected <P> QueryParameterBinding<P> locateBinding(QueryParameterImplementor<P> parameter) {
//noinspection unchecked getSession().checkOpen();
return getQueryParameterBindings().getBinding( parameter ); return getQueryParameterBindings().getBinding( parameter );
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings( {"WeakerAccess", "unchecked"} )
protected <P> QueryParameterBinding<P> locateBinding(String name) { protected <P> QueryParameterBinding<P> locateBinding(String name) {
//noinspection unchecked getSession().checkOpen();
return (QueryParameterBinding) getQueryParameterBindings().getBinding( name ); return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( name );
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings( {"WeakerAccess", "unchecked"} )
protected <P> QueryParameterBinding<P> locateBinding(int position) { protected <P> QueryParameterBinding<P> locateBinding(int position) {
//noinspection unchecked getSession().checkOpen();
return (QueryParameterBinding) getQueryParameterBindings().getBinding( position ); return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( position );
} }
@Override @Override
@ -920,7 +923,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this; return this;
} }
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
private <P> void setParameter(Parameter<P> parameter, Object value, AllowableParameterType type) { private <P> void setParameter(Parameter<P> parameter, Object value, AllowableParameterType type) {
if ( parameter instanceof QueryParameter ) { if ( parameter instanceof QueryParameter ) {
setParameter( (QueryParameter) parameter, value, type ); setParameter( (QueryParameter) parameter, value, type );
@ -943,6 +946,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() ); setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() );
} }
else if ( value instanceof Collection ) { else if ( value instanceof Collection ) {
//noinspection rawtypes
setParameterList( name, (Collection) value ); setParameterList( name, (Collection) value );
} }
else { else {
@ -958,7 +962,9 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
final TypedParameterValue typedParameterValue = (TypedParameterValue) value; final TypedParameterValue typedParameterValue = (TypedParameterValue) value;
setParameter( position, typedParameterValue.getValue(), typedParameterValue.getType() ); setParameter( position, typedParameterValue.getValue(), typedParameterValue.getType() );
} }
if ( value instanceof Collection ) { if ( value instanceof Collection ) {
//noinspection rawtypes
setParameterList( Integer.toString( position ), (Collection) value ); setParameterList( Integer.toString( position ), (Collection) value );
} }
else { else {
@ -968,21 +974,21 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType type) { public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType type) {
locateBinding( parameter ).setBindValue( value, type ); locateBinding( parameter ).setBindValue( value, type );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(String name, Object value, AllowableParameterType type) { public QueryImplementor<R> setParameter(String name, Object value, AllowableParameterType type) {
locateBinding( name ).setBindValue( value, type ); locateBinding( name ).setBindValue( value, type );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor setParameter(int position, Object value, AllowableParameterType type) { public QueryImplementor setParameter(int position, Object value, AllowableParameterType type) {
locateBinding( position ).setBindValue( value, type ); locateBinding( position ).setBindValue( value, type );
return this; return this;
@ -1012,29 +1018,29 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this; return this;
} }
@SuppressWarnings("unchecked")
@Override @Override
public QueryImplementor setParameterList(String name, Collection values) { @SuppressWarnings( {"rawtypes", "unchecked"} )
public QueryImplementor<R> setParameterList(String name, Collection values) {
locateBinding( name ).setBindValues( values ); locateBinding( name ).setBindValues( values );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values) { public QueryImplementor<R> setParameterList(int position, Collection values) {
locateBinding( position ).setBindValues( values ); locateBinding( position ).setBindValues( values );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Collection values, AllowableParameterType type) { public QueryImplementor<R> setParameterList(String name, Collection values, AllowableParameterType type) {
locateBinding( name ).setBindValues( values, type ); locateBinding( name ).setBindValues( values, type );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values, AllowableParameterType type) { public QueryImplementor<R> setParameterList(int position, Collection values, AllowableParameterType type) {
locateBinding( position ).setBindValues( values, type ); locateBinding( position ).setBindValues( values, type );
return this; return this;
@ -1053,21 +1059,21 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType type) { public QueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType type) {
locateBinding( name ).setBindValues( Arrays.asList( values ), type ); locateBinding( name ).setBindValues( Arrays.asList( values ), type );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType type) { public QueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType type) {
locateBinding( position ).setBindValues( Arrays.asList( values ), type ); locateBinding( position ).setBindValues( Arrays.asList( values ), type );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Collection values, Class javaType) { public QueryImplementor<R> setParameterList(String name, Collection values, Class javaType) {
final JavaTypeDescriptor javaDescriptor = getSession().getFactory() final JavaTypeDescriptor javaDescriptor = getSession().getFactory()
.getTypeConfiguration() .getTypeConfiguration()
@ -1102,7 +1108,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values, Class javaType) { public QueryImplementor<R> setParameterList(int position, Collection values, Class javaType) {
final JavaTypeDescriptor javaDescriptor = getSession().getFactory() final JavaTypeDescriptor javaDescriptor = getSession().getFactory()
.getTypeConfiguration() .getTypeConfiguration()
@ -1137,14 +1143,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) { public QueryImplementor<R> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
locateBinding( (QueryParameter) param ).setBindValue( value, temporalType ); locateBinding( (QueryParameter) param ).setBindValue( value, temporalType );
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) { public QueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
locateBinding( (QueryParameter) param ).setBindValue( value, temporalType ); locateBinding( (QueryParameter) param ).setBindValue( value, temporalType );
return this; return this;
@ -1175,8 +1181,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public <T> T getParameterValue(Parameter<T> param) { public <T> T getParameterValue(Parameter<T> param) {
QueryLogging.QUERY_LOGGER.tracef( "#getParameterValue(%s)", param );
final QueryParameterImplementor qp = getParameterMetadata().resolve( param ); final QueryParameterImplementor qp = getParameterMetadata().resolve( param );
if ( qp == null ) { if ( qp == null ) {
throw new IllegalArgumentException( "The parameter [" + param + "] is not part of this Query" ); throw new IllegalArgumentException( "The parameter [" + param + "] is not part of this Query" );
@ -1184,7 +1192,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp ); final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp );
if ( binding == null || !binding.isBound() ) { if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "The parameter [" + param + "] has not yet been bound" ); throw new IllegalStateException( "Parameter value not yet bound : " + param.toString() );
} }
if ( binding.isMultiValued() ) { if ( binding.isMultiValued() ) {
@ -1197,14 +1205,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public Object getParameterValue(String name) { public Object getParameterValue(String name) {
final QueryParameterImplementor qp = getParameterMetadata().getQueryParameter( name ); final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( name );
if ( qp == null ) { if ( parameter == null ) {
throw new IllegalArgumentException( "The parameter [" + name + "] is not part of this Query" ); throw new IllegalArgumentException( "Could not resolve parameter by name - " + name );
} }
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp ); final QueryParameterBinding<?> binding = getQueryParameterBindings().getBinding( parameter );
if ( binding == null || !binding.isBound() ) { if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "The parameter [" + name + "] has not yet been bound" ); throw new IllegalStateException( "Parameter value not yet bound : " + parameter.toString() );
} }
if ( binding.isMultiValued() ) { if ( binding.isMultiValued() ) {
@ -1217,12 +1225,12 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public Object getParameterValue(int position) { public Object getParameterValue(int position) {
final QueryParameterImplementor qp = getParameterMetadata().getQueryParameter( position ); final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( position );
if ( qp == null ) { if ( parameter == null ) {
throw new IllegalArgumentException( "The parameter [" + position + "] is not part of this Query" ); throw new IllegalArgumentException( "Could not resolve parameter by position - " + position );
} }
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp ); final QueryParameterBinding<?> binding = getQueryParameterBindings().getBinding( parameter );
if ( binding == null || !binding.isBound() ) { if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "The parameter [" + position + "] has not yet been bound" ); throw new IllegalStateException( "The parameter [" + position + "] has not yet been bound" );
} }
@ -1271,7 +1279,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override @Override
public QueryImplementor<R> setProperties(Object bean) { public QueryImplementor<R> setProperties(Object bean) {
Class clazz = bean.getClass(); final Class<?> clazz = bean.getClass();
for ( String paramName : getParameterMetadata().getNamedParameterNames() ) { for ( String paramName : getParameterMetadata().getNamedParameterNames() ) {
try { try {
final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess( final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess(
@ -1279,16 +1287,16 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
paramName paramName
); );
final Getter getter = propertyAccess.getGetter(); final Getter getter = propertyAccess.getGetter();
final Class retType = getter.getReturnType(); final Class<?> retType = getter.getReturnType();
final Object object = getter.get( bean ); final Object object = getter.get( bean );
if ( Collection.class.isAssignableFrom( retType ) ) { if ( Collection.class.isAssignableFrom( retType ) ) {
setParameterList( paramName, (Collection) object ); setParameterList( paramName, (Collection<?>) object );
} }
else if ( retType.isArray() ) { else if ( retType.isArray() ) {
setParameterList( paramName, (Object[]) object ); setParameterList( paramName, (Object[]) object );
} }
else { else {
AllowableParameterType type = determineType( paramName, retType ); AllowableParameterType<?> type = determineType( paramName, retType );
setParameter( paramName, object, type ); setParameter( paramName, object, type );
} }
} }
@ -1300,8 +1308,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected AllowableParameterType determineType(String namedParam, Class retType) { protected AllowableParameterType<?> determineType(String namedParam, Class<?> retType) {
AllowableParameterType type = locateBinding( namedParam ).getBindType(); AllowableParameterType<?> type = locateBinding( namedParam ).getBindType();
if ( type == null ) { if ( type == null ) {
type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType(); type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType();
} }
@ -1312,8 +1320,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( "rawtypes" )
public QueryImplementor setProperties(Map map) { public QueryImplementor<R> setProperties(Map map) {
for ( String paramName : getParameterMetadata().getNamedParameterNames() ) { for ( String paramName : getParameterMetadata().getNamedParameterNames() ) {
final Object object = map.get( paramName ); final Object object = map.get( paramName );
if ( object == null ) { if ( object == null ) {
@ -1417,12 +1425,12 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
@Override @Override
public ScrollableResultsImplementor scroll() { public ScrollableResultsImplementor<?> scroll() {
return scroll( getSession().getFactory().getJdbcServices().getJdbcEnvironment().getDialect().defaultScrollMode() ); return scroll( getSession().getFactory().getJdbcServices().getJdbcEnvironment().getDialect().defaultScrollMode() );
} }
@Override @Override
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) { public ScrollableResultsImplementor<?> scroll(ScrollMode scrollMode) {
beforeQuery( false ); beforeQuery( false );
try { try {
return doScroll( scrollMode ); return doScroll( scrollMode );
@ -1432,10 +1440,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
} }
} }
protected abstract ScrollableResultsImplementor doScroll(ScrollMode scrollMode); protected abstract ScrollableResultsImplementor<?> doScroll(ScrollMode scrollMode);
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings( {"unchecked", "rawtypes"} )
public Stream<R> stream() { public Stream<R> stream() {
final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY ); final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults ); final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults );

View File

@ -0,0 +1,21 @@
/*
* 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.sql;
import org.hibernate.query.QueryLogging;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class NativeQueryLogging {
public static final Logger LOGGER = QueryLogging.subLogger( "native" );
public static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
public static final boolean TRACE_ENABLED = LOGGER.isTraceEnabled();
}

View File

@ -19,6 +19,8 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.persistence.AttributeConverter; import javax.persistence.AttributeConverter;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
@ -106,6 +108,7 @@ public class NativeQueryImpl<R>
private final QueryParameterBindings parameterBindings; private final QueryParameterBindings parameterBindings;
private final ResultSetMappingImpl resultSetMapping; private final ResultSetMappingImpl resultSetMapping;
private final boolean resultMappingSuppliedToCtor;
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl(); private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
@ -120,56 +123,78 @@ public class NativeQueryImpl<R>
public NativeQueryImpl( public NativeQueryImpl(
NamedNativeQueryMemento memento, NamedNativeQueryMemento memento,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
super( session ); this(
memento,
() -> {
if ( memento.getResultMappingName() != null ) {
return new ResultSetMappingImpl( memento.getResultMappingName() );
}
else if ( memento.getResultMappingClass() != null ) {
return new ResultSetMappingImpl( memento.getResultMappingClass().getName() );
}
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( memento.getSqlString(), session ); return new ResultSetMappingImpl( memento.getSqlString() );
},
(resultSetMapping, querySpaceConsumer, context ) -> {
if ( memento.getResultMappingName() != null ) {
final NamedResultSetMappingMemento resultSetMappingMemento = session.getFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( memento.getResultMappingName() );
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
}
this.sqlString = parameterInterpretation.getAdjustedSqlString(); if ( memento.getResultMappingClass() != null ) {
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session ); resultSetMapping.addResultBuilder(
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters(); Builders.implicitEntityResultBuilder(
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() ); memento.getResultMappingClass(),
context
)
);
return true;
}
if ( memento.getResultMappingName() != null ) { return false;
this.resultSetMapping = new ResultSetMappingImpl( memento.getResultMappingName() ); },
final NamedResultSetMappingMemento resultSetMappingMemento = getSessionFactory().getQueryEngine() session
.getNamedQueryRepository() );
.getResultSetMappingMemento( memento.getResultMappingName() );
resultSetMappingMemento.resolve(
resultSetMapping,
this::addSynchronizedQuerySpace,
this
);
}
else if ( memento.getResultMappingClass() != null ) {
this.resultSetMapping = new ResultSetMappingImpl( memento.getResultMappingName() );
resultSetMapping.addResultBuilder(
Builders.implicitEntityResultBuilder(
memento.getResultMappingClass(),
this
)
);
}
else {
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
}
applyOptions( memento );
} }
private NativeQueryImpl( @FunctionalInterface
String resultMappingIdentifier, private interface ResultSetMappingHandler {
boolean resolveResultSetMapping(
ResultSetMappingImpl resultSetMapping,
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context);
}
public NativeQueryImpl(
NamedNativeQueryMemento memento, NamedNativeQueryMemento memento,
Supplier<ResultSetMappingImpl> resultSetMappingCreator,
ResultSetMappingHandler resultSetMappingHandler,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
super( session ); super( session );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( memento.getSqlString(), session ); final String mementoSqlString = memento.getSqlString();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( mementoSqlString, session );
this.sqlString = parameterInterpretation.getAdjustedSqlString(); this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session ); this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters(); this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() ); this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.querySpaces = new HashSet<>();
this.resultSetMapping = new ResultSetMappingImpl( resultMappingIdentifier ); this.resultSetMapping = resultSetMappingCreator.get();
//noinspection UnnecessaryLocalVariable
final boolean appliedAnyResults = resultSetMappingHandler.resolveResultSetMapping(
resultSetMapping,
querySpaces::add,
this
);
this.resultMappingSuppliedToCtor = appliedAnyResults;
applyOptions( memento ); applyOptions( memento );
} }
@ -181,12 +206,25 @@ public class NativeQueryImpl<R>
NamedNativeQueryMemento memento, NamedNativeQueryMemento memento,
Class<R> resultJavaType, Class<R> resultJavaType,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
this( memento, session ); this(
memento,
() -> new ResultSetMappingImpl( resultJavaType.getName() ),
(resultSetMapping, querySpaceConsumer, context) -> {
if ( resultJavaType != null ) {
// todo (6.0) : need to add handling for `javax.persistence.NamedNativeQuery#resultSetMapping` // todo (6.0) : really `resultJavaType` could be any type nature - basic, embedded, entity
// and `javax.persistence.NamedNativeQuery#resultClass`
// todo (6.0) : relatedly, does `resultJavaType` come from `NamedNativeQuery#resultClass`? resultSetMapping.addResultBuilder(
Builders.implicitEntityResultBuilder( resultJavaType, context )
);
return true;
}
return false;
},
session
);
} }
/** /**
@ -196,13 +234,21 @@ public class NativeQueryImpl<R>
NamedNativeQueryMemento memento, NamedNativeQueryMemento memento,
String resultSetMappingName, String resultSetMappingName,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
this( resultSetMappingName, memento, session ); this(
memento,
() -> new ResultSetMappingImpl( resultSetMappingName ),
(resultSetMapping, querySpaceConsumer, context) -> {
final NamedResultSetMappingMemento mappingMemento = session.getFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( resultSetMappingName );
assert mappingMemento != null;
mappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
},
session
);
session.getFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( resultSetMappingName )
.resolve( resultSetMapping, this::addSynchronizedQuerySpace, this );
} }
public NativeQueryImpl( public NativeQueryImpl(
@ -211,6 +257,13 @@ public class NativeQueryImpl<R>
AbstractSharedSessionContract session) { AbstractSharedSessionContract session) {
super( session ); super( session );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sqlString, session );
this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( resultSetMappingMemento.getName() ); this.resultSetMapping = new ResultSetMappingImpl( resultSetMappingMemento.getName() );
resultSetMappingMemento.resolve( resultSetMappingMemento.resolve(
resultSetMapping, resultSetMapping,
@ -218,12 +271,7 @@ public class NativeQueryImpl<R>
this this
); );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sqlString, session ); this.resultMappingSuppliedToCtor = true;
this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
} }
private ParameterInterpretation resolveParameterInterpretation( private ParameterInterpretation resolveParameterInterpretation(
@ -268,6 +316,7 @@ public class NativeQueryImpl<R>
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() ); this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( sqlString ); this.resultSetMapping = new ResultSetMappingImpl( sqlString );
this.resultMappingSuppliedToCtor = false;
} }
@Override @Override
@ -310,20 +359,29 @@ public class NativeQueryImpl<R>
} }
@Override @Override
protected boolean canApplyAliasSpecificLockModes() { public LockModeType getLockMode() {
return false; throw new IllegalStateException( "Illegal attempt to get lock mode on a native-query" );
} }
@Override @Override
protected void verifySettingLockMode() { public NativeQueryImplementor<R> setLockOptions(LockOptions lockOptions) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native query" ); super.setLockOptions( lockOptions );
return this;
} }
@Override @Override
protected void verifySettingAliasSpecificLockModes() { public NativeQueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native query" ); super.setLockMode( alias, lockMode );
return this;
} }
@Override
public NativeQueryImplementor<R> setLockMode(LockModeType lockModeType) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native-query" );
}
@Override @Override
public Query<R> applyGraph(RootGraph graph, GraphSemantic semantic) { public Query<R> applyGraph(RootGraph graph, GraphSemantic semantic) {
throw new HibernateException( "A native SQL query cannot use EntityGraphs" ); throw new HibernateException( "A native SQL query cannot use EntityGraphs" );
@ -331,14 +389,22 @@ public class NativeQueryImpl<R>
@Override @Override
public NativeQueryImplementor<R> setTupleTransformer(TupleTransformer transformer) { public NativeQueryImplementor<R> setTupleTransformer(TupleTransformer transformer) {
//noinspection unchecked return (NativeQueryImplementor<R>) super.setTupleTransformer( transformer );
return (NativeQueryImplementor) super.setTupleTransformer( transformer );
} }
@Override @Override
public NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer transformer) { public NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer transformer) {
//noinspection unchecked return (NativeQueryImplementor<R>) super.setResultListTransformer( transformer );
return (NativeQueryImplementor) super.setResultListTransformer( transformer ); }
protected Boolean isSelectQuery() {
if ( resultMappingSuppliedToCtor
|| resultSetMapping.getNumberOfResultBuilders() > 0
|| isReadOnly() ) {
return true;
}
return null;
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -795,23 +861,6 @@ public class NativeQueryImpl<R>
return this; return this;
} }
@Override
public NativeQueryImplementor<R> setLockOptions(LockOptions lockOptions) {
super.setLockOptions( lockOptions );
return this;
}
@Override
public NativeQueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
super.setLockMode( alias, lockMode );
return this;
}
@Override
public NativeQueryImplementor<R> setLockMode(LockModeType lockModeType) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native SQL query" );
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> javaType) { public <T> T unwrap(Class<T> javaType) {

View File

@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.internal.QueryParameterNamedImpl; import org.hibernate.query.internal.QueryParameterNamedImpl;
import org.hibernate.query.internal.QueryParameterPositionalImpl; import org.hibernate.query.internal.QueryParameterPositionalImpl;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;

View File

@ -44,6 +44,16 @@ import org.hibernate.query.spi.QueryImplementor;
public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R>, NameableQuery { public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R>, NameableQuery {
NativeQueryImplementor setCollectionKey(Object key); NativeQueryImplementor setCollectionKey(Object key);
@Override
default LockOptions getLockOptions() {
return null;
}
@Override
default LockModeType getLockMode() {
return null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - NativeQuery // covariant overrides - NativeQuery

View File

@ -6,13 +6,15 @@
*/ */
package org.hibernate.query.sqm; package org.hibernate.query.sqm;
import org.hibernate.HibernateException;
/** /**
* Represents a general uncaught problem performing the interpretation. This might indicate * Represents a general uncaught problem performing the interpretation. This might indicate
* a semantic (user sqm) problem or a bug in the parser. * a semantic (user sqm) problem or a bug in the parser.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class InterpretationException extends RuntimeException { public class InterpretationException extends HibernateException {
public InterpretationException(String query) { public InterpretationException(String query) {
this( query, null ); this( query, null );
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.query.sqm; package org.hibernate.query.sqm;
import org.hibernate.HibernateException;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
/** /**
@ -14,7 +15,7 @@ import org.hibernate.query.SemanticException;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ParsingException extends RuntimeException { public class ParsingException extends HibernateException {
public ParsingException(String message) { public ParsingException(String message) {
super( message ); super( message );
} }

View File

@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.persistence.LockModeType;
import javax.persistence.Parameter; import javax.persistence.Parameter;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import javax.persistence.Tuple; import javax.persistence.Tuple;
@ -39,6 +40,7 @@ import org.hibernate.query.spi.HqlInterpretation;
import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.ParameterMetadataImplementor; import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryInterpretationCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
@ -52,7 +54,6 @@ import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
import org.hibernate.query.sqm.tree.select.SqmQuerySpec; import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
@ -300,7 +301,7 @@ public class QuerySqmImpl<R>
return parameterBindings; return parameterBindings;
} }
private boolean isSelect() { protected Boolean isSelectQuery() {
return sqmStatement instanceof SqmSelectStatement; return sqmStatement instanceof SqmSelectStatement;
} }
@ -314,7 +315,7 @@ public class QuerySqmImpl<R>
} }
@Override @Override
public Query<R> applyGraph(RootGraph graph, GraphSemantic semantic) { public HqlQueryImplementor<R> applyGraph(RootGraph graph, GraphSemantic semantic) {
queryOptions.applyGraph( (RootGraphImplementor<?>) graph, semantic ); queryOptions.applyGraph( (RootGraphImplementor<?>) graph, semantic );
return this; return this;
} }
@ -359,21 +360,23 @@ public class QuerySqmImpl<R>
} }
@Override @Override
protected boolean canApplyAliasSpecificLockModes() { public LockModeType getLockMode() {
return isSelect(); if ( ! isSelectQuery() ) {
} throw new IllegalStateException( "Illegal attempt to access lock-mode for non-select query" );
@Override
protected void verifySettingLockMode() {
if ( !isSelect() ) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a non-SELECT query" );
} }
return super.getLockMode();
} }
@Override @Override
protected void verifySettingAliasSpecificLockModes() { public HqlQueryImplementor<R> setLockMode(LockModeType lockModeType) {
// todo : add a specific Dialect check as well? - if not supported, maybe that can trigger follow-on locks? if ( ! LockModeType.NONE.equals( lockModeType ) ) {
verifySettingLockMode(); if ( ! isSelectQuery() ) {
throw new IllegalStateException( "Illegal attempt to access lock-mode for non-select query" );
}
}
return (HqlQueryImplementor<R>) super.setLockMode( lockModeType );
} }
@Override @Override

View File

@ -19,13 +19,14 @@ public class SqmCreationProcessingStateImpl implements SqmCreationProcessingStat
private final SqmCreationState creationState; private final SqmCreationState creationState;
private final SqmQuery<?> processingQuery; private final SqmQuery<?> processingQuery;
private final SqmPathRegistryImpl processingIndex = new SqmPathRegistryImpl( this ); private final SqmPathRegistryImpl processingIndex;
public SqmCreationProcessingStateImpl( public SqmCreationProcessingStateImpl(
SqmQuery<?> processingQuery, SqmQuery<?> processingQuery,
SqmCreationState creationState) { SqmCreationState creationState) {
this.processingQuery = processingQuery; this.processingQuery = processingQuery;
this.creationState = creationState; this.creationState = creationState;
this.processingIndex = new SqmPathRegistryImpl( this );
} }
@Override @Override

View File

@ -22,10 +22,12 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.dialect.function.TimestampaddFunction; import org.hibernate.dialect.function.TimestampaddFunction;
import org.hibernate.dialect.function.TimestampdiffFunction; import org.hibernate.dialect.function.TimestampdiffFunction;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.Stack;
import org.hibernate.internal.util.collections.StandardStack; import org.hibernate.internal.util.collections.StandardStack;
import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
@ -39,9 +41,9 @@ import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.BinaryArithmeticOperator; import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.UnaryArithmeticOperator; import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.internal.QueryHelper; import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
@ -59,6 +61,7 @@ import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation; import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.EntityValuedPathInterpretation; import org.hibernate.query.sqm.sql.internal.EntityValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.PluralValuedSimplePathInterpretation; import org.hibernate.query.sqm.sql.internal.PluralValuedSimplePathInterpretation;
import org.hibernate.query.sqm.sql.internal.SqlAstProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl; import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation; import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation; import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
@ -112,6 +115,7 @@ import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate; import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate; import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate; import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmEmptinessPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmExistsPredicate; import org.hibernate.query.sqm.tree.predicate.SqmExistsPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate; import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate; import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
@ -156,6 +160,7 @@ import org.hibernate.sql.ast.tree.expression.Every;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.ExtractUnit; import org.hibernate.sql.ast.tree.expression.ExtractUnit;
import org.hibernate.sql.ast.tree.expression.Format; import org.hibernate.sql.ast.tree.expression.Format;
import org.hibernate.sql.ast.tree.expression.JdbcLiteral;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.QueryLiteral; import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.expression.Star; import org.hibernate.sql.ast.tree.expression.Star;
@ -186,11 +191,12 @@ import org.hibernate.sql.exec.spi.JdbcParameters;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.internal.util.NullnessHelper.coalesce;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues; import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.query.BinaryArithmeticOperator.MULTIPLY; import static org.hibernate.query.BinaryArithmeticOperator.MULTIPLY;
import static org.hibernate.query.BinaryArithmeticOperator.SUBTRACT; import static org.hibernate.query.BinaryArithmeticOperator.SUBTRACT;
@ -217,6 +223,8 @@ public abstract class BaseSqmToSqlAstConverter
} }
private final SqlAstCreationContext creationContext; private final SqlAstCreationContext creationContext;
private final SessionFactoryImplementor sessionFactory;
private final QueryOptions queryOptions; private final QueryOptions queryOptions;
private final LoadQueryInfluencers loadQueryInfluencers; private final LoadQueryInfluencers loadQueryInfluencers;
@ -247,7 +255,10 @@ public abstract class BaseSqmToSqlAstConverter
DomainParameterXref domainParameterXref, DomainParameterXref domainParameterXref,
QueryParameterBindings domainParameterBindings) { QueryParameterBindings domainParameterBindings) {
super( creationContext.getServiceRegistry() ); super( creationContext.getServiceRegistry() );
this.creationContext = creationContext; this.creationContext = creationContext;
this.sessionFactory = creationContext.getSessionFactory();
this.queryOptions = queryOptions; this.queryOptions = queryOptions;
this.loadQueryInfluencers = loadQueryInfluencers; this.loadQueryInfluencers = loadQueryInfluencers;
this.domainParameterXref = domainParameterXref; this.domainParameterXref = domainParameterXref;
@ -2288,6 +2299,68 @@ public abstract class BaseSqmToSqlAstConverter
return new ComparisonPredicate( lhs, predicate.getSqmOperator(), rhs ); return new ComparisonPredicate( lhs, predicate.getSqmOperator(), rhs );
} }
@Override
public Object visitIsEmptyPredicate(SqmEmptinessPredicate predicate) {
final QuerySpec subQuerySpec = new QuerySpec( false, 1 );
final SqlAstProcessingState parentState = getProcessingStateStack().getCurrent();
final SqlAstProcessingStateImpl subQueryState = new SqlAstProcessingStateImpl(
parentState,
this,
currentClauseStack::getCurrent
);
getProcessingStateStack().push( subQueryState );
final SqmPluralValuedSimplePath<?> sqmPluralPath = predicate.getPluralPath();
final NavigablePath pluralPathNavPath = sqmPluralPath.getNavigablePath();
final NavigablePath parentNavPath = pluralPathNavPath.getParent();
assert parentNavPath != null;
final TableGroup parentTableGroup = parentState
.getSqlAstCreationState()
.getFromClauseAccess()
.getTableGroup( parentNavPath );
subQueryState.getSqlAstCreationState().getFromClauseAccess().registerTableGroup( parentNavPath, parentTableGroup );
final SqmPathInterpretation<?> sqmPathInterpretation = visitPluralValuedPath( sqmPluralPath );
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) sqmPathInterpretation.getExpressionType();
// note : do not add to `parentTableGroup` as a join
final TableGroupJoin tableGroupJoin = pluralAttributeMapping.createTableGroupJoin(
pluralPathNavPath,
parentTableGroup,
sqmPluralPath.getExplicitAlias(),
SqlAstJoinType.LEFT,
LockMode.NONE,
sqlAliasBaseManager,
subQueryState,
creationContext
);
final TableGroup collectionTableGroup = tableGroupJoin.getJoinedGroup();
subQuerySpec.getFromClause().addRoot( collectionTableGroup );
subQuerySpec.applyPredicate( tableGroupJoin.getPredicate() );
final ForeignKeyDescriptor collectionKeyDescriptor = pluralAttributeMapping.getKeyDescriptor();
final int jdbcTypeCount = collectionKeyDescriptor.getJdbcTypeCount( sessionFactory.getTypeConfiguration() );
assert jdbcTypeCount > 0;
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, StandardBasicTypes.INTEGER );
subQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl(1,0, jdbcLiteral )
);
return new ExistsPredicate( subQuerySpec );
}
@Override @Override
public BetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) { public BetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) {
final Expression expression; final Expression expression;

View File

@ -18,6 +18,7 @@ import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
@ -154,7 +155,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SqmExpression<Class<? extends T>> type() { public SqmExpression<Class<? extends T>> type() {
if ( pathTypeExpression == null ) { if ( pathTypeExpression == null ) {
final String discriminatorPathName = "{type}"; final String discriminatorPathName = EntityDiscriminatorMapping.ROLE_NAME;
final NavigablePath discriminatorNavigablePath = getNavigablePath().append( discriminatorPathName ); final NavigablePath discriminatorNavigablePath = getNavigablePath().append( discriminatorPathName );
final DomainType sqmNodeType = getReferencedPathSource().getSqmPathType(); final DomainType sqmNodeType = getReferencedPathSource().getSqmPathType();

View File

@ -8,23 +8,23 @@ package org.hibernate.query.sqm.tree.predicate;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqmEmptinessPredicate extends AbstractNegatableSqmPredicate { public class SqmEmptinessPredicate extends AbstractNegatableSqmPredicate {
private final SqmPath<?> pluralPath; private final SqmPluralValuedSimplePath<?> pluralPath;
public SqmEmptinessPredicate( public SqmEmptinessPredicate(
SqmPath pluralPath, SqmPluralValuedSimplePath pluralPath,
boolean negated, boolean negated,
NodeBuilder nodeBuilder) { NodeBuilder nodeBuilder) {
super( negated, nodeBuilder ); super( negated, nodeBuilder );
this.pluralPath = pluralPath; this.pluralPath = pluralPath;
} }
public SqmPath<?> getPluralPath() { public SqmPluralValuedSimplePath<?> getPluralPath() {
return pluralPath; return pluralPath;
} }

View File

@ -0,0 +1,16 @@
/*
* 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.sql.ast.spi;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
* @author Steve Ebersole
*/
public interface SqlExpressionAccess {
Expression getSqlExpression();
}

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.internal;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.SqlExpressable; import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlExpressionAccess;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
@ -34,7 +35,7 @@ import java.util.Objects;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqlSelectionImpl implements SqlSelection { public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
private final int jdbcPosition; private final int jdbcPosition;
private final int valuesArrayPosition; private final int valuesArrayPosition;
private final Expression sqlExpression; private final Expression sqlExpression;
@ -94,4 +95,9 @@ public class SqlSelectionImpl implements SqlSelection {
public int hashCode() { public int hashCode() {
return Objects.hash( jdbcPosition, valuesArrayPosition, sqlExpression ); return Objects.hash( jdbcPosition, valuesArrayPosition, sqlExpression );
} }
@Override
public Expression getSqlExpression() {
return sqlExpression;
}
} }

View File

@ -20,7 +20,7 @@ import org.hibernate.jpa.test.metamodel.Order_;
import org.junit.Test; import org.junit.Test;
/** /**
* Similar to {@link org.hibernate.test.jpa.ql.OnKeywordTest}, but here testing from JPA criteria queries. * Similar to {@link org.hibernate.orm.test.query.hql.OnKeywordTest}, but here testing from JPA criteria queries.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */

View File

@ -13,6 +13,7 @@ import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.JpaComplianceStub;
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl; import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl;
@ -60,7 +61,7 @@ public class HqlTranslationNoFactoryTests {
final MetadataImplementor bootModel = modelScope.getDomainModel(); final MetadataImplementor bootModel = modelScope.getDomainModel();
final TypeConfiguration typeConfiguration = bootModel.getTypeConfiguration(); final TypeConfiguration typeConfiguration = bootModel.getTypeConfiguration();
final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( typeConfiguration ); final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( typeConfiguration, new JpaComplianceStub() );
// todo (6.0) (quarkus) : we should limit the type of the last argument here from `RuntimeModelCreationContext` // todo (6.0) (quarkus) : we should limit the type of the last argument here from `RuntimeModelCreationContext`
// which assumes access to SessionFactory // which assumes access to SessionFactory

View File

@ -9,4 +9,4 @@
* Test package for investigating JPA TCK failures - to reproduce them * Test package for investigating JPA TCK failures - to reproduce them
* and, if caused by a Hibernate bug, make sure it does not regress later * and, if caused by a Hibernate bug, make sure it does not regress later
*/ */
package org.hibernate.test.jpa.compliance; package org.hibernate.orm.test.jpa.compliance;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.Collections; import java.util.Collections;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.RollbackException; import javax.persistence.RollbackException;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Parameter; import javax.persistence.Parameter;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.LockModeType; import javax.persistence.LockModeType;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -39,7 +39,9 @@ public class QueryExecutionTest extends BaseNonConfigCoreFunctionalTestCase {
inTransaction( inTransaction(
session -> { session -> {
final List nonDistinctResult = session.createQuery( "select c from Customer c join fetch c.orders" ).list(); final List nonDistinctResult = session.createQuery( "select c from Customer c join fetch c.orders" ).list();
assertThat( nonDistinctResult.size(), CoreMatchers.is( 2 ) ); // note: this was historically `2` because Hibernate would return a root result for each of its fetched rows.
// - that was confusing behavior for users. we have changed this in 6 to be more logical
assertThat( nonDistinctResult.size(), CoreMatchers.is( 1 ) );
final List distinctResult = session.createQuery( "select distinct c from Customer c join fetch c.orders" ).list(); final List distinctResult = session.createQuery( "select distinct c from Customer c join fetch c.orders" ).list();
assertThat( distinctResult.size(), CoreMatchers.is( 1 ) ); assertThat( distinctResult.size(), CoreMatchers.is( 1 ) );

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.Date; import java.util.Date;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -20,6 +20,7 @@ import org.hibernate.dialect.H2Dialect;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.test.sql.storedproc.StoredProcedureResultSetMappingTest; import org.hibernate.test.sql.storedproc.StoredProcedureResultSetMappingTest;
@ -31,6 +32,7 @@ import static org.junit.Assert.fail;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@RequiresDialect( H2Dialect.class ) @RequiresDialect( H2Dialect.class )
@FailureExpected( message = "Procedure/function support not yet implemented", jiraKey = "n/a" )
public class StoredProcedureApiTests extends BaseNonConfigCoreFunctionalTestCase { public class StoredProcedureApiTests extends BaseNonConfigCoreFunctionalTestCase {

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.caching; package org.hibernate.orm.test.jpa.compliance.tck2_2.caching;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.caching; package org.hibernate.orm.test.jpa.compliance.tck2_2.caching;
import java.util.Map; import java.util.Map;
import javax.persistence.Cacheable; import javax.persistence.Cacheable;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.caching; package org.hibernate.orm.test.jpa.compliance.tck2_2.caching;
import java.util.Map; import java.util.Map;
import javax.persistence.Cacheable; import javax.persistence.Cacheable;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.joincolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.joincolumn;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.joincolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.joincolumn;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistry;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.joincolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.joincolumn;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn; package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -10,4 +10,4 @@
* *
* @see org.hibernate.test.jpa.compliance * @see org.hibernate.test.jpa.compliance
*/ */
package org.hibernate.test.jpa.compliance.tck2_2; package org.hibernate.orm.test.jpa.compliance.tck2_2;

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.ql; package org.hibernate.orm.test.query.hql;
import org.hibernate.Session; import org.hibernate.Session;

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.test.jpa.ql; package org.hibernate.orm.test.query.hql;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@ -10,10 +10,17 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import org.hibernate.boot.Metadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,6 +42,13 @@ public class NativeQueryParameterTests {
); );
} }
@Test
public void testJpaStylePositionalParametersInNativeSql(SessionFactoryScope scope) {
scope.inTransaction(
s -> s.createNativeQuery( "select t.subject from ticket t where t.key = ?1" ).setParameter( 1, "ABC-123" ).list()
);
}
@Test @Test
public void testTypedParameterBinding(SessionFactoryScope scope) { public void testTypedParameterBinding(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(

View File

@ -45,9 +45,9 @@ public class JPAQLComplianceTest extends AbstractJPATest {
Session s = openSession( ); Session s = openSession( );
// a control test (a user reported that the JPA 'case insensitivity' support // a control test (a user reported that the JPA 'case insensitivity' support
// caused problems with the "discriminator resolution" code; unable to reproduce)... // caused problems with the "discriminator resolution" code; unable to reproduce)...
s.createQuery( "from MyEntity e where e.class = MySubclassEntity" ); s.createQuery( "select E from MyEntity e where other.class = MySubclassEntity" );
s.createQuery( "from MyEntity e where e.other.class = MySubclassEntity" ); s.createQuery( "select e from MyEntity e where e.other.class = MySubclassEntity" );
s.createQuery( "from MyEntity where other.class = MySubclassEntity" ); s.createQuery( "select e from MyEntity E where e.class = MySubclassEntity" );
s.createQuery( "select object(I) from Item i").list(); s.createQuery( "select object(I) from Item i").list();
s.close(); s.close();

View File

@ -1,22 +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.test.jpa.ql;
import org.hibernate.test.jpa.AbstractJPATest;
import org.junit.Test;
/**
* @author Steve Ebersole
*/
public class NativeQueryTest extends AbstractJPATest {
@Test
public void testJpaStylePositionalParametersInNativeSql() {
inTransaction(
s -> s.createNativeQuery( "select NAME from EJB3_ITEM where ITEM_ID = ?1" ).setParameter( 1, 123L ).list()
);
}
}

View File

@ -12,7 +12,7 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.appender.stdout2=org.apache.log4j.ConsoleAppender log4j.appender.stdout2=org.apache.log4j.ConsoleAppender
log4j.appender.stdout2.Target=System.out log4j.appender.stdout2.Target=System.out
log4j.appender.stdout2.layout=org.apache.log4j.PatternLayout log4j.appender.stdout2.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout2.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{5}:%L - %m%n log4j.appender.stdout2.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{5}:(%C{1}:%L) - %m%n
log4j.appender.unclosedSessionFactoryFile=org.apache.log4j.FileAppender log4j.appender.unclosedSessionFactoryFile=org.apache.log4j.FileAppender
log4j.appender.unclosedSessionFactoryFile.append=true log4j.appender.unclosedSessionFactoryFile.append=true
@ -29,7 +29,7 @@ log4j.logger.org.hibernate.orm.sql.results=debug
log4j.logger.org.hibernate.orm.graph=debug log4j.logger.org.hibernate.orm.graph=debug
log4j.logger.org.hibernate.orm.query.sqm=debug log4j.logger.org.hibernate.orm.query.sqm=debug
log4j.logger.org.hibernate.orm.query.hql=debug log4j.logger.org.hibernate.orm.query.hql=trace
log4j.logger.org.hibernate.sql.results.graph.DomainResultGraphPrinter=debug log4j.logger.org.hibernate.sql.results.graph.DomainResultGraphPrinter=debug
log4j.logger.org.hibernate.tool.hbm2ddl=trace log4j.logger.org.hibernate.tool.hbm2ddl=trace