diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SelectableConsumer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SelectableConsumer.java index 8908f9b341d8..0ad172fe1f8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SelectableConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SelectableConsumer.java @@ -5,6 +5,7 @@ package org.hibernate.metamodel.mapping; import org.checkerframework.checker.nullness.qual.Nullable; +import org.hibernate.engine.jdbc.Size; import java.util.function.BiConsumer; import java.util.function.IntFunction; @@ -27,7 +28,7 @@ public interface SelectableConsumer { /** * Simple form of visitation over a number of columns by name, using - * a separate {@link SelectableMappings} as a base for additional details. + * a separate {@link JdbcMappingContainer} as a base for additional details. *

* Intended for use in visiting table keys, where we know JdbcMappings, etc. * from the identifier. @@ -46,6 +47,149 @@ default void accept(String tableName, JdbcMappingContainer base, String[] column mutableSelectableMapping.forEach( this::accept ); } + /** + * Simple form of visitation over a number of columns by name, using + * a separate {@link SelectableMappings} as a base for additional details. + *

+ * Intended for use in visiting table keys, where we know JdbcMappings, etc. + * from the identifier. + *

+ * The expectation here is for the following details to be available:

+ */ + default void accept(SelectableMappings base, String tableName, String[] columnNames) { + class SelectableMappingIterator implements SelectableMapping { + private final String tableName; + private final SelectableMappings delegate; + private final String[] columnNames; + + private int index; + + public SelectableMappingIterator(String tableName, SelectableMappings delegate, String[] columnNames) { + this.tableName = tableName; + this.delegate = delegate; + this.columnNames = columnNames; + assert delegate.getJdbcTypeCount() == columnNames.length; + } + + private void forEach(BiConsumer consumer) { + for ( index = 0; index < columnNames.length; index++ ) { + consumer.accept( index, this ); + } + } + + @Override + public String getContainingTableExpression() { + return tableName; + } + + @Override + public String getSelectionExpression() { + return columnNames[index]; + } + + @Override + public @Nullable String getCustomReadExpression() { + return null; + } + + @Override + public @Nullable String getCustomWriteExpression() { + return null; + } + + private SelectableMapping getDelegate() { + return delegate.getSelectable( index ); + } + + @Override + public String getSelectableName() { + return getDelegate().getSelectableName(); + } + + @Override + public SelectablePath getSelectablePath() { + return getDelegate().getSelectablePath(); + } + + @Override + public boolean isFormula() { + return getDelegate().isFormula(); + } + + @Override + public boolean isNullable() { + return getDelegate().isNullable(); + } + + @Override + public boolean isInsertable() { + return getDelegate().isInsertable(); + } + + @Override + public boolean isUpdateable() { + return getDelegate().isUpdateable(); + } + + @Override + public boolean isPartitioned() { + return getDelegate().isPartitioned(); + } + + @Override + public @Nullable String getColumnDefinition() { + return getDelegate().getColumnDefinition(); + } + + @Override + public @Nullable Long getLength() { + return getDelegate().getLength(); + } + + @Override + public @Nullable Integer getArrayLength() { + return getDelegate().getArrayLength(); + } + + @Override + public @Nullable Integer getPrecision() { + return getDelegate().getPrecision(); + } + + @Override + public @Nullable Integer getScale() { + return getDelegate().getScale(); + } + + @Override + public @Nullable Integer getTemporalPrecision() { + return getDelegate().getTemporalPrecision(); + } + + @Override + public boolean isLob() { + return getDelegate().isLob(); + } + + @Override + public JdbcMapping getJdbcMapping() { + return getDelegate().getJdbcMapping(); + } + + @Override + public Size toSize() { + return getDelegate().toSize(); + } + } + + final SelectableMappingIterator mutableSelectableMapping = new SelectableMappingIterator( tableName, base, columnNames ); + mutableSelectableMapping.forEach( this::accept ); + } class MutableSelectableMapping implements SelectableMapping { private final String tableName; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SoftDeleteMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SoftDeleteMappingImpl.java index 5bf51bb76520..0c78976e3a6d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SoftDeleteMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SoftDeleteMappingImpl.java @@ -210,8 +210,8 @@ public Predicate createNonDeletedRestriction(TableReference tableReference, SqlE public ColumnValueBinding createNonDeletedValueBinding(ColumnReference softDeleteColumnReference) { final var nonDeletedFragment = strategy == SoftDeleteType.TIMESTAMP - ? new ColumnWriteFragment( null, emptyList(), jdbcMapping ) - : new ColumnWriteFragment( nonDeletedLiteralText, emptyList(), jdbcMapping ); + ? new ColumnWriteFragment( null, emptyList(), this ) + : new ColumnWriteFragment( nonDeletedLiteralText, emptyList(), this ); return new ColumnValueBinding( softDeleteColumnReference, nonDeletedFragment ); } @@ -219,8 +219,8 @@ public ColumnValueBinding createNonDeletedValueBinding(ColumnReference softDelet public ColumnValueBinding createDeletedValueBinding(ColumnReference softDeleteColumnReference) { final ColumnWriteFragment deletedFragment = strategy == SoftDeleteType.TIMESTAMP - ? new ColumnWriteFragment( currentTimestampFunctionName, emptyList(), getJdbcMapping() ) - : new ColumnWriteFragment( deletedLiteralText, emptyList(), jdbcMapping ); + ? new ColumnWriteFragment( currentTimestampFunctionName, emptyList(), this ) + : new ColumnWriteFragment( deletedLiteralText, emptyList(), this ); return new ColumnValueBinding( softDeleteColumnReference, deletedFragment ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 60620859af48..233046defd44 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -1739,8 +1739,8 @@ protected void applyKeyRestrictions( List restrictionBindings) { final var foreignKeyDescriptor = getAttributeMapping().getKeyDescriptor(); assert foreignKeyDescriptor != null; - foreignKeyDescriptor.getKeyPart().forEachSelectable( parameterList ); - for ( var columnValueParameter : parameterList ) { + foreignKeyDescriptor.getKeyPart().forEachSelectable( (selectionIndex, selectableMapping) -> { + final var columnValueParameter = parameterList.addColumValueParameter( selectableMapping ); final var columnReference = columnValueParameter.getColumnReference(); restrictionBindings.add( new ColumnValueBinding( @@ -1748,11 +1748,11 @@ protected void applyKeyRestrictions( new ColumnWriteFragment( "?", columnValueParameter, - columnReference.getJdbcMapping() + selectableMapping ) ) ); - } + }); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index bcf5d2c82439..c652e2d8985d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -296,8 +296,8 @@ public RestrictedTableMutation generateDeleteAllAst(Mutat new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyColumnCount ); final List keyRestrictionBindings = arrayList( keyColumnCount ); final List valueBindings = arrayList( valuesCount ); - foreignKeyDescriptor.getKeyPart().forEachSelectable( parameterBinders ); - for ( var columnValueParameter : parameterBinders ) { + foreignKeyDescriptor.getKeyPart().forEachSelectable( (selectionIndex, selectableMapping) -> { + final var columnValueParameter = parameterBinders.addColumValueParameter( selectableMapping ); final var columnReference = columnValueParameter.getColumnReference(); keyRestrictionBindings.add( new ColumnValueBinding( @@ -305,17 +305,17 @@ public RestrictedTableMutation generateDeleteAllAst(Mutat new ColumnWriteFragment( "?", columnValueParameter, - columnReference.getJdbcMapping() + selectableMapping ) ) ); valueBindings.add( new ColumnValueBinding( columnReference, - new ColumnWriteFragment( "null", columnReference.getJdbcMapping() ) + new ColumnWriteFragment( "null", selectableMapping ) ) ); - } + } ); if ( hasIndex() && !indexContainsFormula ) { attributeMapping.getIndexDescriptor().forEachSelectable( (selectionIndex, selectableMapping) -> { @@ -323,7 +323,7 @@ public RestrictedTableMutation generateDeleteAllAst(Mutat valueBindings.add( new ColumnValueBinding( new ColumnReference( tableReference, selectableMapping ), - new ColumnWriteFragment( "null", selectableMapping.getJdbcMapping() ) + new ColumnWriteFragment( "null", selectableMapping ) ) ); } @@ -484,10 +484,8 @@ public RestrictedTableMutation generateDeleteRowAst(Mutat if ( selectable.isUpdateable() ) { // set null updateBuilder.addValueColumn( - selectable.getSelectionExpression(), NULL, - selectable.getJdbcMapping(), - selectable.isLob() + selectable ); } // restrict @@ -504,10 +502,8 @@ public RestrictedTableMutation generateDeleteRowAst(Mutat final var selectable = indexDescriptor.getSelectable( i ); if ( selectable.isUpdateable() ) { updateBuilder.addValueColumn( - selectable.getSelectionExpression(), NULL, - selectable.getJdbcMapping(), - selectable.isLob() + selectable ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 34a3a651b864..2895a71df053 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -3356,10 +3356,7 @@ protected EntityTableMapping[] buildTableMappings() { .accept( (selectionIndex, selectableMapping) -> { keyColumns.add( new EntityTableMapping.KeyColumn( tableExpression, - selectableMapping.getSelectionExpression(), - selectableMapping.getWriteExpression(), - selectableMapping.isFormula(), - selectableMapping.getJdbcMapping() + selectableMapping ) ); } ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 862ba7b05537..213a84a85e9e 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -671,8 +671,8 @@ protected void visitMutabilityOrderedTables(MutabilityOrderedTableConsumer consu tableName, tableIndex, () -> columnConsumer -> columnConsumer.accept( - tableName, getIdentifierMapping(), + tableName, naturalOrderTableKeyColumns[tableIndex] ) ); @@ -742,9 +742,8 @@ public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilde final TableInsertBuilder tableInsertBuilder = insertGroupBuilder.getTableDetailsBuilder( getRootTableName() ); tableInsertBuilder.addValueColumn( - explicitDiscriminatorColumnName, getDiscriminatorValueString(), - getDiscriminatorMapping().getJdbcMapping() + getDiscriminatorMapping() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index ca5097a6abca..959fb3e43ac7 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -471,9 +471,8 @@ public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilde final TableInsertBuilder tableInsertBuilder = insertGroupBuilder.getTableDetailsBuilder( getRootTableName() ); tableInsertBuilder.addValueColumn( - discriminatorColumnName, discriminatorValue == NULL_DISCRIMINATOR ? NULL : discriminatorSQLValue, - getDiscriminatorMapping().getJdbcMapping() + getDiscriminatorMapping() ); } } @@ -610,8 +609,8 @@ protected void visitMutabilityOrderedTables(MutabilityOrderedTableConsumer consu tableName, tableIndex, () -> columnConsumer -> columnConsumer.accept( - tableName, getIdentifierMapping(), + tableName, keyColumnNames[tableIndex] ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index d91ff9018c3d..090b3437e2c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -384,7 +384,11 @@ protected void visitMutabilityOrderedTables(MutabilityOrderedTableConsumer consu consumer.consume( tableName, 0, - () -> columnConsumer -> columnConsumer.accept( tableName, getIdentifierMapping(), getIdentifierColumnNames() ) + () -> columnConsumer -> columnConsumer.accept( + getIdentifierMapping(), + tableName, + getIdentifierColumnNames() + ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java index 98014cb26964..a03e128970bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java @@ -132,10 +132,8 @@ protected void handleValueGeneration( final String tableName = entityPersister.physicalTableNameForMutation( mapping ); final ColumnValuesTableMutationBuilder tableUpdateBuilder = mutationGroupBuilder.findTableDetailsBuilder( tableName ); tableUpdateBuilder.addValueColumn( - mapping.getSelectionExpression(), writePropertyValue ? "?" : columnValues[j], - mapping.getJdbcMapping(), - mapping.isLob() + mapping ); } ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/EntityTableMapping.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/EntityTableMapping.java index 68837d274df9..2fc00d0bd824 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/EntityTableMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/EntityTableMapping.java @@ -4,18 +4,17 @@ */ package org.hibernate.persister.entity.mutation; -import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jdbc.Expectation; import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMappings; import org.hibernate.metamodel.mapping.TableDetails; +import org.hibernate.metamodel.mapping.internal.SelectableMappingImpl; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlExpressionResolver; @@ -384,118 +383,33 @@ public DomainResult createDomainResult( } } - public static class KeyColumn implements TableDetails.KeyColumn { - private final String tableName; - private final String columnName; - private final String writeExpression; - - private final boolean formula; - - private final JdbcMapping jdbcMapping; - - public KeyColumn( - String tableName, - String columnName, - String writeExpression, - boolean formula, - JdbcMapping jdbcMapping) { - this.tableName = tableName; - this.columnName = columnName; - this.writeExpression = writeExpression; - this.formula = formula; - this.jdbcMapping = jdbcMapping; - } - - public String getColumnName() { - return columnName; - } - - @Override - public String getContainingTableExpression() { - return tableName; - } - - @Override - public String getWriteExpression() { - return writeExpression; - } - - @Override - public String getSelectionExpression() { - return columnName; - } - - @Override - public JdbcMapping getJdbcMapping() { - return jdbcMapping; - } - - @Override - public boolean isFormula() { - return formula; - } - - @Override - public boolean isNullable() { - // keys are never nullable - return false; - } - - @Override - public boolean isInsertable() { - // keys are always insertable, unless this "column" is a formula - return !formula; - } - - @Override - public boolean isUpdateable() { - // keys are never updateable - return false; - } - - @Override - public boolean isPartitioned() { - return false; - } - - @Override - public @Nullable String getColumnDefinition() { - return null; - } - - @Override - public @Nullable Long getLength() { - return null; - } - - @Override - public @Nullable Integer getArrayLength() { - return null; - } - - @Override - public @Nullable Integer getPrecision() { - return null; - } - - @Override - public @Nullable Integer getScale() { - return null; - } - - @Override - public @Nullable Integer getTemporalPrecision() { - return null; - } - - @Override - public @Nullable String getCustomReadExpression() { - return null; + public static class KeyColumn extends SelectableMappingImpl implements TableDetails.KeyColumn { + + public KeyColumn(String tableName, SelectableMapping originalMapping) { + super( + tableName, + originalMapping.getSelectionExpression(), + originalMapping.getSelectablePath(), + originalMapping.getCustomReadExpression(), + originalMapping.getCustomWriteExpression(), + originalMapping.getColumnDefinition(), + originalMapping.getLength(), + originalMapping.getPrecision(), + originalMapping.getScale(), + originalMapping.getTemporalPrecision(), + originalMapping.isLob(), + originalMapping.isNullable(), + originalMapping.isInsertable(), + originalMapping.isUpdateable(), + originalMapping.isPartitioned(), + originalMapping.isFormula(), + originalMapping.getJdbcMapping() + ); } @Override - public @Nullable String getCustomWriteExpression() { - return null; + public String getColumnName() { + return getSelectionExpression(); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinatorStandard.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinatorStandard.java index 397fe335c807..6f475a8cf060 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinatorStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinatorStandard.java @@ -26,7 +26,6 @@ import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMappingsList; -import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.sql.model.MutationOperation; @@ -429,14 +428,11 @@ else if ( isValueGenerationInSql( generator, factory.getJdbcServices().getDialec assert entityPersister().getInsertDelegate() != null; final OnExecutionGenerator generator = (OnExecutionGenerator) entityPersister().getGenerator(); if ( generator.referenceColumnsInSql( dialect ) ) { - final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityPersister().getIdentifierMapping(); final String[] columnValues = generator.getReferencedColumnValues( dialect ); if ( columnValues != null ) { - tableMapping.getKeyMapping().forEachKeyColumn( (i, column) -> tableInsertBuilder.addKeyColumn( - column.getColumnName(), - columnValues[i], - identifierMapping.getJdbcMapping() - ) ); + assert columnValues.length == 1; + assert tableMapping.getKeyMapping().getColumnCount() == 1; + tableInsertBuilder.addKeyColumn( columnValues[0], tableMapping.getKeyMapping().getKeyColumn( 0 ) ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index 2d3d3a645447..dba3b663d578 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -120,6 +120,7 @@ import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression; import org.hibernate.sql.ast.tree.expression.SqlTuple; import org.hibernate.sql.ast.tree.expression.SqlTupleContainer; +import org.hibernate.sql.ast.tree.expression.SqlTypedExpression; import org.hibernate.sql.ast.tree.expression.Star; import org.hibernate.sql.ast.tree.expression.Summarization; import org.hibernate.sql.ast.tree.expression.TrimSpecification; @@ -5664,10 +5665,10 @@ protected void renderCasted(Expression expression) { final List arguments = new ArrayList<>( 2 ); arguments.add( expression ); final CastTarget castTarget; - if ( expression instanceof SqlTypedMappingJdbcParameter parameter ) { - final SqlTypedMapping sqlTypedMapping = parameter.getSqlTypedMapping(); + if ( expression instanceof SqlTypedExpression sqlTypedExpression ) { + final SqlTypedMapping sqlTypedMapping = sqlTypedExpression.getSqlTypedMapping(); castTarget = new CastTarget( - parameter.getJdbcMapping(), + sqlTypedMapping.getJdbcMapping(), sqlTypedMapping.getColumnDefinition(), sqlTypedMapping.getLength(), sqlTypedMapping.getArrayLength(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/SqlTypedExpression.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/SqlTypedExpression.java new file mode 100644 index 000000000000..3099bb357ed5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/SqlTypedExpression.java @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.sql.ast.tree.expression; + +import org.hibernate.metamodel.mapping.SqlTypedMapping; + +/** + * An expression that has SQL type information. + */ +public interface SqlTypedExpression extends Expression { + SqlTypedMapping getSqlTypedMapping(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/SqlTypedMappingJdbcParameter.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/SqlTypedMappingJdbcParameter.java index 5e80bc9e9c8b..87bdad615f62 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/SqlTypedMappingJdbcParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/SqlTypedMappingJdbcParameter.java @@ -6,11 +6,12 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.metamodel.mapping.SqlTypedMapping; +import org.hibernate.sql.ast.tree.expression.SqlTypedExpression; /** * @author Steve Ebersole */ -public class SqlTypedMappingJdbcParameter extends AbstractJdbcParameter { +public class SqlTypedMappingJdbcParameter extends AbstractJdbcParameter implements SqlTypedExpression { private final SqlTypedMapping sqlTypedMapping; @@ -24,6 +25,7 @@ public SqlTypedMappingJdbcParameter(SqlTypedMapping sqlTypedMapping, @Nullable I this.sqlTypedMapping = sqlTypedMapping; } + @Override public SqlTypedMapping getSqlTypedMapping() { return sqlTypedMapping; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java index 9a87e85e1560..10aa1a9e42ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java @@ -6,6 +6,7 @@ import java.util.ArrayList; +import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.Incubating; import org.hibernate.Internal; import org.hibernate.engine.jdbc.mutation.ParameterUsage; @@ -38,12 +39,12 @@ public Object clone() { @Override public void consume(int valueIndex, Object value, SelectableMapping jdbcValueMapping) { - final ColumnValueBinding columnValueBinding = createValueBinding( - jdbcValueMapping.getSelectionExpression(), - value == null ? null : jdbcValueMapping.getWriteExpression(), - jdbcValueMapping.getJdbcMapping() - ); - add( columnValueBinding ); + if ( value == null ) { + addNullRestriction( jdbcValueMapping ); + } + else { + addRestriction( jdbcValueMapping ); + } } @Internal @Incubating @@ -51,22 +52,18 @@ public void addRestriction(ColumnValueBinding valueBinding) { add( valueBinding ); } - public void addNullRestriction(SelectableMapping column) { - add( createValueBinding( column.getSelectionExpression(), null, column.getJdbcMapping() ) ); + public void addRestriction(SelectableMapping column) { + add( createValueBinding( column, column.getWriteExpression() ) ); } - public void addRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { - add( createValueBinding( columnName, columnWriteFragment, jdbcMapping ) ); + public void addNullRestriction(SelectableMapping column) { + add( createValueBinding( column, null ) ); } - protected ColumnValueBinding createValueBinding( - String columnName, - String customWriteExpression, - JdbcMapping jdbcMapping) { + protected ColumnValueBinding createValueBinding(SelectableMapping column, @Nullable String customWriteExpression) { return ColumnValueBindingBuilder.createValueBinding( - columnName, customWriteExpression, - jdbcMapping, + column, mutatingTable, parameterUsage, parameters::apply diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueParameterList.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueParameterList.java index 9d1a6b885fbc..56e58f77eab8 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueParameterList.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueParameterList.java @@ -35,12 +35,14 @@ public Object clone() { @Override public void accept(int selectionIndex, SelectableMapping selectableMapping) { - add( - new ColumnValueParameter( - new ColumnReference( tableReference, selectableMapping ), - parameterUsage - ) - ); + addColumValueParameter( selectableMapping ); + } + + public ColumnValueParameter addColumValueParameter(SelectableMapping selectableMapping) { + final ColumnValueParameter columnValueParameter = + new ColumnValueParameter( new ColumnReference( tableReference, selectableMapping ), parameterUsage ); + add( columnValueParameter ); + return columnValueParameter; } public void apply(Object parameterRef) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnWriteFragment.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnWriteFragment.java index b43df4d58281..10413ab8fb93 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnWriteFragment.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnWriteFragment.java @@ -11,8 +11,10 @@ import org.hibernate.annotations.ColumnTransformer; import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SelectableMapping; +import org.hibernate.metamodel.mapping.SqlTypedMapping; import org.hibernate.sql.ast.SqlAstWalker; -import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.SqlTypedExpression; /** * Models a column's value expression within the SQL AST. Used to model:
    @@ -24,24 +26,24 @@ * * @author Steve Ebersole */ -public class ColumnWriteFragment implements Expression { +public class ColumnWriteFragment implements SqlTypedExpression { private final String fragment; private final List parameters; - private final JdbcMapping jdbcMapping; + private final SelectableMapping selectableMapping; - public ColumnWriteFragment(String fragment, JdbcMapping jdbcMapping) { - this( fragment, Collections.emptyList(), jdbcMapping ); + public ColumnWriteFragment(String fragment, SelectableMapping selectableMapping) { + this( fragment, Collections.emptyList(), selectableMapping ); } - public ColumnWriteFragment(String fragment, ColumnValueParameter parameter, JdbcMapping jdbcMapping) { - this( fragment, Collections.singletonList( parameter ), jdbcMapping ); + public ColumnWriteFragment(String fragment, ColumnValueParameter parameter, SelectableMapping selectableMapping) { + this( fragment, Collections.singletonList( parameter ), selectableMapping ); assert !fragment.contains( "?" ) || parameter != null; } - public ColumnWriteFragment(String fragment, List parameters, JdbcMapping jdbcMapping) { + public ColumnWriteFragment(String fragment, List parameters, SelectableMapping selectableMapping) { this.fragment = fragment; this.parameters = parameters; - this.jdbcMapping = jdbcMapping; + this.selectableMapping = selectableMapping; } public String getFragment() { @@ -52,9 +54,14 @@ public Collection getParameters() { return parameters; } + @Override + public SqlTypedMapping getSqlTypedMapping() { + return selectableMapping; + } + @Override public JdbcMapping getExpressionType() { - return jdbcMapping; + return selectableMapping.getJdbcMapping(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractRestrictedTableMutationBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractRestrictedTableMutationBuilder.java index 8142d1f30acc..5a634ad1dbb9 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractRestrictedTableMutationBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractRestrictedTableMutationBuilder.java @@ -6,7 +6,6 @@ import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.MutationTarget; @@ -66,8 +65,8 @@ public void addNonKeyRestriction(ColumnValueBinding valueBinding) { } @Override - public void addKeyRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { - keyRestrictionBindings.addRestriction( columnName, columnWriteFragment, jdbcMapping ); + public void addKeyRestrictionBinding(SelectableMapping selectableMapping) { + keyRestrictionBindings.addRestriction( selectableMapping ); } @Override @@ -76,13 +75,8 @@ public void addNullOptimisticLockRestriction(SelectableMapping column) { } @Override - public void addOptimisticLockRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { - optimisticLockBindings.addRestriction( columnName, columnWriteFragment, jdbcMapping ); - } - - @Override - public void addLiteralRestriction(String columnName, String sqlLiteralText, JdbcMapping jdbcMapping) { - keyRestrictionBindings.addRestriction( columnName, sqlLiteralText, jdbcMapping ); + public void addOptimisticLockRestriction(SelectableMapping selectableMapping) { + optimisticLockBindings.addRestriction( selectableMapping ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java index cfe663d2bbbf..5e0dcadd1591 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java @@ -8,7 +8,7 @@ import java.util.List; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.TableMapping; @@ -67,10 +67,10 @@ protected List getLobValueBindingList() { } @Override - public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob) { - final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping ); + public void addValueColumn(String columnWriteFragment, SelectableMapping selectableMapping) { + final ColumnValueBinding valueBinding = createValueBinding( columnWriteFragment, selectableMapping ); - if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) { + if ( selectableMapping.isLob() && getJdbcServices().getDialect().forceLobAsLastValue() ) { if ( lobValueBindingList == null ) { lobValueBindingList = new ArrayList<>(); } @@ -87,7 +87,7 @@ public void addValueColumn(ColumnValueBinding valueBinding) { } @Override - public void addKeyColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { - addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindingList ); + public void addKeyColumn(String columnWriteFragment, SelectableMapping selectableMapping) { + addColumn( columnWriteFragment, selectableMapping, keyBindingList ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableMutationBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableMutationBuilder.java index 74b45f7a0471..6255c8a60d72 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableMutationBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableMutationBuilder.java @@ -10,7 +10,7 @@ import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.TableMapping; @@ -76,39 +76,25 @@ protected JdbcServices getJdbcServices() { } protected void addColumn( - String columnName, String columnWriteFragment, - JdbcMapping jdbcMapping, + SelectableMapping selectableMapping, List list) { - final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping ); - list.add( valueBinding ); - } - - protected void addColumn( - String columnName, - String columnWriteFragment, - JdbcMapping jdbcMapping, - ParameterUsage parameterUsage, - List list) { - final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping, parameterUsage ); + final ColumnValueBinding valueBinding = createValueBinding( columnWriteFragment, selectableMapping ); list.add( valueBinding ); } protected ColumnValueBinding createValueBinding( - String columnName, String columnWriteFragment, - JdbcMapping jdbcMapping) { - return createValueBinding( columnName, columnWriteFragment, jdbcMapping, ParameterUsage.SET ); + SelectableMapping selectableMapping) { + return createValueBinding( columnWriteFragment, selectableMapping, ParameterUsage.SET ); } protected ColumnValueBinding createValueBinding( - String columnName, String customWriteExpression, - JdbcMapping jdbcMapping, + SelectableMapping selectableMapping, ParameterUsage parameterUsage) { return ColumnValueBindingBuilder.createValueBinding( - columnName, customWriteExpression, - jdbcMapping, + selectableMapping, getMutatingTable(), parameterUsage, parameters::apply diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java index fd447542885a..5e5d0af8d8e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java @@ -8,7 +8,7 @@ import java.util.List; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationType; @@ -85,14 +85,10 @@ protected List getLobValueBindings() { } @Override - public void addValueColumn( - String columnName, - String columnWriteFragment, - JdbcMapping jdbcMapping, - boolean isLob) { - final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping ); + public void addValueColumn(String columnWriteFragment, SelectableMapping selectableMapping) { + final ColumnValueBinding valueBinding = createValueBinding( columnWriteFragment, selectableMapping ); - if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) { + if ( selectableMapping.isLob() && getJdbcServices().getDialect().forceLobAsLastValue() ) { if ( lobValueBindings == null ) { lobValueBindings = new ArrayList<>(); } @@ -109,10 +105,7 @@ public void addValueColumn(ColumnValueBinding valueBinding) { } @Override - public void addKeyColumn( - String columnName, - String columnWriteFragment, - JdbcMapping jdbcMapping) { - addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindings ); + public void addKeyColumn(String columnWriteFragment, SelectableMapping selectableMapping) { + addColumn( columnWriteFragment, selectableMapping, keyBindings ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValueBindingBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValueBindingBuilder.java index 239e5f1ed57b..90f9164f5812 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValueBindingBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValueBindingBuilder.java @@ -8,9 +8,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.metamodel.mapping.EmbeddableMappingType; -import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueParameter; @@ -35,16 +36,19 @@ public class ColumnValueBindingBuilder { public static ColumnValueBinding createValueBinding( - String columnName, - String writeExpression, - JdbcMapping jdbcMapping, + @Nullable String writeExpression, + SelectableMapping selectableMapping, MutatingTableReference mutatingTableReference, ParameterUsage parameterUsage, Consumer parameterConsumer) { - final ColumnReference columnReference = new ColumnReference( mutatingTableReference, columnName, jdbcMapping ); + final ColumnReference columnReference = new ColumnReference( + mutatingTableReference, + selectableMapping.getSelectionExpression(), + selectableMapping.getJdbcMapping() + ); final ColumnWriteFragment columnWriteFragment = buildWriteFragment( writeExpression, - jdbcMapping, + selectableMapping, mutatingTableReference, columnReference, parameterUsage, @@ -54,8 +58,8 @@ public static ColumnValueBinding createValueBinding( } public static ColumnWriteFragment buildWriteFragment( - String writeExpression, - JdbcMapping jdbcMapping, + @Nullable String writeExpression, + SelectableMapping selectableMapping, MutatingTableReference mutatingTableReference, ColumnReference columnReference, ParameterUsage parameterUsage, @@ -66,28 +70,28 @@ public static ColumnWriteFragment buildWriteFragment( if ( writeExpression.equals( "?" ) || ( writeExpression.contains( "?" ) && !writeExpression.contains( "'" ) ) ) { - return buildParameterizedWriteFragment( writeExpression, jdbcMapping, mutatingTableReference, columnReference, parameterUsage, parameterConsumer ); + return buildParameterizedWriteFragment( writeExpression, selectableMapping, mutatingTableReference, columnReference, parameterUsage, parameterConsumer ); } if ( !writeExpression.contains( "?" ) ) { - return new ColumnWriteFragment( writeExpression, jdbcMapping ); + return new ColumnWriteFragment( writeExpression, selectableMapping ); } if ( containsParameter( writeExpression ) ) { - return buildParameterizedWriteFragment( writeExpression, jdbcMapping, mutatingTableReference, columnReference, parameterUsage, parameterConsumer ); + return buildParameterizedWriteFragment( writeExpression, selectableMapping, mutatingTableReference, columnReference, parameterUsage, parameterConsumer ); } - return new ColumnWriteFragment( writeExpression, jdbcMapping ); + return new ColumnWriteFragment( writeExpression, selectableMapping ); } private static ColumnWriteFragment buildParameterizedWriteFragment( String writeExpression, - JdbcMapping jdbcMapping, + SelectableMapping selectableMapping, MutatingTableReference mutatingTableReference, ColumnReference columnReference, ParameterUsage parameterUsage, Consumer parameterConsumer) { - final JdbcType jdbcType = jdbcMapping.getJdbcType(); + final JdbcType jdbcType = selectableMapping.getJdbcMapping().getJdbcType(); final EmbeddableMappingType aggregateMappingType = jdbcType instanceof AggregateJdbcType aggregateJdbcType ? aggregateJdbcType.getEmbeddableMappingType() @@ -101,12 +105,12 @@ private static ColumnWriteFragment buildParameterizedWriteFragment( aggregateMappingType.forEachSelectable( parameters ); parameterConsumer.accept( parameters ); - return new ColumnWriteFragment( writeExpression, parameters, jdbcMapping ); + return new ColumnWriteFragment( writeExpression, parameters, selectableMapping ); } else { final ColumnValueParameter parameter = new ColumnValueParameter( columnReference, parameterUsage ); parameterConsumer.accept( parameter ); - return new ColumnWriteFragment( writeExpression, parameter, jdbcMapping ); + return new ColumnWriteFragment( writeExpression, parameter, selectableMapping ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java index b7344ed16be6..3a5950d9ac4f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java @@ -6,7 +6,6 @@ import org.hibernate.Incubating; import org.hibernate.Internal; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.TableMutation; @@ -31,39 +30,30 @@ public interface ColumnValuesTableMutationBuilder> ex /** * Add a column as part of the values list */ - void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob); - /** - * Add a column as part of the values list - */ - default void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { - addValueColumn( columnName, columnWriteFragment, jdbcMapping, jdbcMapping.getJdbcType().isLob() ); - } + void addValueColumn(String columnWriteFragment, SelectableMapping selectableMapping); /** * Add a column as part of the values list */ default void addValueColumn(SelectableMapping selectableMapping) { addValueColumn( - selectableMapping.getSelectionExpression(), selectableMapping.getWriteExpression(), - selectableMapping.getJdbcMapping(), - selectableMapping.isLob() + selectableMapping ); } /** * Add a key column */ - void addKeyColumn(String columnName, String valueExpression, JdbcMapping jdbcMapping); + void addKeyColumn(String valueExpression, SelectableMapping selectableMapping); /** * Add a key column */ default void addKeyColumn(int index, SelectableMapping selectableMapping) { addKeyColumn( - selectableMapping.getSelectionExpression(), selectableMapping.getWriteExpression(), - selectableMapping.getJdbcMapping() + selectableMapping ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/RestrictedTableMutationBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/RestrictedTableMutationBuilder.java index 0530a792d77c..32c46ff2f781 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/RestrictedTableMutationBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/RestrictedTableMutationBuilder.java @@ -6,7 +6,6 @@ import org.hibernate.Incubating; import org.hibernate.Internal; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMappings; import org.hibernate.sql.model.MutationOperation; @@ -80,17 +79,13 @@ default void addKeyRestrictionLeniently(SelectableMapping selectableMapping) { if ( selectableMapping.isFormula() ) { return; } - addKeyRestriction( - selectableMapping.getSelectionExpression(), - selectableMapping.getWriteExpression(), - selectableMapping.getJdbcMapping() - ); + addKeyRestrictionBinding( selectableMapping ); } /** - * Add restriction based on the column in the table's key + * Add a restriction as long as the selectable is not a formula and is not nullable */ - void addKeyRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping); + void addKeyRestrictionBinding(SelectableMapping selectableMapping); void addNullOptimisticLockRestriction(SelectableMapping column); @@ -101,20 +96,7 @@ default void addNullRestriction(SelectableMapping column) { /** * Add restriction based on non-version optimistically-locked column */ - default void addOptimisticLockRestriction(SelectableMapping selectableMapping) { - addOptimisticLockRestriction( - selectableMapping.getSelectionExpression(), - selectableMapping.getWriteExpression(), - selectableMapping.getJdbcMapping() - ); - } - - /** - * Add restriction based on non-version optimistically-locked column - */ - void addOptimisticLockRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping); - - void addLiteralRestriction(String columnName, String sqlLiteralText, JdbcMapping jdbcMapping); + void addOptimisticLockRestriction(SelectableMapping selectableMapping); ColumnValueBindingList getKeyRestrictionBindings(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableDeleteBuilderSkipped.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableDeleteBuilderSkipped.java index 63402bf8960d..4afd557d6d71 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableDeleteBuilderSkipped.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableDeleteBuilderSkipped.java @@ -4,7 +4,6 @@ */ package org.hibernate.sql.model.ast.builder; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.ast.ColumnValueBinding; @@ -27,7 +26,7 @@ public void addNonKeyRestriction(ColumnValueBinding valueBinding) { } @Override - public void addKeyRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { + public void addKeyRestrictionBinding(SelectableMapping selectableMapping) { } @Override @@ -35,11 +34,7 @@ public void addNullOptimisticLockRestriction(SelectableMapping column) { } @Override - public void addOptimisticLockRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { - } - - @Override - public void addLiteralRestriction(String columnName, String sqlLiteralText, JdbcMapping jdbcMapping) { + public void addOptimisticLockRestriction(SelectableMapping selectableMapping) { } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java index ba525bd65b60..645bace17596 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java @@ -4,7 +4,6 @@ */ package org.hibernate.sql.model.ast.builder; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueBindingList; @@ -38,7 +37,7 @@ public void addNonKeyRestriction(ColumnValueBinding valueBinding) { } @Override - public void addKeyRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { + public void addKeyRestrictionBinding(SelectableMapping selectableMapping) { // nothing to do } @@ -48,14 +47,10 @@ public void addNullOptimisticLockRestriction(SelectableMapping column) { } @Override - public void addOptimisticLockRestriction(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { + public void addOptimisticLockRestriction(SelectableMapping selectableMapping) { // nothing to do } - @Override - public void addLiteralRestriction(String columnName, String sqlLiteralText, JdbcMapping jdbcMapping) { - } - @Override public ColumnValueBindingList getKeyRestrictionBindings() { return null; @@ -72,7 +67,7 @@ public void addWhereFragment(String fragment) { } @Override - public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob) { + public void addValueColumn(String columnWriteFragment, SelectableMapping selectableMapping) { // nothing to do } @@ -82,7 +77,7 @@ public void addValueColumn(ColumnValueBinding valueBinding) { } @Override - public void addKeyColumn(String columnName, String valueExpression, JdbcMapping jdbcMapping) { + public void addKeyColumn(String valueExpression, SelectableMapping selectableMapping) { // nothing to do } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java index 3901cb158e5b..fff166f2d591 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java @@ -15,6 +15,9 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; +import static java.lang.Math.ceil; +import static java.lang.Math.log; + /** * Descriptor for {@link Double} handling. * @@ -23,6 +26,8 @@ public class DoubleJavaType extends AbstractClassJavaType implements PrimitiveJavaType { public static final DoubleJavaType INSTANCE = new DoubleJavaType(); + //needed for converting precision from binary to decimal digits + private static final double LOG_BASE10OF2 = log(2)/log(10); public DoubleJavaType() { super( Double.class ); @@ -151,9 +156,14 @@ public long getDefaultSqlLength(Dialect dialect, JdbcType jdbcType) { @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { - //this is the number of *binary* digits - //in a double-precision FP number - return dialect.getDoublePrecision(); + if ( jdbcType.isFloat() ) { + //this is the number of *binary* digits + //in a double-precision FP number + return dialect.getDoublePrecision(); + } + else { + return Math.min( dialect.getDefaultDecimalPrecision(), (int) ceil( dialect.getDoublePrecision() * LOG_BASE10OF2 ) ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java index aec3e11d7e0a..e65e1a24deb6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java @@ -15,6 +15,9 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; +import static java.lang.Math.ceil; +import static java.lang.Math.log; + /** * Descriptor for {@link Float} handling. * @@ -22,6 +25,8 @@ */ public class FloatJavaType extends AbstractClassJavaType implements PrimitiveJavaType { public static final FloatJavaType INSTANCE = new FloatJavaType(); + //needed for converting precision from binary to decimal digits + private static final double LOG_BASE10OF2 = log(2)/log(10); public FloatJavaType() { super( Float.class ); @@ -149,9 +154,14 @@ public long getDefaultSqlLength(Dialect dialect, JdbcType jdbcType) { @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { - //this is the number of *binary* digits - //in a single-precision FP number - return dialect.getFloatPrecision(); + if ( jdbcType.isFloat() ) { + //this is the number of *binary* digits + //in a single-precision FP number + return dialect.getFloatPrecision(); + } + else { + return Math.min( dialect.getDefaultDecimalPrecision(), (int) ceil( dialect.getFloatPrecision() * LOG_BASE10OF2 ) ); + } } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/write/OptionalTableUpdateTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/write/OptionalTableUpdateTests.java index 9c745976e197..fb027fa7d0db 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/write/OptionalTableUpdateTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/write/OptionalTableUpdateTests.java @@ -4,9 +4,11 @@ */ package org.hibernate.orm.test.write; +import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.type.SqlTypes; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -17,6 +19,8 @@ import jakarta.persistence.SecondaryTable; import jakarta.persistence.Table; +import java.math.BigDecimal; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -102,6 +106,13 @@ public static class TheEntity { @Basic @Column( table = "supplements" ) private String details; + // Used to provoke https://hibernate.atlassian.net/browse/HHH-19749 + @Column( precision = 6, scale = 2, table = "supplements" ) + private BigDecimal theBigDecimal; + // Used to provoke https://hibernate.atlassian.net/browse/HHH-18860 + @JdbcTypeCode( SqlTypes.NUMERIC ) + @Column( precision = 6, scale = 2, table = "supplements" ) + private Double theDoubleDecimal; private TheEntity() { // for use by Hibernate @@ -132,5 +143,21 @@ public String getDetails() { public void setDetails(String details) { this.details = details; } + + public BigDecimal getTheBigDecimal() { + return theBigDecimal; + } + + public void setTheBigDecimal(BigDecimal discount) { + this.theBigDecimal = discount; + } + + public Double getTheDoubleDecimal() { + return theDoubleDecimal; + } + + public void setTheDoubleDecimal(Double theDoubleDecimal) { + this.theDoubleDecimal = theDoubleDecimal; + } } }