Skip to content

Commit 549af2f

Browse files
committed
HHH-17246 - Guard against Sybase being configured for truncating trailing zeros
Signed-off-by: Jan Schatteman <[email protected]>
1 parent 968a661 commit 549af2f

File tree

3 files changed

+140
-1
lines changed

3 files changed

+140
-1
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import org.hibernate.type.descriptor.jdbc.JsonArrayAsStringJdbcType;
8989
import org.hibernate.type.descriptor.jdbc.JsonAsStringJdbcType;
9090
import org.hibernate.type.descriptor.jdbc.XmlAsStringJdbcType;
91+
import org.hibernate.type.descriptor.jdbc.UuidAsBinaryJdbcType;
9192
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
9293
import org.hibernate.type.descriptor.sql.DdlType;
9394
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
@@ -787,7 +788,7 @@ public void contributeType(CompositeUserType<?> type) {
787788
);
788789
}
789790
else {
790-
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.UUID, SqlTypes.BINARY );
791+
jdbcTypeRegistry.addDescriptorIfAbsent( UuidAsBinaryJdbcType.INSTANCE );
791792
}
792793

793794
final int preferredSqlTypeCodeForArray = getPreferredSqlTypeCodeForArray( serviceRegistry );
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.type.descriptor.jdbc;
6+
7+
import org.hibernate.type.descriptor.ValueExtractor;
8+
import org.hibernate.type.descriptor.WrapperOptions;
9+
import org.hibernate.type.descriptor.java.JavaType;
10+
11+
import java.sql.CallableStatement;
12+
import java.sql.ResultSet;
13+
import java.sql.SQLException;
14+
import java.sql.Types;
15+
import java.util.Arrays;
16+
17+
import static org.hibernate.type.SqlTypes.UUID;
18+
19+
/**
20+
* @author Jan Schatteman
21+
*/
22+
public class UuidAsBinaryJdbcType extends BinaryJdbcType {
23+
24+
public static final UuidAsBinaryJdbcType INSTANCE = new UuidAsBinaryJdbcType();
25+
26+
@Override
27+
public int getDdlTypeCode() {
28+
return Types.BINARY;
29+
}
30+
31+
@Override
32+
public int getDefaultSqlTypeCode() {
33+
return UUID;
34+
}
35+
36+
@Override
37+
public <X> ValueExtractor<X> getExtractor( JavaType<X> javaType ) {
38+
return new BasicExtractor<>( javaType, this ) {
39+
@Override
40+
protected X doExtract( ResultSet rs, int paramIndex, WrapperOptions options ) throws SQLException {
41+
final byte[] bytes = rs.getBytes( paramIndex );
42+
return javaType.wrap( bytes == null || bytes.length == 16 ? bytes : Arrays.copyOf( bytes, 16 ), options );
43+
}
44+
45+
@Override
46+
protected X doExtract( CallableStatement statement, int index, WrapperOptions options ) throws SQLException {
47+
final byte[] bytes = statement.getBytes( index );
48+
return javaType.wrap( bytes == null || bytes.length == 16 ? bytes : Arrays.copyOf( bytes, 16 ), options );
49+
}
50+
51+
@Override
52+
protected X doExtract( CallableStatement statement, String name, WrapperOptions options )
53+
throws SQLException {
54+
final byte[] bytes = statement.getBytes( name );
55+
return javaType.wrap( bytes == null || bytes.length == 16 ? bytes : Arrays.copyOf( bytes, 16 ), options );
56+
}
57+
};
58+
}
59+
60+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.id.uuid;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import org.hibernate.dialect.SybaseASEDialect;
10+
import org.hibernate.testing.orm.junit.DomainModel;
11+
import org.hibernate.testing.orm.junit.JiraKey;
12+
import org.hibernate.testing.orm.junit.RequiresDialect;
13+
import org.hibernate.testing.orm.junit.SessionFactory;
14+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
15+
import org.junit.jupiter.api.AfterEach;
16+
import org.junit.jupiter.api.BeforeEach;
17+
import org.junit.jupiter.api.Test;
18+
19+
import java.util.UUID;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
23+
/**
24+
* @author Jan Schatteman
25+
*/
26+
@RequiresDialect(value = SybaseASEDialect.class)
27+
@DomainModel(annotatedClasses = { SybaseASEUUIDTest.Book.class })
28+
@SessionFactory
29+
public class SybaseASEUUIDTest {
30+
31+
private static final UUID uuid = UUID.fromString("53886a8a-7082-4879-b430-25cb94415b00");
32+
33+
@BeforeEach
34+
void setUp(SessionFactoryScope scope) {
35+
scope.inTransaction( session -> {
36+
final Book book = new Book(uuid, "John Doe");
37+
session.persist( book );
38+
} );
39+
}
40+
41+
@AfterEach
42+
void tearDown(SessionFactoryScope scope) {
43+
scope.inTransaction(
44+
session -> session.createMutationQuery( "delete from Book" ).executeUpdate()
45+
);
46+
}
47+
48+
@Test
49+
@JiraKey( value = "HHH-17246" )
50+
public void testTrailingZeroByteTruncation(SessionFactoryScope scope) {
51+
scope.inSession(
52+
session -> assertEquals( 15, session.createNativeQuery("select id from Book", byte[].class).getSingleResult().length )
53+
);
54+
scope.inTransaction(
55+
session -> {
56+
Book b = session.createQuery( "from Book", Book.class ).getSingleResult();
57+
assertEquals(uuid, b.id);
58+
}
59+
);
60+
}
61+
62+
@Entity(name = "Book")
63+
static class Book {
64+
@Id
65+
UUID id;
66+
67+
String author;
68+
69+
public Book() {
70+
}
71+
72+
public Book(UUID id, String author) {
73+
this.id = id;
74+
this.author = author;
75+
}
76+
}
77+
78+
}

0 commit comments

Comments
 (0)