@SuppressWarnings("squid:S2447") // null is explicitly documented as a possible return value.
    // TODO: MariaDB connector 2.0.2 appearantly fixes this problem, and MySQL-ConnectorJ 6.0.6 did not have it in
    // the first place.. Replace this crude workaround with a proper JDBC driver version check
    public Boolean hasBugJdbcConstraintsDeferrable() throws DatabaseException {
    """
	Tests if this MySQL / MariaDB database has a bug where the JDBC driver returns constraints as
	DEFERRABLE INITIAL IMMEDIATE even though neither MySQL nor MariaDB support DEFERRABLE CONSTRAINTs at all.
	We need to know about this because this could lead to errors in database snapshots.
	@return true if this database is affected, false if not, null if we cannot tell (e.g. OfflineConnection)
    """
        if (getConnection() instanceof OfflineConnection)
            return null;
        if (getHasJdbcConstraintDeferrableBug() != null)  // cached value
            return getHasJdbcConstraintDeferrableBug();

        String randomIdentifier = "TMP_" + StringUtil.randomIdentifer(16);
        try
        {
            // Get the real connection and metadata reference
            java.sql.Connection conn = ((JdbcConnection) getConnection()).getUnderlyingConnection();
            java.sql.DatabaseMetaData metaData = conn.getMetaData();
            String sql = "CREATE TABLE " + randomIdentifier + " (\n" +
                    "  id INT PRIMARY KEY,\n" +
                    "  self_ref INT NOT NULL,\n" +
                    "  CONSTRAINT c_self_ref FOREIGN KEY(self_ref) REFERENCES " + randomIdentifier + "(id)\n" +
                    ")";
            ExecutorService.getInstance().getExecutor(this).execute(new RawSqlStatement(sql));

            try (
                ResultSet rs = metaData.getImportedKeys(getDefaultCatalogName(), getDefaultSchemaName(), randomIdentifier)
            ) {
                if (!rs.next()) {
                    throw new UnexpectedLiquibaseException("Error during testing for MySQL/MariaDB JDBC driver bug: " +
                            "could not retrieve JDBC metadata information for temporary table '" +
                            randomIdentifier + "'");
                }
                if (rs.getShort("DEFERRABILITY") != DatabaseMetaData.importedKeyNotDeferrable) {
                    setHasJdbcConstraintDeferrableBug(true);
                    Scope.getCurrentScope().getLog(getClass()).warning(LogType.LOG, "Your MySQL/MariaDB database JDBC driver might have " +
                            "a bug where constraints are reported as DEFERRABLE, even though MySQL/MariaDB do not " +
                            "support this feature. A workaround for this problem will be used. Please check with " +
                            "MySQL/MariaDB for availability of fixed JDBC drivers to avoid this warning.");
                } else {
                    setHasJdbcConstraintDeferrableBug(false);
                }
            }

        } catch (DatabaseException|SQLException e) {
            throw new UnexpectedLiquibaseException("Error during testing for MySQL/MariaDB JDBC driver bug.", e);
        } finally {
                ExecutorService.getInstance().reset();
                ExecutorService.getInstance().getExecutor(this).execute(
                        new RawSqlStatement("DROP TABLE " + randomIdentifier));
        }

        return getHasJdbcConstraintDeferrableBug();
    }
@SuppressWarnings("squid:S2447") // null is explicitly documented as a possible return value.
    // TODO: MariaDB connector 2.0.2 appearantly fixes this problem, and MySQL-ConnectorJ 6.0.6 did not have it in
    // the first place.. Replace this crude workaround with a proper JDBC driver version check
    public Boolean hasBugJdbcConstraintsDeferrable() throws DatabaseException {
        if (getConnection() instanceof OfflineConnection)
            return null;
        if (getHasJdbcConstraintDeferrableBug() != null)  // cached value
            return getHasJdbcConstraintDeferrableBug();

        String randomIdentifier = "TMP_" + StringUtil.randomIdentifer(16);
        try
        {
            // Get the real connection and metadata reference
            java.sql.Connection conn = ((JdbcConnection) getConnection()).getUnderlyingConnection();
            java.sql.DatabaseMetaData metaData = conn.getMetaData();
            String sql = "CREATE TABLE " + randomIdentifier + " (\n" +
                    "  id INT PRIMARY KEY,\n" +
                    "  self_ref INT NOT NULL,\n" +
                    "  CONSTRAINT c_self_ref FOREIGN KEY(self_ref) REFERENCES " + randomIdentifier + "(id)\n" +
                    ")";
            ExecutorService.getInstance().getExecutor(this).execute(new RawSqlStatement(sql));

            try (
                ResultSet rs = metaData.getImportedKeys(getDefaultCatalogName(), getDefaultSchemaName(), randomIdentifier)
            ) {
                if (!rs.next()) {
                    throw new UnexpectedLiquibaseException("Error during testing for MySQL/MariaDB JDBC driver bug: " +
                            "could not retrieve JDBC metadata information for temporary table '" +
                            randomIdentifier + "'");
                }
                if (rs.getShort("DEFERRABILITY") != DatabaseMetaData.importedKeyNotDeferrable) {
                    setHasJdbcConstraintDeferrableBug(true);
                    Scope.getCurrentScope().getLog(getClass()).warning(LogType.LOG, "Your MySQL/MariaDB database JDBC driver might have " +
                            "a bug where constraints are reported as DEFERRABLE, even though MySQL/MariaDB do not " +
                            "support this feature. A workaround for this problem will be used. Please check with " +
                            "MySQL/MariaDB for availability of fixed JDBC drivers to avoid this warning.");
                } else {
                    setHasJdbcConstraintDeferrableBug(false);
                }
            }

        } catch (DatabaseException|SQLException e) {
            throw new UnexpectedLiquibaseException("Error during testing for MySQL/MariaDB JDBC driver bug.", e);
        } finally {
                ExecutorService.getInstance().reset();
                ExecutorService.getInstance().getExecutor(this).execute(
                        new RawSqlStatement("DROP TABLE " + randomIdentifier));
        }

        return getHasJdbcConstraintDeferrableBug();
    }
@ SuppressWarnings ( "squid:S2447" ) // null is explicitly documented as a possible return value. // TODO: MariaDB connector 2.0.2 appearantly fixes this problem, and MySQL-ConnectorJ 6.0.6 did not have it in // the first place.. Replace this crude workaround with a proper JDBC driver version check public Boolean hasBugJdbcConstraintsDeferrable ( ) throws DatabaseException { if ( getConnection ( ) instanceof OfflineConnection ) return null ; if ( getHasJdbcConstraintDeferrableBug ( ) != null ) // cached value return getHasJdbcConstraintDeferrableBug ( ) ; String randomIdentifier = "TMP_" + StringUtil . randomIdentifer ( 16 ) ; try { // Get the real connection and metadata reference java . sql . Connection conn = ( ( JdbcConnection ) getConnection ( ) ) . getUnderlyingConnection ( ) ; java . sql . DatabaseMetaData metaData = conn . getMetaData ( ) ; String sql = "CREATE TABLE " + randomIdentifier + " (\n" + "  id INT PRIMARY KEY,\n" + "  self_ref INT NOT NULL,\n" + "  CONSTRAINT c_self_ref FOREIGN KEY(self_ref) REFERENCES " + randomIdentifier + "(id)\n" + ")" ; ExecutorService . getInstance ( ) . getExecutor ( this ) . execute ( new RawSqlStatement ( sql ) ) ; try ( ResultSet rs = metaData . getImportedKeys ( getDefaultCatalogName ( ) , getDefaultSchemaName ( ) , randomIdentifier ) ) { if ( ! rs . next ( ) ) { throw new UnexpectedLiquibaseException ( "Error during testing for MySQL/MariaDB JDBC driver bug: " + "could not retrieve JDBC metadata information for temporary table '" + randomIdentifier + "'" ) ; } if ( rs . getShort ( "DEFERRABILITY" ) != DatabaseMetaData . importedKeyNotDeferrable ) { setHasJdbcConstraintDeferrableBug ( true ) ; Scope . getCurrentScope ( ) . getLog ( getClass ( ) ) . warning ( LogType . LOG , "Your MySQL/MariaDB database JDBC driver might have " + "a bug where constraints are reported as DEFERRABLE, even though MySQL/MariaDB do not " + "support this feature. A workaround for this problem will be used. Please check with " + "MySQL/MariaDB for availability of fixed JDBC drivers to avoid this warning." ) ; } else { setHasJdbcConstraintDeferrableBug ( false ) ; } } } catch ( DatabaseException | SQLException e ) { throw new UnexpectedLiquibaseException ( "Error during testing for MySQL/MariaDB JDBC driver bug." , e ) ; } finally { ExecutorService . getInstance ( ) . reset ( ) ; ExecutorService . getInstance ( ) . getExecutor ( this ) . execute ( new RawSqlStatement ( "DROP TABLE " + randomIdentifier ) ) ; } return getHasJdbcConstraintDeferrableBug ( ) ; }
Tests if this MySQL / MariaDB database has a bug where the JDBC driver returns constraints as
DEFERRABLE INITIAL IMMEDIATE even though neither MySQL nor MariaDB support DEFERRABLE CONSTRAINTs at all.
We need to know about this because this could lead to errors in database snapshots.
@return true if this database is affected, false if not, null if we cannot tell (e.g. OfflineConnection)
Tests if this MySQL / MariaDB database has a bug where the JDBC driver returns constraints as DEFERRABLE INITIAL IMMEDIATE even though neither MySQL nor MariaDB support DEFERRABLE CONSTRAINTs at all . We need to know about this because this could lead to errors in database snapshots .