Rename result.SqlSelectionImpl to ResultSetMappingSqlSelection. Introduce support for resolving the selection type also for normal JdbcValuesMapping.

This commit is contained in:
Christian Beikov 2021-12-23 17:32:12 +01:00
parent 313bc2666c
commit 1aefd1977a
28 changed files with 245 additions and 209 deletions

View File

@ -43,11 +43,6 @@ public class QueryHints {
*/
public static final String CACHEABLE = "org.hibernate.cacheable";
/**
* Is the query callable? Note: only valid for named native sql queries.
*/
public static final String CALLABLE = "org.hibernate.callable";
/**
* Defines a comment to be applied to the SQL sent to the database.
*

View File

@ -69,7 +69,7 @@ public class DomainResultCreationStateImpl
private final JdbcValuesMetadata jdbcResultsMetadata;
private final Consumer<SqlSelection> sqlSelectionConsumer;
private final Map<String, SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
private final Map<String, ResultSetMappingSqlSelection> sqlSelectionMap = new HashMap<>();
private boolean allowPositionalSelections = true;
private final SqlAliasBaseManager sqlAliasBaseManager;
@ -258,16 +258,16 @@ public class DomainResultCreationStateImpl
public Expression resolveSqlExpression(
String key,
Function<SqlAstProcessingState, Expression> creator) {
final SqlSelectionImpl existing = sqlSelectionMap.get( key );
final ResultSetMappingSqlSelection existing = sqlSelectionMap.get( key );
if ( existing != null ) {
return existing;
}
final Expression created = creator.apply( this );
if ( created instanceof SqlSelectionImpl ) {
sqlSelectionMap.put( key, (SqlSelectionImpl) created );
sqlSelectionConsumer.accept( (SqlSelectionImpl) created );
if ( created instanceof ResultSetMappingSqlSelection ) {
sqlSelectionMap.put( key, (ResultSetMappingSqlSelection) created );
sqlSelectionConsumer.accept( (ResultSetMappingSqlSelection) created );
}
else if ( created instanceof ColumnReference ) {
final ColumnReference columnReference = (ColumnReference) created;
@ -275,7 +275,7 @@ public class DomainResultCreationStateImpl
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnExpression );
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl(
final ResultSetMappingSqlSelection sqlSelection = new ResultSetMappingSqlSelection(
valuesArrayPosition,
columnReference.getJdbcMapping()
);
@ -297,7 +297,7 @@ public class DomainResultCreationStateImpl
if ( expression == null ) {
throw new IllegalArgumentException( "Expression cannot be null" );
}
assert expression instanceof SqlSelectionImpl;
assert expression instanceof ResultSetMappingSqlSelection;
return (SqlSelection) expression;
}

View File

@ -19,7 +19,6 @@ import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.Internal;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -332,7 +331,7 @@ public class ResultSetMappingImpl implements ResultSetMapping {
final String name = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) jdbcMapping );
final ResultSetMappingSqlSelection sqlSelection = new ResultSetMappingSqlSelection( valuesArrayPosition, (BasicValuedMapping) jdbcMapping );
sqlSelectionConsumer.accept( sqlSelection );
return new BasicResult( valuesArrayPosition, name, jdbcMapping.getJavaTypeDescriptor() );

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.query.results;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
@ -13,6 +14,7 @@ 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.tree.expression.Expression;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration;
@ -23,21 +25,20 @@ import org.hibernate.type.spi.TypeConfiguration;
*
* @author Steve Ebersole
*/
public class SqlSelectionImpl implements SqlSelection, Expression, SqlExpressionAccess {
public class ResultSetMappingSqlSelection implements SqlSelection, Expression, SqlExpressionAccess {
private final int valuesArrayPosition;
private final BasicValuedMapping valueMapping;
private final JdbcMapping jdbcMapping;
public SqlSelectionImpl(int valuesArrayPosition, BasicValuedMapping valueMapping) {
public ResultSetMappingSqlSelection(int valuesArrayPosition, BasicValuedMapping valueMapping) {
this.valuesArrayPosition = valuesArrayPosition;
this.valueMapping = valueMapping;
this.jdbcMapping = valueMapping.getJdbcMapping();
}
public SqlSelectionImpl(int valuesArrayPosition, JdbcMapping jdbcMapping) {
public ResultSetMappingSqlSelection(int valuesArrayPosition, JdbcMapping jdbcMapping) {
this.valuesArrayPosition = valuesArrayPosition;
this.jdbcMapping = jdbcMapping;
this.valueMapping = null;
}
@ -55,11 +56,21 @@ public class SqlSelectionImpl implements SqlSelection, Expression, SqlExpression
return this;
}
@Override
public SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) {
return this;
}
@Override
public int getValuesArrayPosition() {
return valuesArrayPosition;
}
@Override
public int getJdbcResultSetIndex() {
return valuesArrayPosition + 1;
}
@Override
public Expression getExpression() {
return this;

View File

@ -17,7 +17,7 @@ import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.MissingSqlSelectionException;
import org.hibernate.query.results.PositionalSelectionsNotAllowedException;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
@ -108,7 +108,7 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, Basi
// we just care about the registration here. The ModelPart will find it later
creationState.resolveSqlExpression(
createColumnReferenceKey( tableReference, mappedColumn ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, referencedModelPart )
processingState -> new ResultSetMappingSqlSelection( valuesArrayPosition, referencedModelPart )
);
return (BasicFetch<?>) parent.generateFetchableFetch(

View File

@ -13,7 +13,7 @@ import org.hibernate.engine.FetchTiming;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
@ -88,7 +88,7 @@ public class CompleteFetchBuilderEntityValuedModelPart
processingState -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, selectableMapping.getJdbcMapping() );
return new ResultSetMappingSqlSelection( valuesArrayPosition, selectableMapping.getJdbcMapping() );
}
),
modelPart.getJavaTypeDescriptor(),

View File

@ -12,7 +12,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
@ -83,7 +83,7 @@ public class CompleteResultBuilderBasicModelPart
processingState -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, modelPart );
return new ResultSetMappingSqlSelection( valuesArrayPosition, modelPart );
}
),
modelPart.getJavaTypeDescriptor(),

View File

@ -15,7 +15,7 @@ import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.sql.ast.spi.SqlSelection;
@ -128,7 +128,7 @@ public class CompleteResultBuilderBasicValuedConverted<O,R> implements CompleteR
}
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, underlyingMapping );
return new ResultSetMappingSqlSelection( valuesArrayPosition, underlyingMapping );
}
),
valueConverter.getDomainJavaDescriptor(),

View File

@ -11,11 +11,10 @@ import java.util.function.BiFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -135,7 +134,7 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
}
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, basicType );
return new ResultSetMappingSqlSelection( valuesArrayPosition, basicType );
}
),
explicitJavaTypeDescriptor,

View File

@ -22,7 +22,7 @@ import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FromClauseAccessImpl;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
@ -161,7 +161,7 @@ public class CompleteResultBuilderCollectionStandard implements CompleteResultBu
final BasicValuedMapping basicType = (BasicValuedMapping) selectableMapping.getJdbcMapping();
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition(
jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, basicType );
return new ResultSetMappingSqlSelection( valuesArrayPosition, basicType );
}
),
selectableMapping.getJdbcMapping().getMappedJavaTypeDescriptor(),

View File

@ -25,7 +25,7 @@ import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
@ -214,7 +214,7 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
state -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
return new ResultSetMappingSqlSelection( valuesArrayPosition, jdbcMapping );
}
),
jdbcMapping.getMappedJavaTypeDescriptor(),

View File

@ -18,9 +18,8 @@ import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
@ -104,7 +103,7 @@ public class DynamicFetchBuilderStandard
state -> {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, selectableMapping.getJdbcMapping() );
return new ResultSetMappingSqlSelection( valuesArrayPosition, selectableMapping.getJdbcMapping() );
}
),
selectableMapping.getJdbcMapping().getMappedJavaTypeDescriptor(),

View File

@ -12,8 +12,7 @@ import java.util.function.BiFunction;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResult;
@ -86,7 +85,7 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder, Nati
state -> {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, attributeMapping );
return new ResultSetMappingSqlSelection( valuesArrayPosition, attributeMapping );
}
),
attributeMapping.getJavaTypeDescriptor(),

View File

@ -14,9 +14,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
@ -124,7 +123,7 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
);
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
return new ResultSetMappingSqlSelection( valuesArrayPosition, (BasicValuedMapping) basicType );
}
),
basicValueConverter.getDomainJavaDescriptor(),

View File

@ -11,9 +11,8 @@ import java.util.function.BiFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -149,7 +148,7 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
sessionFactory
);
}
return new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
return new ResultSetMappingSqlSelection( valuesArrayPosition, (BasicValuedMapping) basicType );
}
);

View File

@ -23,8 +23,7 @@ import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.TableGroupImpl;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
@ -278,7 +277,7 @@ public class DynamicResultBuilderEntityStandard
state -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
return new ResultSetMappingSqlSelection( valuesArrayPosition, jdbcMapping );
}
),
jdbcMapping.getMappedJavaTypeDescriptor(),

View File

@ -17,7 +17,7 @@ import org.hibernate.query.results.BasicValuedFetchBuilder;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -79,7 +79,7 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder, BasicVal
processingState -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( column );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, fetchable );
return new ResultSetMappingSqlSelection( valuesArrayPosition, fetchable );
}
);

View File

@ -76,6 +76,9 @@ public class SelfRenderingFunctionSqlAstExpression
@Override
public JdbcMappingContainer getExpressionType() {
if ( type instanceof SqlExpressable ) {
return (JdbcMappingContainer) type;
}
return expressable;
}
@ -93,35 +96,13 @@ public class SelfRenderingFunctionSqlAstExpression
jdbcPosition,
valuesArrayPosition,
this
) {
@Override
public ValueExtractor getJdbcValueExtractor() {
// the superclass implementation calls
// getExpressionType() on us to get the
// MappingModelExpressable, which we
// might not have, due to the code in
// SelfRenderingFunctionSqlAstExpression
if ( type instanceof SqlExpressable ) {
return ( (SqlExpressable) type ).getJdbcMapping().getJdbcValueExtractor();
}
else if ( expressable != null ) {
return super.getJdbcValueExtractor();
}
else {
throw new SemanticException("function return type is unknown, so function cannot occur in select");
}
}
};
);
}
@Override
public DomainResult createDomainResult(
String resultVariable,
DomainResultCreationState creationState) {
if ( type==null ) {
throw new SemanticException("function return type is unknown, so function cannot occur in select");
}
return new BasicResult(
creationState.getSqlAstCreationState().getSqlExpressionResolver()
.resolveSqlSelection(
@ -190,8 +171,7 @@ public class SelfRenderingFunctionSqlAstExpression
return ( (SqlExpressable) type ).getJdbcMapping();
}
else {
//TODO: do something else if we have a MappingModelExpressable?
throw new SemanticException("function return type is unknown, so function cannot occur in select");
return ( (SqlExpressable) expressable ).getJdbcMapping();
}
}

View File

@ -10,7 +10,7 @@ import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlSelection;
@ -55,7 +55,7 @@ public class DiscriminatorPathInterpretation extends AbstractSqmPathInterpretati
int valuesArrayPosition,
JavaType javaTypeDescriptor,
TypeConfiguration typeConfiguration) {
return new SqlSelectionImpl( valuesArrayPosition, getDiscriminatorMapping() );
return new ResultSetMappingSqlSelection( valuesArrayPosition, getDiscriminatorMapping() );
}
@Override

View File

@ -61,7 +61,5 @@ public interface SqlSelection extends SqlAstNode {
void accept(SqlAstWalker sqlAstWalker);
default void prepare(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) {
// By default we have nothing to do. Here as a hook for NativeQuery mapping resolutions
}
SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory);
}

View File

@ -0,0 +1,48 @@
/*
* 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.results.internal;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.ValueExtractor;
/**
*
* @author Christian Beikov
*/
public class ResolvedSqlSelection extends SqlSelectionImpl {
private final BasicType<Object> resolvedType;
public ResolvedSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
Expression sqlExpression,
BasicType<Object> resolvedType) {
super( jdbcPosition, valuesArrayPosition, sqlExpression );
this.resolvedType = resolvedType;
}
@Override
public ValueExtractor getJdbcValueExtractor() {
return resolvedType.getJdbcMapping().getJdbcValueExtractor();
}
@Override
public JdbcMappingContainer getExpressionType() {
return resolvedType;
}
@Override
public SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) {
return this;
}
}

View File

@ -8,12 +8,17 @@ package org.hibernate.sql.results.internal;
import java.util.Objects;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
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.tree.expression.Expression;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import org.hibernate.type.BasicType;
import org.hibernate.type.JavaObjectType;
import org.hibernate.type.descriptor.ValueExtractor;
/**
@ -54,8 +59,6 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
@Override
public ValueExtractor getJdbcValueExtractor() {
return ( (SqlExpressable) sqlExpression.getExpressionType() ).getJdbcMapping().getJdbcValueExtractor();
// return jdbcValueExtractor;
// return jdbcMapping.getJdbcValueExtractor();
}
@Override
@ -73,11 +76,34 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
return getExpression().getExpressionType();
}
@Override
public Expression getSqlExpression() {
return sqlExpression;
}
@Override
public void accept(SqlAstWalker interpreter) {
sqlExpression.accept( interpreter );
}
@Override
public SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) {
if ( sqlExpression.getExpressionType() instanceof JavaObjectType ) {
final BasicType<Object> resolvedType = jdbcResultsMetadata.resolveType(
jdbcPosition,
null,
sessionFactory
);
return new ResolvedSqlSelection(
jdbcPosition,
valuesArrayPosition,
sqlExpression,
resolvedType
);
}
return this;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
@ -86,19 +112,14 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
if ( o == null || getClass() != o.getClass() ) {
return false;
}
SqlSelectionImpl that = (SqlSelectionImpl) o;
return jdbcPosition == that.jdbcPosition &&
valuesArrayPosition == that.valuesArrayPosition &&
Objects.equals( sqlExpression, that.sqlExpression );
final SqlSelection that = (SqlSelection) o;
return jdbcPosition == that.getJdbcResultSetIndex() &&
valuesArrayPosition == that.getValuesArrayPosition() &&
Objects.equals( sqlExpression, that.getExpression() );
}
@Override
public int hashCode() {
return Objects.hash( jdbcPosition, valuesArrayPosition, sqlExpression );
}
@Override
public Expression getSqlExpression() {
return sqlExpression;
}
}

View File

@ -6,8 +6,8 @@
*/
package org.hibernate.sql.results.jdbc.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.spi.SqlSelection;
@ -26,11 +26,11 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
* @author Steve Ebersole
*/
public class JdbcValuesMappingProducerStandard implements JdbcValuesMappingProducer {
private final JdbcValuesMapping resolvedMapping;
public JdbcValuesMappingProducerStandard(List<SqlSelection> sqlSelections, List<DomainResult<?>> domainResults) {
resolvedMapping = new StandardJdbcValuesMapping( sqlSelections, domainResults );
this.resolvedMapping = new StandardJdbcValuesMapping( sqlSelections, domainResults );
}
@Override
@ -42,10 +42,21 @@ public class JdbcValuesMappingProducerStandard implements JdbcValuesMappingProdu
public JdbcValuesMapping resolve(
JdbcValuesMetadata jdbcResultsMetadata,
SessionFactoryImplementor sessionFactory) {
for ( SqlSelection sqlSelection : resolvedMapping.getSqlSelections() ) {
sqlSelection.prepare( jdbcResultsMetadata, sessionFactory );
final List<SqlSelection> sqlSelections = resolvedMapping.getSqlSelections();
List<SqlSelection> resolvedSelections = null;
for ( int i = 0; i < sqlSelections.size(); i++ ) {
final SqlSelection sqlSelection = sqlSelections.get( i );
final SqlSelection resolvedSelection = sqlSelection.resolve( jdbcResultsMetadata, sessionFactory );
if ( resolvedSelection != sqlSelection ) {
if ( resolvedSelections == null ) {
resolvedSelections = new ArrayList<>( sqlSelections );
}
resolvedSelections.set( i, resolvedSelection );
}
}
return resolvedMapping;
if ( resolvedSelections == null ) {
return resolvedMapping;
}
return new StandardJdbcValuesMapping( resolvedSelections, resolvedMapping.getDomainResults() );
}
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.sql.results.jdbc.internal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
@ -13,6 +14,7 @@ import org.hibernate.HibernateException;
import org.hibernate.cache.spi.QueryKey;
import org.hibernate.cache.spi.QueryResultsCache;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.exec.ExecutionException;
@ -274,13 +276,8 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
return false;
}
try {
readCurrentRowValues();
return true;
}
catch (SQLException e) {
throw makeExecutionException( "Error reading ResultSet row values", e );
}
readCurrentRowValues();
return true;
}
private ExecutionException makeExecutionException(String message, SQLException cause) {
@ -293,13 +290,15 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
);
}
private void readCurrentRowValues() throws SQLException {
private void readCurrentRowValues() {
final ResultSet resultSet = resultSetAccess.getResultSet();
final SharedSessionContractImplementor session = executionContext.getSession();
for ( final SqlSelection sqlSelection : sqlSelections ) {
try {
currentRowJdbcValues[ sqlSelection.getValuesArrayPosition() ] = sqlSelection.getJdbcValueExtractor().extract(
resultSetAccess.getResultSet(),
resultSet,
sqlSelection.getJdbcResultSetIndex(),
executionContext.getSession()
session
);
}
catch (Exception e) {

View File

@ -4,7 +4,7 @@
* 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.sql.refcursor;
package org.hibernate.orm.test.sql.refcursor;
import java.sql.Connection;
import java.sql.PreparedStatement;
@ -68,7 +68,7 @@ public class CursorFromCallableTest extends BaseCoreFunctionalTestCase {
Assert.assertEquals(
Arrays.asList( new NumValue( 1, "Line 1" ), new NumValue( 2, "Line 2" ) ),
session.getNamedQuery( "NumValue.getSomeValues" ).list()
session.createNamedStoredProcedureQuery( "NumValue.getSomeValues" ).getResultList()
);
session.getTransaction().commit();
@ -86,12 +86,12 @@ public class CursorFromCallableTest extends BaseCoreFunctionalTestCase {
// for ( int i = 0; i < maxCursors + 10; ++i ) { named_query_execution }
Assert.assertEquals(
Arrays.asList( new NumValue( 1, "Line 1" ), new NumValue( 2, "Line 2" ) ),
session.getNamedQuery( "NumValue.getSomeValues" ).list()
session.createNamedStoredProcedureQuery( "NumValue.getSomeValues" ).getResultList()
);
JdbcCoordinator jdbcCoordinator = ( (SessionImplementor) session ).getJdbcCoordinator();
Assert.assertFalse(
"Prepared statement and result set should be released after query execution.",
jdbcCoordinator.getResourceRegistry().hasRegisteredResources()
jdbcCoordinator.getLogicalConnection().getResourceRegistry().hasRegisteredResources()
);
session.getTransaction().commit();
session.close();
@ -115,7 +115,7 @@ public class CursorFromCallableTest extends BaseCoreFunctionalTestCase {
finally {
if ( preparedStatement != null ) {
try {
jdbcCoordinator.getResourceRegistry().release( preparedStatement );
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( preparedStatement );
}
catch ( Throwable ignore ) {
// ignore...

View File

@ -4,24 +4,29 @@
* 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.sql.refcursor;
package org.hibernate.orm.test.sql.refcursor;
import java.io.Serializable;
import java.sql.ResultSet;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedNativeQueries;
import jakarta.persistence.NamedNativeQuery;
import jakarta.persistence.QueryHint;
import jakarta.persistence.NamedStoredProcedureQuery;
import jakarta.persistence.ParameterMode;
import jakarta.persistence.StoredProcedureParameter;
import jakarta.persistence.Table;
@Entity
@Table(name = "BOT_NUMVALUE")
@NamedNativeQueries({
@NamedNativeQuery(name = "NumValue.getSomeValues",
query = "{ ? = call f_test_return_cursor() }",
resultClass = NumValue.class, hints = { @QueryHint(name = "org.hibernate.callable", value = "true") })
})
@NamedStoredProcedureQuery(
name = "NumValue.getSomeValues",
procedureName = "f_test_return_cursor",
resultClasses = NumValue.class,
parameters = {
@StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, type = ResultSet.class)
}
)
public class NumValue implements Serializable {
@Id
@Column(name = "BOT_NUM", nullable = false)

View File

@ -0,0 +1,62 @@
/*
* 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.orm.test.temporal;
import java.sql.Timestamp;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner.
*/
@TestForIssue( jiraKey = "HHH-8401")
@RequiresDialect( value = MySQLDialect.class, majorVersion = 5, minorVersion = 7)
@ServiceRegistry
@DomainModel( standardModels = StandardDomainModel.GAMBIT )
@SessionFactory
public class MySQL57TimestampFspFunctionTest {
@Test
public void testTimeStampFunctions(SessionFactoryScope scope) {
// current_timestamp(), localtime(), and localtimestamp() are synonyms for now(),
// which returns the time at which the statement began to execute.
// the returned values for now(), current_timestamp(), localtime(), and
// localtimestamp() should be the same.
// sysdate() is the time at which the function itself is executed, so the
// value returned for sysdate() should be different.
scope.inSession(
s -> {
Query q = s.createQuery(
"select now(), current_timestamp(), localtime(), localtimestamp(), sysdate()"
);
Object[] oArray = (Object[]) q.uniqueResult();
for ( Object o : oArray ) {
( (Timestamp) o ).setNanos( 0 );
}
final Timestamp now = (Timestamp) oArray[0];
assertEquals( now, oArray[1] );
assertEquals( now, oArray[2] );
assertEquals( now, oArray[3] );
assertTrue( now.compareTo( (Timestamp) oArray[4] ) <= 0 );
}
);
}
}

View File

@ -1,87 +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.temporal;
import java.sql.Timestamp;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.junit.Test;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.MySQL57Dialect;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner.
*/
@TestForIssue( jiraKey = "HHH-8401")
@RequiresDialect( MySQL57Dialect.class )
public class MySQL57TimestampFspFunctionTest extends BaseCoreFunctionalTestCase {
@Test
public void testTimeStampFunctions() {
// add an entity just so it can be queried.
Session s=openSession();
Transaction tx = s.beginTransaction();
s.persist( new Entity() );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
// current_timestamp(), localtime(), and localtimestamp() are synonyms for now(),
// which returns the time at which the statement began to execute.
// the returned values for now(), current_timestamp(), localtime(), and
// localtimestamp() should be the same.
// sysdate() is the time at which the function itself is executed, so the
// value returned for sysdate() should be different.
Query q=s.createQuery(
"select now(), current_timestamp(), localtime(), localtimestamp(), sysdate() from MySQL57TimestampFspFunctionTest$Entity"
);
Object[] oArray = (Object[]) q.uniqueResult();
final Timestamp now = (Timestamp) oArray[0];
assertEquals( now, oArray[1] );
assertEquals( now, oArray[2] );
assertEquals( now, oArray[3] );
final Timestamp sysdate = (Timestamp) oArray[4];
assertTrue( now.compareTo( sysdate ) < 0 );
// all should have nanos > 0
assertTrue( now.getNanos() > 0 );
assertTrue( sysdate.getNanos() > 0 );
tx.commit();
s.close();
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Entity.class };
}
// If MySQL supported something like Oracle's "dual", then this entity wouldn't be needed.
@jakarta.persistence.Entity
@Table(name = "DummyEntity")
public static class Entity {
@GeneratedValue
@Id
private long id;
}
}