HHH-15182 - Remove support for MariaDB versions older than 10.3

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2022-06-17 19:57:27 +02:00 committed by Christian Beikov
parent 5b0b1fa680
commit 17fa97d1b0
6 changed files with 361 additions and 32 deletions

View File

@ -0,0 +1,183 @@
/*
* 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.community.dialect;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.InnoDBStorageEngine;
import org.hibernate.dialect.MySQLStorageEngine;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.sequence.MariaDBSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMariaDBDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes;
/**
* A {@linkplain Dialect SQL dialect} for MariaDB
*
* @author Vlad Mihalcea
* @author Gavin King
*/
public class MariaDBLegacyDialect extends MySQLLegacyDialect {
private static final DatabaseVersion VERSION5 = DatabaseVersion.make( 5 );
private static final DatabaseVersion VERSION57 = DatabaseVersion.make( 5, 7 );
public MariaDBLegacyDialect() {
this( DatabaseVersion.make( 5 ) );
}
public MariaDBLegacyDialect(DatabaseVersion version) {
super(version);
}
public MariaDBLegacyDialect(DialectResolutionInfo info) {
super(info);
}
@Override
public DatabaseVersion getMySQLVersion() {
return getVersion().isBefore( 5, 3 )
? VERSION5
: VERSION57;
}
@Override
public NationalizationSupport getNationalizationSupport() {
return NationalizationSupport.IMPLICIT;
}
@Override
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry(queryEngine);
if ( getVersion().isSameOrAfter( 10, 2 ) ) {
CommonFunctionFactory commonFunctionFactory = new CommonFunctionFactory( queryEngine );
commonFunctionFactory.windowFunctions();
commonFunctionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
queryEngine.getSqmFunctionRegistry().registerNamed(
"json_valid",
queryEngine.getTypeConfiguration()
.getBasicTypeRegistry()
.resolve( StandardBasicTypes.BOOLEAN )
);
if ( getVersion().isSameOrAfter( 10, 3, 3 ) ) {
commonFunctionFactory.inverseDistributionOrderedSetAggregates_windowEmulation();
}
}
}
@Override
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return new StandardSqlAstTranslatorFactory() {
@Override
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
SessionFactoryImplementor sessionFactory, Statement statement) {
return new MariaDBLegacySqlAstTranslator<>( sessionFactory, statement );
}
};
}
@Override
public boolean supportsWindowFunctions() {
return getVersion().isSameOrAfter( 10, 2 );
}
@Override
public boolean supportsColumnCheck() {
return getVersion().isSameOrAfter( 10, 2 );
}
@Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE;
}
@Override
public boolean supportsIfExistsBeforeConstraintName() {
return getVersion().isSameOrAfter( 10 );
}
@Override
public boolean supportsIfExistsAfterAlterTable() {
return getVersion().isSameOrAfter( 10, 5 );
}
@Override
public SequenceSupport getSequenceSupport() {
return getVersion().isBefore( 10, 3 )
? super.getSequenceSupport()
: MariaDBSequenceSupport.INSTANCE;
}
@Override
public String getQuerySequencesString() {
return getSequenceSupport().supportsSequences()
? "select table_name from information_schema.TABLES where table_schema=database() and table_type='SEQUENCE'"
: super.getQuerySequencesString(); //fancy way to write "null"
}
@Override
public SequenceInformationExtractor getSequenceInformationExtractor() {
return getSequenceSupport().supportsSequences()
? SequenceInformationExtractorMariaDBDatabaseImpl.INSTANCE
: super.getSequenceInformationExtractor();
}
@Override
public boolean supportsSkipLocked() {
//only supported on MySQL and as of 10.6
return getVersion().isSameOrAfter( 10, 6 );
}
@Override
public boolean supportsNoWait() {
return getVersion().isSameOrAfter( 10, 3 );
}
@Override
public boolean supportsWait() {
return getVersion().isSameOrAfter( 10, 3 );
}
@Override
boolean supportsForShare() {
//only supported on MySQL
return false;
}
@Override
boolean supportsAliasLocks() {
//only supported on MySQL
return false;
}
@Override
public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData)
throws SQLException {
// some MariaDB drivers does not return case strategy info
builder.setUnquotedCaseStrategy( IdentifierCaseStrategy.MIXED );
builder.setQuotedCaseStrategy( IdentifierCaseStrategy.MIXED );
return super.buildIdentifierHelper( builder, dbMetaData );
}
}

View File

@ -0,0 +1,149 @@
/*
* 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.community.dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.sql.ast.tree.expression.Summarization;
import org.hibernate.sql.ast.tree.from.QueryPartTableReference;
import org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate;
import org.hibernate.sql.ast.tree.select.QueryGroup;
import org.hibernate.sql.ast.tree.select.QueryPart;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.exec.spi.JdbcOperation;
/**
* A SQL AST translator for MariaDB.
*
* @author Christian Beikov
*/
public class MariaDBLegacySqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
public MariaDBLegacySqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
super( sessionFactory, statement );
}
@Override
protected void renderExpressionAsClauseItem(Expression expression) {
expression.accept( this );
}
@Override
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
final boolean isNegated = booleanExpressionPredicate.isNegated();
if ( isNegated ) {
appendSql( "not(" );
}
booleanExpressionPredicate.getExpression().accept( this );
if ( isNegated ) {
appendSql( CLOSE_PARENTHESIS );
}
}
@Override
protected String getForShare(int timeoutMillis) {
return " lock in share mode";
}
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
// Check if current query part is already row numbering to avoid infinite recursion
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart && supportsWindowFunctions() && !isRowsOnlyFetchClauseType( queryPart );
}
@Override
public void visitQueryGroup(QueryGroup queryGroup) {
if ( shouldEmulateFetchClause( queryGroup ) ) {
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
}
else {
super.visitQueryGroup( queryGroup );
}
}
@Override
public void visitQuerySpec(QuerySpec querySpec) {
if ( shouldEmulateFetchClause( querySpec ) ) {
emulateFetchOffsetWithWindowFunctions( querySpec, true );
}
else {
super.visitQuerySpec( querySpec );
}
}
@Override
public void visitQueryPartTableReference(QueryPartTableReference tableReference) {
emulateQueryPartTableReferenceColumnAliasing( tableReference );
}
@Override
public void visitOffsetFetchClause(QueryPart queryPart) {
if ( !isRowNumberingCurrentQueryPart() ) {
renderCombinedLimitClause( queryPart );
}
}
@Override
protected void renderSearchClause(CteStatement cte) {
// MariaDB does not support this, but it's just a hint anyway
}
@Override
protected void renderCycleClause(CteStatement cte) {
// MariaDB does not support this, but it can be emulated
}
@Override
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
renderComparisonDistinctOperator( lhs, operator, rhs );
}
@Override
protected void renderPartitionItem(Expression expression) {
if ( expression instanceof Literal ) {
appendSql( "'0'" );
}
else if ( expression instanceof Summarization ) {
Summarization summarization = (Summarization) expression;
renderCommaSeparated( summarization.getGroupings() );
appendSql( " with " );
appendSql( summarization.getKind().sqlText() );
}
else {
expression.accept( this );
}
}
@Override
public boolean supportsRowValueConstructorSyntaxInSet() {
return false;
}
@Override
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
return false;
}
@Override
protected boolean supportsIntersect() {
return getDialect().getVersion().isSameOrAfter( 10, 3 );
}
@Override
protected boolean supportsDistinctFromPredicate() {
// It supports a proprietary operator
return true;
}
private boolean supportsWindowFunctions() {
return getDialect().getVersion().isSameOrAfter( 10, 2 );
}
}

View File

@ -34,11 +34,11 @@ import org.hibernate.type.StandardBasicTypes;
* @author Gavin King
*/
public class MariaDBDialect extends MySQLDialect {
private static final DatabaseVersion VERSION5 = DatabaseVersion.make( 5 );
private static final DatabaseVersion VERSION57 = DatabaseVersion.make( 5, 7 );
private static final DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 10, 3 );
private static final DatabaseVersion MYSQL57 = DatabaseVersion.make( 5, 7 );
public MariaDBDialect() {
this( DatabaseVersion.make( 5 ) );
this( MINIMUM_VERSION );
}
public MariaDBDialect(DatabaseVersion version) {
@ -51,9 +51,12 @@ public class MariaDBDialect extends MySQLDialect {
@Override
public DatabaseVersion getMySQLVersion() {
return getVersion().isBefore( 5, 3 )
? VERSION5
: VERSION57;
return MYSQL57;
}
@Override
protected DatabaseVersion getMinimumSupportedVersion() {
return MINIMUM_VERSION;
}
@Override
@ -65,20 +68,16 @@ public class MariaDBDialect extends MySQLDialect {
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry(queryEngine);
if ( getVersion().isSameOrAfter( 10, 2 ) ) {
CommonFunctionFactory commonFunctionFactory = new CommonFunctionFactory( queryEngine );
commonFunctionFactory.windowFunctions();
commonFunctionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
queryEngine.getSqmFunctionRegistry().registerNamed(
"json_valid",
queryEngine.getTypeConfiguration()
.getBasicTypeRegistry()
.resolve( StandardBasicTypes.BOOLEAN )
);
if ( getVersion().isSameOrAfter( 10, 3, 3 ) ) {
commonFunctionFactory.inverseDistributionOrderedSetAggregates_windowEmulation();
}
}
CommonFunctionFactory commonFunctionFactory = new CommonFunctionFactory( queryEngine );
commonFunctionFactory.windowFunctions();
commonFunctionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
queryEngine.getSqmFunctionRegistry().registerNamed(
"json_valid",
queryEngine.getTypeConfiguration()
.getBasicTypeRegistry()
.resolve( StandardBasicTypes.BOOLEAN )
);
commonFunctionFactory.inverseDistributionOrderedSetAggregates_windowEmulation();
}
@Override
@ -94,12 +93,12 @@ public class MariaDBDialect extends MySQLDialect {
@Override
public boolean supportsWindowFunctions() {
return getVersion().isSameOrAfter( 10, 2 );
return true;
}
@Override
public boolean supportsColumnCheck() {
return getVersion().isSameOrAfter( 10, 2 );
return true;
}
@Override
@ -109,7 +108,7 @@ public class MariaDBDialect extends MySQLDialect {
@Override
public boolean supportsIfExistsBeforeConstraintName() {
return getVersion().isSameOrAfter( 10 );
return true;
}
@Override
@ -119,9 +118,7 @@ public class MariaDBDialect extends MySQLDialect {
@Override
public SequenceSupport getSequenceSupport() {
return getVersion().isBefore( 10, 3 )
? super.getSequenceSupport()
: MariaDBSequenceSupport.INSTANCE;
return MariaDBSequenceSupport.INSTANCE;
}
@Override
@ -146,12 +143,12 @@ public class MariaDBDialect extends MySQLDialect {
@Override
public boolean supportsNoWait() {
return getVersion().isSameOrAfter( 10, 3 );
return true;
}
@Override
public boolean supportsWait() {
return getVersion().isSameOrAfter( 10, 3 );
return true;
}
@Override

View File

@ -134,7 +134,7 @@ public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSq
@Override
protected boolean supportsIntersect() {
return getDialect().getVersion().isSameOrAfter( 10, 3 );
return true;
}
@Override
@ -144,6 +144,6 @@ public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSq
}
private boolean supportsWindowFunctions() {
return getDialect().getVersion().isSameOrAfter( 10, 2 );
return true;
}
}

View File

@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
/**
* @author Nathan Xu
*/
@RequiresDialect(value = MariaDBDialect.class, majorVersion = 10, minorVersion = 3)
@RequiresDialect(value = MariaDBDialect.class)
public class MariaDBExtractSequenceMetadataTest {
private static String primaryDbName;

View File

@ -38,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Vlad Mihalcea
*/
@TestForIssue(jiraKey = "HHH-12973")
@RequiresDialect(value = MariaDBDialect.class, majorVersion = 10, minorVersion = 3)
@RequiresDialect(value = MariaDBDialect.class)
@Jpa(
annotatedClasses = {
SequenceInformationMariaDBTest.Book.class,