HHH-15503 Add UUID support for MariaDB 10.7

This commit is contained in:
Christian Beikov 2022-09-13 20:01:24 +02:00
parent 56125e2614
commit 69668c32b7
6 changed files with 164 additions and 5 deletions

4
Jenkinsfile vendored
View File

@ -125,7 +125,7 @@ stage('Build') {
break; break;
case "mariadb": case "mariadb":
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') { docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
docker.image('mariadb:10.5.8').pull() docker.image('mariadb:10.7.5').pull()
} }
sh "./docker_db.sh mariadb" sh "./docker_db.sh mariadb"
state[buildEnv.tag]['containerName'] = "mariadb" state[buildEnv.tag]['containerName'] = "mariadb"
@ -148,7 +148,7 @@ stage('Build') {
break; break;
case "oracle": case "oracle":
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') { docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
docker.image('quillbuilduser/oracle-18-xe').pull() docker.image('gvenzl/oracle-xe:18.4.0-full').pull()
} }
sh "./docker_db.sh oracle_18" sh "./docker_db.sh oracle_18"
state[buildEnv.tag]['containerName'] = "oracle" state[buildEnv.tag]['containerName'] = "oracle"

View File

@ -65,7 +65,7 @@ mysql_8_0() {
mariadb() { mariadb() {
$CONTAINER_CLI rm -f mariadb || true $CONTAINER_CLI rm -f mariadb || true
$CONTAINER_CLI run --name mariadb -e MYSQL_USER=hibernate_orm_test -e MYSQL_PASSWORD=hibernate_orm_test -e MYSQL_DATABASE=hibernate_orm_test -e MYSQL_ROOT_PASSWORD=hibernate_orm_test -p3306:3306 -d docker.io/mariadb:10.5.8 --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --skip-character-set-client-handshake $CONTAINER_CLI run --name mariadb -e MYSQL_USER=hibernate_orm_test -e MYSQL_PASSWORD=hibernate_orm_test -e MYSQL_DATABASE=hibernate_orm_test -e MYSQL_ROOT_PASSWORD=hibernate_orm_test -p3306:3306 -d docker.io/mariadb:10.7.5 --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --skip-character-set-client-handshake
OUTPUT= OUTPUT=
n=0 n=0
until [ "$n" -ge 5 ] until [ "$n" -ge 5 ]

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.sequence.MariaDBSequenceSupport; import org.hibernate.dialect.sequence.MariaDBSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
@ -18,6 +19,7 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -26,6 +28,13 @@ import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMariaDBDatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMariaDBDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import static org.hibernate.type.SqlTypes.OTHER;
import static org.hibernate.type.SqlTypes.UUID;
/** /**
* A {@linkplain Dialect SQL dialect} for MariaDB * A {@linkplain Dialect SQL dialect} for MariaDB
@ -80,6 +89,44 @@ public class MariaDBDialect extends MySQLDialect {
commonFunctionFactory.inverseDistributionOrderedSetAggregates_windowEmulation(); commonFunctionFactory.inverseDistributionOrderedSetAggregates_windowEmulation();
} }
@Override
protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.registerColumnTypes( typeContributions, serviceRegistry );
final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry();
if ( getVersion().isSameOrAfter( 10, 7 ) ) {
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( UUID, "uuid", this ) );
}
}
@Override
public JdbcType resolveSqlTypeDescriptor(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
JdbcTypeRegistry jdbcTypeRegistry) {
switch ( jdbcTypeCode ) {
case OTHER:
switch ( columnTypeName ) {
case "uuid":
jdbcTypeCode = UUID;
break;
}
break;
}
return super.resolveSqlTypeDescriptor( columnTypeName, jdbcTypeCode, precision, scale, jdbcTypeRegistry );
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
.getJdbcTypeRegistry();
if ( getVersion().isSameOrAfter( 10, 7 ) ) {
jdbcTypeRegistry.addDescriptorIfAbsent( VarcharUUIDJdbcType.INSTANCE );
}
}
@Override @Override
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() { public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return new StandardSqlAstTranslatorFactory() { return new StandardSqlAstTranslatorFactory() {

View File

@ -0,0 +1,91 @@
/*
* 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.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
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.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcType;
/**
* Specialized type mapping for {@link UUID} and the UUID SQL data type,
* which binds and reads the UUID through JDBC <code>getString</code>/<code>setString</code> methods.
*
*/
public class VarcharUUIDJdbcType implements JdbcType {
/**
* Singleton access
*/
public static final VarcharUUIDJdbcType INSTANCE = new VarcharUUIDJdbcType();
@Override
public int getJdbcTypeCode() {
return SqlTypes.VARCHAR;
}
@Override
public int getDefaultSqlTypeCode() {
return SqlTypes.UUID;
}
@Override
public String toString() {
return "MariaDBUUIDJdbcType";
}
@Override
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
return UUID.class;
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
st.setString( index, getJavaType().unwrap( value, String.class, options ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
st.setString( name, getJavaType().unwrap( value, String.class, options ) );
}
};
}
@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 {
return getJavaType().wrap( rs.getString( paramIndex ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( index ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( name ), options );
}
};
}
}

View File

@ -13,8 +13,10 @@ import jakarta.persistence.Id;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.VarcharUUIDJdbcType;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.UUIDJavaType; import org.hibernate.type.descriptor.java.UUIDJavaType;
@ -50,11 +52,18 @@ public class UUIDBasedIdInterpretationTest {
@Test @Test
@JiraKey( "HHH-10564" ) @JiraKey( "HHH-10564" )
@RequiresDialect( value = MySQLDialect.class, majorVersion = 5 ) @RequiresDialect(value = MySQLDialect.class, matchSubTypes = false)
public void testMySQL(DomainModelScope scope) { public void testMySQL(DomainModelScope scope) {
checkUuidTypeUsed( scope, VarbinaryJdbcType.class ); checkUuidTypeUsed( scope, VarbinaryJdbcType.class );
} }
@Test
@JiraKey( "HHH-10564" )
@RequiresDialect(value = MariaDBDialect.class, majorVersion = 10, minorVersion = 7)
public void testMariaDB(DomainModelScope scope) {
checkUuidTypeUsed( scope, VarcharUUIDJdbcType.class );
}
@Test @Test
@JiraKey( "HHH-10564" ) @JiraKey( "HHH-10564" )
@RequiresDialect( value = PostgreSQLDialect.class, majorVersion = 9, minorVersion = 4 ) @RequiresDialect( value = PostgreSQLDialect.class, majorVersion = 9, minorVersion = 4 )

View File

@ -9,4 +9,16 @@
This guide discusses migration from Hibernate ORM version 6.2. For migration from This guide discusses migration from Hibernate ORM version 6.2. For migration from
earlier versions, see any other pertinent migration guides as well. earlier versions, see any other pertinent migration guides as well.
* link:../../../6.0/migration-guide/migration-guide.html[6.2 Migration guide] * link:../../../6.1/migration-guide/migration-guide.html[6.1 Migration guide]
* link:../../../6.0/migration-guide/migration-guide.html[6.0 Migration guide]
== Default DDL type changes
=== UUID mapping changes on MariaDB
On MariaDB, the type code `SqlType.UUID` now by default refers to the DDL type `uuid`, whereas before it was using `binary(16)`.
Due to this change, schema validation errors could occur on existing databases.
The migration to `uuid` requires a migration expression like `cast(old as uuid)`.
To retain backwards compatibility, configure the setting `hibernate.type.preferred_uuid_jdbc_type` to `BINARY`.