Search in sources :

Example 36 with SessionFactory

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

the class TableSelectTest method testBug22038729.

/**
 * Tests fix for Bug#22038729, X DEVAPI: ANY API CALL AFTER A FAILED CALL PROC() RESULTS IN HANG
 * and for duplicate Bug#25575010, X DEVAPI: ANY API CALL AFTER A FAILED SELECT RESULTS IN HANG
 *
 * @throws Exception
 */
@Test
public void testBug22038729() throws Exception {
    final Field pf = CoreSession.class.getDeclaredField("protocol");
    pf.setAccessible(true);
    try {
        sqlUpdate("drop table if exists testBug22038729");
        sqlUpdate("create table testBug22038729 (c1 int, c2 int unsigned, id bigint)");
        sqlUpdate("insert into testBug22038729 values(10, 100, -9223372036854775808)");
        sqlUpdate("insert into testBug22038729 values(11, 11, 9223372036854775806)");
        sqlUpdate("drop procedure if exists testBug22038729p");
        sqlUpdate("create procedure testBug22038729p (in p1 int,IN p2 char(20)) begin select -10;select id+1000 from testBug22038729; end;");
        // XProtocol.readRowOrNull()
        Session sess = new SessionFactory().getSession(this.testProperties);
        Table t1 = sess.getDefaultSchema().getTable("testBug22038729");
        RowResult rows = t1.select("c1-c2").orderBy("c1 DESC").execute();
        assertTrue(rows.hasNext());
        Row r = rows.next();
        assertEquals(0, r.getInt(0));
        assertThrows(XProtocolError.class, "ERROR 1690 \\(22003\\) BIGINT UNSIGNED value is out of range .*", () -> rows.hasNext());
        // It was hanging
        sess.close();
        // XProtocol.readRowOrNull()
        sess = new SessionFactory().getSession(this.testProperties);
        SqlResult rs1 = sess.sql("select c1-c2 from testBug22038729 order by c1 desc").execute();
        assertEquals(0, rs1.fetchOne().getInt(0));
        assertThrows(XProtocolError.class, "ERROR 1690 \\(22003\\) BIGINT UNSIGNED value is out of range .*", () -> rs1.fetchOne());
        // It was hanging
        sess.close();
        // XProtocol.drainRows()
        sess = new SessionFactory().getSession(this.testProperties);
        sess.sql("select c1-c2 from testBug22038729 order by c1 desc").execute();
        XProtocol xp = (XProtocol) pf.get(((SessionImpl) sess).getSession());
        assertThrows(XProtocolError.class, "ERROR 1690 \\(22003\\) BIGINT UNSIGNED value is out of range .*", () -> {
            xp.drainRows();
            return xp;
        });
        // It was hanging
        sess.close();
        sess = new SessionFactory().getSession(this.testProperties);
        SqlResult rs2 = sess.sql("call testBug22038729p(?, ?)").bind(10).bind("X").execute();
        assertTrue(rs2.hasData());
        assertTrue(rs2.hasNext());
        r = rs2.next();
        assertEquals(-10, r.getInt(0));
        assertFalse(rs2.hasNext());
        assertTrue(rs2.nextResult());
        assertTrue(rs2.hasData());
        assertTrue(rs2.hasNext());
        r = rs2.next();
        assertEquals(-9223372036854774808L, r.getLong(0));
        assertThrows(XProtocolError.class, "ERROR 1690 \\(22003\\) BIGINT value is out of range .*", () -> rs2.hasNext());
        // It was hanging
        sess.close();
    } finally {
        sqlUpdate("drop table if exists testBug22038729");
        sqlUpdate("drop procedure if exists testBug22038729p");
    }
}
Also used : SessionFactory(com.mysql.cj.xdevapi.SessionFactory) Field(java.lang.reflect.Field) RowResult(com.mysql.cj.xdevapi.RowResult) Table(com.mysql.cj.xdevapi.Table) SqlResult(com.mysql.cj.xdevapi.SqlResult) Row(com.mysql.cj.xdevapi.Row) XProtocol(com.mysql.cj.protocol.x.XProtocol) SessionImpl(com.mysql.cj.xdevapi.SessionImpl) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Example 37 with SessionFactory

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

the class TableUpdateTest method testPreparedStatements.

@Test
public void testPreparedStatements() {
    assumeTrue(mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.14")), "MySQL 8.0.14+ is required to run this test.");
    try {
        // Prepare test data.
        testPreparedStatementsResetData();
        SessionFactory sf = new SessionFactory();
        /*
             * Test common usage.
             */
        Session testSession = sf.getSession(this.testProperties);
        int sessionThreadId = getThreadId(testSession);
        assertPreparedStatementsCount(sessionThreadId, 0, 1);
        assertPreparedStatementsStatusCounts(testSession, 0, 0, 0);
        Table testTbl1 = testSession.getDefaultSchema().getTable("testPrepareUpdate_1");
        Table testTbl2 = testSession.getDefaultSchema().getTable("testPrepareUpdate_2");
        Table testTbl3 = testSession.getDefaultSchema().getTable("testPrepareUpdate_3");
        Table testTbl4 = testSession.getDefaultSchema().getTable("testPrepareUpdate_4");
        // Initialize several UpdateStatement objects.
        // Update all.
        UpdateStatement testUpdate1 = testTbl1.update().where("true").set("ord", expr("ord * 10"));
        // Criteria with one placeholder.
        UpdateStatement testUpdate2 = testTbl2.update().where("ord >= :n").set("ord", expr("ord * 10"));
        // Criteria with same placeholder repeated.
        UpdateStatement testupdate3 = testTbl3.update().where("ord >= :n AND ord <= :n + 1").set("ord", expr("ord * 10"));
        // Criteria with multiple placeholders.
        UpdateStatement testUpdate4 = testTbl4.update().where("ord >= :n AND ord <= :m").set("ord", expr("ord * 10"));
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate1, 0, -1);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate2, 0, -1);
        assertPreparedStatementsCountsAndId(testSession, 0, testupdate3, 0, -1);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate4, 0, -1);
        // A. Set binds: 1st execute -> non-prepared.
        assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate1, 0, -1);
        assertTestPreparedStatementsResult(testUpdate2.bind("n", 2).execute(), 3, testTbl2.getName(), 1, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate2, 0, -1);
        assertTestPreparedStatementsResult(testupdate3.bind("n", 2).execute(), 2, testTbl3.getName(), 1, 20, 30, 4);
        assertPreparedStatementsCountsAndId(testSession, 0, testupdate3, 0, -1);
        assertTestPreparedStatementsResult(testUpdate4.bind("n", 2).bind("m", 3).execute(), 2, testTbl4.getName(), 1, 20, 30, 4);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate4, 0, -1);
        assertPreparedStatementsStatusCounts(testSession, 0, 0, 0);
        testPreparedStatementsResetData();
        // B. Set orderBy resets execution count: 1st execute -> non-prepared.
        assertTestPreparedStatementsResult(testUpdate1.orderBy("id").execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate1, 0, -1);
        assertTestPreparedStatementsResult(testUpdate2.orderBy("id").execute(), 3, testTbl2.getName(), 1, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate2, 0, -1);
        assertTestPreparedStatementsResult(testupdate3.orderBy("id").execute(), 2, testTbl3.getName(), 1, 20, 30, 4);
        assertPreparedStatementsCountsAndId(testSession, 0, testupdate3, 0, -1);
        assertTestPreparedStatementsResult(testUpdate4.orderBy("id").execute(), 2, testTbl4.getName(), 1, 20, 30, 4);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate4, 0, -1);
        assertPreparedStatementsStatusCounts(testSession, 0, 0, 0);
        testPreparedStatementsResetData();
        // C. Set binds reuse statement: 2nd execute -> prepare + execute.
        assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 1, testUpdate1, 1, 1);
        assertTestPreparedStatementsResult(testUpdate2.bind("n", 3).execute(), 2, testTbl2.getName(), 1, 2, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 2, testUpdate2, 2, 1);
        assertTestPreparedStatementsResult(testupdate3.bind("n", 3).execute(), 2, testTbl3.getName(), 1, 2, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 3, testupdate3, 3, 1);
        assertTestPreparedStatementsResult(testUpdate4.bind("m", 4).execute(), 3, testTbl4.getName(), 1, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate4, 4, 1);
        assertPreparedStatementsStatusCounts(testSession, 4, 4, 0);
        testPreparedStatementsResetData();
        // D. Set binds reuse statement: 3rd execute -> execute.
        assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate1, 1, 2);
        assertTestPreparedStatementsResult(testUpdate2.bind("n", 4).execute(), 1, testTbl2.getName(), 1, 2, 3, 40);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate2, 2, 2);
        assertTestPreparedStatementsResult(testupdate3.bind("n", 1).execute(), 2, testTbl3.getName(), 10, 20, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testupdate3, 3, 2);
        assertTestPreparedStatementsResult(testUpdate4.bind("m", 2).execute(), 1, testTbl4.getName(), 1, 20, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate4, 4, 2);
        assertPreparedStatementsStatusCounts(testSession, 4, 8, 0);
        testPreparedStatementsResetData();
        // E. Set new values deallocates and resets execution count: 1st execute -> deallocate + non-prepared.
        assertTestPreparedStatementsResult(testUpdate1.set("ord", expr("ord * 100")).execute(), 4, testTbl1.getName(), 100, 200, 300, 400);
        assertPreparedStatementsCountsAndId(testSession, 3, testUpdate1, 0, -1);
        assertTestPreparedStatementsResult(testUpdate2.set("ord", expr("ord * 100")).execute(), 1, testTbl2.getName(), 1, 2, 3, 400);
        assertPreparedStatementsCountsAndId(testSession, 2, testUpdate2, 0, -1);
        assertTestPreparedStatementsResult(testupdate3.set("ord", expr("ord * 100")).execute(), 2, testTbl3.getName(), 100, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 1, testupdate3, 0, -1);
        assertTestPreparedStatementsResult(testUpdate4.set("ord", expr("ord * 100")).execute(), 1, testTbl4.getName(), 1, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate4, 0, -1);
        assertPreparedStatementsStatusCounts(testSession, 4, 8, 4);
        testPreparedStatementsResetData();
        // F. No Changes: 2nd execute -> prepare + execute.
        assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 100, 200, 300, 400);
        assertPreparedStatementsCountsAndId(testSession, 1, testUpdate1, 1, 1);
        assertTestPreparedStatementsResult(testUpdate2.execute(), 1, testTbl2.getName(), 1, 2, 3, 400);
        assertPreparedStatementsCountsAndId(testSession, 2, testUpdate2, 2, 1);
        assertTestPreparedStatementsResult(testupdate3.execute(), 2, testTbl3.getName(), 100, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 3, testupdate3, 3, 1);
        assertTestPreparedStatementsResult(testUpdate4.execute(), 1, testTbl4.getName(), 1, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate4, 4, 1);
        assertPreparedStatementsStatusCounts(testSession, 8, 12, 4);
        testPreparedStatementsResetData();
        // G. Set limit for the first time deallocates and re-prepares: 1st execute -> re-prepare + execute.
        assertTestPreparedStatementsResult(testUpdate1.limit(1).execute(), 1, testTbl1.getName(), 100, 2, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate1, 1, 1);
        assertTestPreparedStatementsResult(testUpdate2.limit(1).execute(), 1, testTbl2.getName(), 1, 2, 3, 400);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate2, 2, 1);
        assertTestPreparedStatementsResult(testupdate3.limit(1).execute(), 1, testTbl3.getName(), 100, 2, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testupdate3, 3, 1);
        assertTestPreparedStatementsResult(testUpdate4.limit(1).execute(), 1, testTbl4.getName(), 1, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate4, 4, 1);
        assertPreparedStatementsStatusCounts(testSession, 12, 16, 8);
        testPreparedStatementsResetData();
        // H. Set limit reuse prepared statement: 2nd execute -> execute.
        assertTestPreparedStatementsResult(testUpdate1.limit(2).execute(), 2, testTbl1.getName(), 100, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate1, 1, 2);
        assertTestPreparedStatementsResult(testUpdate2.limit(2).execute(), 1, testTbl2.getName(), 1, 2, 3, 400);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate2, 2, 2);
        assertTestPreparedStatementsResult(testupdate3.limit(2).execute(), 2, testTbl3.getName(), 100, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testupdate3, 3, 2);
        assertTestPreparedStatementsResult(testUpdate4.limit(2).execute(), 1, testTbl4.getName(), 1, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate4, 4, 2);
        assertPreparedStatementsStatusCounts(testSession, 12, 20, 8);
        testPreparedStatementsResetData();
        // I. Set orderBy deallocates and resets execution count, set limit has no effect: 1st execute -> deallocate + non-prepared.
        assertTestPreparedStatementsResult(testUpdate1.orderBy("id").limit(1).execute(), 1, testTbl1.getName(), 100, 2, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 3, testUpdate1, 0, -1);
        assertTestPreparedStatementsResult(testUpdate2.orderBy("id").limit(1).execute(), 1, testTbl2.getName(), 1, 2, 3, 400);
        assertPreparedStatementsCountsAndId(testSession, 2, testUpdate2, 0, -1);
        assertTestPreparedStatementsResult(testupdate3.orderBy("id").limit(1).execute(), 1, testTbl3.getName(), 100, 2, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 1, testupdate3, 0, -1);
        assertTestPreparedStatementsResult(testUpdate4.orderBy("id").limit(1).execute(), 1, testTbl4.getName(), 1, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 0, testUpdate4, 0, -1);
        assertPreparedStatementsStatusCounts(testSession, 12, 20, 12);
        testPreparedStatementsResetData();
        // J. Set limit reuse statement: 2nd execute -> prepare + execute.
        assertTestPreparedStatementsResult(testUpdate1.limit(2).execute(), 2, testTbl1.getName(), 100, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 1, testUpdate1, 1, 1);
        assertTestPreparedStatementsResult(testUpdate2.limit(2).execute(), 1, testTbl2.getName(), 1, 2, 3, 400);
        assertPreparedStatementsCountsAndId(testSession, 2, testUpdate2, 2, 1);
        assertTestPreparedStatementsResult(testupdate3.limit(2).execute(), 2, testTbl3.getName(), 100, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 3, testupdate3, 3, 1);
        assertTestPreparedStatementsResult(testUpdate4.limit(2).execute(), 1, testTbl4.getName(), 1, 200, 3, 4);
        assertPreparedStatementsCountsAndId(testSession, 4, testUpdate4, 4, 1);
        assertPreparedStatementsStatusCounts(testSession, 16, 24, 12);
        testPreparedStatementsResetData();
        testSession.close();
        // Prepared statements won't live past the closing of the session.
        assertPreparedStatementsCount(sessionThreadId, 0, 10);
        /*
             * Test falling back onto non-prepared statements.
             */
        testSession = sf.getSession(this.testProperties);
        int origMaxPrepStmtCount = this.session.sql("SELECT @@max_prepared_stmt_count").execute().fetchOne().getInt(0);
        try {
            // Allow preparing only one more statement.
            this.session.sql("SET GLOBAL max_prepared_stmt_count = ?").bind(getPreparedStatementsCount() + 1).execute();
            sessionThreadId = getThreadId(testSession);
            assertPreparedStatementsCount(sessionThreadId, 0, 1);
            assertPreparedStatementsStatusCounts(testSession, 0, 0, 0);
            testTbl1 = testSession.getDefaultSchema().getTable("testPrepareUpdate_1");
            testTbl2 = testSession.getDefaultSchema().getTable("testPrepareUpdate_2");
            testUpdate1 = testTbl1.update().where("true").set("ord", expr("ord * 10"));
            testUpdate2 = testTbl2.update().where("true").set("ord", expr("ord * 10"));
            // 1st execute -> don't prepare.
            assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
            assertPreparedStatementsCountsAndId(testSession, 0, testUpdate1, 0, -1);
            assertTestPreparedStatementsResult(testUpdate2.execute(), 4, testTbl2.getName(), 10, 20, 30, 40);
            assertPreparedStatementsCountsAndId(testSession, 0, testUpdate2, 0, -1);
            assertPreparedStatementsStatusCounts(testSession, 0, 0, 0);
            testPreparedStatementsResetData();
            // 2nd execute -> prepare + execute.
            assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
            assertPreparedStatementsCountsAndId(testSession, 1, testUpdate1, 1, 1);
            // Fails preparing, execute as non-prepared.
            assertTestPreparedStatementsResult(testUpdate2.execute(), 4, testTbl2.getName(), 10, 20, 30, 40);
            assertPreparedStatementsCountsAndId(testSession, 1, testUpdate2, 0, -1);
            // Failed prepare also counts.
            assertPreparedStatementsStatusCounts(testSession, 2, 1, 0);
            testPreparedStatementsResetData();
            // 3rd execute -> execute.
            assertTestPreparedStatementsResult(testUpdate1.execute(), 4, testTbl1.getName(), 10, 20, 30, 40);
            assertPreparedStatementsCountsAndId(testSession, 1, testUpdate1, 1, 2);
            // Execute as non-prepared.
            assertTestPreparedStatementsResult(testUpdate2.execute(), 4, testTbl2.getName(), 10, 20, 30, 40);
            assertPreparedStatementsCountsAndId(testSession, 1, testUpdate2, 0, -1);
            assertPreparedStatementsStatusCounts(testSession, 2, 2, 0);
            testPreparedStatementsResetData();
            testSession.close();
            // Prepared statements won't live past the closing of the session.
            assertPreparedStatementsCount(sessionThreadId, 0, 10);
        } finally {
            this.session.sql("SET GLOBAL max_prepared_stmt_count = ?").bind(origMaxPrepStmtCount).execute();
        }
    } finally {
        for (int i = 0; i < 4; i++) {
            sqlUpdate("DROP TABLE IF EXISTS testPrepareUpdate_" + (i + 1));
        }
    }
}
Also used : SessionFactory(com.mysql.cj.xdevapi.SessionFactory) UpdateStatement(com.mysql.cj.xdevapi.UpdateStatement) Table(com.mysql.cj.xdevapi.Table) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Aggregations

SessionFactory (com.mysql.cj.xdevapi.SessionFactory)37 Session (com.mysql.cj.xdevapi.Session)35 Test (org.junit.jupiter.api.Test)33 JsonString (com.mysql.cj.xdevapi.JsonString)23 Collection (com.mysql.cj.xdevapi.Collection)21 ExecutionException (java.util.concurrent.ExecutionException)20 WrongArgumentException (com.mysql.cj.exceptions.WrongArgumentException)17 Schema (com.mysql.cj.xdevapi.Schema)16 DocResult (com.mysql.cj.xdevapi.DocResult)8 CoreSession (com.mysql.cj.CoreSession)7 Table (com.mysql.cj.xdevapi.Table)7 DbDoc (com.mysql.cj.xdevapi.DbDoc)6 Row (com.mysql.cj.xdevapi.Row)6 SqlResult (com.mysql.cj.xdevapi.SqlResult)6 RowResult (com.mysql.cj.xdevapi.RowResult)4 SessionImpl (com.mysql.cj.xdevapi.SessionImpl)4 Properties (java.util.Properties)4 DbDocImpl (com.mysql.cj.xdevapi.DbDocImpl)3 FindStatement (com.mysql.cj.xdevapi.FindStatement)3 SelectStatement (com.mysql.cj.xdevapi.SelectStatement)3