HHH-17795 fix an NPE and add a test for 'on conflict on constraint'

This commit is contained in:
Gavin King 2024-03-02 09:36:37 +01:00
parent 9b4e61c984
commit e02317f3d6
4 changed files with 48 additions and 6 deletions

View File

@ -110,13 +110,18 @@ values
/**
* a 'conflict' clause in an 'insert' statement
*/
conflictClause: ON CONFLICT conflictTarget? conflictAction;
conflictClause
: ON CONFLICT conflictTarget? DO conflictAction
;
conflictTarget
: ON CONSTRAINT identifier
| LEFT_PAREN simplePath (COMMA simplePath)* RIGHT_PAREN;
| LEFT_PAREN simplePath (COMMA simplePath)* RIGHT_PAREN
;
conflictAction
: DO NOTHING
| DO UPDATE setClause whereClause?
: NOTHING
| UPDATE setClause whereClause?
;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -45,7 +45,6 @@ import org.hibernate.annotations.common.reflection.XPackage;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
import org.hibernate.boot.model.convert.spi.RegisteredConversion;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.InFlightMetadataCollector;

View File

@ -70,7 +70,7 @@ public class SqmConflictClause<T> implements SqmVisitableNode, JpaConflictClause
@Override
public SqmConflictClause<T> conflictOnConstraint(@Nullable String constraintName) {
if ( !constraintPaths.isEmpty() ) {
if ( constraintPaths != null && !constraintPaths.isEmpty() ) {
throw new IllegalStateException( "Constraint paths were already set: " + constraintPaths );
}
this.constraintName = constraintName;

View File

@ -0,0 +1,38 @@
package org.hibernate.orm.test.query.hql;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SessionFactory
@DomainModel(annotatedClasses = InsertConflictOnConstraintTest.Constrained.class)
@RequiresDialect(PostgreSQLDialect.class)
public class InsertConflictOnConstraintTest {
@Test void test(SessionFactoryScope scope) {
scope.inTransaction( s -> s.persist(new Constrained()));
scope.inTransaction( s -> s.createMutationQuery("insert into Constrained(id, name, count) values (4,'Gavin',69) on conflict on constraint constrained_count_name_key do update set count = 96").executeUpdate());
scope.inSession( s -> assertEquals(96, s.createSelectionQuery("select count from Constrained", int.class).getSingleResult()));
}
@Entity(name = "Constrained")
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"count","name"}))
static class Constrained {
@Id
@GeneratedValue
long id;
String name = "Gavin";
int count = 69;
}
}