Skip to content

Commit 12d09d3

Browse files
committed
[HHH-19365]on duplicate key update do nothing
1 parent d689617 commit 12d09d3

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/GaussDBSqlAstTranslator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ protected void renderFromClauseAfterUpdateSet(UpdateStatement statement) {
114114

115115
@Override
116116
protected void visitConflictClause(ConflictClause conflictClause) {
117-
visitStandardConflictClause( conflictClause );
117+
visitOnDuplicateKeyConflictClauseWithDoNothing( conflictClause );
118118
}
119119

120120
@Override

hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,6 +2051,43 @@ protected void visitOnDuplicateKeyConflictClause(ConflictClause conflictClause)
20512051
clauseStack.pop();
20522052
}
20532053

2054+
protected void visitOnDuplicateKeyConflictClauseWithDoNothing(ConflictClause conflictClause) {
2055+
if ( conflictClause == null ) {
2056+
return;
2057+
}
2058+
// The duplicate key clause does not support specifying the constraint name or constraint column names,
2059+
// but to allow compatibility, we have to require the user to specify either one in the SQM conflict clause.
2060+
// To allow meaningful usage, we simply ignore the constraint column names in this emulation.
2061+
// A possible problem with this is when the constraint column names contain the primary key columns,
2062+
// but the insert fails due to a unique constraint violation. This emulation will not cause a failure to be
2063+
// propagated, but instead will run the respective conflict action.
2064+
final String constraintName = conflictClause.getConstraintName();
2065+
if ( constraintName != null ) {
2066+
if ( conflictClause.isDoUpdate() ) {
2067+
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
2068+
}
2069+
else {
2070+
return;
2071+
}
2072+
}
2073+
clauseStack.push( Clause.CONFLICT );
2074+
appendSql( " on duplicate key update" );
2075+
final List<Assignment> assignments = conflictClause.getAssignments();
2076+
if ( assignments.isEmpty() ) {
2077+
try {
2078+
clauseStack.push( Clause.SET );
2079+
appendSql( " nothing " );
2080+
}
2081+
finally {
2082+
clauseStack.pop();
2083+
}
2084+
}
2085+
else {
2086+
renderPredicatedSetAssignments( assignments, conflictClause.getPredicate() );
2087+
}
2088+
clauseStack.pop();
2089+
}
2090+
20542091
private void renderPredicatedSetAssignments(List<Assignment> assignments, Predicate predicate) {
20552092
char separator = ' ';
20562093
try {

hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictTests.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ public void cleanupData(SessionFactoryScope scope) {
6161
}
6262

6363
@Test
64-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict do\"")
6564
public void testOnConflictDoNothing(SessionFactoryScope scope) {
6665
scope.inTransaction(
6766
session -> {
@@ -86,7 +85,6 @@ public void testOnConflictDoNothing(SessionFactoryScope scope) {
8685

8786
@Test
8887
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class)
89-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(\"")
9088
public void testOnConflictDoUpdate(SessionFactoryScope scope) {
9189
scope.inTransaction(
9290
session -> {
@@ -114,7 +112,6 @@ public void testOnConflictDoUpdate(SessionFactoryScope scope) {
114112

115113
@Test
116114
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class)
117-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(")
118115
public void testOnConflictDoUpdateWithWhere(SessionFactoryScope scope) {
119116
scope.inTransaction(
120117
session -> {
@@ -134,6 +131,10 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy
134131
// Sybase seems to report all matched rows as affected and ignores additional predicates
135132
assertEquals( 1, updated );
136133
}
134+
else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof GaussDBDialect ) {
135+
// GaussDB seems to report all matched rows as affected and ignores additional predicates
136+
assertEquals( 1, updated );
137+
}
137138
else {
138139
assertEquals( 0, updated );
139140
}
@@ -145,7 +146,6 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy
145146

146147
@Test
147148
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class)
148-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(")
149149
public void testOnConflictDoUpdateWithWhereCriteria(SessionFactoryScope scope) {
150150
scope.inTransaction(
151151
session -> {
@@ -171,6 +171,10 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy
171171
// Sybase seems to report all matched rows as affected and ignores additional predicates
172172
assertEquals( 1, updated );
173173
}
174+
else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof GaussDBDialect ) {
175+
// GaussDB seems to report all matched rows as affected and ignores additional predicates
176+
assertEquals( 1, updated );
177+
}
174178
else {
175179
assertEquals( 0, updated );
176180
}
@@ -181,7 +185,6 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy
181185
}
182186

183187
@Test
184-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict do\"")
185188
public void testOnConflictDoNothingMultiTable(SessionFactoryScope scope) {
186189
scope.inTransaction(
187190
session -> {
@@ -209,7 +212,6 @@ public void testOnConflictDoNothingMultiTable(SessionFactoryScope scope) {
209212
@Test
210213
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class)
211214
@SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "MERGE into a table that has a self-referential FK does not work")
212-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(")
213215
public void testOnConflictDoUpdateMultiTable(SessionFactoryScope scope) {
214216
scope.inTransaction(
215217
session -> {
@@ -238,7 +240,6 @@ public void testOnConflictDoUpdateMultiTable(SessionFactoryScope scope) {
238240
@Test
239241
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class)
240242
@SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "MERGE into a table that has a self-referential FK does not work")
241-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "syntax error at or near \"conflict(\"")
242243
public void testOnConflictDoUpdateWithWhereMultiTable(SessionFactoryScope scope) {
243244
scope.inTransaction(
244245
session -> {
@@ -258,6 +259,10 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy
258259
// Sybase seems to report all matched rows as affected and ignores additional predicates
259260
assertEquals( 1, updated );
260261
}
262+
else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof GaussDBDialect ) {
263+
// GaussDB seems to report all matched rows as affected and ignores additional predicates
264+
assertEquals( 1, updated );
265+
}
261266
else {
262267
assertEquals( 0, updated );
263268
}

hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictWithCriteriaCopyTreeEnabledTests.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import jakarta.persistence.Id;
99
import jakarta.persistence.Tuple;
1010
import org.hibernate.cfg.QuerySettings;
11-
import org.hibernate.dialect.GaussDBDialect;
1211
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
1312
import org.hibernate.query.criteria.JpaCriteriaInsertSelect;
1413
import org.hibernate.query.criteria.JpaCriteriaInsertValues;
@@ -19,7 +18,6 @@
1918
import org.hibernate.testing.orm.junit.SessionFactory;
2019
import org.hibernate.testing.orm.junit.SessionFactoryScope;
2120
import org.hibernate.testing.orm.junit.Setting;
22-
import org.hibernate.testing.orm.junit.SkipForDialect;
2321
import org.junit.jupiter.api.Test;
2422

2523

@@ -34,7 +32,6 @@
3432
)
3533
@SessionFactory
3634
@JiraKey("HHH-19314")
37-
@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support")
3835
public class InsertConflictWithCriteriaCopyTreeEnabledTests {
3936

4037
@Test

0 commit comments

Comments
 (0)