HHH-17246 - Guard against Sybase being configured for truncating trailing zeros
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
ab9eb9a496
commit
532d5460d4
|
@ -90,6 +90,7 @@ import org.hibernate.type.descriptor.jdbc.JsonAsStringJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.XmlArrayJdbcTypeConstructor;
|
||||
import org.hibernate.type.descriptor.jdbc.XmlAsStringArrayJdbcTypeConstructor;
|
||||
import org.hibernate.type.descriptor.jdbc.XmlAsStringJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UuidAsBinaryJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
|
@ -752,7 +753,7 @@ public class MetadataBuildingProcess {
|
|||
);
|
||||
}
|
||||
else {
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.UUID, SqlTypes.BINARY );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UuidAsBinaryJdbcType.INSTANCE );
|
||||
}
|
||||
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( JsonAsStringJdbcType.VARCHAR_INSTANCE );
|
||||
|
|
|
@ -298,7 +298,7 @@ public class JsonHelper {
|
|||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
case SqlTypes.DURATION:
|
||||
case SqlTypes.UUID:
|
||||
case SqlTypes.UUID:
|
||||
// These types need to be serialized as JSON string, but don't have a need for escaping
|
||||
appender.append( '"' );
|
||||
javaType.appendEncodedString( appender, value );
|
||||
|
|
|
@ -82,6 +82,7 @@ import org.hibernate.tool.schema.spi.Exporter;
|
|||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.NullType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.OracleUUIDJavaType;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -1041,6 +1042,8 @@ public class OracleDialect extends Dialect {
|
|||
)
|
||||
);
|
||||
|
||||
typeContributions.contributeJavaType( OracleUUIDJavaType.INSTANCE );
|
||||
|
||||
if(getVersion().isSameOrAfter(23)) {
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
jdbcTypeRegistry.addDescriptor(OracleEnumJdbcType.INSTANCE);
|
||||
|
|
|
@ -64,6 +64,7 @@ import static org.hibernate.type.SqlTypes.TIMESTAMP;
|
|||
import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC;
|
||||
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
|
||||
import static org.hibernate.type.SqlTypes.TINYINT;
|
||||
import static org.hibernate.type.SqlTypes.UUID;
|
||||
import static org.hibernate.type.SqlTypes.VARBINARY;
|
||||
|
||||
public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||
|
@ -209,6 +210,7 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
|||
case BINARY:
|
||||
case VARBINARY:
|
||||
case LONG32VARBINARY:
|
||||
case UUID:
|
||||
return template.replace(
|
||||
placeholder,
|
||||
jdbcType.getSqlTypeName() + "_from_json(json_query(" + parentPartExpression + columnExpression + "' returning " + jsonTypeName + "))"
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.type.descriptor.java;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
public class OracleUUIDJavaType extends UUIDJavaType {
|
||||
|
||||
/* This class is related to the changes that were made for HHH-17246 */
|
||||
|
||||
public static final OracleUUIDJavaType INSTANCE = new OracleUUIDJavaType();
|
||||
|
||||
@Override
|
||||
public String toString(UUID value) {
|
||||
return NoDashesStringTransformer.INSTANCE.transform( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID fromString(CharSequence string) {
|
||||
return NoDashesStringTransformer.INSTANCE.parse( string.toString() );
|
||||
}
|
||||
}
|
|
@ -37,10 +37,12 @@ public class UUIDJavaType extends AbstractClassJavaType<UUID> {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(UUID value) {
|
||||
return ToStringTransformer.INSTANCE.transform( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID fromString(CharSequence string) {
|
||||
return ToStringTransformer.INSTANCE.parse( string.toString() );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.type.descriptor.jdbc;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.UUID;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
public class UuidAsBinaryJdbcType extends BinaryJdbcType {
|
||||
|
||||
public static final UuidAsBinaryJdbcType INSTANCE = new UuidAsBinaryJdbcType();
|
||||
|
||||
@Override
|
||||
public int getDdlTypeCode() {
|
||||
return Types.BINARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor( JavaType<X> javaType ) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract( ResultSet rs, int paramIndex, WrapperOptions options ) throws SQLException {
|
||||
final byte[] bytes = rs.getBytes( paramIndex );
|
||||
return javaType.wrap( bytes == null || bytes.length == 16 ? bytes : Arrays.copyOf( bytes, 16 ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract( CallableStatement statement, int index, WrapperOptions options ) throws SQLException {
|
||||
final byte[] bytes = statement.getBytes( index );
|
||||
return javaType.wrap( bytes == null || bytes.length == 16 ? bytes : Arrays.copyOf( bytes, 16 ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract( CallableStatement statement, String name, WrapperOptions options )
|
||||
throws SQLException {
|
||||
final byte[] bytes = statement.getBytes( name );
|
||||
return javaType.wrap( bytes == null || bytes.length == 16 ? bytes : Arrays.copyOf( bytes, 16 ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.orm.test.id.uuid;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import org.hibernate.annotations.JdbcType;
|
||||
import org.hibernate.dialect.SybaseASEDialect;
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
@RequiresDialect(value = SybaseASEDialect.class)
|
||||
@DomainModel(annotatedClasses = { SybaseASEUUIDTest.Book.class })
|
||||
@SessionFactory
|
||||
public class SybaseASEUUIDTest {
|
||||
|
||||
private static final UUID uuid = UUID.fromString("53886a8a-7082-4879-b430-25cb94415b00");
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
final Book book = new Book(uuid, "John Doe");
|
||||
session.persist( book );
|
||||
} );
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> session.createMutationQuery( "delete from Book" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@JiraKey( value = "HHH-17246" )
|
||||
public void testTrailingZeroByteTruncation(SessionFactoryScope scope) {
|
||||
scope.inSession(
|
||||
session -> assertEquals( 15, session.createNativeQuery("select id from Book", byte[].class).getSingleResult().length )
|
||||
);
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Book b = session.createQuery( "from Book", Book.class ).getSingleResult();
|
||||
assertEquals(uuid, b.id);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
static class Book {
|
||||
@Id
|
||||
// The purpose is to effectively provoke the trailing 0 bytes truncation
|
||||
@JdbcType( SybaseUuidAsVarbinaryJdbcType.class )
|
||||
UUID id;
|
||||
|
||||
String author;
|
||||
|
||||
public Book() {
|
||||
}
|
||||
|
||||
public Book(UUID id, String author) {
|
||||
this.id = id;
|
||||
this.author = author;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.orm.test.id.uuid;
|
||||
|
||||
import org.hibernate.type.descriptor.jdbc.UuidAsBinaryJdbcType;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
public class SybaseUuidAsVarbinaryJdbcType extends UuidAsBinaryJdbcType {
|
||||
@Override
|
||||
public int getDdlTypeCode() {
|
||||
return Types.VARBINARY;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue