| // SPDX-License-Identifier: LGPL-2.1-or-later |
| // Copyright (c) 2012-2014 Monty Program Ab |
| // Copyright (c) 2015-2021 MariaDB Corporation Ab |
| |
| package org.mariadb.jdbc.integration; |
| |
| import static org.junit.jupiter.api.Assertions.*; |
| |
| import java.io.ByteArrayInputStream; |
| import java.math.BigDecimal; |
| import java.sql.*; |
| import java.time.LocalDate; |
| import java.time.LocalDateTime; |
| import java.util.Random; |
| import org.junit.jupiter.api.*; |
| import org.mariadb.jdbc.Connection; |
| import org.mariadb.jdbc.MariaDbBlob; |
| import org.mariadb.jdbc.Statement; |
| |
| public class PreparedStatementTest extends Common { |
| |
| @AfterAll |
| public static void drop() throws SQLException { |
| Statement stmt = sharedConn.createStatement(); |
| stmt.execute("DROP TABLE IF EXISTS prepare1"); |
| stmt.execute("DROP TABLE IF EXISTS prepare2"); |
| stmt.execute("DROP TABLE IF EXISTS prepare3"); |
| stmt.execute("DROP TABLE IF EXISTS prepare4"); |
| } |
| |
| @BeforeAll |
| public static void beforeAll2() throws SQLException { |
| drop(); |
| Statement stmt = sharedConn.createStatement(); |
| stmt.execute("CREATE TABLE prepare1 (t1 int not null primary key auto_increment, t2 int)"); |
| stmt.execute("CREATE TABLE prepare2 (t1 int not null primary key auto_increment, t2 int)"); |
| stmt.execute("CREATE TABLE prepare3 (t1 LONGTEXT, t2 LONGTEXT, t3 LONGTEXT, t4 LONGTEXT)"); |
| stmt.execute("CREATE TABLE prepare4 (t1 int)"); |
| stmt.execute("INSERT INTO prepare4 VALUES (1),(2),(3),(4),(5)"); |
| createSequenceTables(); |
| } |
| |
| @Test |
| public void prep() throws SQLException { |
| try (PreparedStatement stmt = sharedConn.prepareStatement("SELECT ?")) { |
| assertEquals(ResultSet.TYPE_FORWARD_ONLY, stmt.getResultSetType()); |
| assertEquals(ResultSet.CONCUR_READ_ONLY, stmt.getResultSetConcurrency()); |
| assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, stmt.getResultSetHoldability()); |
| assertEquals(sharedConn, stmt.getConnection()); |
| } |
| |
| try (PreparedStatement stmt = |
| sharedConn.prepareStatement( |
| "SELECT ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) { |
| assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, stmt.getResultSetType()); |
| assertEquals(ResultSet.CONCUR_UPDATABLE, stmt.getResultSetConcurrency()); |
| assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, stmt.getResultSetHoldability()); |
| assertEquals(sharedConn, stmt.getConnection()); |
| } |
| |
| try (PreparedStatement stmt = |
| sharedConn.prepareStatement( |
| "SELECT ?", |
| ResultSet.TYPE_SCROLL_INSENSITIVE, |
| ResultSet.CONCUR_UPDATABLE, |
| ResultSet.CLOSE_CURSORS_AT_COMMIT)) { |
| assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, stmt.getResultSetType()); |
| assertEquals(ResultSet.CONCUR_UPDATABLE, stmt.getResultSetConcurrency()); |
| // not supported |
| assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, stmt.getResultSetHoldability()); |
| assertEquals(sharedConn, stmt.getConnection()); |
| } |
| } |
| |
| @Test |
| public void execute() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| execute(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| execute(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts&cachePrepStmts=false")) { |
| execute(con); |
| } |
| } |
| |
| private void execute(Connection conn) throws SQLException { |
| Statement stmt = conn.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = |
| conn.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| |
| assertFalse(preparedStatement.execute()); |
| |
| ParameterMetaData paramMeta = preparedStatement.getParameterMetaData(); |
| paramMeta.getParameterTypeName(1); |
| paramMeta = preparedStatement.getParameterMetaData(); |
| paramMeta.getParameterTypeName(1); |
| |
| // verification |
| ResultSet rs = stmt.executeQuery("SELECT * FROM prepare1"); |
| assertTrue(rs.next()); |
| assertEquals(5, rs.getInt(1)); |
| assertEquals(10, rs.getInt(2)); |
| assertFalse(rs.next()); |
| |
| // prepare is already done. must only execute. |
| preparedStatement.setInt(1, 7); |
| preparedStatement.setInt(2, 12); |
| assertFalse(preparedStatement.execute()); |
| |
| rs = stmt.executeQuery("SELECT * FROM prepare1 WHERE t1 > 5"); |
| assertTrue(rs.next()); |
| assertEquals(7, rs.getInt(1)); |
| assertEquals(12, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| conn.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| preparedStatement.setInt(1, 4); |
| assertTrue(preparedStatement.execute()); |
| ResultSet rs = preparedStatement.getResultSet(); |
| assertTrue(rs.next()); |
| assertEquals(5, rs.getInt(1)); |
| assertEquals(10, rs.getInt(2)); |
| assertTrue(rs.next()); |
| assertEquals(7, rs.getInt(1)); |
| assertEquals(12, rs.getInt(2)); |
| assertFalse(rs.next()); |
| |
| preparedStatement.setMaxRows(1); |
| preparedStatement.setInt(1, 4); |
| assertTrue(preparedStatement.execute()); |
| rs = preparedStatement.getResultSet(); |
| assertTrue(rs.next()); |
| assertEquals(5, rs.getInt(1)); |
| assertEquals(10, rs.getInt(2)); |
| if (isMariaDBServer()) { |
| // setMaxRows() has no effect for mysql, since not supporting SET STATEMENT SQL_SELECT_LIMIT |
| assertFalse(rs.next()); |
| } |
| } |
| |
| // prepare not cached (length > 8K) |
| StringBuilder sql = new StringBuilder("INSERT INTO prepare1(t1, t2) VALUES (?,?) /*"); |
| for (int i = 0; i < 900; i++) { |
| sql.append("1234567890"); |
| } |
| sql.append("*/"); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = conn.prepareStatement(sql.toString())) { |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| assertFalse(preparedStatement.execute()); |
| |
| ParameterMetaData paramMeta = preparedStatement.getParameterMetaData(); |
| paramMeta.getParameterTypeName(1); |
| paramMeta = preparedStatement.getParameterMetaData(); |
| paramMeta.getParameterTypeName(1); |
| |
| // verification |
| ResultSet rs = stmt.executeQuery("SELECT * FROM prepare1"); |
| assertTrue(rs.next()); |
| assertEquals(5, rs.getInt(1)); |
| assertEquals(10, rs.getInt(2)); |
| assertFalse(rs.next()); |
| |
| // prepare is already done. must only execute. |
| preparedStatement.setInt(1, 7); |
| preparedStatement.setInt(2, 12); |
| assertFalse(preparedStatement.execute()); |
| |
| rs = stmt.executeQuery("SELECT * FROM prepare1 WHERE t1 > 5"); |
| assertTrue(rs.next()); |
| assertEquals(7, rs.getInt(1)); |
| assertEquals(12, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| } |
| |
| @Test |
| public void executeWithoutAllParameters() throws SQLException { |
| executeWithoutAllParameters(sharedConn); |
| executeWithoutAllParameters(sharedConnBinary); |
| } |
| |
| public void executeWithoutAllParameters(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.setInt(2, 10); |
| Common.assertThrowsContains( |
| SQLException.class, |
| preparedStatement::executeUpdate, |
| "Parameter at position 1 is not " + "set"); |
| |
| preparedStatement.setNull(1, Types.VARBINARY); |
| preparedStatement.executeUpdate(); |
| ResultSet rs = stmt.executeQuery("SELECT * FROM prepare1"); |
| assertTrue(rs.next()); |
| assertEquals(1, rs.getInt(1)); |
| assertEquals(10, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| } |
| |
| @Test |
| public void executeUpdate() throws SQLException { |
| Statement stmt = sharedConn.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = |
| sharedConn.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| assertEquals(1, preparedStatement.executeUpdate()); |
| |
| // verification that query without resultset return an empty resultset |
| preparedStatement.clearParameters(); |
| Common.assertThrowsContains( |
| SQLException.class, |
| preparedStatement::executeQuery, |
| "Parameter at position 1 is not set"); |
| preparedStatement.setInt(2, 11); |
| preparedStatement.setInt(1, 6); |
| ResultSet rs0 = preparedStatement.executeQuery(); |
| assertFalse(rs0.next()); |
| |
| // verification |
| ResultSet rs = stmt.executeQuery("SELECT * FROM prepare1"); |
| assertTrue(rs.next()); |
| assertEquals(5, rs.getInt(1)); |
| assertEquals(10, rs.getInt(2)); |
| assertTrue(rs.next()); |
| assertEquals(6, rs.getInt(1)); |
| assertEquals(11, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| sharedConn.prepareStatement("SELECT * FROM prepare1")) { |
| Common.assertThrowsContains( |
| SQLException.class, |
| preparedStatement::executeUpdate, |
| "the given SQL statement produces an unexpected ResultSet object"); |
| } |
| } |
| |
| @Test |
| public void executeQuery() throws SQLException { |
| executeQuery(sharedConn); |
| executeQuery(sharedConnBinary); |
| try (Connection con = createCon("useServerPrepStmts=true&enableSkipMeta=false")) { |
| executeQuery(con); |
| } |
| try (Connection con = createCon("useServerPrepStmts=true&enableSkipMeta=true")) { |
| executeQuery(con); |
| } |
| } |
| |
| @Test |
| public void tryMaybeNotPreparable() throws SQLException { |
| try (Connection con = createCon("useServerPrepStmts")) { |
| try (PreparedStatement prep = con.prepareStatement("CREATE TABLE maybeCreate(id int)")) { |
| prep.execute(); |
| } |
| } finally { |
| sharedConn.createStatement().execute("DROP TABLE IF EXISTS maybeCreate"); |
| } |
| try (Connection con = createCon("useServerPrepStmts")) { |
| try (PreparedStatement prep = |
| con.prepareStatement("CREATE PROCEDURE maybeProc(IN I date) BEGIN SELECT I; END")) { |
| prep.execute(); |
| } |
| } finally { |
| sharedConn.createStatement().execute("DROP PROCEDURE IF EXISTS maybeProc"); |
| } |
| } |
| |
| private void executeQuery(Connection con) throws SQLException { |
| // https://jira.mariadb.org/browse/XPT-282 |
| Assumptions.assumeFalse(isXpand()); |
| Statement stmt = con.createStatement(); |
| stmt.execute("DROP TABLE IF EXISTS prepare10"); |
| stmt.execute("CREATE TABLE prepare10 (t1 int not null primary key auto_increment, t2 int)"); |
| stmt.execute("INSERT INTO prepare10(t1, t2) VALUES (5,10), (40,20), (127,45)"); |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("SELECT * FROM prepare10 WHERE t1 > ?")) { |
| preparedStatement.setInt(1, 20); |
| ResultSet rs = preparedStatement.executeQuery(); |
| assertTrue(rs.next()); |
| assertEquals(40, rs.getInt(1)); |
| assertEquals(20, rs.getInt(2)); |
| assertTrue(rs.next()); |
| assertEquals(127, rs.getInt(1)); |
| assertEquals(45, rs.getInt(2)); |
| assertFalse(rs.next()); |
| Common.assertThrowsContains( |
| SQLException.class, () -> preparedStatement.setInt(-20, 2), "wrong parameter index -20"); |
| |
| preparedStatement.setInt(1, 50); |
| rs = preparedStatement.executeQuery(); |
| assertTrue(rs.next()); |
| assertEquals(127, rs.getInt(1)); |
| assertEquals(45, rs.getInt(2)); |
| assertFalse(rs.next()); |
| Common.assertThrowsContains( |
| SQLException.class, () -> preparedStatement.setInt(-20, 2), "wrong parameter index -20"); |
| stmt.execute("ALTER TABLE prepare10 ADD COLUMN t3 varchar(20) default 'tt'"); |
| preparedStatement.setInt(1, 20); |
| rs = preparedStatement.executeQuery(); |
| assertTrue(rs.next()); |
| assertEquals(40, rs.getInt(1)); |
| assertEquals(20, rs.getInt(2)); |
| assertEquals("tt", rs.getString(3)); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("SELECT * FROM prepare10 WHERE t1 > ?")) { |
| preparedStatement.setInt(1, 20); |
| preparedStatement.executeQuery(); |
| } |
| } |
| |
| @Test |
| public void clearParameters() throws Exception { |
| // error crashing maxscale 6.1.x |
| Assumptions.assumeTrue( |
| !sharedConn.getMetaData().getDatabaseProductVersion().contains("maxScale-6.1.") |
| && !"skysql-ha".equals(System.getenv("srv"))); |
| try (org.mariadb.jdbc.Connection con = createCon("&useServerPrepStmts=false")) { |
| clearParameters(con); |
| } |
| try (org.mariadb.jdbc.Connection con = createCon("&useServerPrepStmts")) { |
| clearParameters(con); |
| } |
| } |
| |
| public void clearParameters(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| preparedStatement.clearParameters(); |
| assertThrows(SQLException.class, preparedStatement::execute); |
| } |
| } |
| |
| @Test |
| public void closeOnCompletion() throws SQLException { |
| PreparedStatement preparedStatement = |
| sharedConn.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?"); |
| Assertions.assertFalse(preparedStatement.isCloseOnCompletion()); |
| preparedStatement.closeOnCompletion(); |
| Assertions.assertTrue(preparedStatement.isCloseOnCompletion()); |
| Assertions.assertFalse(preparedStatement.isClosed()); |
| preparedStatement.setInt(1, 0); |
| ResultSet rs = preparedStatement.executeQuery(); |
| Assertions.assertFalse(rs.isClosed()); |
| Assertions.assertFalse(preparedStatement.isClosed()); |
| rs.close(); |
| Assertions.assertTrue(rs.isClosed()); |
| Assertions.assertTrue(preparedStatement.isClosed()); |
| } |
| |
| @Test |
| public void executeBatch() throws SQLException { |
| executeBatch(sharedConn); |
| executeBatch(sharedConnBinary); |
| try (Connection con = createCon("allowLocalInfile=true")) { |
| executeBatch(con); |
| } |
| try (Connection con = createCon("allowLocalInfile=true&useServerPrepStmts=true")) { |
| executeBatch(con); |
| } |
| } |
| |
| private void executeBatch(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| stmt.execute("START TRANSACTION"); |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| |
| try (PreparedStatement preparedStatement2 = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement2.setInt(1, 15); |
| preparedStatement2.setInt(2, 110); |
| preparedStatement2.addBatch(); |
| preparedStatement2.executeBatch(); |
| } |
| |
| int[] res = preparedStatement.executeBatch(); |
| assertEquals(0, res.length); |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| preparedStatement.addBatch(); |
| res = preparedStatement.executeBatch(); |
| assertEquals(1, res.length); |
| res = preparedStatement.executeBatch(); |
| assertEquals(0, res.length); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.setInt(1, 40); |
| preparedStatement.setInt(2, 20); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 127); |
| preparedStatement.setInt(2, 45); |
| preparedStatement.addBatch(); |
| int[] res = preparedStatement.executeBatch(); |
| assertEquals(2, res.length); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| preparedStatement.setInt(1, 20); |
| ResultSet rs = preparedStatement.executeQuery(); |
| assertTrue(rs.next()); |
| assertEquals(40, rs.getInt(1)); |
| assertEquals(20, rs.getInt(2)); |
| assertTrue(rs.next()); |
| assertEquals(127, rs.getInt(1)); |
| assertEquals(45, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| con.commit(); |
| } |
| |
| @Test |
| public void executeWrongBatch() throws SQLException { |
| executeWrongBatch(sharedConn); |
| executeWrongBatch(sharedConnBinary); |
| try (Connection con = createCon("useBulkStmts=false&useServerPrepStmts=true")) { |
| executeWrongBatch(con); |
| } |
| } |
| |
| private void executeWrongBatch(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| stmt.execute("SET sql_mode = concat(@@sql_mode,',ERROR_FOR_DIVISION_BY_ZERO')"); |
| try (PreparedStatement preparedStatement = con.prepareStatement("SELECT 5/?")) { |
| preparedStatement.setInt(1, 5); |
| preparedStatement.addBatch(); |
| preparedStatement.executeBatch(); |
| |
| preparedStatement.setInt(1, 5); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 0); |
| preparedStatement.addBatch(); |
| try { |
| preparedStatement.executeBatch(); |
| } catch (BatchUpdateException e) { |
| // eat |
| } |
| } |
| } |
| |
| @Test |
| public void executeBatchMultiple() throws SQLException { |
| // xpand don't support DO command |
| Assumptions.assumeFalse(isXpand()); |
| try (Connection con = createCon("allowMultiQueries&useBulkStmts=false")) { |
| executeBatchMultiple(con); |
| } |
| } |
| |
| private void executeBatchMultiple(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?);DO 1")) { |
| int[] res = preparedStatement.executeBatch(); |
| assertEquals(0, res.length); |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| preparedStatement.addBatch(); |
| res = preparedStatement.executeBatch(); |
| assertEquals(1, res.length); |
| res = preparedStatement.executeBatch(); |
| assertEquals(0, res.length); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?);DO 1")) { |
| preparedStatement.setInt(1, 40); |
| preparedStatement.setInt(2, 20); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 127); |
| preparedStatement.setInt(2, 45); |
| preparedStatement.addBatch(); |
| int[] res = preparedStatement.executeBatch(); |
| assertEquals(2, res.length); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| preparedStatement.setInt(1, 20); |
| ResultSet rs = preparedStatement.executeQuery(); |
| assertTrue(rs.next()); |
| assertEquals(40, rs.getInt(1)); |
| assertEquals(20, rs.getInt(2)); |
| assertTrue(rs.next()); |
| assertEquals(127, rs.getInt(1)); |
| assertEquals(45, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| } |
| |
| @Test |
| public void executeLargeBatch() throws SQLException { |
| executeLargeBatch(sharedConn); |
| executeLargeBatch(sharedConnBinary); |
| try (Connection con = createCon("allowLocalInfile=true")) { |
| executeLargeBatch(con); |
| } |
| try (Connection con = createCon("allowLocalInfile=true&useServerPrepStmts=true")) { |
| executeLargeBatch(con); |
| } |
| } |
| |
| private void executeLargeBatch(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.executeLargeBatch(); |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setInt(2, 10); |
| preparedStatement.addBatch(); |
| preparedStatement.executeLargeBatch(); |
| preparedStatement.executeLargeBatch(); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| preparedStatement.setInt(1, 40); |
| preparedStatement.setInt(2, 20); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 127); |
| preparedStatement.setInt(2, 45); |
| preparedStatement.addBatch(); |
| preparedStatement.executeLargeBatch(); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| preparedStatement.setInt(1, 20); |
| ResultSet rs = preparedStatement.executeQuery(); |
| assertTrue(rs.next()); |
| assertEquals(40, rs.getInt(1)); |
| assertEquals(20, rs.getInt(2)); |
| assertTrue(rs.next()); |
| assertEquals(127, rs.getInt(1)); |
| assertEquals(45, rs.getInt(2)); |
| assertFalse(rs.next()); |
| } |
| } |
| |
| @Test |
| public void executeBatchGenerated() throws SQLException { |
| try (PreparedStatement preparedStatement = |
| sharedConn.prepareStatement( |
| "INSERT INTO prepare2(t2) VALUES (?)", java.sql.Statement.RETURN_GENERATED_KEYS)) { |
| preparedStatement.setInt(1, 10); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 20); |
| preparedStatement.addBatch(); |
| preparedStatement.executeBatch(); |
| ResultSet rs = preparedStatement.getGeneratedKeys(); |
| assertTrue(rs.next()); |
| assertEquals(1, rs.getInt(1)); |
| assertTrue(rs.next()); |
| assertEquals(2, rs.getInt(1)); |
| assertFalse(rs.next()); |
| } |
| |
| try (PreparedStatement preparedStatement = |
| sharedConnBinary.prepareStatement( |
| "INSERT INTO prepare2(t2) VALUES (?)", java.sql.Statement.RETURN_GENERATED_KEYS)) { |
| preparedStatement.setInt(1, 10); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 20); |
| preparedStatement.addBatch(); |
| preparedStatement.executeBatch(); |
| ResultSet rs = preparedStatement.getGeneratedKeys(); |
| assertTrue(rs.next()); |
| assertEquals(3, rs.getInt(1)); |
| assertTrue(rs.next()); |
| assertEquals(4, rs.getInt(1)); |
| assertFalse(rs.next()); |
| } |
| |
| try (Connection con = createCon("allowMultiQueries")) { |
| try (PreparedStatement preparedStatement = |
| con.prepareStatement( |
| "INSERT INTO prepare2(t2) VALUES (?);INSERT INTO prepare2(t2) VALUES (?)", |
| java.sql.Statement.RETURN_GENERATED_KEYS)) { |
| preparedStatement.setInt(1, 30); |
| preparedStatement.setInt(2, 50); |
| preparedStatement.execute(); |
| ResultSet rs = preparedStatement.getGeneratedKeys(); |
| assertTrue(rs.next()); |
| assertEquals(5, rs.getInt(1)); |
| assertTrue(rs.next()); |
| assertEquals(6, rs.getInt(1)); |
| assertFalse(rs.next()); |
| |
| preparedStatement.setInt(1, 210); |
| preparedStatement.setInt(2, 110); |
| preparedStatement.addBatch(); |
| preparedStatement.setInt(1, 220); |
| preparedStatement.setInt(2, 220); |
| preparedStatement.addBatch(); |
| preparedStatement.executeBatch(); |
| |
| rs = preparedStatement.getGeneratedKeys(); |
| assertTrue(rs.next()); |
| assertEquals(7, rs.getInt(1)); |
| assertTrue(rs.next()); |
| assertEquals(8, rs.getInt(1)); |
| assertTrue(rs.next()); |
| assertEquals(9, rs.getInt(1)); |
| assertTrue(rs.next()); |
| assertEquals(10, rs.getInt(1)); |
| assertFalse(rs.next()); |
| } |
| } |
| } |
| |
| @Test |
| public void emptyExecuteBatch() throws SQLException { |
| Statement stmt = sharedConn.createStatement(); |
| stmt.execute("TRUNCATE prepare1"); |
| stmt.execute("INSERT INTO prepare1(t1, t2) VALUES (5,10), (40,20), (127,45)"); |
| try (PreparedStatement preparedStatement = |
| sharedConn.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| assertEquals(0, preparedStatement.executeBatch().length); |
| } |
| try (PreparedStatement preparedStatement = |
| sharedConnBinary.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| assertEquals(0, preparedStatement.executeBatch().length); |
| } |
| try (PreparedStatement preparedStatement = |
| sharedConn.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| assertEquals(0, preparedStatement.executeLargeBatch().length); |
| } |
| try (PreparedStatement preparedStatement = |
| sharedConnBinary.prepareStatement("SELECT * FROM prepare1 WHERE t1 > ?")) { |
| assertEquals(0, preparedStatement.executeLargeBatch().length); |
| } |
| } |
| |
| @Test |
| public void moreResults() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| moreResults(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| moreResults(con); |
| } |
| } |
| |
| private void moreResults(Connection con) throws SQLException { |
| // error MXS-3929 for maxscale 6.2.0 |
| Assumptions.assumeTrue( |
| !sharedConn.getMetaData().getDatabaseProductVersion().contains("maxScale-6.2.0")); |
| |
| Statement stmt = con.createStatement(); |
| stmt.execute("DROP PROCEDURE IF EXISTS multi"); |
| stmt.setFetchSize(3); |
| stmt.execute( |
| "CREATE PROCEDURE multi() BEGIN SELECT * from sequence_1_to_10; SELECT * FROM" |
| + " sequence_1_to_10;SELECT 2; END"); |
| stmt.execute("CALL multi()"); |
| Assertions.assertTrue(stmt.getMoreResults()); |
| ResultSet rs = stmt.getResultSet(); |
| int i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| Assertions.assertEquals(11, i); |
| stmt.setFetchSize(3); |
| PreparedStatement prep = con.prepareStatement("CALL multi()"); |
| rs = prep.executeQuery(); |
| Assertions.assertFalse(rs.isClosed()); |
| prep.setFetchSize(0); // force more result to load all remaining result-set |
| Assertions.assertTrue(prep.getMoreResults()); |
| Assertions.assertTrue(rs.isClosed()); |
| rs = prep.getResultSet(); |
| i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| |
| prep.setFetchSize(3); |
| rs = prep.executeQuery(); |
| Assertions.assertFalse(rs.isClosed()); |
| prep.setFetchSize(0); // force more result to load all remaining result-set |
| Assertions.assertTrue(prep.getMoreResults(java.sql.Statement.KEEP_CURRENT_RESULT)); |
| Assertions.assertFalse(rs.isClosed()); |
| i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| Assertions.assertEquals(11, i); |
| rs = prep.getResultSet(); |
| i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| Assertions.assertEquals(11, i); |
| |
| rs = prep.executeQuery(); |
| prep.close(); |
| assertTrue(rs.isClosed()); |
| } |
| |
| @Test |
| public void moreRowLimitedResults() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| moreRowLimitedResults(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| moreRowLimitedResults(con); |
| } |
| } |
| |
| private void moreRowLimitedResults(Connection con) throws SQLException { |
| // error MXS-3929 for maxscale 6.2.0 |
| Assumptions.assumeTrue( |
| !sharedConn.getMetaData().getDatabaseProductVersion().contains("maxScale-6.2.0")); |
| |
| Statement stmt = con.createStatement(); |
| stmt.execute("DROP PROCEDURE IF EXISTS multi"); |
| stmt.setFetchSize(3); |
| stmt.setMaxRows(5); |
| stmt.execute( |
| "CREATE PROCEDURE multi() BEGIN SELECT * from prepare4; SELECT * FROM prepare4;SELECT 2;" |
| + " END"); |
| stmt.execute("CALL multi()"); |
| Assertions.assertTrue(stmt.getMoreResults()); |
| ResultSet rs = stmt.getResultSet(); |
| int i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| Assertions.assertEquals(6, i); |
| stmt.setFetchSize(3); |
| PreparedStatement prep = con.prepareStatement("CALL multi()"); |
| prep.setMaxRows(20); |
| rs = prep.executeQuery(); |
| Assertions.assertFalse(rs.isClosed()); |
| prep.setFetchSize(0); // force more result to load all remaining result-set |
| Assertions.assertTrue(prep.getMoreResults()); |
| Assertions.assertTrue(rs.isClosed()); |
| rs = prep.getResultSet(); |
| i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| |
| prep.setFetchSize(3); |
| prep.setMaxRows(5); |
| rs = prep.executeQuery(); |
| Assertions.assertFalse(rs.isClosed()); |
| prep.setFetchSize(0); // force more result to load all remaining result-set |
| Assertions.assertTrue(prep.getMoreResults(java.sql.Statement.KEEP_CURRENT_RESULT)); |
| Assertions.assertFalse(rs.isClosed()); |
| i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| Assertions.assertEquals(6, i); |
| rs = prep.getResultSet(); |
| i = 1; |
| while (rs.next()) { |
| Assertions.assertEquals(i++, rs.getInt(1)); |
| } |
| Assertions.assertEquals(6, i); |
| |
| rs = prep.executeQuery(); |
| prep.close(); |
| assertTrue(rs.isClosed()); |
| } |
| |
| @Test |
| public void prepareWithError() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| prepareWithError(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| prepareWithError(con); |
| } |
| } |
| |
| private void prepareWithError(Connection con) throws SQLException { |
| Assumptions.assumeTrue(isMariaDBServer()); |
| Statement stmt = con.createStatement(); |
| stmt.execute("DROP TABLE IF EXISTS prepareError"); |
| stmt.setFetchSize(3); |
| stmt.execute("CREATE TABLE prepareError(id int primary key, val varchar(10))"); |
| stmt.execute("INSERT INTO prepareError(id, val) values (1, 'val1')"); |
| try (PreparedStatement prep = |
| con.prepareStatement("INSERT INTO prepareError(id, val) VALUES (?,?)")) { |
| prep.setInt(1, 1); |
| prep.setString(2, "val2"); |
| try { |
| prep.execute(); |
| fail(); |
| } catch (SQLException e) { |
| assertTrue( |
| e.getMessage() |
| .contains("Duplicate key in container: `testj`.`prepareError` Primary key:") |
| || e.getMessage().contains("Duplicate entry '1' for key 'PRIMARY'")); |
| } |
| } |
| try (PreparedStatement prep = con.prepareStatement("Wrong command")) { |
| try { |
| prep.execute(); |
| fail(); |
| } catch (SQLException e) { |
| assertTrue( |
| e.getMessage().contains("syntax error: syntax error near") |
| || e.getMessage().contains("You have an error in your SQL syntax")); |
| } |
| } |
| } |
| |
| @Test |
| public void streamNotFinished() throws SQLException { |
| Statement stmt = sharedConn.createStatement(); |
| stmt.setFetchSize(2); |
| ResultSet rs = stmt.executeQuery("SELECT * FROM sequence_1_to_10"); |
| |
| Statement stmt2 = sharedConn.createStatement(); |
| ResultSet rs2 = stmt2.executeQuery("SELECT 1"); |
| rs2.next(); |
| assertEquals(1, rs2.getInt(1)); |
| for (int i = 1; i <= 10; i++) { |
| rs.next(); |
| assertEquals(i, rs.getInt(1)); |
| } |
| } |
| |
| @Test |
| public void expectedError() throws SQLException { |
| try (PreparedStatement prep = sharedConn.prepareStatement("SELECT ?")) { |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.addBatch("SELECT 1"), |
| "addBatch(String sql) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.execute("SELECT 1"), |
| "execute(String sql) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.execute("SELECT 1", Statement.NO_GENERATED_KEYS), |
| "execute(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.execute("SELECT 1", new int[] {}), |
| "execute(String sql, int[] columnIndexes) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.execute("SELECT 1", new String[] {}), |
| "execute(String sql, String[] columnNames) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeQuery("SELECT 1"), |
| "executeQuery(String sql) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeUpdate("SELECT 1"), |
| "executeUpdate(String sql) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeUpdate("SELECT 1", Statement.NO_GENERATED_KEYS), |
| "executeUpdate(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeUpdate("SELECT 1", new int[] {}), |
| "executeUpdate(String sql, int[] columnIndexes) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeUpdate("SELECT 1", new String[] {}), |
| "executeUpdate(String sql, String[] columnNames) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeLargeUpdate("SELECT 1"), |
| "executeLargeUpdate(String sql) cannot be called on preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeLargeUpdate("SELECT 1", Statement.NO_GENERATED_KEYS), |
| "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on" |
| + " preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeLargeUpdate("SELECT 1", new int[] {}), |
| "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on" |
| + " preparedStatement"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> prep.executeLargeUpdate("SELECT 1", new String[] {}), |
| "executeLargeUpdate(String sql, String[] columnNames) cannot be called on" |
| + " preparedStatement"); |
| } |
| } |
| |
| @Test |
| public void largeMaxRows() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| largeMaxRows(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| largeMaxRows(con); |
| } |
| } |
| |
| private void largeMaxRows(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("DROP TABLE IF EXISTS largeMaxRows"); |
| stmt.setFetchSize(3); |
| stmt.execute("CREATE TABLE largeMaxRows(id int)"); |
| try (PreparedStatement prep = con.prepareStatement("INSERT INTO largeMaxRows(id) VALUE (?)")) { |
| for (int i = 1; i < 51; i++) { |
| prep.setInt(1, i); |
| prep.execute(); |
| } |
| } |
| |
| try (PreparedStatement prep = con.prepareStatement("SELECT * FROM largeMaxRows")) { |
| assertEquals(0L, prep.getLargeMaxRows()); |
| ResultSet rs = prep.executeQuery(); |
| int i = 0; |
| while (rs.next()) { |
| i++; |
| assertEquals(i, rs.getInt(1)); |
| } |
| assertEquals(50, i); |
| |
| try { |
| prep.setLargeMaxRows(-1); |
| Assertions.fail(); |
| } catch (SQLException e) { |
| assertTrue(e.getMessage().contains("max rows cannot be negative")); |
| } |
| prep.setLargeMaxRows(10); |
| assertEquals(10L, prep.getLargeMaxRows()); |
| |
| rs = prep.executeQuery(); |
| i = 0; |
| while (rs.next()) { |
| i++; |
| assertEquals(i, rs.getInt(1)); |
| } |
| assertEquals(10, i); |
| |
| prep.setQueryTimeout(2); |
| rs = prep.executeQuery(); |
| i = 0; |
| while (rs.next()) { |
| i++; |
| assertEquals(i, rs.getInt(1)); |
| } |
| assertEquals(10, i); |
| |
| prep.setQueryTimeout(20); |
| prep.setLargeMaxRows(0); |
| rs = prep.executeQuery(); |
| i = 0; |
| while (rs.next()) { |
| i++; |
| assertEquals(i, rs.getInt(1)); |
| } |
| assertEquals(50, i); |
| prep.setQueryTimeout(0); |
| prep.setQueryTimeout(0); |
| } |
| } |
| |
| @Test |
| public void largeMaxRowsBatch() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| largeMaxRowsBatch(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| largeMaxRowsBatch(con); |
| } |
| } |
| |
| private void prepareInsert(PreparedStatement prep) throws SQLException { |
| prep.setInt(1, 0); |
| prep.addBatch(); |
| prep.setInt(1, 1); |
| prep.addBatch(); |
| prep.executeBatch(); |
| } |
| |
| private void largeMaxRowsBatch(Connection con) throws SQLException { |
| Statement stmt = con.createStatement(); |
| stmt.execute("DROP TABLE IF EXISTS large_max_rows_batch"); |
| stmt.setFetchSize(3); |
| stmt.execute("CREATE TABLE large_max_rows_batch(id int)"); |
| try (PreparedStatement prep = |
| con.prepareStatement("INSERT INTO large_max_rows_batch(id) VALUE (?)")) { |
| prepareInsert(prep); |
| |
| prep.setMaxRows(1); |
| prepareInsert(prep); |
| |
| prep.setQueryTimeout(1); |
| prepareInsert(prep); |
| |
| prep.setMaxRows(0); |
| prepareInsert(prep); |
| |
| prep.setLargeMaxRows(2); |
| prepareInsert(prep); |
| |
| prep.setQueryTimeout(0); |
| prepareInsert(prep); |
| } |
| ResultSet rs = stmt.executeQuery("SELECT count(*) FROM large_max_rows_batch"); |
| rs.next(); |
| assertEquals(12, rs.getInt(1)); |
| } |
| |
| @Test |
| public void decrementCache() throws SQLException { |
| decrementCache("&useServerPrepStmts=true&prepStmtCacheSize=5"); |
| decrementCache("&useServerPrepStmts=true&useServerPrepStmts=false"); |
| } |
| |
| public void decrementCache(String connString) throws SQLException { |
| try (Connection con = createCon(connString)) { |
| PreparedStatement prep = con.prepareStatement("SELECT 1"); |
| prep.execute(); |
| PreparedStatement prep2 = con.prepareStatement("SELECT 1"); |
| prep2.execute(); |
| |
| for (int i = 1; i < 10; i++) { |
| try (PreparedStatement prep1 = con.prepareStatement("SELECT " + i)) { |
| prep1.execute(); |
| prep1.setQueryTimeout(1); |
| } |
| } |
| |
| prep.setQueryTimeout(1); // will close prepare |
| prep.setQueryTimeout(2); // will close prepare |
| prep.execute(); |
| prep.close(); |
| prep2.close(); |
| } |
| } |
| |
| @Test |
| public void prepareStatementConcur() throws SQLException { |
| try (Connection con = createCon("&useServerPrepStmts=false")) { |
| prepareStatementConcur(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts")) { |
| prepareStatementConcur(con); |
| } |
| try (Connection con = createCon("&useServerPrepStmts=false&disablePipeline")) { |
| prepareStatementConcur(con); |
| } |
| } |
| |
| private void prepareStatementConcur(Connection con) throws SQLException { |
| try (PreparedStatement prep = con.prepareStatement("SELECT 1", new int[] {})) { |
| prep.execute(); |
| } |
| |
| try (PreparedStatement prep = con.prepareStatement("SELECT 1", new String[] {})) { |
| prep.execute(); |
| } |
| |
| try (PreparedStatement prep = |
| con.prepareStatement("SELECT 1", Statement.RETURN_GENERATED_KEYS)) { |
| assertEquals(ResultSet.CONCUR_READ_ONLY, prep.getResultSetConcurrency()); |
| assertEquals(ResultSet.TYPE_FORWARD_ONLY, prep.getResultSetType()); |
| prep.execute(); |
| } |
| try (PreparedStatement prep = |
| con.prepareStatement( |
| "SELECT 1", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) { |
| assertEquals(ResultSet.CONCUR_UPDATABLE, prep.getResultSetConcurrency()); |
| assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, prep.getResultSetType()); |
| |
| prep.execute(); |
| } |
| } |
| |
| @Test |
| public void more2BytesParameters() throws Throwable { |
| int[] rnds = new int[100000]; |
| StringBuilder sb = new StringBuilder("select ?"); |
| for (int i = 0; i < 100000; i++) { |
| rnds[i] = (int) (Math.random() * 1000); |
| } |
| for (int i = 1; i < 100000; i++) { |
| sb.append(",?"); |
| } |
| String sql = sb.toString(); |
| |
| try (PreparedStatement st = sharedConnBinary.prepareStatement(sql)) { |
| for (int i = 1; i <= 100000; i++) { |
| st.setInt(i, rnds[i - 1]); |
| } |
| try { |
| st.executeQuery(); |
| fail(); |
| } catch (SQLException e) { |
| assertTrue( |
| e.getMessage().contains("memory exhausted near \",\"") |
| || e.getMessage().contains("Prepared statement contains too many placeholders")); |
| } |
| } |
| assertTrue(sharedConnBinary.isValid(1)); |
| } |
| |
| private String generateLongText(int len) { |
| int leftLimit = 97; // letter 'a' |
| int rightLimit = 122; // letter 'z' |
| Random random = new Random(); |
| return random |
| .ints(leftLimit, rightLimit) |
| .limit(len) |
| .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) |
| .toString(); |
| } |
| |
| @Test |
| public void skippingRes() throws SQLException { |
| int maxAllowedPacket = getMaxAllowedPacket(); |
| Assumptions.assumeTrue(maxAllowedPacket > 35_000_000); |
| skippingRes(sharedConn); |
| skippingRes(sharedConnBinary); |
| try (Connection compressText = |
| createCon("useCompression&maxAllowedPacket=" + maxAllowedPacket)) { |
| skippingRes(compressText); |
| } |
| try (Connection compressBinary = |
| createCon("useCompression&useServerPrepStmts&maxAllowedPacket=" + maxAllowedPacket)) { |
| skippingRes(compressBinary); |
| } |
| } |
| |
| private void skippingRes(java.sql.Connection con) throws SQLException { |
| con.createStatement().execute("TRUNCATE prepare3"); |
| String longText = generateLongText(20_000_000); |
| String mediumText = generateLongText(10_000_000); |
| String smallIntText = generateLongText(60_000); |
| |
| try (PreparedStatement prep = con.prepareStatement("INSERT INTO prepare3 values (?,?,?,?)")) { |
| prep.setString(1, longText); |
| prep.setString(2, mediumText); |
| prep.setString(3, smallIntText); |
| prep.setString(4, "expected"); |
| prep.execute(); |
| } |
| |
| try (PreparedStatement prep = con.prepareStatement("SELECT * FROM prepare3")) { |
| ResultSet rs = prep.executeQuery(); |
| rs.next(); |
| assertEquals("expected", rs.getString(4)); |
| assertEquals(smallIntText, rs.getString(3)); |
| assertEquals(mediumText, rs.getString(2)); |
| assertEquals(longText, rs.getString(1)); |
| } |
| } |
| |
| @Test |
| public void wrongPosition() throws SQLException { |
| try (PreparedStatement prep = sharedConn.prepareStatement("SELECT 1 FROM DUAL WHERE 0=1")) { |
| ResultSet rs = prep.executeQuery(); |
| Common.assertThrowsContains(SQLException.class, () -> rs.getString(1), "wrong row position"); |
| Common.assertThrowsContains( |
| SQLException.class, () -> rs.getString("1"), "wrong row position"); |
| Common.assertThrowsContains( |
| SQLException.class, () -> rs.getObject(1, String.class), "wrong row position"); |
| } |
| try (PreparedStatement prep = sharedConn.prepareStatement("SELECT 1 FROM DUAL")) { |
| ResultSet rs = prep.executeQuery(); |
| rs.next(); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> rs.getString(-1), |
| "Wrong index position. Is -1 but must be in 1-1 range"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> rs.getString(10), |
| "Wrong index position. Is 10 but must be in 1-1 range"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> rs.getObject(-1, String.class), |
| "Wrong index position. Is -1 but must be in 1-1 range"); |
| Common.assertThrowsContains( |
| SQLException.class, |
| () -> rs.getObject(10, String.class), |
| "Wrong index position. Is 10 but must be in 1-1 range"); |
| } |
| } |
| |
| @Test |
| public void prepareStmtToString() throws SQLException { |
| prepareStmtToString(sharedConn, "ClientPreparedStatement"); |
| prepareStmtToString(sharedConnBinary, "ServerPreparedStatement"); |
| } |
| |
| public void prepareStmtToString(java.sql.Connection conn, String prefix) throws SQLException { |
| try (PreparedStatement preparedStatement = |
| conn.prepareStatement("INSERT INTO prepare1(t1, t2) VALUES (?,?)")) { |
| |
| assertEquals( |
| prefix + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[]}", |
| preparedStatement.toString()); |
| |
| preparedStatement.setInt(1, 5); |
| preparedStatement.setLong(2, 10L); |
| assertEquals( |
| prefix + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[5,10]}", |
| preparedStatement.toString()); |
| |
| preparedStatement.setNull(2, Types.VARBINARY); |
| assertEquals( |
| prefix + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[5,null]}", |
| preparedStatement.toString()); |
| preparedStatement.setNull(1, Types.VARBINARY); |
| preparedStatement.setBytes(2, new byte[] {(byte) 'a', (byte) 'b'}); |
| assertEquals( |
| prefix |
| + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[null,_binary 'ab']}", |
| preparedStatement.toString()); |
| |
| preparedStatement.setBlob(1, new MariaDbBlob(new byte[] {0, 1, 2, 3, 4, 5})); |
| preparedStatement.setAsciiStream(2, new ByteArrayInputStream("test3".getBytes())); |
| assertEquals( |
| prefix |
| + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[<interface" |
| + " java.sql.Blob>,<class java.io.InputStream>]}", |
| preparedStatement.toString()); |
| |
| preparedStatement.setObject(1, LocalDateTime.parse("2010-01-12T01:55:12")); |
| preparedStatement.setObject(2, LocalDate.parse("2011-01-01")); |
| assertEquals( |
| prefix |
| + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:['2010-01-12" |
| + " 01:55:12','2011-01-01']}", |
| preparedStatement.toString()); |
| |
| preparedStatement.setBigDecimal(1, new BigDecimal("158.9876543210")); |
| preparedStatement.setString(2, "test"); |
| assertEquals( |
| prefix |
| + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)'," |
| + " parameters:[158.9876543210,'test']}", |
| preparedStatement.toString()); |
| |
| preparedStatement.setString(3, "unusedParam"); |
| assertEquals( |
| prefix |
| + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)'," |
| + " parameters:[158.9876543210,'test','unusedParam']}", |
| preparedStatement.toString()); |
| } |
| } |
| } |