HHH-16103 - MERGE for optional table updates on SQL Server
This commit is contained in:
parent
375f6b5f14
commit
5525b8d9b7
|
@ -40,7 +40,6 @@ import java.util.TimeZone;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.Length;
|
import org.hibernate.Length;
|
||||||
|
@ -147,7 +146,7 @@ import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.spi.StringBuilderSqlAppender;
|
import org.hibernate.sql.ast.spi.StringBuilderSqlAppender;
|
||||||
import org.hibernate.sql.model.MutationOperation;
|
import org.hibernate.sql.model.MutationOperation;
|
||||||
import org.hibernate.sql.model.internal.TableUpsert;
|
import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||||
import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation;
|
import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||||
|
@ -192,6 +191,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static java.lang.Math.ceil;
|
import static java.lang.Math.ceil;
|
||||||
|
@ -4709,9 +4709,9 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
||||||
*/
|
*/
|
||||||
public MutationOperation createUpsertOperation(
|
public MutationOperation createUpsertOperation(
|
||||||
EntityMutationTarget mutationTarget,
|
EntityMutationTarget mutationTarget,
|
||||||
TableUpsert tableUpsert,
|
OptionalTableUpdate optionalTableUpdate,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory) {
|
||||||
return new OptionalTableUpdateOperation( mutationTarget, tableUpsert, factory );
|
return new OptionalTableUpdateOperation( mutationTarget, optionalTableUpdate, factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,7 +62,7 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.tree.Statement;
|
import org.hibernate.sql.ast.tree.Statement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
import org.hibernate.sql.model.MutationOperation;
|
import org.hibernate.sql.model.MutationOperation;
|
||||||
import org.hibernate.sql.model.internal.TableUpsert;
|
import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||||
|
@ -874,9 +874,9 @@ public class H2Dialect extends Dialect {
|
||||||
@Override
|
@Override
|
||||||
public MutationOperation createUpsertOperation(
|
public MutationOperation createUpsertOperation(
|
||||||
EntityMutationTarget mutationTarget,
|
EntityMutationTarget mutationTarget,
|
||||||
TableUpsert tableUpsert,
|
OptionalTableUpdate optionalTableUpdate,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory) {
|
||||||
final H2SqlAstTranslator<?> translator = new H2SqlAstTranslator<>( factory, tableUpsert );
|
final H2SqlAstTranslator<?> translator = new H2SqlAstTranslator<>( factory, optionalTableUpdate );
|
||||||
return translator.visitUpsert( tableUpsert );
|
return translator.visitUpsert( optionalTableUpdate );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
import org.hibernate.sql.model.MutationOperation;
|
import org.hibernate.sql.model.MutationOperation;
|
||||||
import org.hibernate.sql.model.ast.ColumnValueBinding;
|
import org.hibernate.sql.model.ast.ColumnValueBinding;
|
||||||
|
import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||||
import org.hibernate.sql.model.internal.TableInsertStandard;
|
import org.hibernate.sql.model.internal.TableInsertStandard;
|
||||||
import org.hibernate.sql.model.internal.TableUpsert;
|
|
||||||
import org.hibernate.sql.model.jdbc.UpsertOperation;
|
import org.hibernate.sql.model.jdbc.UpsertOperation;
|
||||||
|
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
|
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
|
||||||
|
@ -312,7 +312,7 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
||||||
return getDialect().getVersion().isSameOrAfter( 1, 4, 198 );
|
return getDialect().getVersion().isSameOrAfter( 1, 4, 198 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutationOperation visitUpsert(TableUpsert tableUpsert) {
|
public MutationOperation visitUpsert(OptionalTableUpdate optionalTableUpdate) {
|
||||||
// template:
|
// template:
|
||||||
//
|
//
|
||||||
// merge into [table] as t
|
// merge into [table] as t
|
||||||
|
@ -326,35 +326,35 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
||||||
// when matched
|
// when matched
|
||||||
// then update set ...
|
// then update set ...
|
||||||
|
|
||||||
renderMergeInto( tableUpsert );
|
renderMergeInto( optionalTableUpdate );
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
renderMergeUsing( tableUpsert );
|
renderMergeUsing( optionalTableUpdate );
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
renderMergeOn( tableUpsert );
|
renderMergeOn( optionalTableUpdate );
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
renderMergeInsert( tableUpsert );
|
renderMergeInsert( optionalTableUpdate );
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
renderMergeDelete( tableUpsert );
|
renderMergeDelete( optionalTableUpdate );
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
renderMergeUpdate( tableUpsert );
|
renderMergeUpdate( optionalTableUpdate );
|
||||||
|
|
||||||
return new UpsertOperation(
|
return new UpsertOperation(
|
||||||
tableUpsert.getMutatingTable().getTableMapping(),
|
optionalTableUpdate.getMutatingTable().getTableMapping(),
|
||||||
tableUpsert.getMutationTarget(),
|
optionalTableUpdate.getMutationTarget(),
|
||||||
getSql(),
|
getSql(),
|
||||||
getParameterBinders()
|
getParameterBinders()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMergeInto(TableUpsert tableUpsert) {
|
private void renderMergeInto(OptionalTableUpdate optionalTableUpdate) {
|
||||||
appendSql( "merge into " );
|
appendSql( "merge into " );
|
||||||
appendSql( tableUpsert.getMutatingTable().getTableName() );
|
appendSql( optionalTableUpdate.getMutatingTable().getTableName() );
|
||||||
appendSql( " as t" );
|
appendSql( " as t" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMergeUsing(TableUpsert tableUpsert) {
|
private void renderMergeUsing(OptionalTableUpdate optionalTableUpdate) {
|
||||||
final List<ColumnValueBinding> valueBindings = tableUpsert.getValueBindings();
|
final List<ColumnValueBinding> valueBindings = optionalTableUpdate.getValueBindings();
|
||||||
final List<ColumnValueBinding> keyBindings = tableUpsert.getKeyBindings();
|
final List<ColumnValueBinding> keyBindings = optionalTableUpdate.getKeyBindings();
|
||||||
|
|
||||||
final StringBuilder columnList = new StringBuilder();
|
final StringBuilder columnList = new StringBuilder();
|
||||||
|
|
||||||
|
@ -382,12 +382,12 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
||||||
appendSql( ")" );
|
appendSql( ")" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMergeOn(TableUpsert tableUpsert) {
|
private void renderMergeOn(OptionalTableUpdate optionalTableUpdate) {
|
||||||
appendSql( "on " );
|
appendSql( "on " );
|
||||||
|
|
||||||
// todo : optimistic locks?
|
// todo : optimistic locks?
|
||||||
|
|
||||||
final List<ColumnValueBinding> keyBindings = tableUpsert.getKeyBindings();
|
final List<ColumnValueBinding> keyBindings = optionalTableUpdate.getKeyBindings();
|
||||||
for ( int i = 0; i < keyBindings.size(); i++ ) {
|
for ( int i = 0; i < keyBindings.size(); i++ ) {
|
||||||
final ColumnValueBinding keyBinding = keyBindings.get( i );
|
final ColumnValueBinding keyBinding = keyBindings.get( i );
|
||||||
if ( i > 0 ) {
|
if ( i > 0 ) {
|
||||||
|
@ -399,9 +399,9 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMergeInsert(TableUpsert tableUpsert) {
|
private void renderMergeInsert(OptionalTableUpdate optionalTableUpdate) {
|
||||||
final List<ColumnValueBinding> valueBindings = tableUpsert.getValueBindings();
|
final List<ColumnValueBinding> valueBindings = optionalTableUpdate.getValueBindings();
|
||||||
final List<ColumnValueBinding> keyBindings = tableUpsert.getKeyBindings();
|
final List<ColumnValueBinding> keyBindings = optionalTableUpdate.getKeyBindings();
|
||||||
|
|
||||||
final StringBuilder valuesList = new StringBuilder();
|
final StringBuilder valuesList = new StringBuilder();
|
||||||
|
|
||||||
|
@ -428,8 +428,8 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
||||||
appendSql( ")" );
|
appendSql( ")" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMergeDelete(TableUpsert tableUpsert) {
|
private void renderMergeDelete(OptionalTableUpdate optionalTableUpdate) {
|
||||||
final List<ColumnValueBinding> valueBindings = tableUpsert.getValueBindings();
|
final List<ColumnValueBinding> valueBindings = optionalTableUpdate.getValueBindings();
|
||||||
|
|
||||||
appendSql( " when matched " );
|
appendSql( " when matched " );
|
||||||
for ( int i = 0; i < valueBindings.size(); i++ ) {
|
for ( int i = 0; i < valueBindings.size(); i++ ) {
|
||||||
|
@ -441,8 +441,8 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
||||||
appendSql( " then delete" );
|
appendSql( " then delete" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMergeUpdate(TableUpsert tableUpsert) {
|
private void renderMergeUpdate(OptionalTableUpdate optionalTableUpdate) {
|
||||||
final List<ColumnValueBinding> valueBindings = tableUpsert.getValueBindings();
|
final List<ColumnValueBinding> valueBindings = optionalTableUpdate.getValueBindings();
|
||||||
|
|
||||||
appendSql( " when matched then update set " );
|
appendSql( " when matched then update set " );
|
||||||
for ( int i = 0; i < valueBindings.size(); i++ ) {
|
for ( int i = 0; i < valueBindings.size(); i++ ) {
|
||||||
|
|
|
@ -13,13 +13,12 @@ import org.hibernate.sql.model.MutationOperation;
|
||||||
import org.hibernate.sql.model.MutationTarget;
|
import org.hibernate.sql.model.MutationTarget;
|
||||||
import org.hibernate.sql.model.TableMapping;
|
import org.hibernate.sql.model.TableMapping;
|
||||||
import org.hibernate.sql.model.ast.ColumnValueBinding;
|
import org.hibernate.sql.model.ast.ColumnValueBinding;
|
||||||
import org.hibernate.sql.model.ast.ColumnValueParameter;
|
|
||||||
import org.hibernate.sql.model.ast.MutatingTableReference;
|
import org.hibernate.sql.model.ast.MutatingTableReference;
|
||||||
import org.hibernate.sql.model.ast.RestrictedTableMutation;
|
import org.hibernate.sql.model.ast.RestrictedTableMutation;
|
||||||
|
import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||||
import org.hibernate.sql.model.internal.TableUpdateCustomSql;
|
import org.hibernate.sql.model.internal.TableUpdateCustomSql;
|
||||||
import org.hibernate.sql.model.internal.TableUpdateNoSet;
|
import org.hibernate.sql.model.internal.TableUpdateNoSet;
|
||||||
import org.hibernate.sql.model.internal.TableUpdateStandard;
|
import org.hibernate.sql.model.internal.TableUpdateStandard;
|
||||||
import org.hibernate.sql.model.internal.TableUpsert;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard TableUpdateBuilder implementation
|
* Standard TableUpdateBuilder implementation
|
||||||
|
@ -62,7 +61,7 @@ public class TableUpdateBuilderStandard<O extends MutationOperation> extends Abs
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getMutatingTable().getTableMapping().isOptional() ) {
|
if ( getMutatingTable().getTableMapping().isOptional() ) {
|
||||||
return (RestrictedTableMutation<O>) new TableUpsert(
|
return (RestrictedTableMutation<O>) new OptionalTableUpdate(
|
||||||
getMutatingTable(),
|
getMutatingTable(),
|
||||||
getMutationTarget(),
|
getMutationTarget(),
|
||||||
valueBindings,
|
valueBindings,
|
||||||
|
|
|
@ -34,12 +34,12 @@ import static org.hibernate.sql.model.ast.AbstractTableUpdate.collectParameters;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class TableUpsert
|
public class OptionalTableUpdate
|
||||||
extends AbstractRestrictedTableMutation<MutationOperation>
|
extends AbstractRestrictedTableMutation<MutationOperation>
|
||||||
implements RestrictedTableMutation<MutationOperation> {
|
implements RestrictedTableMutation<MutationOperation> {
|
||||||
private final List<ColumnValueBinding> valueBindings;
|
private final List<ColumnValueBinding> valueBindings;
|
||||||
|
|
||||||
public TableUpsert(
|
public OptionalTableUpdate(
|
||||||
MutatingTableReference mutatingTable,
|
MutatingTableReference mutatingTable,
|
||||||
MutationTarget<?> mutationTarget,
|
MutationTarget<?> mutationTarget,
|
||||||
List<ColumnValueBinding> valueBindings,
|
List<ColumnValueBinding> valueBindings,
|
||||||
|
@ -55,7 +55,7 @@ public class TableUpsert
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TableUpsert(
|
public OptionalTableUpdate(
|
||||||
MutatingTableReference mutatingTable,
|
MutatingTableReference mutatingTable,
|
||||||
MutationTarget<?> mutationTarget,
|
MutationTarget<?> mutationTarget,
|
||||||
String comment,
|
String comment,
|
||||||
|
@ -75,7 +75,7 @@ public class TableUpsert
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getLoggableName() {
|
protected String getLoggableName() {
|
||||||
return "TableUpsert";
|
return "OptionalTableUpdate";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -46,13 +46,13 @@ import org.hibernate.sql.model.ast.MutatingTableReference;
|
||||||
import org.hibernate.sql.model.ast.TableDelete;
|
import org.hibernate.sql.model.ast.TableDelete;
|
||||||
import org.hibernate.sql.model.ast.TableInsert;
|
import org.hibernate.sql.model.ast.TableInsert;
|
||||||
import org.hibernate.sql.model.ast.TableUpdate;
|
import org.hibernate.sql.model.ast.TableUpdate;
|
||||||
|
import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||||
import org.hibernate.sql.model.internal.TableDeleteCustomSql;
|
import org.hibernate.sql.model.internal.TableDeleteCustomSql;
|
||||||
import org.hibernate.sql.model.internal.TableDeleteStandard;
|
import org.hibernate.sql.model.internal.TableDeleteStandard;
|
||||||
import org.hibernate.sql.model.internal.TableInsertCustomSql;
|
import org.hibernate.sql.model.internal.TableInsertCustomSql;
|
||||||
import org.hibernate.sql.model.internal.TableInsertStandard;
|
import org.hibernate.sql.model.internal.TableInsertStandard;
|
||||||
import org.hibernate.sql.model.internal.TableUpdateCustomSql;
|
import org.hibernate.sql.model.internal.TableUpdateCustomSql;
|
||||||
import org.hibernate.sql.model.internal.TableUpdateStandard;
|
import org.hibernate.sql.model.internal.TableUpdateStandard;
|
||||||
import org.hibernate.sql.model.internal.TableUpsert;
|
|
||||||
|
|
||||||
import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER;
|
import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
||||||
|
|
||||||
public OptionalTableUpdateOperation(
|
public OptionalTableUpdateOperation(
|
||||||
MutationTarget<?> mutationTarget,
|
MutationTarget<?> mutationTarget,
|
||||||
TableUpsert upsert,
|
OptionalTableUpdate upsert,
|
||||||
@SuppressWarnings("unused") SessionFactoryImplementor factory) {
|
@SuppressWarnings("unused") SessionFactoryImplementor factory) {
|
||||||
this.mutationTarget = (EntityMutationTarget) mutationTarget;
|
this.mutationTarget = (EntityMutationTarget) mutationTarget;
|
||||||
this.tableMapping = (EntityTableMapping) upsert.getMutatingTable().getTableMapping();
|
this.tableMapping = (EntityTableMapping) upsert.getMutatingTable().getTableMapping();
|
||||||
|
|
Loading…
Reference in New Issue