From ef0cc752c602c494740a117d2bf414566aae7756 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Tue, 9 Apr 2024 20:23:58 +0200 Subject: [PATCH] HHH-17934 generate a correct SQL merge statement (adds the version check if necessary) Signed-off-by: Gavin King --- .../dialect/SqlAstTranslatorWithMerge.java | 23 +++++++++++++++++-- .../test/stateless/UpsertVersionedTest.java | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SqlAstTranslatorWithMerge.java b/hibernate-core/src/main/java/org/hibernate/dialect/SqlAstTranslatorWithMerge.java index be143614a5..5d646d225f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SqlAstTranslatorWithMerge.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SqlAstTranslatorWithMerge.java @@ -50,6 +50,11 @@ public abstract class SqlAstTranslatorWithMerge extends ); } + @Override + public void visitOptionalTableUpdate(OptionalTableUpdate tableUpdate) { + renderMergeStatement(tableUpdate); + } + /** * Renders the OptionalTableUpdate as a MERGE query. * @@ -207,8 +212,9 @@ public abstract class SqlAstTranslatorWithMerge extends protected void renderMergeDelete(OptionalTableUpdate optionalTableUpdate) { final List valueBindings = optionalTableUpdate.getValueBindings(); + final List optimisticLockBindings = optionalTableUpdate.getOptimisticLockBindings(); - appendSql( " when matched " ); + renderWhenMatched( optimisticLockBindings ); for ( int i = 0; i < valueBindings.size(); i++ ) { final ColumnValueBinding binding = valueBindings.get( i ); appendSql( " and " ); @@ -220,8 +226,10 @@ public abstract class SqlAstTranslatorWithMerge extends protected void renderMergeUpdate(OptionalTableUpdate optionalTableUpdate) { final List valueBindings = optionalTableUpdate.getValueBindings(); + final List optimisticLockBindings = optionalTableUpdate.getOptimisticLockBindings(); - appendSql( " when matched then update set " ); + renderWhenMatched( optimisticLockBindings ); + appendSql( " then update set " ); for ( int i = 0; i < valueBindings.size(); i++ ) { final ColumnValueBinding binding = valueBindings.get( i ); if ( i > 0 ) { @@ -232,4 +240,15 @@ public abstract class SqlAstTranslatorWithMerge extends binding.getColumnReference().appendColumnForWrite( this, "s" ); } } + + private void renderWhenMatched(List optimisticLockBindings) { + appendSql( " when matched" ); + for (int i = 0; i < optimisticLockBindings.size(); i++) { + final ColumnValueBinding binding = optimisticLockBindings.get( i ); + appendSql(" and "); + binding.getColumnReference().appendColumnForWrite( this, "t" ); + appendSql("<="); + binding.getValueExpression().accept( this ); + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/UpsertVersionedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/UpsertVersionedTest.java index 1ae36bb72a..e6363d4f2b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/UpsertVersionedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/UpsertVersionedTest.java @@ -15,7 +15,7 @@ import static org.junit.Assert.assertEquals; public class UpsertVersionedTest { @Test void test(SessionFactoryScope scope) { scope.inStatelessTransaction(s-> { - s.upsert(new Record(123L,1L,"hello earth")); + s.upsert(new Record(123L,0L,"hello earth")); s.upsert(new Record(456L,2L,"hello mars")); }); scope.inStatelessTransaction(s-> {