HHH-15511 - fix version determination for CockroachDB
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
e62a376262
commit
1d76f970e8
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
@ -14,6 +15,8 @@ import java.util.Calendar;
|
|||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
|
@ -34,6 +37,7 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
|||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
|
@ -63,6 +67,8 @@ import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
|||
import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.query.sqm.TemporalUnit.DAY;
|
||||
import static org.hibernate.query.sqm.TemporalUnit.NATIVE;
|
||||
import static org.hibernate.type.SqlTypes.BINARY;
|
||||
|
@ -97,10 +103,14 @@ import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithM
|
|||
*/
|
||||
public class CockroachDialect extends Dialect {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, CockroachDialect.class.getName() );
|
||||
private static final CockroachDBIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new CockroachDBIdentityColumnSupport();
|
||||
// KNOWN LIMITATIONS:
|
||||
// * no support for java.sql.Clob
|
||||
|
||||
// Pre-compile and reuse pattern
|
||||
private static final Pattern CRDB_VERSION_PATTERN = Pattern.compile( "v[\\d]+(\\.[\\d]+)?(\\.[\\d]+)?" );
|
||||
|
||||
private static final DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 21, 1 );
|
||||
|
||||
private final PostgreSQLDriverKind driverKind;
|
||||
|
@ -110,8 +120,8 @@ public class CockroachDialect extends Dialect {
|
|||
}
|
||||
|
||||
public CockroachDialect(DialectResolutionInfo info) {
|
||||
super(info);
|
||||
driverKind = PostgreSQLDriverKind.determineKind( info );
|
||||
this( fetchDataBaseVersion( info ), PostgreSQLDriverKind.determineKind( info ) );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
public CockroachDialect(DatabaseVersion version) {
|
||||
|
@ -124,6 +134,46 @@ public class CockroachDialect extends Dialect {
|
|||
this.driverKind = driverKind;
|
||||
}
|
||||
|
||||
protected static DatabaseVersion fetchDataBaseVersion( DialectResolutionInfo info ) {
|
||||
String versionString = null;
|
||||
if ( info.getDatabaseMetadata() != null ) {
|
||||
try (java.sql.Statement s = info.getDatabaseMetadata().getConnection().createStatement() ) {
|
||||
final ResultSet rs = s.executeQuery( "SELECT version()" );
|
||||
if ( rs.next() ) {
|
||||
versionString = rs.getString( 1 );
|
||||
}
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return parseVersion( versionString );
|
||||
}
|
||||
|
||||
protected static DatabaseVersion parseVersion(String versionString ) {
|
||||
DatabaseVersion databaseVersion = null;
|
||||
// What the DB select returns is similar to "CockroachDB CCL v21.2.10 (x86_64-unknown-linux-gnu, built 2022/05/02 17:38:58, go1.16.6)"
|
||||
Matcher m = CRDB_VERSION_PATTERN.matcher( versionString == null ? "" : versionString );
|
||||
if ( m.find() ) {
|
||||
String[] versionParts = m.group().substring( 1 ).split( "\\." );
|
||||
// if we got to this point, there is at least a major version, so no need to check [].length > 0
|
||||
int majorVersion = Integer.parseInt( versionParts[0] );
|
||||
int minorVersion = versionParts.length > 1 ? Integer.parseInt( versionParts[1] ) : 0;
|
||||
int microVersion = versionParts.length > 2 ? Integer.parseInt( versionParts[2] ) : 0;
|
||||
|
||||
databaseVersion= new SimpleDatabaseVersion( majorVersion, minorVersion, microVersion);
|
||||
}
|
||||
if ( databaseVersion == null ) {
|
||||
LOG.unableToDetermineCockroachDatabaseVersion(
|
||||
MINIMUM_VERSION.getDatabaseMajorVersion() + "." +
|
||||
MINIMUM_VERSION.getDatabaseMinorVersion() + "." +
|
||||
MINIMUM_VERSION.getDatabaseMicroVersion()
|
||||
);
|
||||
databaseVersion = MINIMUM_VERSION;
|
||||
}
|
||||
return databaseVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseVersion getMinimumSupportedVersion() {
|
||||
return MINIMUM_VERSION;
|
||||
|
|
|
@ -1794,4 +1794,8 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
@Message(value = "The %2$s version for [%s] is no longer supported, hence certain features may not work properly. The minimum supported version is %3$s. Check the community dialects project for available legacy versions.", id = 511)
|
||||
void unsupportedDatabaseVersion(String databaseName, String actualVersion, String minimumVersion);
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "The database version version for the Cockroach Dialect could not be determined. The minimum supported version (%s) has been set instead.", id = 512)
|
||||
void unableToDetermineCockroachDatabaseVersion(String minimumVersion);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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.orm.test.dialect.unit;
|
||||
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.DatabaseVersion;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.logger.Triggerable;
|
||||
import org.hibernate.testing.orm.logger.LoggerInspectionExtension;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
public class CockroachDialectVersionTest {
|
||||
|
||||
private Triggerable triggerable;
|
||||
|
||||
@RegisterExtension
|
||||
public LoggerInspectionExtension logger = LoggerInspectionExtension
|
||||
.builder().setLogger(
|
||||
Logger.getMessageLogger( CoreMessageLogger.class, CockroachDialect.class.getName() )
|
||||
).build();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
triggerable = logger.watchForLogMessages("HHH000512" );
|
||||
triggerable.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-15511")
|
||||
public void testCockroachDialectVersionParsing() {
|
||||
String failMsg = "HHH000511: The database version version for the Cockroach Dialect could not be determined ... should have been logged";
|
||||
|
||||
CockroachDBTestDialect testDialect = new CockroachDBTestDialect( null );
|
||||
Assertions.assertTrue( triggerable.wasTriggered(), failMsg);
|
||||
DatabaseVersion dv = testDialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMajorVersion(), dv.getMajor() );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMinorVersion(), dv.getMinor() );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMicroVersion(), dv.getMicro() );
|
||||
triggerable.reset();
|
||||
|
||||
testDialect = new CockroachDBTestDialect( "" );
|
||||
Assertions.assertTrue( triggerable.wasTriggered(), failMsg);
|
||||
dv = testDialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMajorVersion(), dv.getMajor() );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMinorVersion(), dv.getMinor() );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMicroVersion(), dv.getMicro() );
|
||||
triggerable.reset();
|
||||
|
||||
testDialect = new CockroachDBTestDialect( "Some version lacking string" );
|
||||
Assertions.assertTrue( triggerable.wasTriggered(), failMsg);
|
||||
dv = testDialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMajorVersion(), dv.getMajor() );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMinorVersion(), dv.getMinor() );
|
||||
assertEquals( testDialect.getMinimumVersion().getDatabaseMicroVersion(), dv.getMicro() );
|
||||
triggerable.reset();
|
||||
|
||||
// using a fictitious major version, to avoid minimum version warnings
|
||||
Dialect dialect = new CockroachDBTestDialect( "CockroachDB CCL v99.2.10 (x86_64-unknown-linux-gnu, built 2022/05/02 17:38:58, go1.16.6)" );
|
||||
|
||||
dv = dialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( 99, dv.getMajor() );
|
||||
assertEquals( 2, dv.getMinor() );
|
||||
assertEquals( 10, dv.getMicro() );
|
||||
|
||||
dialect = new CockroachDBTestDialect("CockroachDB CCL v99.2. (x86_64-unknown-linux-gnu, built 2022/05/02 17:38:58, go1.16.6)");
|
||||
dv = dialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( 99, dv.getMajor() );
|
||||
assertEquals( 2, dv.getMinor() );
|
||||
assertEquals( 0, dv.getMicro() );
|
||||
|
||||
dialect = new CockroachDBTestDialect("CockroachDB CCL v99.2 (x86_64-unknown-linux-gnu, built 2022/05/02 17:38:58, go1.16.6)");
|
||||
dv = dialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( 99, dv.getMajor() );
|
||||
assertEquals( 2, dv.getMinor() );
|
||||
assertEquals( 0, dv.getMicro() );
|
||||
|
||||
dialect = new CockroachDBTestDialect("CockroachDB CCL v99. (x86_64-unknown-linux-gnu, built 2022/05/02 17:38:58, go1.16.6)");
|
||||
dv = dialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( 99, dv.getMajor() );
|
||||
assertEquals( 0, dv.getMinor() );
|
||||
assertEquals( 0, dv.getMicro() );
|
||||
|
||||
dialect = new CockroachDBTestDialect("CockroachDB CCL v99 (x86_64-unknown-linux-gnu, built 2022/05/02 17:38:58, go1.16.6)");
|
||||
dv = dialect.getVersion();
|
||||
assertNotNull( dv );
|
||||
assertEquals( 99, dv.getMajor() );
|
||||
assertEquals( 0, dv.getMinor() );
|
||||
assertEquals( 0, dv.getMicro() );
|
||||
}
|
||||
|
||||
private static final class CockroachDBTestDialect extends CockroachDialect {
|
||||
private CockroachDBTestDialect(String versionString) {
|
||||
super (parseVersion( versionString ));
|
||||
}
|
||||
|
||||
private DatabaseVersion getMinimumVersion() {
|
||||
return getMinimumSupportedVersion();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue