initial working dynamic instantiation support;

cleanup
This commit is contained in:
Steve Ebersole 2019-09-19 15:13:50 -05:00
parent 055ce0c542
commit 5631a702a7
42 changed files with 662 additions and 594 deletions

View File

@ -14,12 +14,14 @@
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -41,6 +43,7 @@
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.SerializationException; import org.hibernate.type.SerializationException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
/** /**
@ -64,6 +67,8 @@ public class MetadataSources implements Serializable {
private LinkedHashSet<String> annotatedClassNames = new LinkedHashSet<>(); private LinkedHashSet<String> annotatedClassNames = new LinkedHashSet<>();
private LinkedHashSet<String> annotatedPackages = new LinkedHashSet<>(); private LinkedHashSet<String> annotatedPackages = new LinkedHashSet<>();
private Map<String,Class<?>> extraQueryImports;
public MetadataSources() { public MetadataSources() {
this( new BootstrapServiceRegistryBuilder().build() ); this( new BootstrapServiceRegistryBuilder().build() );
} }
@ -111,6 +116,10 @@ public Collection<String> getAnnotatedClassNames() {
return annotatedClassNames; return annotatedClassNames;
} }
public Map<String,Class<?>> getExtraQueryImports() {
return extraQueryImports;
}
public ServiceRegistry getServiceRegistry() { public ServiceRegistry getServiceRegistry() {
return serviceRegistry; return serviceRegistry;
} }
@ -196,6 +205,16 @@ public MetadataSources addAnnotatedClass(Class annotatedClass) {
return this; return this;
} }
/**
* Var-arg form of {@link #addAnnotatedClass}
*/
public MetadataSources addAnnotatedClasses(Class<?>... annotatedClasses) {
if ( annotatedClasses != null && annotatedClasses.length > 0 ) {
Collections.addAll( this.annotatedClasses, annotatedClasses );
}
return this;
}
/** /**
* Read metadata from the annotations attached to the given class. The important * Read metadata from the annotations attached to the given class. The important
* distinction here is that the {@link Class} will not be accessed until later * distinction here is that the {@link Class} will not be accessed until later
@ -210,6 +229,26 @@ public MetadataSources addAnnotatedClassName(String annotatedClassName) {
return this; return this;
} }
/**
* Var-arg form of {@link #addAnnotatedClassName}
*/
public MetadataSources addAnnotatedClassNames(String... annotatedClassNames) {
if ( annotatedClassNames != null && annotatedClassNames.length > 0 ) {
Collections.addAll( this.annotatedClassNames, annotatedClassNames );
}
return this;
}
public MetadataSources addQueryImport(String importedName, Class<?> target) {
if ( extraQueryImports == null ) {
extraQueryImports = new HashMap<>();
}
extraQueryImports.put( importedName, target );
return this;
}
/** /**
* Read package-level metadata. * Read package-level metadata.
* *

View File

@ -30,6 +30,7 @@ public class ManagedResourcesImpl implements ManagedResources {
private Set<String> annotatedClassNames = new LinkedHashSet<>(); private Set<String> annotatedClassNames = new LinkedHashSet<>();
private Set<String> annotatedPackageNames = new LinkedHashSet<>(); private Set<String> annotatedPackageNames = new LinkedHashSet<>();
private List<Binding> mappingFileBindings = new ArrayList<>(); private List<Binding> mappingFileBindings = new ArrayList<>();
private Map<String, Class<?>> extraQueryImports;
public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapContext bootstrapContext) { public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapContext bootstrapContext) {
final ManagedResourcesImpl impl = new ManagedResourcesImpl(); final ManagedResourcesImpl impl = new ManagedResourcesImpl();
@ -38,6 +39,7 @@ public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapCo
impl.annotatedClassNames.addAll( sources.getAnnotatedClassNames() ); impl.annotatedClassNames.addAll( sources.getAnnotatedClassNames() );
impl.annotatedPackageNames.addAll( sources.getAnnotatedPackages() ); impl.annotatedPackageNames.addAll( sources.getAnnotatedPackages() );
impl.mappingFileBindings.addAll( sources.getXmlBindings() ); impl.mappingFileBindings.addAll( sources.getXmlBindings() );
impl.extraQueryImports = sources.getExtraQueryImports();
return impl; return impl;
} }
@ -69,6 +71,11 @@ public Collection<Binding> getXmlMappingBindings() {
return Collections.unmodifiableList( mappingFileBindings ); return Collections.unmodifiableList( mappingFileBindings );
} }
@Override
public Map<String, Class<?>> getExtraQueryImports() {
return extraQueryImports;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// package private // package private

View File

@ -7,6 +7,8 @@
package org.hibernate.boot.model.process.spi; package org.hibernate.boot.model.process.spi;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.hibernate.boot.AttributeConverterInfo; import org.hibernate.boot.AttributeConverterInfo;
import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.jaxb.spi.Binding;
@ -66,4 +68,6 @@ public interface ManagedResources {
* @return The list of bindings for all known XML mapping files. * @return The list of bindings for all known XML mapping files.
*/ */
Collection<Binding> getXmlMappingBindings(); Collection<Binding> getXmlMappingBindings();
Map<String,Class<?>> getExtraQueryImports();
} }

View File

@ -8,6 +8,7 @@
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
@ -304,9 +305,24 @@ public void finishUp() {
} }
} }
applyExtraQueryImports( managedResources, metadataCollector );
return metadataCollector.buildMetadataInstance( rootMetadataBuildingContext ); return metadataCollector.buildMetadataInstance( rootMetadataBuildingContext );
} }
private static void applyExtraQueryImports(
ManagedResources managedResources,
InFlightMetadataCollectorImpl metadataCollector) {
final Map<String, Class<?>> extraQueryImports = managedResources.getExtraQueryImports();
if ( extraQueryImports == null || extraQueryImports.isEmpty() ) {
return;
}
for ( Map.Entry<String, Class<?>> entry : extraQueryImports.entrySet() ) {
metadataCollector.addImport( entry.getKey(), entry.getValue().getName() );
}
}
// todo (7.0) : buildJandexInitializer // todo (7.0) : buildJandexInitializer
// private static JandexInitManager buildJandexInitializer( // private static JandexInitManager buildJandexInitializer(
// MetadataBuildingOptions options, // MetadataBuildingOptions options,

View File

@ -81,6 +81,8 @@ default ServiceRegistry getServiceRegistry() {
void visitEmbeddables(Consumer<EmbeddableDomainType<?>> action); void visitEmbeddables(Consumer<EmbeddableDomainType<?>> action);
String qualifyImportableName(String queryName);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Covariant returns // Covariant returns

View File

@ -269,6 +269,11 @@ public <T> List<RootGraphImplementor<? super T>> findEntityGraphsByJavaType(Clas
return results; return results;
} }
@Override
public String qualifyImportableName(String queryName) {
return resolveImportedName( queryName );
}
private String resolveImportedName(String name) { private String resolveImportedName(String name) {
String result = nameToImportNameMap.get( name ); String result = nameToImportNameMap.get( name );
if ( result == null ) { if ( result == null ) {

View File

@ -238,9 +238,4 @@ public String getAlias() {
public NodeBuilder nodeBuilder() { public NodeBuilder nodeBuilder() {
return null; return null;
} }
@Override
public SqmExpressable getExpressableType() {
return expressableType;
}
} }

View File

@ -570,11 +570,7 @@ else if ( ctx.dynamicInstantiationTarget().LIST() != null ) {
else { else {
final String className = ctx.dynamicInstantiationTarget().dotIdentifierSequence().getText(); final String className = ctx.dynamicInstantiationTarget().dotIdentifierSequence().getText();
try { try {
final Class<?> targetJavaType = classForName( className ); final JavaTypeDescriptor jtd = resolveInstantiationTargetJtd( className );
final JavaTypeDescriptor jtd = creationContext.getJpaMetamodel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( targetJavaType );
dynamicInstantiation = SqmDynamicInstantiation.forClassInstantiation( dynamicInstantiation = SqmDynamicInstantiation.forClassInstantiation(
jtd, jtd,
creationContext.getNodeBuilder() creationContext.getNodeBuilder()
@ -592,6 +588,14 @@ else if ( ctx.dynamicInstantiationTarget().LIST() != null ) {
return dynamicInstantiation; return dynamicInstantiation;
} }
private JavaTypeDescriptor resolveInstantiationTargetJtd(String className) {
final Class<?> targetJavaType = classForName( creationContext.getJpaMetamodel().qualifyImportableName( className ) );
return creationContext.getJpaMetamodel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( targetJavaType );
}
private Class classForName(String className) { private Class classForName(String className) {
return creationContext.getServiceRegistry().getService( ClassLoaderService.class ).classForName( className ); return creationContext.getServiceRegistry().getService( ClassLoaderService.class ).classForName( className );
} }

View File

@ -20,7 +20,7 @@
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
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.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
@ -35,12 +35,12 @@
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.function.SqmFunction; import org.hibernate.query.sqm.function.SqmFunction;
import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker; import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess; import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation; 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.SqlAstQuerySpecProcessingStateImpl; import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqmExpressionInterpretation;
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;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
@ -614,8 +614,12 @@ public SqmPathInterpretation<?> visitPluralValuedPath(SqmPluralValuedSimplePath
// General expressions // General expressions
@Override @Override
public SqmExpressionInterpretation visitLiteral(SqmLiteral literal) { public Expression visitLiteral(SqmLiteral literal) {
return literal; return new QueryLiteral(
literal.getLiteralValue(),
(BasicValuedMapping) SqmMappingModelHelper.resolveMappingModelExpressable( literal, this ),
getCurrentClauseStack().getCurrent()
);
} }
private final Map<SqmParameter,List<JdbcParameter>> jdbcParamsBySqmParam = new IdentityHashMap<>(); private final Map<SqmParameter,List<JdbcParameter>> jdbcParamsBySqmParam = new IdentityHashMap<>();
@ -627,12 +631,12 @@ public Map<SqmParameter, List<JdbcParameter>> getJdbcParamsBySqmParam() {
} }
@Override @Override
public SqmExpressionInterpretation visitNamedParameterExpression(SqmNamedParameter expression) { public Expression visitNamedParameterExpression(SqmNamedParameter expression) {
return consumeSqmParameter( expression ); return consumeSqmParameter( expression );
} }
private SqmExpressionInterpretation consumeSqmParameter(SqmParameter sqmParameter) { private Expression consumeSqmParameter(SqmParameter sqmParameter) {
final MappingModelExpressable valueMapping = determineValueMapping( sqmParameter ); final MappingModelExpressable valueMapping = determineValueMapping( sqmParameter );
final List<JdbcParameter> jdbcParametersForSqm = new ArrayList<>(); final List<JdbcParameter> jdbcParametersForSqm = new ArrayList<>();
@ -1242,7 +1246,7 @@ public CaseSearchedExpression visitSearchedCaseExpression(SqmCaseSearched<?> exp
public Object visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral) { public Object visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral) {
return new QueryLiteral( return new QueryLiteral(
sqmEnumLiteral.getEnumValue(), sqmEnumLiteral.getEnumValue(),
determineValueMapping( sqmEnumLiteral ), (BasicValuedMapping) determineValueMapping( sqmEnumLiteral ),
getCurrentClauseStack().getCurrent() getCurrentClauseStack().getCurrent()
); );
} }
@ -1251,7 +1255,7 @@ public Object visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral) {
public Object visitFieldLiteral(SqmFieldLiteral sqmFieldLiteral) { public Object visitFieldLiteral(SqmFieldLiteral sqmFieldLiteral) {
return new QueryLiteral( return new QueryLiteral(
sqmFieldLiteral.getValue(), sqmFieldLiteral.getValue(),
determineValueMapping( sqmFieldLiteral ), (BasicValuedMapping) determineValueMapping( sqmFieldLiteral ),
getCurrentClauseStack().getCurrent() getCurrentClauseStack().getCurrent()
); );
} }
@ -1322,11 +1326,7 @@ public ComparisonPredicate visitComparisonPredicate(SqmComparisonPredicate predi
final Expression lhs; final Expression lhs;
try { try {
lhs = ( (SqmExpressionInterpretation) predicate.getLeftHandExpression().accept( this ) ).toSqlExpression( lhs = (Expression) predicate.getLeftHandExpression().accept( this );
getCurrentClauseStack().getCurrent(),
this,
this
);
} }
finally { finally {
inferableTypeAccessStack.pop(); inferableTypeAccessStack.pop();
@ -1336,11 +1336,7 @@ public ComparisonPredicate visitComparisonPredicate(SqmComparisonPredicate predi
final Expression rhs; final Expression rhs;
try { try {
rhs = ( (SqmExpressionInterpretation) predicate.getRightHandExpression().accept( this ) ).toSqlExpression( rhs = (Expression) predicate.getRightHandExpression().accept( this );
getCurrentClauseStack().getCurrent(),
this,
this
);
} }
finally { finally {
inferableTypeAccessStack.pop(); inferableTypeAccessStack.pop();
@ -1472,13 +1468,7 @@ public InListPredicate visitInListPredicate(SqmInListPredicate<?> predicate) {
domainParameterXref.addExpansion( domainParam, sqmParameter, sqmParamToConsume ); domainParameterXref.addExpansion( domainParam, sqmParameter, sqmParamToConsume );
} }
inListPredicate.addExpression( inListPredicate.addExpression( consumeSqmParameter( sqmParamToConsume ) );
consumeSqmParameter( sqmParamToConsume ).toSqlExpression(
getCurrentClauseStack().getCurrent(),
this,
this
)
);
} }
} }
finally { finally {

View File

@ -6,8 +6,10 @@
*/ */
package org.hibernate.query.sqm.sql; package org.hibernate.query.sqm.sql;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.sql.SqlAstCreationState; import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.sql.ast.Clause;
/** /**
* Specialized SemanticQueryWalker (SQM visitor) for producing SQL AST. * Specialized SemanticQueryWalker (SQM visitor) for producing SQL AST.
@ -15,4 +17,5 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAstCreationState { public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAstCreationState {
Stack<Clause> getCurrentClauseStack();
} }

View File

@ -10,15 +10,16 @@
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.query.NavigablePath; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper; import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.sql.SqlAstCreationState; import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.sql.ast.Clause; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.update.Assignment; import org.hibernate.sql.ast.tree.update.Assignment;
@ -44,45 +45,63 @@ public static <T> BasicValuedPathInterpretation<T> from(
null null
); );
return new BasicValuedPathInterpretation<>( sqmPath, mapping, tableGroup ); final ColumnReference columnReference = (ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
mapping.getContainingTableExpression(),
mapping.getMappedColumnExpression()
),
sacs -> new ColumnReference(
mapping.getMappedColumnExpression(),
tableGroup.resolveTableReference( mapping.getContainingTableExpression() )
.getIdentificationVariable(),
mapping.getJdbcMapping(),
sqlAstCreationState.getCreationContext().getSessionFactory()
)
);
return new BasicValuedPathInterpretation<>( columnReference, sqmPath, mapping, tableGroup );
} }
private final ColumnReference columnReference;
private final SqmBasicValuedSimplePath<T> sqmPath; private final SqmBasicValuedSimplePath<T> sqmPath;
private final BasicValuedModelPart mapping; private final BasicValuedModelPart mapping;
private final TableGroup tableGroup; private final TableGroup tableGroup;
private Expression expression;
private BasicValuedPathInterpretation( private BasicValuedPathInterpretation(
ColumnReference columnReference,
SqmBasicValuedSimplePath<T> sqmPath, SqmBasicValuedSimplePath<T> sqmPath,
BasicValuedModelPart mapping, BasicValuedModelPart mapping,
TableGroup tableGroup) { TableGroup tableGroup) {
assert columnReference != null;
this.columnReference = columnReference;
assert sqmPath != null;
this.sqmPath = sqmPath; this.sqmPath = sqmPath;
assert mapping != null;
this.mapping = mapping; this.mapping = mapping;
assert tableGroup != null;
this.tableGroup = tableGroup; this.tableGroup = tableGroup;
} }
@Override @Override
public NavigablePath getNavigablePath() { public SqmPath<T> getInterpretedSqmPath() {
return sqmPath.getNavigablePath(); return sqmPath;
} }
@Override @Override
public SqmPathSource<T> getSqmPathSource() { public ModelPart getExpressionType() {
return sqmPath.getReferencedPathSource(); return mapping;
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DomainResultProducer // DomainResultProducer
@Override
public DomainResultProducer<T> getDomainResultProducer(
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
return this;
}
@Override @Override
public DomainResult<T> createDomainResult( public DomainResult<T> createDomainResult(
String resultVariable, String resultVariable,
@ -95,17 +114,6 @@ public void applySqlSelections(DomainResultCreationState creationState) {
mapping.applySqlSelections( getNavigablePath(), tableGroup, creationState ); mapping.applySqlSelections( getNavigablePath(), tableGroup, creationState );
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqmExpressionInterpretation
@Override
public Expression toSqlExpression(
Clause clause, SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override @Override
public void applySqlAssignments( public void applySqlAssignments(
Expression newValueExpression, Expression newValueExpression,
@ -115,6 +123,11 @@ public void applySqlAssignments(
throw new NotYetImplementedFor6Exception( getClass() ); throw new NotYetImplementedFor6Exception( getClass() );
} }
@Override
public void accept(SqlAstWalker sqlTreeWalker) {
columnReference.accept( sqlTreeWalker );
}
@Override @Override
public String toString() { public String toString() {
return "BasicValuedPathInterpretation(" + sqmPath.getNavigablePath().getFullPath() + ')'; return "BasicValuedPathInterpretation(" + sqmPath.getNavigablePath().getFullPath() + ')';

View File

@ -10,15 +10,15 @@
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.query.NavigablePath; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper; import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.sql.SqlAstCreationState; import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.sql.ast.Clause; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.update.Assignment; import org.hibernate.sql.ast.tree.update.Assignment;
@ -28,59 +28,67 @@
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathInterpretation<T>, DomainResultProducer<T> { public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathInterpretation<T> {
/** /**
* Static factory * Static factory
*/ */
public static <T> EmbeddableValuedPathInterpretation<T> from( public static <T> EmbeddableValuedPathInterpretation<T> from(
SqmEmbeddedValuedSimplePath<T> sqmPath, SqmEmbeddedValuedSimplePath<T> sqmPath,
SqlAstCreationState sqlAstCreationState, SqmToSqlAstConverter converter,
SemanticQueryWalker sqmWalker) { SemanticQueryWalker sqmWalker) {
final TableGroup tableGroup = SqmMappingModelHelper.resolveLhs( sqmPath.getNavigablePath(), sqlAstCreationState ); final TableGroup tableGroup = SqmMappingModelHelper.resolveLhs( sqmPath.getNavigablePath(), converter );
tableGroup.getModelPart().prepareAsLhs( sqmPath.getNavigablePath(), sqlAstCreationState ); tableGroup.getModelPart().prepareAsLhs( sqmPath.getNavigablePath(), converter );
final EmbeddableValuedModelPart mapping = (EmbeddableValuedModelPart) tableGroup.getModelPart().findSubPart( final EmbeddableValuedModelPart mapping = (EmbeddableValuedModelPart) tableGroup.getModelPart().findSubPart(
sqmPath.getReferencedPathSource().getPathName(), sqmPath.getReferencedPathSource().getPathName(),
null null
); );
return new EmbeddableValuedPathInterpretation<>( sqmPath, mapping, tableGroup ); return new EmbeddableValuedPathInterpretation<>(
mapping.toSqlExpression(
tableGroup,
converter.getCurrentClauseStack().getCurrent(),
converter,
converter
),
sqmPath,
mapping,
tableGroup
);
} }
private final Expression sqlExpression;
private final SqmEmbeddedValuedSimplePath<T> sqmPath; private final SqmEmbeddedValuedSimplePath<T> sqmPath;
private final EmbeddableValuedModelPart mapping; private final EmbeddableValuedModelPart mapping;
private final TableGroup tableGroup; private final TableGroup tableGroup;
public EmbeddableValuedPathInterpretation( public EmbeddableValuedPathInterpretation(
Expression sqlExpression,
SqmEmbeddedValuedSimplePath<T> sqmPath, SqmEmbeddedValuedSimplePath<T> sqmPath,
EmbeddableValuedModelPart mapping, EmbeddableValuedModelPart mapping,
TableGroup tableGroup) { TableGroup tableGroup) {
this.sqlExpression = sqlExpression;
this.sqmPath = sqmPath; this.sqmPath = sqmPath;
this.mapping = mapping; this.mapping = mapping;
this.tableGroup = tableGroup; this.tableGroup = tableGroup;
} }
@Override @Override
public NavigablePath getNavigablePath() { public SqmPath<T> getInterpretedSqmPath() {
return sqmPath.getNavigablePath(); return sqmPath;
} }
@Override @Override
public SqmPathSource<T> getSqmPathSource() { public ModelPart getExpressionType() {
return sqmPath.getReferencedPathSource(); return mapping;
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DomainResultProducer
@Override @Override
public DomainResultProducer<T> getDomainResultProducer( public void accept(SqlAstWalker sqlTreeWalker) {
SqmToSqlAstConverter walker, sqlExpression.accept( sqlTreeWalker );
SqlAstCreationState sqlAstCreationState) {
return this;
} }
@Override @Override
@ -93,18 +101,6 @@ public void applySqlSelections(DomainResultCreationState creationState) {
mapping.applySqlSelections( getNavigablePath(), tableGroup, creationState ); mapping.applySqlSelections( getNavigablePath(), tableGroup, creationState );
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqmPathInterpretation
@Override
public Expression toSqlExpression(
Clause clause,
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
return mapping.toSqlExpression( tableGroup, clause, walker, sqlAstCreationState );
}
@Override @Override
public void applySqlAssignments( public void applySqlAssignments(
Expression newValueExpression, Expression newValueExpression,

View File

@ -1,34 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sqm.sql.internal;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
* The interpretation of an SqmExpression as part of the SQM -> SQL conversion.
*
* Allows multi-column navigable references to be used anywhere a (SqlExpression)
* can be. The trick is to properly define methods on this interface for how the
* thing should be rendered into the SQL AST.
*
* @author Steve Ebersole
*/
public interface SqmExpressionInterpretation<T> extends SqmSelectableInterpretation<T> {
SqmExpressable<T> getExpressableType();
default Expression toSqlExpression(
Clause clause,
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
}

View File

@ -9,13 +9,8 @@
import java.util.List; import java.util.List;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.model.domain.internal.DomainModelHelper;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.SqlTuple; import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.exec.spi.JdbcParameter; import org.hibernate.sql.exec.spi.JdbcParameter;
@ -23,44 +18,34 @@
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqmParameterInterpretation implements SqmExpressionInterpretation { public class SqmParameterInterpretation implements Expression {
private final SqmParameter sqmParameter; private final SqmParameter sqmParameter;
private final List<JdbcParameter> jdbcParameters;
private final MappingModelExpressable valueMapping; private final MappingModelExpressable valueMapping;
private final Expression resolvedExpression;
public SqmParameterInterpretation( public SqmParameterInterpretation(
SqmParameter sqmParameter, SqmParameter sqmParameter,
List<JdbcParameter> jdbcParameters, List<JdbcParameter> jdbcParameters,
MappingModelExpressable valueMapping) { MappingModelExpressable valueMapping) {
this.sqmParameter = sqmParameter;
this.valueMapping = valueMapping; this.valueMapping = valueMapping;
assert jdbcParameters != null; assert jdbcParameters != null;
assert jdbcParameters.size() > 0; assert jdbcParameters.size() > 0;
this.sqmParameter = sqmParameter; this.resolvedExpression = jdbcParameters.size() == 1
this.jdbcParameters = jdbcParameters; ? jdbcParameters.get( 0 )
: new SqlTuple( jdbcParameters, valueMapping );
} }
@Override @Override
public SqmExpressable getExpressableType() { public void accept(SqlAstWalker sqlTreeWalker) {
return sqmParameter.getExpressableType(); resolvedExpression.accept( sqlTreeWalker );
} }
@Override @Override
public Expression toSqlExpression( public MappingModelExpressable getExpressionType() {
Clause clause, return valueMapping;
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
if ( jdbcParameters.size() == 1 ) {
return jdbcParameters.get( 0 );
}
return new SqlTuple( jdbcParameters, valueMapping );
}
@Override
public DomainResultProducer getDomainResultProducer(
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
throw new SemanticException( "SqmParameter parameter cannot be a DomainResult" );
} }
} }

View File

@ -6,68 +6,26 @@
*/ */
package org.hibernate.query.sqm.sql.internal; package org.hibernate.query.sqm.sql.internal;
import java.util.List; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.sql.ConversionException;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.from.TableGroup;
/** /**
* todo (6.0) : consider having `SqmPathInterpretation` extend `org.hibernate.sql.ast.tree.expression.Expression`. * Interpretation of a {@link SqmPath} as part of the translation to SQL AST
* - Basic paths would logically resolve to a `ColumnReference` *
* - Composite and entity-valued paths would logically resolve to a `SqlTuple` * @see org.hibernate.query.sqm.sql.SqmToSqlAstConverter
* @see #getInterpretedSqmPath
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface SqmPathInterpretation<T> extends SqmExpressionInterpretation<T> { public interface SqmPathInterpretation<T> extends Expression, DomainResultProducer<T> {
NavigablePath getNavigablePath(); default NavigablePath getNavigablePath() {
return getInterpretedSqmPath().getNavigablePath();
@Override
default SqmPathSource<T> getExpressableType() {
return getSqmPathSource();
} }
SqmPathSource<T> getSqmPathSource(); SqmPath<T> getInterpretedSqmPath();
// @Override @Override
// default Expression toSqlExpression(SqlAstCreationState sqlAstCreationState) { ModelPart getExpressionType();
// throw new NotYetImplementedFor6Exception( getClass() );
// final TableGroup tableGroup;
//
// if ( getSqmPathSource() instanceof BasicSqmPathSource ) {
// // maybe we should register the LHS TableGroup for the basic value
// // under its NavigablePath, similar to what we do for embeddables
// tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( getNavigablePath().getParent() );
// }
// else {
// // for embeddable-, entity- and plural-valued Navigables we maybe do not have a TableGroup
// final TableGroup thisTableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( getNavigablePath() );
// if ( thisTableGroup != null ) {
// tableGroup = thisTableGroup;
// }
// else {
// final NavigablePath lhsNavigablePath = getNavigablePath().getParent();
// if ( lhsNavigablePath == null ) {
// throw new ConversionException( "Could not find TableGroup to use - " + getNavigablePath().getFullPath() );
// }
// tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( lhsNavigablePath );
// }
// }
//
// sqlAstCreationState.getCreationContext().getDomainModel().resolveMappingExpressable( )
//
// final List list = getNavigable().resolveColumnReferences( tableGroup, sqlAstCreationState );
// if ( list.size() == 1 ) {
// assert list.get( 0 ) instanceof Expression;
// return (Expression) list.get( 0 );
// }
//
// return new SqlTuple( list, sqlAstCreationState.getJdbcMapping() );
// }
} }

View File

@ -13,7 +13,6 @@
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.Consumer;
import java.util.function.Supplier;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
@ -32,10 +31,6 @@
import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter; import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.SqlAstCreationState; import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.sql.results.internal.domain.instantiation.DynamicInstantiation;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType; import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation; import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
@ -53,6 +48,7 @@
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer; import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.results.internal.domain.instantiation.DynamicInstantiation;
import org.hibernate.sql.results.spi.CircularFetchDetector; import org.hibernate.sql.results.spi.CircularFetchDetector;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
@ -141,8 +137,7 @@ public Void visitSelection(SqmSelection sqmSelection) {
} }
private DomainResultProducer resolveDomainResultProducer(SqmSelection sqmSelection) { private DomainResultProducer resolveDomainResultProducer(SqmSelection sqmSelection) {
SqmSelectableInterpretation<?> interpretation = (SqmSelectableInterpretation<?>) sqmSelection.getSelectableNode().accept( this ); return (DomainResultProducer) sqmSelection.getSelectableNode().accept( this );
return interpretation.getDomainResultProducer( this, getSqlAstCreationState() );
} }
private int fetchDepth = 0; private int fetchDepth = 0;

View File

@ -1,20 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sqm.sql.internal;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
/**
* @author Steve Ebersole
*/
public interface SqmSelectableInterpretation<T> {
default DomainResultProducer<T> getDomainResultProducer(SqmToSqlAstConverter walker, SqlAstCreationState sqlAstCreationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
}

View File

@ -1,36 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sqm.sql.internal;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.query.sqm.sql.ConversionException;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.sql.ast.tree.from.TableGroup;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("WeakerAccess")
public class SqmSqlHelper {
private SqmSqlHelper() {
}
public static TableGroup resolveTableGroup(SqmPath<?> sqmPath, SqlAstCreationState creationState) {
SqmPath<?> lhs = sqmPath;
while ( lhs.getReferencedPathSource().getSqmPathType() instanceof EmbeddableDomainType ) {
lhs = lhs.getLhs();
}
final TableGroup tableGroup = creationState.getFromClauseAccess().findTableGroup( lhs.getNavigablePath() );
if ( tableGroup != null ) {
return tableGroup;
}
throw new ConversionException( "Could not locate TableGroup to use : " + lhs.getNavigablePath() );
}
}

View File

@ -0,0 +1,57 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sqm.sql.internal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmTuple;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
/**
* @author Steve Ebersole
*/
public class SqmTupleInterpretation<T> extends SqlTuple {
public static <T> SqmTupleInterpretation<T> from(
SqmTuple<T> sqmTuple,
SemanticQueryWalker<?> walker,
SqlAstCreationState sqlAstCreationState) {
final List<Expression> groupedSqlExpressions = new ArrayList<>();
for ( SqmExpression<?> groupedExpression : sqmTuple.getGroupedExpressions() ) {
groupedSqlExpressions.add( (Expression) groupedExpression.accept( walker ) );
}
return new SqmTupleInterpretation<>(
sqmTuple,
groupedSqlExpressions,
SqmMappingModelHelper.resolveMappingModelExpressable( sqmTuple, sqlAstCreationState )
);
}
private final SqmTuple<T> interpretedSqmTuple;
public SqmTupleInterpretation(
SqmTuple<T> sqmTuple,
List<? extends Expression> expressions,
MappingModelExpressable valueMapping) {
super( expressions, valueMapping );
interpretedSqmTuple = sqmTuple;
}
public SqmTuple<T> getInterpretedSqmTuple() {
return interpretedSqmTuple;
}
}

View File

@ -31,11 +31,6 @@ public AbstractSqmExpression(SqmExpressable<T> type, NodeBuilder criteriaBuilder
super( type, criteriaBuilder ); super( type, criteriaBuilder );
} }
@Override
public SqmExpressable<T> getExpressableType() {
return getNodeType();
}
@Override @Override
public final void applyInferableType(SqmExpressable<?> type) { public final void applyInferableType(SqmExpressable<?> type) {
if ( type == null ) { if ( type == null ) {

View File

@ -65,11 +65,6 @@ public EnumJavaTypeDescriptor<Enum> getExpressableJavaTypeDescriptor() {
return referencedEnumTypeDescriptor; return referencedEnumTypeDescriptor;
} }
@Override
public SqmExpressable<Enum> getExpressableType() {
return expressable;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SemanticPathPart // SemanticPathPart

View File

@ -16,7 +16,6 @@
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.sqm.SqmExpressable; import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.sql.internal.SqmExpressionInterpretation;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.select.SqmSelectableNode; import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
@ -29,7 +28,7 @@
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>, SqmExpressionInterpretation<T> { public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T> {
/** /**
* The expression's type. * The expression's type.
* *

View File

@ -77,11 +77,6 @@ public T getValue() {
return value; return value;
} }
@Override
public SqmExpressable<T> getExpressableType() {
return expressable;
}
public JavaTypeDescriptor<T> getFieldJavaTypeDescriptor() { public JavaTypeDescriptor<T> getFieldJavaTypeDescriptor() {
return fieldJavaTypeDescriptor; return fieldJavaTypeDescriptor;
} }

View File

@ -9,13 +9,7 @@
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.SqmExpressable; import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
/** /**
* Represents a literal value in the sqm, e.g.<ul> * Represents a literal value in the sqm, e.g.<ul>
@ -46,18 +40,6 @@ public <R> R accept(SemanticQueryWalker<R> walker) {
return walker.visitLiteral( this ); return walker.visitLiteral( this );
} }
@Override
public Expression toSqlExpression(
Clause clause,
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
return new QueryLiteral(
getLiteralValue(),
SqmMappingModelHelper.resolveMappingModelExpressable( this, sqlAstCreationState ),
clause
);
}
@Override @Override
public String asLoggableText() { public String asLoggableText() {
return "Literal( " + value + ")"; return "Literal( " + value + ")";

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.query.sqm.tree.expression; package org.hibernate.query.sqm.tree.expression;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -16,14 +15,7 @@
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.SqmExpressable; import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.query.sqm.sql.internal.SqmExpressionInterpretation;
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection; import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
@ -38,7 +30,7 @@
*/ */
public class SqmTuple<T> public class SqmTuple<T>
extends AbstractSqmExpression<T> extends AbstractSqmExpression<T>
implements JpaCompoundSelection<T>, SqmExpressionInterpretation<T> { implements JpaCompoundSelection<T> {
private final List<SqmExpression<?>> groupedExpressions; private final List<SqmExpression<?>> groupedExpressions;
public SqmTuple(NodeBuilder nodeBuilder, SqmExpression<?>... groupedExpressions) { public SqmTuple(NodeBuilder nodeBuilder, SqmExpression<?>... groupedExpressions) {
@ -63,6 +55,10 @@ public SqmTuple(List<SqmExpression<?>> groupedExpressions, SqmExpressable<T> typ
applyInferableType( type ); applyInferableType( type );
} }
public List<SqmExpression<?>> getGroupedExpressions() {
return groupedExpressions;
}
@Override @Override
public SqmExpressable<T> getNodeType() { public SqmExpressable<T> getNodeType() {
final SqmExpressable<T> expressableType = super.getNodeType(); final SqmExpressable<T> expressableType = super.getNodeType();
@ -86,37 +82,6 @@ public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitTuple( this ); return walker.visitTuple( this );
} }
@Override
public Expression toSqlExpression(
Clause clause,
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
final List<Expression> groupedSqlExpressions = new ArrayList<>();
for ( SqmExpression groupedExpression : groupedExpressions ) {
final SqmExpressionInterpretation interpretation = (SqmExpressionInterpretation) groupedExpression.accept( walker );
final Expression sqlExpression = interpretation.toSqlExpression(
clause, walker,
sqlAstCreationState
);
groupedSqlExpressions.add( sqlExpression );
}
return new SqlTuple(
groupedSqlExpressions,
sqlAstCreationState.getCreationContext().getDomainModel()
.resolveMappingExpressable( getExpressableType() )
);
}
@Override
public DomainResultProducer getDomainResultProducer(
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
return null;
}
@Override @Override
public String asLoggableText() { public String asLoggableText() {
return toString(); return toString();
@ -134,7 +99,7 @@ public boolean isCompoundSelection() {
@Override @Override
public List<? extends JpaSelection<?>> getSelectionItems() { public List<? extends JpaSelection<?>> getSelectionItems() {
return groupedExpressions; return getGroupedExpressions();
} }
} }

View File

@ -8,7 +8,6 @@
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -16,15 +15,12 @@
import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.criteria.JpaRoot;
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.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom; import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot; import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -102,20 +98,6 @@ public <S extends E> SqmTreatedPath<E, S> treatAs(EntityDomainType<S> treatTarge
return new SqmTreatedRoot<>( this, treatTarget, nodeBuilder() ); return new SqmTreatedRoot<>( this, treatTarget, nodeBuilder() );
} }
@Override
public DomainResultProducer<E> getDomainResultProducer(
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
return this;
}
@Override
public Expression toSqlExpression(
Clause clause, SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override @Override
public void visitJdbcTypes(Consumer<JdbcMapping> action, TypeConfiguration typeConfiguration) { public void visitJdbcTypes(Consumer<JdbcMapping> action, TypeConfiguration typeConfiguration) {
final String entityName = getReferencedPathSource().getHibernateEntityName(); final String entityName = getReferencedPathSource().getHibernateEntityName();

View File

@ -9,12 +9,7 @@
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.persistence.criteria.Selection; import javax.persistence.criteria.Selection;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.query.sqm.sql.internal.SqmSelectableInterpretation;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.SqmVisitableNode; import org.hibernate.query.sqm.tree.SqmVisitableNode;
@ -24,7 +19,7 @@
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface SqmSelectableNode<T> extends JpaSelection<T>, SqmTypedNode<T>, SqmVisitableNode, SqmSelectableInterpretation<T> { public interface SqmSelectableNode<T> extends JpaSelection<T>, SqmTypedNode<T>, SqmVisitableNode {
/** /**
* Visit each of this selectable's direct sub-selectables - used to * Visit each of this selectable's direct sub-selectables - used to
* support JPA's {@link Selection} model (which is really a "selectable", * support JPA's {@link Selection} model (which is really a "selectable",
@ -34,8 +29,4 @@ public interface SqmSelectableNode<T> extends JpaSelection<T>, SqmTypedNode<T>,
* @see Selection#getCompoundSelectionItems() * @see Selection#getCompoundSelectionItems()
*/ */
void visitSubSelectableNodes(Consumer<SqmSelectableNode<?>> jpaSelectionConsumer); void visitSubSelectableNodes(Consumer<SqmSelectableNode<?>> jpaSelectionConsumer);
default DomainResultProducer<T> getDomainResultProducer(SqmToSqlAstConverter walker, SqlAstCreationState sqlAstCreationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
} }

View File

@ -25,8 +25,8 @@
import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.criteria.JpaSubQuery; import org.hibernate.query.criteria.JpaSubQuery;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.tree.SqmQuery; import org.hibernate.query.sqm.tree.SqmQuery;
import org.hibernate.query.sqm.tree.domain.SqmBagJoin; import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
import org.hibernate.query.sqm.tree.domain.SqmListJoin; import org.hibernate.query.sqm.tree.domain.SqmListJoin;
@ -72,11 +72,6 @@ public SqmSubQuery(
this.parent = parent; this.parent = parent;
} }
@Override
public SqmExpressable<T> getExpressableType() {
return expressableType;
}
@Override @Override
public SqmQuery<?> getContainingQuery() { public SqmQuery<?> getContainingQuery() {
return parent; return parent;

View File

@ -22,5 +22,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface JdbcLiteralFormatter<T> { public interface JdbcLiteralFormatter<T> {
String NULL = "null";
String toJdbcLiteral(T value, Dialect dialect, SharedSessionContractImplementor session); String toJdbcLiteral(T value, Dialect dialect, SharedSessionContractImplementor session);
} }

View File

@ -8,17 +8,24 @@
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.function.Consumer;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBinder; import org.hibernate.sql.exec.spi.JdbcParameterBinder;
import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
/** /**
* We classify literals different based on their source so that we can handle then differently * We classify literals different based on their source so that we can handle then differently
@ -31,10 +38,10 @@
public abstract class AbstractLiteral<T> public abstract class AbstractLiteral<T>
implements JdbcParameterBinder, Expression, DomainResultProducer<T> { implements JdbcParameterBinder, Expression, DomainResultProducer<T> {
private final Object value; private final Object value;
private final MappingModelExpressable type; private final BasicValuedMapping type;
private final Clause clause; private final Clause clause;
public AbstractLiteral(Object value, MappingModelExpressable type, Clause clause) { public AbstractLiteral(Object value, BasicValuedMapping type, Clause clause) {
this.value = value; this.value = value;
this.type = type; this.type = type;
this.clause = clause; this.clause = clause;
@ -49,15 +56,51 @@ public boolean isInSelect() {
} }
@Override @Override
public MappingModelExpressable getExpressionType() { public BasicValuedMapping getExpressionType() {
return type; return type;
} }
@Override @Override
public DomainResult createDomainResult( public DomainResult<T> createDomainResult(
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
throw new NotYetImplementedFor6Exception( getClass() ); final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
this,
type.getMappedTypeDescriptor().getMappedJavaTypeDescriptor(),
creationState.getSqlAstCreationState()
.getCreationContext()
.getSessionFactory()
.getTypeConfiguration()
);
//noinspection unchecked
return new BasicResult<>(
sqlSelection.getJdbcResultSetIndex(),
resultVariable,
type.getMappedTypeDescriptor().getMappedJavaTypeDescriptor()
);
}
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaTypeDescriptor javaTypeDescriptor,
TypeConfiguration typeConfiguration) {
return new SqlSelectionImpl(
jdbcPosition,
valuesArrayPosition,
this,
type.getJdbcMapping()
);
}
@Override
public void visitJdbcTypes(
Consumer<JdbcMapping> action,
TypeConfiguration typeConfiguration) {
action.accept( type.getJdbcMapping() );
} }
@Override @Override

View File

@ -6,7 +6,7 @@
*/ */
package org.hibernate.sql.ast.tree.expression; package org.hibernate.sql.ast.tree.expression;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
@ -16,7 +16,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class QueryLiteral<T> extends AbstractLiteral<T> { public class QueryLiteral<T> extends AbstractLiteral<T> {
public QueryLiteral(Object value, MappingModelExpressable expressableType, Clause clause) { public QueryLiteral(Object value, BasicValuedMapping expressableType, Clause clause) {
super( value, expressableType, clause ); super( value, expressableType, clause );
} }

View File

@ -12,9 +12,6 @@
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
@ -77,10 +74,4 @@ public TableReference getPrimaryTableReference() {
public List<TableReferenceJoin> getTableReferenceJoins() { public List<TableReferenceJoin> getTableReferenceJoins() {
return tableJoins; return tableJoins;
} }
@Override
public DomainResultProducer getDomainResultProducer(
SqmToSqlAstConverter walker, SqlAstCreationState sqlAstCreationState) {
return this;
}
} }

View File

@ -11,11 +11,9 @@
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.query.sqm.sql.internal.SqmSelectableInterpretation;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -30,7 +28,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface TableGroup public interface TableGroup
extends SqlAstNode, ColumnReferenceQualifier, DomainResultProducer, SqmSelectableInterpretation { extends SqlAstNode, ColumnReferenceQualifier, DomainResultProducer {
NavigablePath getNavigablePath(); NavigablePath getNavigablePath();
ModelPartContainer getModelPart(); ModelPartContainer getModelPart();

View File

@ -37,6 +37,10 @@ public JavaTypeDescriptor getResultJavaTypeDescriptor() {
public ArgumentReader<A> createResultAssembler( public ArgumentReader<A> createResultAssembler(
Consumer<Initializer> initializerCollector, Consumer<Initializer> initializerCollector,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
return null; //noinspection unchecked
return new ArgumentReader(
realDomainResult.createResultAssembler( initializerCollector, creationState ),
getResultVariable()
);
} }
} }

View File

@ -6,20 +6,15 @@
*/ */
package org.hibernate.sql.results.internal.domain.instantiation; package org.hibernate.sql.results.internal.domain.instantiation;
import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.query.DynamicInstantiationNature; import org.hibernate.query.DynamicInstantiationNature;
import org.hibernate.query.sqm.sql.ConversionException; import org.hibernate.query.sqm.sql.ConversionException;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.query.sqm.tree.expression.Compatibility;
import org.hibernate.sql.results.spi.AssemblerCreationState;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -116,131 +111,124 @@ public String toString() {
public DomainResult createDomainResult( public DomainResult createDomainResult(
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
throw new NotYetImplementedFor6Exception( getClass() ); //noinspection unchecked
return new DynamicInstantiationResultImpl(
resultVariable,
getNature(),
getTargetJavaTypeDescriptor(),
getArguments().stream()
.map( argument -> argument.buildArgumentDomainResult( creationState ) )
.collect( Collectors.toList() )
);
} }
//
// @Override
// @SuppressWarnings("unchecked") // @SuppressWarnings("unchecked")
// public DomainResult createDomainResult( // private static DomainResultAssembler resolveAssembler(
// String resultVariable, // DynamicInstantiation dynamicInstantiation,
// DomainResultCreationState creationState) { // boolean areAllArgumentsAliased,
// return new DynamicInstantiationResult( // boolean areAnyArgumentsAliased,
// resultVariable, // List<String> duplicatedAliases,
// getNature(), // List<ArgumentReader<?>> argumentReaders,
// (JavaTypeDescriptor) getTargetJavaTypeDescriptor(), // AssemblerCreationState creationState) {
// getArguments().stream() //
// .map( argument -> argument.buildArgumentDomainResult( creationState ) ) // if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.LIST ) {
// .collect( Collectors.toList() ) // if ( log.isDebugEnabled() && areAnyArgumentsAliased ) {
// ); // log.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" );
// }
// return new DynamicInstantiationListAssemblerImpl(
// (JavaTypeDescriptor<List>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
// argumentReaders
// );
// }
// else if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.MAP ) {
// if ( ! areAllArgumentsAliased ) {
// throw new IllegalStateException( "Map dynamic instantiation contained one or more arguments with no alias" );
// }
// if ( !duplicatedAliases.isEmpty() ) {
// throw new IllegalStateException(
// "Map dynamic instantiation contained arguments with duplicated aliases [" + StringHelper.join( ",", duplicatedAliases ) + "]"
// );
// }
// return new DynamicInstantiationMapAssemblerImpl(
// (JavaTypeDescriptor<Map>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
// argumentReaders
// );
// }
// else {
// // find a constructor matching argument types
// constructor_loop:
// for ( Constructor constructor : dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getDeclaredConstructors() ) {
// if ( constructor.getParameterTypes().length != dynamicInstantiation.arguments.size() ) {
// continue;
// }
//
// for ( int i = 0; i < dynamicInstantiation.arguments.size(); i++ ) {
// final ArgumentReader argumentReader = argumentReaders.get( i );
// final JavaTypeDescriptor argumentTypeDescriptor = creationState.getSqlAstCreationContext().getDomainModel()
// .getTypeConfiguration()
// .getJavaTypeDescriptorRegistry()
// .resolveDescriptor( constructor.getParameterTypes()[i] );
//
// final boolean assignmentCompatible = Compatibility.areAssignmentCompatible(
// argumentTypeDescriptor,
// argumentReader.getAssembledJavaTypeDescriptor()
// );
// if ( !assignmentCompatible ) {
// log.debugf(
// "Skipping constructor for dynamic-instantiation match due to argument mismatch [%s] : %s -> %s",
// i,
// constructor.getParameterTypes()[i].getName(),
// argumentTypeDescriptor.getJavaType().getName()
// );
// continue constructor_loop;
// }
// }
//
// constructor.setAccessible( true );
// return new DynamicInstantiationConstructorAssemblerImpl(
// constructor,
// dynamicInstantiation.getTargetJavaTypeDescriptor(),
// argumentReaders
// );
// }
//
// log.debugf(
// "Could not locate appropriate constructor for dynamic instantiation of [%s]; attempting bean-injection instantiation",
// dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getName()
// );
//
//
// if ( ! areAllArgumentsAliased ) {
// throw new IllegalStateException(
// "Could not determine appropriate instantiation strategy - no matching constructor found and one or more arguments did not define alias for bean-injection"
// );
// }
// if ( !duplicatedAliases.isEmpty() ) {
// throw new IllegalStateException(
// "Could not determine appropriate instantiation strategy - no matching constructor found and arguments defined duplicated aliases [" +
// StringHelper.join( ",", duplicatedAliases ) + "] for bean-injection"
// );
// }
//
// return new DynamicInstantiationInjectionAssemblerImpl(
// dynamicInstantiation.getTargetJavaTypeDescriptor(),
// argumentReaders
// );
// }
// } // }
// //
@SuppressWarnings("unchecked") // class Builder {
private static DomainResultAssembler resolveAssembler( // private final DynamicInstantiationNature nature;
DynamicInstantiation dynamicInstantiation, // private final JavaTypeDescriptor<T> targetJavaTypeDescriptor;
boolean areAllArgumentsAliased, // private List<DynamicInstantiationArgument> arguments;
boolean areAnyArgumentsAliased, //
List<String> duplicatedAliases, // public Builder(
List<ArgumentReader<?>> argumentReaders, // DynamicInstantiationNature nature,
AssemblerCreationState creationState) { // JavaTypeDescriptor<T> targetJavaTypeDescriptor) {
// this.nature = nature;
if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.LIST ) { // this.targetJavaTypeDescriptor = targetJavaTypeDescriptor;
if ( log.isDebugEnabled() && areAnyArgumentsAliased ) { // }
log.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" ); //
} //
return new DynamicInstantiationListAssemblerImpl( // }
(JavaTypeDescriptor<List>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
argumentReaders
);
}
else if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.MAP ) {
if ( ! areAllArgumentsAliased ) {
throw new IllegalStateException( "Map dynamic instantiation contained one or more arguments with no alias" );
}
if ( !duplicatedAliases.isEmpty() ) {
throw new IllegalStateException(
"Map dynamic instantiation contained arguments with duplicated aliases [" + StringHelper.join( ",", duplicatedAliases ) + "]"
);
}
return new DynamicInstantiationMapAssemblerImpl(
(JavaTypeDescriptor<Map>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
argumentReaders
);
}
else {
// find a constructor matching argument types
constructor_loop:
for ( Constructor constructor : dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getDeclaredConstructors() ) {
if ( constructor.getParameterTypes().length != dynamicInstantiation.arguments.size() ) {
continue;
}
for ( int i = 0; i < dynamicInstantiation.arguments.size(); i++ ) {
final ArgumentReader argumentReader = argumentReaders.get( i );
final JavaTypeDescriptor argumentTypeDescriptor = creationState.getSqlAstCreationContext().getDomainModel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( constructor.getParameterTypes()[i] );
final boolean assignmentCompatible = Compatibility.areAssignmentCompatible(
argumentTypeDescriptor,
argumentReader.getAssembledJavaTypeDescriptor()
);
if ( !assignmentCompatible ) {
log.debugf(
"Skipping constructor for dynamic-instantiation match due to argument mismatch [%s] : %s -> %s",
i,
constructor.getParameterTypes()[i].getName(),
argumentTypeDescriptor.getJavaType().getName()
);
continue constructor_loop;
}
}
constructor.setAccessible( true );
return new DynamicInstantiationConstructorAssemblerImpl(
constructor,
dynamicInstantiation.getTargetJavaTypeDescriptor(),
argumentReaders
);
}
log.debugf(
"Could not locate appropriate constructor for dynamic instantiation of [%s]; attempting bean-injection instantiation",
dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getName()
);
if ( ! areAllArgumentsAliased ) {
throw new IllegalStateException(
"Could not determine appropriate instantiation strategy - no matching constructor found and one or more arguments did not define alias for bean-injection"
);
}
if ( !duplicatedAliases.isEmpty() ) {
throw new IllegalStateException(
"Could not determine appropriate instantiation strategy - no matching constructor found and arguments defined duplicated aliases [" +
StringHelper.join( ",", duplicatedAliases ) + "] for bean-injection"
);
}
return new DynamicInstantiationInjectionAssemblerImpl(
dynamicInstantiation.getTargetJavaTypeDescriptor(),
argumentReaders
);
}
}
class Builder {
private final DynamicInstantiationNature nature;
private final JavaTypeDescriptor<T> targetJavaTypeDescriptor;
private List<DynamicInstantiationArgument> arguments;
public Builder(
DynamicInstantiationNature nature,
JavaTypeDescriptor<T> targetJavaTypeDescriptor) {
this.nature = nature;
this.targetJavaTypeDescriptor = targetJavaTypeDescriptor;
}
}
} }

View File

@ -12,11 +12,14 @@
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import static org.hibernate.sql.ast.spi.JdbcLiteralFormatter.NULL;
/** /**
* Descriptor for {@link Types#NVARCHAR NVARCHAR} handling. * Descriptor for {@link Types#NVARCHAR NVARCHAR} handling.
* *
@ -38,6 +41,11 @@ public boolean canBeRemapped() {
return true; return true;
} }
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
return (value, dialect, session) -> value == null ? NULL : "'" + value.toString() + "'";
}
@Override @Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) { public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) { return new BasicBinder<X>( javaTypeDescriptor, this ) {

View File

@ -12,11 +12,14 @@
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import static org.hibernate.sql.ast.spi.JdbcLiteralFormatter.NULL;
/** /**
* Descriptor for {@link Types#VARCHAR VARCHAR} handling. * Descriptor for {@link Types#VARCHAR VARCHAR} handling.
* *
@ -38,6 +41,11 @@ public boolean canBeRemapped() {
return true; return true;
} }
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
return (value, dialect, session) -> value == null ? NULL : "'" + value.toString() + "'";
}
@Override @Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) { public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) { return new BasicBinder<X>( javaTypeDescriptor, this ) {

View File

@ -163,6 +163,14 @@ public static class Component {
private String attribute1; private String attribute1;
private String attribute2; private String attribute2;
public Component() {
}
public Component(String attribute1, String attribute2) {
this.attribute1 = attribute1;
this.attribute2 = attribute2;
}
public String getAttribute1() { public String getAttribute1() {
return attribute1; return attribute1;
} }

View File

@ -125,15 +125,6 @@ public void testSimpleHqlInterpretation(SessionFactoryScope scope) {
); );
} }
@Test
public void testSimpleHqlExecution(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<String> query = session.createQuery( "select e.name from SimpleEntity e", String.class );
query.list();
}
);
}
@Test @Test
public void testConvertedHqlInterpretation(SessionFactoryScope scope) { public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
@ -232,46 +223,6 @@ public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
); );
} }
@Test
public void testConvertedHqlExecution(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<Gender> query = session.createQuery( "select e.gender from SimpleEntity e", Gender.class );
query.list();
}
);
}
@Test
public void testSelectRootHqlExecution(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<SimpleEntity> query = session.createQuery( "select e from SimpleEntity e", SimpleEntity.class );
query.list();
}
);
}
@Test
public void testSelectEmbeddedHqlExecution(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<Component> query = session.createQuery( "select e.component from SimpleEntity e", Component.class );
query.list();
}
);
}
@Test
public void testSelectEmbeddableSubPathHqlExecution(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<String> query = session.createQuery( "select e.component.attribute1 from SimpleEntity e", String.class );
query.list();
}
);
}
@Test @Test
public void testBadQueryResultType(SessionFactoryScope scope) { public void testBadQueryResultType(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(

View File

@ -10,8 +10,10 @@
import java.util.List; import java.util.List;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Component;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity; import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender; import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
import org.hibernate.query.Query;
import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
@ -24,6 +26,7 @@
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.FEMALE; import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.FEMALE;
import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE; import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
@ -33,13 +36,21 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@DomainModel( @DomainModel(
annotatedClasses = SimpleEntity.class annotatedClasses = SimpleEntity.class,
extraQueryImportClasses = {
SmokeTests.ListItemDto.class,
SmokeTests.CategorizedListItemDto.class,
SmokeTests.CompoundDto.class,
SmokeTests.BasicSetterBasedDto.class
}
) )
@ServiceRegistry( @ServiceRegistry(
settings = @ServiceRegistry.Setting( settings = {
name = AvailableSettings.HBM2DDL_AUTO, @ServiceRegistry.Setting(
value = "create-drop" name = AvailableSettings.HBM2DDL_AUTO,
) value = "create-drop"
)
}
) )
@SessionFactory @SessionFactory
public class SmokeTests { public class SmokeTests {
@ -53,6 +64,7 @@ public void setUp(SessionFactoryScope scope) {
simpleEntity.setGender( FEMALE ); simpleEntity.setGender( FEMALE );
simpleEntity.setName( "Fab" ); simpleEntity.setName( "Fab" );
simpleEntity.setGender2( MALE ); simpleEntity.setGender2( MALE );
simpleEntity.setComponent( new Component( "a1", "a2" ) );
session.save( simpleEntity ); session.save( simpleEntity );
} }
); );
@ -73,7 +85,7 @@ public void tearDown(SessionFactoryScope scope) {
} }
@Test @Test
public void testSelectEntityFieldHqlExecution(SessionFactoryScope scope) { public void testHqlSelectEntityBasicAttribute(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final QueryImplementor<String> query = session.createQuery( final QueryImplementor<String> query = session.createQuery(
@ -88,7 +100,7 @@ public void testSelectEntityFieldHqlExecution(SessionFactoryScope scope) {
} }
@Test @Test
public void testSelectGenderHql(SessionFactoryScope scope) { public void testHqlSelectConvertedAttribute(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final QueryImplementor<Gender> query = session.createQuery( final QueryImplementor<Gender> query = session.createQuery(
@ -103,7 +115,7 @@ public void testSelectGenderHql(SessionFactoryScope scope) {
} }
@Test @Test
public void testSelectEntityHqlExecution(SessionFactoryScope scope) { public void testHqlSelectRootEntity(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final QueryImplementor<SimpleEntity> query = session.createQuery( final QueryImplementor<SimpleEntity> query = session.createQuery(
@ -117,6 +129,168 @@ public void testSelectEntityHqlExecution(SessionFactoryScope scope) {
assertThat( simpleEntity.getGender(), is(FEMALE) ); assertThat( simpleEntity.getGender(), is(FEMALE) );
assertThat( simpleEntity.getGender2(), is(MALE) ); assertThat( simpleEntity.getGender2(), is(MALE) );
assertThat( simpleEntity.getName(), is("Fab") ); assertThat( simpleEntity.getName(), is("Fab") );
assertThat( simpleEntity.getComponent(), notNullValue() );
assertThat( simpleEntity.getComponent().getAttribute1(), is( "a1" ) );
assertThat( simpleEntity.getComponent().getAttribute2(), is( "a2" ) );
}
);
}
@Test
public void testHqlSelectEmbeddedAttribute(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<Component> query = session.createQuery( "select e.component from SimpleEntity e", Component.class );
final Component component = query.uniqueResult();
assertThat( component, notNullValue() );
assertThat( component.getAttribute1(), is( "a1" ) );
assertThat( component.getAttribute2(), is( "a2" ) );
}
);
}
@Test
public void testHqlSelectEmbeddableSubAttribute(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<String> query = session.createQuery( "select e.component.attribute1 from SimpleEntity e", String.class );
final String attribute1 = query.uniqueResult();
assertThat( attribute1, is( "a1" ) );
}
);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Dynamic instantiations
public static class ListItemDto {
private String code;
private String value;
public ListItemDto(String code, String value) {
this.code = code;
this.value = value;
}
}
public static class CategorizedListItemDto {
private ListItemDto category;
private String code;
private String value;
public CategorizedListItemDto(ListItemDto category, String code, String value) {
this.category = category;
this.code = code;
this.value = value;
}
}
public static class CompoundDto {
private ListItemDto first;
private ListItemDto second;
public CompoundDto(ListItemDto first, ListItemDto second) {
this.first = first;
this.second = second;
}
}
public static class BasicSetterBasedDto {
private String code;
private String value;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@Test
public void testHqlBasicDynamicInstantiation(SessionFactoryScope scope) {
scope.getSessionFactory().inTransaction(
session -> {
final Query<ListItemDto> query = session.createQuery(
"select new ListItemDto( e.component.attribute1, e.name ) from SimpleEntity e",
ListItemDto.class
);
final ListItemDto dto = query.getSingleResult();
assertThat( dto, notNullValue() );
assertThat( dto.code, is( "a1" ) );
assertThat( dto.value, is( "Fab" ) );
}
);
}
@Test
public void testHqlNestedDynamicInstantiation(SessionFactoryScope scope) {
scope.getSessionFactory().inTransaction(
session -> {
final Query<CategorizedListItemDto> query = session.createQuery(
"select new CategorizedListItemDto( new ListItemDto( e.component.attribute2, e.component.attribute1 ), e.component.attribute1, e.name ) from SimpleEntity e",
CategorizedListItemDto.class
);
final CategorizedListItemDto dto = query.getSingleResult();
assertThat( dto, notNullValue() );
assertThat( dto.category, notNullValue() );
assertThat( dto.category.code, is( "a2") );
assertThat( dto.category.value, is( "a1") );
assertThat( dto.code, is( "a1" ) );
assertThat( dto.value, is( "Fab" ) );
}
);
}
@Test
public void testHqlMultipleDynamicInstantiation(SessionFactoryScope scope) {
scope.getSessionFactory().inTransaction(
session -> {
final Query<CompoundDto> query = session.createQuery(
"select new CompoundDto( new ListItemDto( e.component.attribute1, e.name ), new ListItemDto( e.component.attribute2, e.name ) ) from SimpleEntity e",
CompoundDto.class
);
final CompoundDto dto = query.getSingleResult();
assertThat( dto, notNullValue() );
assertThat( dto.first, notNullValue() );
assertThat( dto.first.code, is( "a1" ) );
assertThat( dto.first.value, is( "Fab" ) );
assertThat( dto.second, notNullValue() );
assertThat( dto.second.code, is( "a2" ) );
assertThat( dto.second.value, is( "Fab" ) );
}
);
}
@Test
public void testBasicSetterDynamicInstantiation(SessionFactoryScope scope) {
scope.getSessionFactory().inTransaction(
session -> {
final Query<BasicSetterBasedDto> query = session.createQuery(
"select new BasicSetterBasedDto( e.component.attribute1 as code, e.name as value ) from SimpleEntity e",
BasicSetterBasedDto.class
);
final BasicSetterBasedDto dto = query.getSingleResult();
assertThat( dto, notNullValue() );
assertThat( dto.code, is( "a1" ) );
assertThat( dto.value, is( "Fab" ) );
} }
); );
} }

View File

@ -93,4 +93,11 @@
Class[] annotatedClasses() default {}; Class[] annotatedClasses() default {};
String[] annotatedClassNames() default {}; String[] annotatedClassNames() default {};
String[] xmlMappings() default {}; String[] xmlMappings() default {};
ExtraQueryImport[] extraQueryImports() default {};
Class<?>[] extraQueryImportClasses() default {};
@interface ExtraQueryImport {
String name();
Class<?> importedClass();
}
} }

View File

@ -95,6 +95,14 @@ public static DomainModelScope findMetamodelScope(Object testInstance, Extension
metadataSources.addResource( xmlMapping ); metadataSources.addResource( xmlMapping );
} }
for ( DomainModel.ExtraQueryImport extraQueryImport : domainModelAnnotation.extraQueryImports() ) {
metadataSources.addQueryImport( extraQueryImport.name(), extraQueryImport.importedClass() );
}
for ( Class<?> importedClass : domainModelAnnotation.extraQueryImportClasses() ) {
metadataSources.addQueryImport( importedClass.getSimpleName(), importedClass );
}
return (MetadataImplementor) metadataSources.buildMetadata(); return (MetadataImplementor) metadataSources.buildMetadata();
}; };
} }