HHH-14358 - Added test and fix to support null binding for PostgreSQL
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
cbf4acde33
commit
2521e72d37
|
@ -63,7 +63,6 @@ import org.hibernate.type.JavaObjectType;
|
|||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
@ -352,7 +351,7 @@ public class CockroachLegacyDialect extends Dialect {
|
|||
// Don't use this type due to https://github.com/pgjdbc/pgjdbc/issues/2862
|
||||
//jdbcTypeRegistry.addDescriptor( TimestampUtcAsOffsetDateTimeJdbcType.INSTANCE );
|
||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLUUIDJdbcType.INSTANCE );
|
||||
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getIntervalJdbcType( serviceRegistry ) );
|
||||
|
||||
|
@ -376,7 +375,7 @@ public class CockroachLegacyDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
else {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLUUIDJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
||||
if ( getVersion().isSameOrAfter( 20, 0 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
||||
|
|
|
@ -42,7 +42,6 @@ import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
|
|||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.dialect.unique.CreateTableUniqueDelegate;
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
|
@ -83,7 +82,6 @@ import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.XmlJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl;
|
||||
|
@ -1365,8 +1363,8 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
|||
}
|
||||
|
||||
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
||||
// HHH-9562
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
// HHH-9562 / HHH-14358
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLUUIDJdbcType.INSTANCE );
|
||||
if ( getVersion().isSameOrAfter( 9, 2 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
|
||||
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||
|
@ -1393,7 +1391,7 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
|||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructCastingJdbcType.INSTANCE );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLUUIDJdbcType.INSTANCE );
|
||||
if ( getVersion().isSameOrAfter( 9, 2 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
||||
|
|
|
@ -369,7 +369,7 @@ public class CockroachDialect extends Dialect {
|
|||
// Don't use this type due to https://github.com/pgjdbc/pgjdbc/issues/2862
|
||||
//jdbcTypeRegistry.addDescriptor( TimestampUtcAsOffsetDateTimeJdbcType.INSTANCE );
|
||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLUUIDJdbcType.INSTANCE );
|
||||
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getIntervalJdbcType( serviceRegistry ) );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getInetJdbcType( serviceRegistry ) );
|
||||
|
|
|
@ -84,7 +84,6 @@ import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.XmlJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl;
|
||||
|
@ -1413,7 +1412,6 @@ public class PostgreSQLDialect extends Dialect {
|
|||
//jdbcTypeRegistry.addDescriptor( TimestampUtcAsOffsetDateTimeJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( XmlJdbcType.INSTANCE );
|
||||
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE ); // HHH-9562
|
||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getInetJdbcType( serviceRegistry ) );
|
||||
|
@ -1449,6 +1447,7 @@ public class PostgreSQLDialect extends Dialect {
|
|||
);
|
||||
|
||||
jdbcTypeRegistry.addDescriptor( new PostgreSQLEnumJdbcType() );
|
||||
jdbcTypeRegistry.addDescriptor( PostgreSQLUUIDJdbcType.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
public class PostgreSQLUUIDJdbcType extends UUIDJdbcType {
|
||||
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final PostgreSQLUUIDJdbcType INSTANCE = new PostgreSQLUUIDJdbcType();
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
|
||||
st.setNull( index, getJdbcType().getJdbcTypeCode(), "uuid" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
|
||||
st.setNull( name, getJdbcType().getJdbcTypeCode(), "uuid" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, getJavaType().unwrap( value, UUID.class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, getJavaType().unwrap( value, UUID.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -11,15 +11,19 @@ import java.util.UUID;
|
|||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Query;
|
||||
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
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.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -31,9 +35,9 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect(value = PostgreSQLDialect.class)
|
||||
@DomainModel(annotatedClasses = { PostgreSQLUUIDGeneratedValueTest.Book.class })
|
||||
@DomainModel(annotatedClasses = { PostgreSQLUUIDTest.Book.class })
|
||||
@SessionFactory
|
||||
public class PostgreSQLUUIDGeneratedValueTest {
|
||||
public class PostgreSQLUUIDTest {
|
||||
|
||||
private UUID id;
|
||||
|
||||
|
@ -49,6 +53,15 @@ public class PostgreSQLUUIDGeneratedValueTest {
|
|||
assertThat( id, notNullValue() );
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createMutationQuery( "delete from Book" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJPQL(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
|
@ -77,6 +90,20 @@ public class PostgreSQLUUIDGeneratedValueTest {
|
|||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@JiraKey( value = "HHH-14358" )
|
||||
public void testUUIDNullBinding(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query query = session.createQuery( "SELECT b FROM Book b WHERE :id is null or b.id = :id", Book.class );
|
||||
query.setParameter("id", null);
|
||||
List<?> results = Assertions.assertDoesNotThrow( query::getResultList,
|
||||
"Should not throw a PSQLException of type \"could not determine data type of parameter\" " );
|
||||
Assertions.assertEquals( 1, results.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
static class Book {
|
||||
|
|
@ -4,9 +4,9 @@ import java.util.UUID;
|
|||
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.PostgreSQLUUIDJdbcType;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -55,7 +55,7 @@ public class PreferredUuidJdbcTypeTest {
|
|||
assertThat( uuidJdbcType ).isEqualTo( CharJdbcType.INSTANCE );
|
||||
|
||||
final JdbcType uuidType = jdbcTypeRegistry.getDescriptor( SqlTypes.UUID );
|
||||
assertThat( uuidType ).isOfAnyClassIn( UUIDJdbcType.class );
|
||||
assertThat( uuidType ).isOfAnyClassIn( UUIDJdbcType.class, PostgreSQLUUIDJdbcType.class );
|
||||
|
||||
// a simple duration field with no overrides - so should be using a default JdbcType
|
||||
assertThat( entityDescriptor.findAttributeMapping( "uuid" )
|
||||
|
|
Loading…
Reference in New Issue