Add an optional getMinimumSupportedVersion() to Dialect, for validation purposes

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2022-06-01 18:53:15 +02:00 committed by Jan Schatteman
parent a488e1a269
commit 4947af946a
3 changed files with 156 additions and 7 deletions

View File

@ -41,7 +41,6 @@ import java.util.regex.Pattern;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.Query;
import org.hibernate.ScrollMode;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.boot.model.TypeContributions;
@ -96,6 +95,7 @@ import org.hibernate.exception.spi.ConversionContext;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.MathHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
@ -110,15 +110,16 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.Query;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.FetchClauseType;
import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.sqm.NullOrdering;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.TrimSpec;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sqm.mutation.internal.temptable.AfterUseAction;
import org.hibernate.query.sqm.mutation.internal.temptable.BeforeUseAction;
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableInsertStrategy;
@ -165,12 +166,49 @@ import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
import jakarta.persistence.TemporalType;
import static java.lang.Math.ceil;
import static java.lang.Math.log;
import static org.hibernate.internal.util.StringHelper.parseCommaSeparatedString;
import static org.hibernate.type.SqlTypes.*;
import static org.hibernate.type.SqlTypes.ARRAY;
import static org.hibernate.type.SqlTypes.BIGINT;
import static org.hibernate.type.SqlTypes.BINARY;
import static org.hibernate.type.SqlTypes.BLOB;
import static org.hibernate.type.SqlTypes.BOOLEAN;
import static org.hibernate.type.SqlTypes.CHAR;
import static org.hibernate.type.SqlTypes.CLOB;
import static org.hibernate.type.SqlTypes.DATE;
import static org.hibernate.type.SqlTypes.DECIMAL;
import static org.hibernate.type.SqlTypes.DOUBLE;
import static org.hibernate.type.SqlTypes.FLOAT;
import static org.hibernate.type.SqlTypes.INTEGER;
import static org.hibernate.type.SqlTypes.LONG32NVARCHAR;
import static org.hibernate.type.SqlTypes.LONG32VARBINARY;
import static org.hibernate.type.SqlTypes.LONG32VARCHAR;
import static org.hibernate.type.SqlTypes.NCHAR;
import static org.hibernate.type.SqlTypes.NCLOB;
import static org.hibernate.type.SqlTypes.NUMERIC;
import static org.hibernate.type.SqlTypes.NVARCHAR;
import static org.hibernate.type.SqlTypes.REAL;
import static org.hibernate.type.SqlTypes.SMALLINT;
import static org.hibernate.type.SqlTypes.TIME;
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.TIME_WITH_TIMEZONE;
import static org.hibernate.type.SqlTypes.TINYINT;
import static org.hibernate.type.SqlTypes.VARBINARY;
import static org.hibernate.type.SqlTypes.VARCHAR;
import static org.hibernate.type.SqlTypes.isCharacterType;
import static org.hibernate.type.SqlTypes.isFloatOrRealOrDouble;
import static org.hibernate.type.SqlTypes.isIntegral;
import static org.hibernate.type.SqlTypes.isNumericOrDecimal;
import static org.hibernate.type.SqlTypes.isNumericType;
import static org.hibernate.type.SqlTypes.isVarbinaryType;
import static org.hibernate.type.SqlTypes.isVarcharType;
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END;
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_DATE;
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIME;
@ -235,6 +273,8 @@ public abstract class Dialect implements ConversionContext {
private static final Pattern ESCAPE_CLOSING_COMMENT_PATTERN = Pattern.compile( "\\*/" );
private static final Pattern ESCAPE_OPENING_COMMENT_PATTERN = Pattern.compile( "/\\*" );
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, Dialect.class.getName() );
//needed for converting precision from decimal to binary digits
protected static final double LOG_BASE2OF10 = log(10)/log(2);
@ -259,17 +299,31 @@ public abstract class Dialect implements ConversionContext {
protected Dialect(DatabaseVersion version) {
this.version = version;
checkVersion();
registerDefaultKeywords();
initDefaultProperties();
}
protected Dialect(DialectResolutionInfo info) {
this.version = info.makeCopy();
checkVersion();
registerDefaultKeywords();
registerKeywords(info);
initDefaultProperties();
}
protected void checkVersion() {
final DatabaseVersion version = getVersion();
final DatabaseVersion minimumVersion = getMinimumSupportedVersion();
if ( version != null && version.isBefore( minimumVersion.getMajor(), minimumVersion.getMinor(), minimumVersion.getMicro() ) ) {
LOG.unsupportedDatabaseVersion(
getClass().getName(),
version.getMajor() + "." + version.getMinor() + "." + version.getMicro(),
minimumVersion.getMajor() + "." + minimumVersion.getMinor() + "." + minimumVersion.getMicro()
);
}
}
/**
* Set appropriate default values for configuration properties.
*/
@ -475,6 +529,10 @@ public abstract class Dialect implements ConversionContext {
return version;
}
protected DatabaseVersion getMinimumSupportedVersion() {
return SimpleDatabaseVersion.ZERO_VERSION;
}
/**
* Resolves the {@link SqlTypes} type code for the given column type name as reported by the database,
* or <code>null</code> if it can't be resolved.
@ -1217,8 +1275,8 @@ public abstract class Dialect implements ConversionContext {
* {@link Types#LONGVARBINARY LONGVARBINARY} as the same type, since
* Hibernate doesn't really differentiate these types.
*
* @param column1 the first column type info
* @param column2 the second column type info
* @param typeCode1 the first column type info
* @param typeCode2 the second column type info
*
* @return {@code true} if the two type codes are equivalent
*/

View File

@ -1792,4 +1792,8 @@ public interface CoreMessageLogger extends BasicLogger {
@Message(value = "Association with `fetch=\"join\"`/`@Fetch(FetchMode.JOIN)` and `lazy=\"true\"`/`FetchType.LAZY` found. This will be interpreted as lazy: %s", id = 510)
void fetchModeJoinWithLazyWarning(String role);
@LogMessage(level = WARN)
@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);
}

View File

@ -0,0 +1,87 @@
/*
* 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;
import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.SimpleDatabaseVersion;
import org.hibernate.internal.CoreMessageLogger;
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;
/**
* @author Jan Schatteman
*/
public class DialectMinimumVersionTest {
private Triggerable triggerable;
@RegisterExtension
public LoggerInspectionExtension logger = LoggerInspectionExtension
.builder().setLogger(
Logger.getMessageLogger( CoreMessageLogger.class, Dialect.class.getName() )
).build();
@BeforeEach
public void setUp() {
triggerable = logger.watchForLogMessages("HHH000511" );
triggerable.reset();
}
@Test
public void testLessThanDialectMinimumVersion() {
String failMsg = "HHH000511: The version for ... is no longer supported ... should have been logged";
DummyDialect dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 9, 5, 1 ) );
Assertions.assertTrue( triggerable.wasTriggered(), failMsg);
triggerable.reset();
dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 10, 4, 1 ) );
Assertions.assertTrue( triggerable.wasTriggered(), failMsg);
triggerable.reset();
dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 10, 5, 0 ) );
Assertions.assertTrue( triggerable.wasTriggered(), failMsg);
}
@Test
public void testMoreThanDialectMinimumVersion() {
String failMsg = "HHH000511: The version for ... is no longer supported ... should not have been logged";
DummyDialect dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 11, 5, 1 ) );
Assertions.assertFalse( triggerable.wasTriggered(), failMsg );
triggerable.reset();
dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 10, 6, 1 ) );
Assertions.assertFalse( triggerable.wasTriggered(), failMsg );
triggerable.reset();
dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 10, 5, 2 ) );
Assertions.assertFalse( triggerable.wasTriggered(), failMsg );
}
@Test
public void testSameAsDialectMinimumVersion() {
DummyDialect dummyDialect = new DummyDialect( new SimpleDatabaseVersion( 10, 5, 1 ) );
Assertions.assertFalse( triggerable.wasTriggered(), "HHH000511: The version for ... is no longer supported ... should not have been logged" );
}
private final static class DummyDialect extends Dialect {
private DummyDialect(DatabaseVersion version) {
super( version );
}
@Override
protected DatabaseVersion getMinimumSupportedVersion() {
return new SimpleDatabaseVersion( 10, 5, 1 );
}
}
}