HHH-16228 Dialect instance might be wrapped when doing instanceof checks for capabilities

To properly support the idea of wrapping the Dialect, we need
to take this into account whenever an `instanceof` is used
to check for Dialect capabilities.
Also some code is casting to the expected Dialect.
This commit is contained in:
Sanne Grinovero 2023-02-27 15:32:34 +00:00
parent d5145e1f5a
commit cf2e723d6f
9 changed files with 55 additions and 11 deletions

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.community.dialect;
import org.hibernate.dialect.DialectDelegateWrapper;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.MySQLSqlAstTranslator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -245,7 +246,7 @@ public class MySQLLegacySqlAstTranslator<T extends JdbcOperation> extends Abstra
@Override
public MySQLDialect getDialect() {
return (MySQLDialect) super.getDialect();
return (MySQLDialect) DialectDelegateWrapper.extractRealDialect( super.getDialect() );
}
@Override

View File

@ -109,6 +109,23 @@ public class DialectDelegateWrapper extends Dialect {
}
/**
* Extract the wrapped dialect, recursively until a non-wrapped implementation is found;
* this is useful for all the code needing to know "of which type" the underlying
* implementation actually is.
* @param dialect the Dialect to unwrap
* @return a Dialect implementation which is not a DialectDelegateWrapper; could be the same as the argument.
*/
public static Dialect extractRealDialect(Dialect dialect) {
Objects.requireNonNull( dialect );
if ( !( dialect instanceof DialectDelegateWrapper ) ) {
return dialect;
}
else {
return extractRealDialect( ( (DialectDelegateWrapper) dialect ).wrapped );
}
}
/**
* Exposed so to allow code needing to know the implementation.
* @return the wrapped Dialect
*/

View File

@ -33,7 +33,7 @@ public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSq
public MariaDBSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
super( sessionFactory, statement );
this.dialect = (MariaDBDialect) super.getDialect();
this.dialect = (MariaDBDialect) DialectDelegateWrapper.extractRealDialect( super.getDialect() );
}
@Override

View File

@ -281,7 +281,7 @@ public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
@Override
public MySQLDialect getDialect() {
return (MySQLDialect) super.getDialect();
return (MySQLDialect) DialectDelegateWrapper.extractRealDialect( super.getDialect() );
}
@Override

View File

@ -11,6 +11,7 @@ import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.QualifiedName;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DialectDelegateWrapper;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.id.enhanced.SequenceStructure;
@ -43,7 +44,8 @@ public class OrderedSequenceStructure extends SequenceStructure {
Class<?> numberType) {
super( jdbcEnvironment, "envers", qualifiedSequenceName, initialValue, incrementSize, numberType );
this.sequenceObject = new OrderedSequence();
if ( jdbcEnvironment.getDialect() instanceof OracleDialect ) {
final Dialect dialect = DialectDelegateWrapper.extractRealDialect( jdbcEnvironment.getDialect() );
if ( dialect instanceof OracleDialect ) {
this.suffix = ( noCache ? " NOCACHE" : "" ) + " ORDER";
}
else {

View File

@ -14,6 +14,7 @@ import java.util.Objects;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DialectDelegateWrapper;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.envers.boot.internal.EnversService;
@ -59,8 +60,9 @@ public class SinglePropertyMapper extends AbstractPropertyMapper implements Simp
Object oldObj) {
data.put( propertyData.getName(), newObj );
boolean dbLogicallyDifferent = true;
final Dialect dialect = session.getFactory().getJdbcServices()
Dialect dialect = session.getFactory().getJdbcServices()
.getDialect();
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
if ( ( dialect instanceof OracleDialect ) && (newObj instanceof String || oldObj instanceof String) ) {
// Don't generate new revision when database replaces empty string with NULL during INSERT or UPDATE statements.
dbLogicallyDifferent = !(StringTools.isEmpty( newObj ) && StringTools.isEmpty( oldObj ));

View File

@ -12,6 +12,7 @@ import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DialectDelegateWrapper;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.PostgreSQLDialect;
@ -110,6 +111,7 @@ abstract public class DialectChecks {
public static class SupportsRowValueConstructorSyntaxCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof AbstractHANADialect
|| dialect instanceof CockroachDialect
|| dialect instanceof MySQLDialect

View File

@ -15,6 +15,7 @@ import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DialectDelegateWrapper;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MariaDBDialect;
@ -149,6 +150,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsRowValueConstructorSyntaxCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof AbstractHANADialect
|| dialect instanceof CockroachDialect
|| dialect instanceof MySQLDialect
@ -158,6 +160,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsJdbcDriverProxying implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return !( dialect instanceof DB2Dialect
|| dialect instanceof DerbyDialect
|| dialect instanceof FirebirdDialect );
@ -245,12 +248,14 @@ abstract public class DialectFeatureChecks {
public static class SupportsPadWithChar implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return !( dialect instanceof DerbyDialect );
}
}
public static class SupportsGroupByRollup implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof DB2Dialect
|| dialect instanceof OracleDialect
|| dialect instanceof PostgreSQLDialect
@ -263,6 +268,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsGroupByGroupingSets implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof DB2Dialect
|| dialect instanceof OracleDialect
|| dialect instanceof PostgreSQLDialect
@ -297,6 +303,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsCharCodeConversion implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
// Derby doesn't support the `ASCII` or `CHR` functions
return !( dialect instanceof DerbyDialect );
}
@ -304,6 +311,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsReplace implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
// Derby doesn't support the `REPLACE` function
return !( dialect instanceof DerbyDialect );
}
@ -353,6 +361,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsOrderByInCorrelatedSubquery implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect.supportsOrderByInSubquery()
// For some reason, HANA doesn't support order by in correlated subqueries...
&& !( dialect instanceof AbstractHANADialect );
@ -385,6 +394,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsStringAggregation implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof H2Dialect
|| dialect instanceof HSQLDialect
|| dialect instanceof MySQLDialect
@ -400,6 +410,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsInverseDistributionFunctions implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof H2Dialect && dialect.getVersion().isSameOrAfter( 2 )
|| dialect instanceof PostgreSQLDialect
|| dialect instanceof AbstractHANADialect
@ -413,6 +424,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsHypotheticalSetFunctions implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof H2Dialect && dialect.getVersion().isSameOrAfter( 2 )
|| dialect instanceof PostgreSQLDialect
|| dialect instanceof AbstractHANADialect
@ -426,6 +438,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsWindowFunctions implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
// Derby doesn't really support window functions, only row_number()
return dialect.supportsWindowFunctions() && !( dialect instanceof DerbyDialect );
}
@ -433,6 +446,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsFilterClause implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
// Derby doesn't really support window functions, only row_number()
return dialect instanceof PostgreSQLDialect;
}
@ -440,6 +454,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsSubqueryInOnClause implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
// TiDB db does not support subqueries for ON condition
return !( dialect instanceof TiDBDialect );
}
@ -447,6 +462,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsFullJoin implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
// TiDB db does not support subqueries for ON condition
return !( dialect instanceof H2Dialect
|| dialect instanceof MySQLDialect
@ -457,6 +473,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsMedian implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return !( dialect instanceof MySQLDialect
|| dialect instanceof SybaseDialect
|| dialect instanceof DerbyDialect
@ -474,6 +491,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsTruncateTable implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
dialect = DialectDelegateWrapper.extractRealDialect( dialect );
return dialect instanceof MySQLDialect
|| dialect instanceof H2Dialect
|| dialect instanceof SQLServerDialect

View File

@ -29,6 +29,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DialectDelegateWrapper;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.PostgreSQLDialect;
@ -589,37 +590,38 @@ public class TransactionUtil {
public static void setJdbcTimeout(Session session, long millis) {
final Dialect dialect = session.getSessionFactory().unwrap( SessionFactoryImplementor.class ).getJdbcServices().getDialect();
session.doWork( connection -> {
if ( dialect instanceof PostgreSQLDialect || dialect instanceof CockroachDialect ) {
Dialect extractedDialect = DialectDelegateWrapper.extractRealDialect( dialect );
if ( extractedDialect instanceof PostgreSQLDialect || extractedDialect instanceof CockroachDialect ) {
try (Statement st = connection.createStatement()) {
//Prepared Statements fail for SET commands
st.execute(String.format( "SET statement_timeout TO %d", millis / 10));
}
}
else if( dialect instanceof MySQLDialect ) {
else if( extractedDialect instanceof MySQLDialect ) {
try (PreparedStatement st = connection.prepareStatement("SET SESSION innodb_lock_wait_timeout = ?")) {
st.setLong( 1, TimeUnit.MILLISECONDS.toSeconds( millis ) );
st.execute();
}
}
else if( dialect instanceof H2Dialect ) {
else if( extractedDialect instanceof H2Dialect ) {
try (PreparedStatement st = connection.prepareStatement("SET LOCK_TIMEOUT ?")) {
st.setLong( 1, millis / 10 );
st.execute();
}
}
else if( dialect instanceof SQLServerDialect ) {
else if( extractedDialect instanceof SQLServerDialect ) {
try (Statement st = connection.createStatement()) {
//Prepared Statements fail for SET commands
st.execute(String.format( "SET LOCK_TIMEOUT %d", millis / 10));
}
}
else if( dialect instanceof AbstractHANADialect ) {
else if( extractedDialect instanceof AbstractHANADialect ) {
try (Statement st = connection.createStatement()) {
//Prepared Statements fail for SET commands
st.execute(String.format( "SET TRANSACTION LOCK WAIT TIMEOUT %d", millis ));
}
}
else if( dialect instanceof SybaseASEDialect ) {
else if( extractedDialect instanceof SybaseASEDialect ) {
try (Statement st = connection.createStatement()) {
//Prepared Statements fail for SET commands
st.execute(String.format( "SET LOCK WAIT %d", millis/1000 ));