Search in sources :

Example 96 with JdbcConnection

use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.

the class DefaultConnectionPlugin method openInitialConnection.

@Override
public void openInitialConnection(ConnectionUrl connectionUrl) throws SQLException {
    if (this.currentConnectionProvider.getCurrentConnection() != null) {
        return;
    }
    HostInfo mainHostInfo = connectionUrl.getMainHost();
    JdbcConnection connection = this.connectionProvider.connect(mainHostInfo);
    this.currentConnectionProvider.setCurrentConnection(connection, mainHostInfo);
}
Also used : JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) HostInfo(com.mysql.cj.conf.HostInfo)

Example 97 with JdbcConnection

use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.

the class StatementsTest method testServerPreparedStatementsCaching.

/**
 * WL#11101 - Remove de-cache and close of SSPSs on double call to close()
 *
 * @throws Exception
 */
@Test
public void testServerPreparedStatementsCaching() throws Exception {
    // Non prepared statements must be non-poolable by default.
    assertFalse(this.stmt.isPoolable());
    Field stmtsCacheField = ConnectionImpl.class.getDeclaredField("serverSideStatementCache");
    stmtsCacheField.setAccessible(true);
    ToIntFunction<Connection> getStmtsCacheSize = (c) -> {
        try {
            LRUCache<?, ?> stmtsCacheObj = (LRUCache<?, ?>) stmtsCacheField.get(c);
            return stmtsCacheObj == null ? -1 : stmtsCacheObj.size();
        } catch (IllegalArgumentException | IllegalAccessException e) {
            fail("Fail getting the statemets cache size.");
            return -1;
        }
    };
    Function<Connection, ServerPreparedStatement> getStmtsCacheSingleElem = (c) -> {
        try {
            @SuppressWarnings("unchecked") LRUCache<?, ServerPreparedStatement> stmtsCacheObj = (LRUCache<?, ServerPreparedStatement>) stmtsCacheField.get(c);
            return stmtsCacheObj.get(stmtsCacheObj.keySet().iterator().next());
        } catch (IllegalArgumentException | IllegalAccessException e) {
            fail("Fail getting the statemets cache element.");
            return null;
        }
    };
    final String sql1 = "SELECT 1, ?";
    final String sql2 = "SELECT 2, ?";
    boolean useSPS = false;
    boolean cachePS = false;
    do {
        Properties props = new Properties();
        props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        props.setProperty(PropertyKey.useServerPrepStmts.getKeyName(), Boolean.toString(useSPS));
        props.setProperty(PropertyKey.cachePrepStmts.getKeyName(), Boolean.toString(cachePS));
        props.setProperty(PropertyKey.prepStmtCacheSize.getKeyName(), "5");
        boolean cachedSPS = useSPS && cachePS;
        /*
             * Cache the prepared statement and de-cache it later.
             * (*) if server prepared statement and caching is enabled.
             */
        {
            JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
            PreparedStatement testPstmt = testConn.prepareStatement(sql1);
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertTrue(testPstmt.isPoolable());
            // Caches this PS (*).
            testPstmt.close();
            assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
            // No-op.
            testPstmt.close();
            assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
            if (cachedSPS) {
                assertTrue(testPstmt.isPoolable());
                // De-caches this PS; it gets automatically closed (*).
                testPstmt.setPoolable(false);
                assertEquals(0, testConn.getActiveStatementCount());
                assertEquals(0, getStmtsCacheSize.applyAsInt(testConn));
            }
            // No-op.
            testPstmt.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
                testPstmt.setPoolable(false);
                return null;
            });
            assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
                testPstmt.isPoolable();
                return null;
            });
            testConn.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
        }
        /*
             * Set not to cache the prepared statement.
             * (*) if server prepared statement and caching is enabled.
             */
        {
            JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
            PreparedStatement testPstmt = testConn.prepareStatement(sql1);
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertTrue(testPstmt.isPoolable());
            // Don't cache this PS (*).
            testPstmt.setPoolable(false);
            assertFalse(testPstmt.isPoolable());
            // Doesn't cache this PS (*).
            testPstmt.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            // No-op.
            testPstmt.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
                testPstmt.setPoolable(true);
                return null;
            });
            assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
                testPstmt.isPoolable();
                return null;
            });
            testConn.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
        }
        /*
             * Set not to cache the prepared statement but change mind before closing it.
             * Reuse the cached prepared statement and don't re-cache it.
             * (*) if server prepared statement and caching is enabled.
             */
        {
            JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
            PreparedStatement testPstmt = testConn.prepareStatement(sql1);
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            // Don't cache this PS (*).
            testPstmt.setPoolable(false);
            assertFalse(testPstmt.isPoolable());
            testPstmt.setPoolable(true);
            // Changed my mind, let it be cached (*).
            assertTrue(testPstmt.isPoolable());
            // Caches this PS (*).
            testPstmt.close();
            assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
            // No-op.
            testPstmt.close();
            assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
            PreparedStatement testPstmtOld = testPstmt;
            // Takes the cached statement (*), or creates a fresh one.
            testPstmt = testConn.prepareStatement(sql1);
            if (cachedSPS) {
                assertSame(testPstmtOld, testPstmt);
            } else {
                assertNotSame(testPstmtOld, testPstmt);
            }
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertTrue(testPstmt.isPoolable());
            // Don't cache this PS (*).
            testPstmt.setPoolable(false);
            assertFalse(testPstmt.isPoolable());
            // Doesn't cache this PS (*).
            testPstmt.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            testPstmtOld = testPstmt;
            // Creates a fresh prepared statement.
            testPstmt = testConn.prepareStatement(sql1);
            assertNotSame(testPstmtOld, testPstmt);
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertTrue(testPstmt.isPoolable());
            testConn.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
        }
        /*
             * Caching of multiple copies of same prepared statement.
             * (*) if server prepared statement and caching is enabled.
             */
        {
            int psCount = 5;
            JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
            PreparedStatement[] testPstmts = new PreparedStatement[psCount];
            for (int i = 0; i < psCount; i++) {
                testPstmts[i] = testConn.prepareStatement(sql1);
            }
            assertEquals(5, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            for (int i = 0; i < psCount; i++) {
                assertTrue(testPstmts[i].isPoolable());
                // Caches this PS and replaces existing if same (*).
                testPstmts[i].close();
                assertEquals(cachedSPS ? psCount - i : psCount - i - 1, testConn.getActiveStatementCount());
                assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
                if (cachedSPS) {
                    assertSame(testPstmts[i], getStmtsCacheSingleElem.apply(testConn));
                }
            }
            PreparedStatement testPstmt = testConn.prepareStatement(sql1);
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            for (int i = 0; i < psCount; i++) {
                if (cachedSPS && i == psCount - 1) {
                    assertSame(testPstmts[i], testPstmt);
                } else {
                    assertNotSame(testPstmts[i], testPstmt);
                }
            }
            // Don't cache this PS (*).
            testPstmt.setPoolable(false);
            // Doesn't cache this PS (*).
            testPstmt.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            testConn.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
        }
        /*
             * Combine caching different prepared statements.
             * (*) if server prepared statement and caching is enabled.
             */
        {
            int psCount = 5;
            JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
            PreparedStatement[] testPstmts1 = new PreparedStatement[psCount];
            for (int i = 0; i < psCount; i++) {
                testPstmts1[i] = testConn.prepareStatement(sql1);
            }
            PreparedStatement testPstmt = testConn.prepareStatement(sql2);
            assertEquals(6, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            assertTrue(testPstmt.isPoolable());
            // Caches this PS (*).
            testPstmt.close();
            assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
            for (int i = 0; i < psCount; i++) {
                assertTrue(testPstmts1[i].isPoolable());
                // Caches this PS and replaces existing if same (*).
                testPstmts1[i].close();
                assertEquals(cachedSPS ? psCount - i + 1 : psCount - i - 1, testConn.getActiveStatementCount());
                assertEquals(cachedSPS ? 2 : -1, getStmtsCacheSize.applyAsInt(testConn));
            }
            PreparedStatement testPstmt1 = testConn.prepareStatement(sql1);
            assertEquals(cachedSPS ? 2 : 1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
            for (int i = 0; i < psCount; i++) {
                if (cachedSPS && i == psCount - 1) {
                    assertSame(testPstmts1[i], testPstmt1);
                } else {
                    assertNotSame(testPstmts1[i], testPstmt1);
                }
            }
            PreparedStatement testPstmt2 = testConn.prepareStatement(sql2);
            assertEquals(2, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            if (cachedSPS) {
                assertSame(testPstmt, testPstmt2);
            } else {
                assertNotSame(testPstmt, testPstmt2);
            }
            // Don't cache this PS (*).
            testPstmt1.setPoolable(false);
            // Doesn't cache this PS (*).
            testPstmt1.close();
            assertEquals(1, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            // Don't cache this PS (*).
            testPstmt2.setPoolable(false);
            // Doesn't cache this PS (*).
            testPstmt2.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
            testConn.close();
            assertEquals(0, testConn.getActiveStatementCount());
            assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
        }
    } while ((useSPS = !useSPS) || (cachePS = !cachePS));
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) BaseTestCase(testsuite.BaseTestCase) Connection(java.sql.Connection) CharArrayReader(java.io.CharArrayReader) Time(java.sql.Time) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) MysqlType(com.mysql.cj.MysqlType) ZonedDateTime(java.time.ZonedDateTime) Assertions.assertNotEquals(org.junit.jupiter.api.Assertions.assertNotEquals) BigDecimal(java.math.BigDecimal) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) ByteArrayInputStream(java.io.ByteArrayInputStream) ResultSet(java.sql.ResultSet) SslMode(com.mysql.cj.conf.PropertyDefinitions.SslMode) LocalTime(java.time.LocalTime) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) CharsetMappingWrapper(com.mysql.cj.CharsetMappingWrapper) NClob(java.sql.NClob) ZoneOffset(java.time.ZoneOffset) OffsetTime(java.time.OffsetTime) MySQLStatementCancelledException(com.mysql.cj.jdbc.exceptions.MySQLStatementCancelledException) Timestamp(java.sql.Timestamp) ParameterBindings(com.mysql.cj.jdbc.ParameterBindings) Reader(java.io.Reader) Assertions.assertNotSame(org.junit.jupiter.api.Assertions.assertNotSame) PreparedStatement(java.sql.PreparedStatement) Test(org.junit.jupiter.api.Test) OffsetDateTime(java.time.OffsetDateTime) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) LocalDate(java.time.LocalDate) CallableStatement(java.sql.CallableStatement) MySQLTimeoutException(com.mysql.cj.jdbc.exceptions.MySQLTimeoutException) ResultSetMetaData(java.sql.ResultSetMetaData) Types(java.sql.Types) Assertions.fail(org.junit.jupiter.api.Assertions.fail) MysqlErrorNumbers(com.mysql.cj.exceptions.MysqlErrorNumbers) ServerPreparedStatement(com.mysql.cj.jdbc.ServerPreparedStatement) CountingReBalanceStrategy(testsuite.regression.ConnectionRegressionTest.CountingReBalanceStrategy) ByteArrayOutputStream(java.io.ByteArrayOutputStream) BatchUpdateException(java.sql.BatchUpdateException) LocalDateTime(java.time.LocalDateTime) SimpleDateFormat(java.text.SimpleDateFormat) Callable(java.util.concurrent.Callable) Function(java.util.function.Function) JDBCType(java.sql.JDBCType) SQLException(java.sql.SQLException) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) ClientPreparedStatement(com.mysql.cj.jdbc.ClientPreparedStatement) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Properties(java.util.Properties) ToIntFunction(java.util.function.ToIntFunction) ConnectionImpl(com.mysql.cj.jdbc.ConnectionImpl) LRUCache(com.mysql.cj.util.LRUCache) ServerStatusDiffInterceptor(com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor) Field(java.lang.reflect.Field) TimeUtil(com.mysql.cj.util.TimeUtil) Assertions.assertSame(org.junit.jupiter.api.Assertions.assertSame) Date(java.sql.Date) AfterEach(org.junit.jupiter.api.AfterEach) StringReader(java.io.StringReader) DateTimeFormatter(java.time.format.DateTimeFormatter) Statement(java.sql.Statement) StringUtils(com.mysql.cj.util.StringUtils) MysqlConnection(com.mysql.cj.MysqlConnection) PropertyKey(com.mysql.cj.conf.PropertyKey) InputStream(java.io.InputStream) SQLException(java.sql.SQLException) Connection(java.sql.Connection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) PreparedStatement(java.sql.PreparedStatement) ServerPreparedStatement(com.mysql.cj.jdbc.ServerPreparedStatement) ClientPreparedStatement(com.mysql.cj.jdbc.ClientPreparedStatement) Properties(java.util.Properties) Field(java.lang.reflect.Field) LRUCache(com.mysql.cj.util.LRUCache) ServerPreparedStatement(com.mysql.cj.jdbc.ServerPreparedStatement) Test(org.junit.jupiter.api.Test)

Example 98 with JdbcConnection

use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.

the class ConnectionProxy method autodetectClusterAndCreateProxyInstance.

/**
 * Checks if connection is associated with Aurora cluster and instantiates a new
 * AuroraConnectionProxy if needed. Otherwise it returns a single-host connection.
 *
 * @param connectionUrl {@link ConnectionUrl} instance containing the lists of hosts available to
 *     switch on.
 * @throws SQLException if an error occurs
 */
public static JdbcConnection autodetectClusterAndCreateProxyInstance(ConnectionUrl connectionUrl) throws SQLException {
    boolean pluginsEnabled = Boolean.parseBoolean(connectionUrl.getConnectionArgumentsAsProperties().getProperty(PropertyKey.useConnectionPlugins.getKeyName(), Boolean.toString(true)));
    if (pluginsEnabled) {
        final ConnectionProxy connProxy = new ConnectionProxy(connectionUrl);
        return (JdbcConnection) java.lang.reflect.Proxy.newProxyInstance(JdbcConnection.class.getClassLoader(), new Class<?>[] { JdbcConnection.class }, connProxy);
    }
    final IConnectionProvider connectionProvider = new BasicConnectionProvider();
    return connectionProvider.connect(connectionUrl.getMainHost());
}
Also used : JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) BasicConnectionProvider(com.mysql.cj.jdbc.ha.plugins.BasicConnectionProvider) IConnectionProvider(com.mysql.cj.jdbc.ha.plugins.IConnectionProvider)

Example 99 with JdbcConnection

use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.

the class ConnectionRegressionTest method testExpiredPassword.

@Test
public void testExpiredPassword() throws Exception {
    assumeTrue(versionMeetsMinimum(5, 6, 10), "MySQL 5.6.10+ is required to run this test.");
    Connection testConn = null;
    Statement testSt = null;
    ResultSet testRs = null;
    Properties urlProps = getPropertiesFromTestsuiteUrl();
    String dbname = urlProps.getProperty(PropertyKey.DBNAME.getKeyName());
    try {
        createUser("'must_change1'@'%'", "IDENTIFIED BY 'aha'");
        this.stmt.executeUpdate("grant all on `" + dbname + "`.* to 'must_change1'@'%'");
        createUser("'must_change2'@'%'", "IDENTIFIED BY 'aha'");
        this.stmt.executeUpdate("grant all on `" + dbname + "`.* to 'must_change2'@'%'");
        // workaround for Bug#77732
        if (versionMeetsMinimum(5, 7, 6) && !versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("GRANT SELECT ON `performance_schema`.`session_variables` TO 'must_change1'@'%'");
            this.stmt.executeUpdate("GRANT SELECT ON `performance_schema`.`session_variables` TO 'must_change2'@'%'");
        }
        this.stmt.executeUpdate(versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'must_change1'@'%', 'must_change2'@'%' PASSWORD EXPIRE" : "ALTER USER 'must_change1'@'%' PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
        Properties props = new Properties();
        props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        // ALTER USER can be prepared as of 5.6.8 (BUG#14646014)
        if (versionMeetsMinimum(5, 6, 8)) {
            props.setProperty(PropertyKey.useServerPrepStmts.getKeyName(), "true");
            testConn = getConnectionWithProps(props);
            this.pstmt = testConn.prepareStatement(versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'must_change1'@'%', 'must_change2'@'%' PASSWORD EXPIRE" : "ALTER USER 'must_change1'@'%' PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
            this.pstmt.executeUpdate();
            this.pstmt.close();
            this.pstmt = testConn.prepareStatement(versionMeetsMinimum(5, 7, 6) ? "ALTER USER ?, 'must_change2'@'%' PASSWORD EXPIRE" : "ALTER USER ? PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
            this.pstmt.setString(1, "must_change1");
            this.pstmt.executeUpdate();
            this.pstmt.close();
            testConn.close();
        }
        props.setProperty(PropertyKey.USER.getKeyName(), "must_change1");
        props.setProperty(PropertyKey.PASSWORD.getKeyName(), "aha");
        try {
            testConn = getConnectionWithProps(props);
            fail("SQLException expected due to password expired");
        } catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e1) {
            if ((e1 instanceof SQLException && (((SQLException) e1).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || ((SQLException) e1).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN)) || e1 instanceof PasswordExpiredException || e1 instanceof ClosedOnExpiredPasswordException) {
                props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "false");
                try {
                    testConn = getConnectionWithProps(props);
                    testSt = testConn.createStatement();
                    testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
                    testRs.close();
                    fail("SQLException expected due to password expired");
                } catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e3) {
                    if (e3 instanceof SQLException && (((SQLException) e3).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) || e3 instanceof ClosedOnExpiredPasswordException) {
                        testSt.close();
                        testConn = getConnectionWithProps(props);
                        testSt = testConn.createStatement();
                    }
                    if (testSt == null) {
                        testSt = testConn.createStatement();
                    }
                    testSt.executeUpdate(versionMeetsMinimum(5, 7, 6) ? "ALTER USER USER() IDENTIFIED BY 'newpwd'" : "SET PASSWORD = PASSWORD('newpwd')");
                    testConn.close();
                    props.setProperty(PropertyKey.USER.getKeyName(), "must_change1");
                    props.setProperty(PropertyKey.PASSWORD.getKeyName(), "newpwd");
                    props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "true");
                    testConn = getConnectionWithProps(props);
                    testSt = testConn.createStatement();
                    testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
                    assertTrue(testRs.next());
                    // change user
                    try {
                        ((JdbcConnection) testConn).changeUser("must_change2", "aha");
                        fail("SQLException expected due to password expired");
                    } catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e4) {
                        if (e4 instanceof SQLException && (((SQLException) e4).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || ((SQLException) e4).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) || e4 instanceof PasswordExpiredException || e4 instanceof ClosedOnExpiredPasswordException) {
                            props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "false");
                            testConn = getConnectionWithProps(props);
                            try {
                                ((JdbcConnection) testConn).changeUser("must_change2", "aha");
                                testSt = testConn.createStatement();
                                testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
                                fail("SQLException expected due to password expired");
                            } catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e5) {
                                if (e5 instanceof SQLException && ((SQLException) e5).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN || e5 instanceof ClosedOnExpiredPasswordException) {
                                    testConn = getConnectionWithProps(props);
                                    testSt = testConn.createStatement();
                                }
                                testSt = testConn.createStatement();
                                testSt.executeUpdate(versionMeetsMinimum(5, 7, 6) ? "ALTER USER USER() IDENTIFIED BY 'newpwd'" : "SET PASSWORD = PASSWORD('newpwd')");
                                testConn.close();
                                props.setProperty(PropertyKey.USER.getKeyName(), "must_change2");
                                props.setProperty(PropertyKey.PASSWORD.getKeyName(), "newpwd");
                                props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "true");
                                testConn = getConnectionWithProps(props);
                                testSt = testConn.createStatement();
                                testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
                                assertTrue(testRs.next());
                            }
                        } else {
                            throw e4;
                        }
                    }
                }
            } else {
                throw e1;
            }
        }
    } finally {
        if (testRs != null) {
            testRs.close();
        }
        if (testSt != null) {
            testSt.close();
        }
        if (testConn != null) {
            testConn.close();
        }
    }
}
Also used : PasswordExpiredException(com.mysql.cj.exceptions.PasswordExpiredException) SQLException(java.sql.SQLException) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) ServerPreparedStatement(com.mysql.cj.jdbc.ServerPreparedStatement) ClientPreparedStatement(com.mysql.cj.jdbc.ClientPreparedStatement) ReplicationConnection(com.mysql.cj.jdbc.ha.ReplicationConnection) MysqlPooledConnection(com.mysql.cj.jdbc.MysqlPooledConnection) SuspendableXAConnection(com.mysql.cj.jdbc.SuspendableXAConnection) Connection(java.sql.Connection) XAConnection(javax.sql.XAConnection) PooledConnection(javax.sql.PooledConnection) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) ResultSet(java.sql.ResultSet) ClosedOnExpiredPasswordException(com.mysql.cj.exceptions.ClosedOnExpiredPasswordException) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) Properties(java.util.Properties) Test(org.junit.jupiter.api.Test)

Example 100 with JdbcConnection

use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.

the class ConnectionRegressionTest method subTestBug22848249D.

/*
     * Tests adding hosts from the connection group without affecting current active connections.
     */
private void subTestBug22848249D() throws Exception {
    final String defaultHost = getPropertiesFromTestsuiteUrl().getProperty(PropertyKey.HOST.getKeyName());
    final String defaultPort = getPropertiesFromTestsuiteUrl().getProperty(PropertyKey.PORT.getKeyName());
    final String host1 = "first";
    final String host2 = "second";
    final String host3 = "third";
    final String host4 = "fourth";
    final String hostPort1 = host1 + ":" + defaultPort;
    final String hostPort2 = host2 + ":" + defaultPort;
    final String hostPort3 = host3 + ":" + defaultPort;
    final String hostPort4 = host4 + ":" + defaultPort;
    final String lbConnGroup = "Bug22848249D";
    System.out.println("testBug22848249D:");
    System.out.println("********************************************************************************");
    /*
         * Initial connection will be able to use only the hosts available when it was initialized, even after adding new ones to the connection group.
         */
    Properties props = new Properties();
    props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
    props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
    props.setProperty(PropertyKey.loadBalanceHostRemovalGracePeriod.getKeyName(), "0");
    props.setProperty(PropertyKey.loadBalanceConnectionGroup.getKeyName(), lbConnGroup);
    Connection testConn = getUnreliableLoadBalancedConnection(new String[] { host1, host2 }, props);
    testConn.setAutoCommit(false);
    String connectedHost = ((JdbcConnection) testConn).getHost();
    assertConnectionsHistory(UnreliableSocketFactory.getHostConnectedStatus(connectedHost));
    assertEquals(2, ConnectionGroupManager.getActiveHostCount(lbConnGroup));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort1));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort2));
    // Add two hosts.
    UnreliableSocketFactory.mapHost(host3, defaultHost);
    ConnectionGroupManager.addHost(lbConnGroup, hostPort3, false);
    UnreliableSocketFactory.mapHost(host4, defaultHost);
    ConnectionGroupManager.addHost(lbConnGroup, hostPort4, false);
    assertEquals(4, ConnectionGroupManager.getActiveHostCount(lbConnGroup));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort1));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort2));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort3));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort4));
    // Force some transaction boundaries and check that the new hosts aren't used.
    int connectionSwaps = 0;
    for (int i = 0; i < 100; i++) {
        testConn.rollback();
        String newConnectedHost = ((JdbcConnection) testConn).getHost();
        assertFalse(newConnectedHost.equals(host3));
        assertFalse(newConnectedHost.equals(host4));
        if (!connectedHost.equals(newConnectedHost)) {
            connectedHost = newConnectedHost;
            connectionSwaps++;
        }
    }
    System.out.println("\t1. Swapped connections " + connectionSwaps + " times out of 100, without hitting the newly added host(s).");
    // Non-deterministic, but something must be wrong if there are no swaps after 100 transaction boundaries.
    assertTrue(connectionSwaps > 0);
    // Make sure the connection is working fine.
    this.rs = testConn.createStatement().executeQuery("SELECT 'testBug22848249'");
    assertTrue(this.rs.next());
    assertEquals("testBug22848249", this.rs.getString(1));
    testConn.close();
    /*
         * New connection will be able to use all hosts.
         */
    testConn = getUnreliableLoadBalancedConnection(new String[] { host1, host2, host3, host4 }, props);
    testConn.setAutoCommit(false);
    connectedHost = ((JdbcConnection) testConn).getHost();
    assertConnectionsHistory(UnreliableSocketFactory.getHostConnectedStatus(connectedHost));
    assertEquals(4, ConnectionGroupManager.getActiveHostCount(lbConnGroup));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort1));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort2));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort3));
    assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort4));
    // Force some transaction boundaries while checking that the removed hosts are never used.
    connectionSwaps = 0;
    Set<String> hostsUsed = new HashSet<>();
    for (int i = 0; i < 100 && hostsUsed.size() < 4; i++) {
        testConn.rollback();
        String newConnectedHost = ((JdbcConnection) testConn).getHost();
        if (!connectedHost.equals(newConnectedHost)) {
            hostsUsed.add(newConnectedHost);
            connectedHost = newConnectedHost;
            connectionSwaps++;
        }
    }
    System.out.println("\t2. Swapped connections " + connectionSwaps + " times out of 100 or before using all hosts.");
    // Non-deterministic, but something must be wrong if there are no swaps after 100 transaction boundaries.
    assertTrue(connectionSwaps > 0);
    assertEquals(4, hostsUsed.size());
    // Make sure the connection is working fine.
    this.rs = testConn.createStatement().executeQuery("SELECT 'testBug22848249'");
    assertTrue(this.rs.next());
    assertEquals("testBug22848249", this.rs.getString(1));
    testConn.close();
}
Also used : ReplicationConnection(com.mysql.cj.jdbc.ha.ReplicationConnection) MysqlPooledConnection(com.mysql.cj.jdbc.MysqlPooledConnection) SuspendableXAConnection(com.mysql.cj.jdbc.SuspendableXAConnection) Connection(java.sql.Connection) XAConnection(javax.sql.XAConnection) PooledConnection(javax.sql.PooledConnection) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) Properties(java.util.Properties) HashSet(java.util.HashSet)

Aggregations

JdbcConnection (com.mysql.cj.jdbc.JdbcConnection)280 Properties (java.util.Properties)216 Test (org.junit.jupiter.api.Test)207 Connection (java.sql.Connection)175 MysqlConnection (com.mysql.cj.MysqlConnection)149 XAConnection (javax.sql.XAConnection)100 SQLException (java.sql.SQLException)97 ReplicationConnection (com.mysql.cj.jdbc.ha.ReplicationConnection)96 PooledConnection (javax.sql.PooledConnection)90 MysqlPooledConnection (com.mysql.cj.jdbc.MysqlPooledConnection)81 MysqlXAConnection (com.mysql.cj.jdbc.MysqlXAConnection)79 SuspendableXAConnection (com.mysql.cj.jdbc.SuspendableXAConnection)78 Statement (java.sql.Statement)77 ServerPreparedStatement (com.mysql.cj.jdbc.ServerPreparedStatement)66 PreparedStatement (java.sql.PreparedStatement)66 ResultSet (java.sql.ResultSet)65 ClientPreparedStatement (com.mysql.cj.jdbc.ClientPreparedStatement)60 CommunicationsException (com.mysql.cj.jdbc.exceptions.CommunicationsException)60 IOException (java.io.IOException)54 SQLFeatureNotSupportedException (java.sql.SQLFeatureNotSupportedException)45