Skip to content

Commit 532d546

Browse files
jrenaatbeikov
authored andcommitted
HHH-17246 - Guard against Sybase being configured for truncating trailing zeros
Signed-off-by: Jan Schatteman <[email protected]>
1 parent ab9eb9a commit 532d546

File tree

9 files changed

+196
-2
lines changed

9 files changed

+196
-2
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
@@ -90,6 +90,7 @@
9090
import org.hibernate.type.descriptor.jdbc.XmlArrayJdbcTypeConstructor;
9191
import org.hibernate.type.descriptor.jdbc.XmlAsStringArrayJdbcTypeConstructor;
9292
import org.hibernate.type.descriptor.jdbc.XmlAsStringJdbcType;
93+
import org.hibernate.type.descriptor.jdbc.UuidAsBinaryJdbcType;
9394
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
9495
import org.hibernate.type.descriptor.sql.DdlType;
9596
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
@@ -752,7 +753,7 @@ public void contributeType(CompositeUserType<?> type) {
752753
);
753754
}
754755
else {
755-
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.UUID, SqlTypes.BINARY );
756+
jdbcTypeRegistry.addDescriptorIfAbsent( UuidAsBinaryJdbcType.INSTANCE );
756757
}
757758

758759
jdbcTypeRegistry.addDescriptorIfAbsent( JsonAsStringJdbcType.VARCHAR_INSTANCE );

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ private static void convertedBasicValueToString(
298298
case SqlTypes.DECIMAL:
299299
case SqlTypes.NUMERIC:
300300
case SqlTypes.DURATION:
301-
case SqlTypes.UUID:
301+
case SqlTypes.UUID:
302302
// These types need to be serialized as JSON string, but don't have a need for escaping
303303
appender.append( '"' );
304304
javaType.appendEncodedString( appender, value );

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import org.hibernate.type.JavaObjectType;
8383
import org.hibernate.type.NullType;
8484
import org.hibernate.type.StandardBasicTypes;
85+
import org.hibernate.type.descriptor.java.OracleUUIDJavaType;
8586
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
8687
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
8788
import org.hibernate.type.descriptor.jdbc.JdbcType;
@@ -1041,6 +1042,8 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
10411042
)
10421043
);
10431044

1045+
typeContributions.contributeJavaType( OracleUUIDJavaType.INSTANCE );
1046+
10441047
if(getVersion().isSameOrAfter(23)) {
10451048
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeRegistry();
10461049
jdbcTypeRegistry.addDescriptor(OracleEnumJdbcType.INSTANCE);

hibernate-core/src/main/java/org/hibernate/dialect/aggregate/OracleAggregateSupport.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC;
6565
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
6666
import static org.hibernate.type.SqlTypes.TINYINT;
67+
import static org.hibernate.type.SqlTypes.UUID;
6768
import static org.hibernate.type.SqlTypes.VARBINARY;
6869

6970
public class OracleAggregateSupport extends AggregateSupportImpl {
@@ -209,6 +210,7 @@ public String aggregateComponentCustomReadExpression(
209210
case BINARY:
210211
case VARBINARY:
211212
case LONG32VARBINARY:
213+
case UUID:
212214
return template.replace(
213215
placeholder,
214216
jdbcType.getSqlTypeName() + "_from_json(json_query(" + parentPartExpression + columnExpression + "' returning " + jsonTypeName + "))"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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.java;
6+
7+
import java.util.UUID;
8+
9+
/**
10+
* @author Jan Schatteman
11+
*/
12+
public class OracleUUIDJavaType extends UUIDJavaType {
13+
14+
/* This class is related to the changes that were made for HHH-17246 */
15+
16+
public static final OracleUUIDJavaType INSTANCE = new OracleUUIDJavaType();
17+
18+
@Override
19+
public String toString(UUID value) {
20+
return NoDashesStringTransformer.INSTANCE.transform( value );
21+
}
22+
23+
@Override
24+
public UUID fromString(CharSequence string) {
25+
return NoDashesStringTransformer.INSTANCE.parse( string.toString() );
26+
}
27+
}

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ public boolean useObjectEqualsHashCode() {
3737
return true;
3838
}
3939

40+
@Override
4041
public String toString(UUID value) {
4142
return ToStringTransformer.INSTANCE.transform( value );
4243
}
4344

45+
@Override
4446
public UUID fromString(CharSequence string) {
4547
return ToStringTransformer.INSTANCE.parse( string.toString() );
4648
}
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: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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.annotations.JdbcType;
10+
import org.hibernate.dialect.SybaseASEDialect;
11+
import org.hibernate.testing.orm.junit.DomainModel;
12+
import org.hibernate.testing.orm.junit.JiraKey;
13+
import org.hibernate.testing.orm.junit.RequiresDialect;
14+
import org.hibernate.testing.orm.junit.SessionFactory;
15+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
16+
import org.junit.jupiter.api.AfterEach;
17+
import org.junit.jupiter.api.BeforeEach;
18+
import org.junit.jupiter.api.Test;
19+
20+
import java.util.UUID;
21+
22+
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
24+
/**
25+
* @author Jan Schatteman
26+
*/
27+
@RequiresDialect(value = SybaseASEDialect.class)
28+
@DomainModel(annotatedClasses = { SybaseASEUUIDTest.Book.class })
29+
@SessionFactory
30+
public class SybaseASEUUIDTest {
31+
32+
private static final UUID uuid = UUID.fromString("53886a8a-7082-4879-b430-25cb94415b00");
33+
34+
@BeforeEach
35+
void setUp(SessionFactoryScope scope) {
36+
scope.inTransaction( session -> {
37+
final Book book = new Book(uuid, "John Doe");
38+
session.persist( book );
39+
} );
40+
}
41+
42+
@AfterEach
43+
void tearDown(SessionFactoryScope scope) {
44+
scope.inTransaction(
45+
session -> session.createMutationQuery( "delete from Book" ).executeUpdate()
46+
);
47+
}
48+
49+
@Test
50+
@JiraKey( value = "HHH-17246" )
51+
public void testTrailingZeroByteTruncation(SessionFactoryScope scope) {
52+
scope.inSession(
53+
session -> assertEquals( 15, session.createNativeQuery("select id from Book", byte[].class).getSingleResult().length )
54+
);
55+
scope.inTransaction(
56+
session -> {
57+
Book b = session.createQuery( "from Book", Book.class ).getSingleResult();
58+
assertEquals(uuid, b.id);
59+
}
60+
);
61+
}
62+
63+
@Entity(name = "Book")
64+
static class Book {
65+
@Id
66+
// The purpose is to effectively provoke the trailing 0 bytes truncation
67+
@JdbcType( SybaseUuidAsVarbinaryJdbcType.class )
68+
UUID id;
69+
70+
String author;
71+
72+
public Book() {
73+
}
74+
75+
public Book(UUID id, String author) {
76+
this.id = id;
77+
this.author = author;
78+
}
79+
}
80+
81+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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 org.hibernate.type.descriptor.jdbc.UuidAsBinaryJdbcType;
8+
import java.sql.Types;
9+
10+
/**
11+
* @author Jan Schatteman
12+
*/
13+
public class SybaseUuidAsVarbinaryJdbcType extends UuidAsBinaryJdbcType {
14+
@Override
15+
public int getDdlTypeCode() {
16+
return Types.VARBINARY;
17+
}
18+
}

0 commit comments

Comments
 (0)