package org.mariadb.jdbc; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.sql.*; import java.util.Properties; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.*; public class StatementTest extends BaseTest { private static final int ER_BAD_FIELD_ERROR = 1054; private static final int ER_NON_INSERTABLE_TABLE = 1471; private static final int ER_NO_SUCH_TABLE = 1146; private static final int ER_CMD_NOT_PERMIT = 1148; private static final int ER_NONUPDATEABLE_COLUMN = 1348; private static final int ER_PARSE_ERROR = 1064; private static final int ER_NO_PARTITION_FOR_GIVEN_VALUE = 1526; private static final int ER_LOAD_DATA_INVALID_COLUMN = 1611; private static final int ER_ADD_PARTITION_NO_NEW_PARTITION = 1514; private static final String ER_BAD_FIELD_ERROR_STATE = "42S22"; private static final String ER_NON_INSERTABLE_TABLE_STATE = "HY000"; private static final String ER_NO_SUCH_TABLE_STATE = "42S02"; private static final String ER_NONUPDATEABLE_COLUMN_STATE = "HY000"; private static final String ER_PARSE_ERROR_STATE = "42000"; private static final String ER_NO_PARTITION_FOR_GIVEN_VALUE_STATE = "HY000"; private static final String ER_LOAD_DATA_INVALID_COLUMN_STATE = "HY000"; private static final String ER_ADD_PARTITION_NO_NEW_PARTITION_STATE = "HY000"; /** * Initializing tables. * * @throws SQLException exception */ @BeforeClass() public static void initClass() throws SQLException { createTable("vendor_code_test", "id int not null primary key auto_increment, test boolean"); createTable("vendor_code_test2", "a INT", "PARTITION BY KEY (a) (PARTITION x0, PARTITION x1)"); createTable("vendor_code_test3", "a INT", "PARTITION BY LIST(a) (PARTITION p0 VALUES IN (1))"); createTable("StatementTestt1", "c1 INT, c2 VARCHAR(255)"); } @Test public void wrapperTest() throws SQLException { try (Statement statement = sharedConnection.createStatement()) { assertTrue(statement.isWrapperFor(Statement.class)); assertFalse(statement.isWrapperFor(SQLException.class)); assertThat(statement.unwrap(Statement.class), equalTo(statement)); try { statement.unwrap(SQLException.class); fail("MariaDbStatement class unwrapped as SQLException class"); } catch (SQLException sqle) { //normal exception } catch (Exception e) { fail(); } } } /** * Conj-90. * * @throws SQLException exception */ @Test public void reexecuteStatementTest() throws SQLException { try (Connection connection = setConnection("&allowMultiQueries=true")) { try (PreparedStatement stmt = connection.prepareStatement("SELECT 1")) { stmt.setFetchSize(Integer.MIN_VALUE); ResultSet rs = stmt.executeQuery(); rs.next(); rs = stmt.executeQuery(); } } } @Test(expected = SQLException.class) public void afterConnectionClosedTest() throws SQLException { Connection conn2 = DriverManager.getConnection("jdbc:mariadb://localhost:3306/test?user=root"); Statement st1 = conn2.createStatement(); st1.close(); conn2.close(); Statement st2 = conn2.createStatement(); assertTrue(false); st2.close(); } @Test public void testColumnsDoNotExist() throws SQLException { try { sharedConnection.createStatement().executeQuery( "select * from vendor_code_test where crazy_column_that_does_not_exist = 1"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { assertEquals(ER_BAD_FIELD_ERROR, sqlException.getErrorCode()); assertEquals(ER_BAD_FIELD_ERROR_STATE, sqlException.getSQLState()); } } @Test public void testNonInsertableTable() throws SQLException { Statement statement = sharedConnection.createStatement(); statement.execute("create or replace view vendor_code_test_view as select id as id1, id as id2, test " + "from vendor_code_test"); try { statement.executeQuery("insert into vendor_code_test_view VALUES (null, null, true)"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { assertEquals(ER_NON_INSERTABLE_TABLE, sqlException.getErrorCode()); assertEquals(ER_NON_INSERTABLE_TABLE_STATE, sqlException.getSQLState()); } } @Test public void testNoSuchTable() throws SQLException, UnsupportedEncodingException { Statement statement = sharedConnection.createStatement(); statement.execute("drop table if exists vendor_code_test_"); try { statement.execute("SELECT * FROM vendor_code_test_"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { if (sqlException.getErrorCode() != ER_NO_SUCH_TABLE && sqlException.getErrorCode() != ER_CMD_NOT_PERMIT) { fail("Wrong error code message"); } assertEquals(ER_NO_SUCH_TABLE_STATE, sqlException.getSQLState()); } } @Test public void testNoSuchTableBatchUpdate() throws SQLException, UnsupportedEncodingException { Statement statement = sharedConnection.createStatement(); statement.execute("drop table if exists vendor_code_test_"); statement.addBatch("INSERT INTO vendor_code_test_ VALUES('dummyValue')"); try { statement.executeBatch(); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { if (sqlException.getErrorCode() != ER_NO_SUCH_TABLE && sqlException.getErrorCode() != ER_CMD_NOT_PERMIT) { fail("Wrong error code message"); } assertEquals(ER_NO_SUCH_TABLE_STATE, sqlException.getSQLState()); } } @Test public void testNonUpdateableColumn() throws SQLException { Statement statement = sharedConnection.createStatement(); statement.execute("create or replace view vendor_code_test_view as select *," + " 1 as derived_column_that_does_no_exist from vendor_code_test"); try { statement.executeQuery("UPDATE vendor_code_test_view SET derived_column_that_does_no_exist = 1"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { assertEquals(ER_NONUPDATEABLE_COLUMN, sqlException.getErrorCode()); assertEquals(ER_NONUPDATEABLE_COLUMN_STATE, sqlException.getSQLState()); } } @Test public void testParseErrorAddPartitionNoNewPartition() throws SQLException { Statement statement = sharedConnection.createStatement(); try { statement.execute("totally_not_a_sql_command_this_cannot_be_parsed"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { assertEquals(ER_PARSE_ERROR, sqlException.getErrorCode()); assertEquals(ER_PARSE_ERROR_STATE, sqlException.getSQLState()); } } @Test public void testAddPartitionNoNewPartition() throws SQLException { Statement statement = sharedConnection.createStatement(); try { statement.execute("ALTER TABLE vendor_code_test2 ADD PARTITION PARTITIONS 0"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { assertEquals(ER_ADD_PARTITION_NO_NEW_PARTITION, sqlException.getErrorCode()); assertEquals(ER_ADD_PARTITION_NO_NEW_PARTITION_STATE, sqlException.getSQLState()); } } @Test public void testNoPartitionForGivenValue() throws SQLException { Statement statement = sharedConnection.createStatement(); statement.execute("INSERT INTO vendor_code_test3 VALUES (1)"); try { statement.execute("INSERT INTO vendor_code_test3 VALUES (2)"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { assertEquals(ER_NO_PARTITION_FOR_GIVEN_VALUE, sqlException.getErrorCode()); assertEquals(ER_NO_PARTITION_FOR_GIVEN_VALUE_STATE, sqlException.getSQLState()); } } @Test public void testLoadDataInvalidColumn() throws SQLException, UnsupportedEncodingException { Statement statement = sharedConnection.createStatement(); try { statement.execute("drop view if exists v2"); } catch (SQLException e) { //if view doesn't exist, and mode throw warning as error } statement.execute("CREATE VIEW v2 AS SELECT 1 + 2 AS c0, c1, c2 FROM StatementTestt1;"); try { MariaDbStatement mysqlStatement; if (statement.isWrapperFor(MariaDbStatement.class)) { mysqlStatement = statement.unwrap(MariaDbStatement.class); } else { throw new RuntimeException("Mariadb JDBC adaptor must be used"); } try { String data = "\"1\", \"string1\"\n" + "\"2\", \"string2\"\n" + "\"3\", \"string3\"\n"; ByteArrayInputStream loadDataInfileFile = new ByteArrayInputStream(data.getBytes("utf-8")); mysqlStatement.setLocalInfileInputStream(loadDataInfileFile); mysqlStatement.executeUpdate("LOAD DATA LOCAL INFILE 'dummyFileName' INTO TABLE v2 " + "FIELDS ESCAPED BY '\\\\' " + "TERMINATED BY ',' " + "ENCLOSED BY '\"'" + "LINES TERMINATED BY '\n' (c0, c2)"); fail("The above statement should result in an exception"); } catch (SQLException sqlException) { if (sqlException.getErrorCode() != ER_LOAD_DATA_INVALID_COLUMN && sqlException.getErrorCode() != ER_NONUPDATEABLE_COLUMN) { fail(); } assertEquals(ER_LOAD_DATA_INVALID_COLUMN_STATE, sqlException.getSQLState()); } } finally { try { statement.execute("drop view if exists v2"); } catch (SQLException e) { //if view doesn't exist, and mode throw warning as error } } } @Test public void statementClose() throws SQLException { Properties infos = new Properties(); infos.put("socketTimeout", 1000); try (Connection connection = createProxyConnection(infos)) { Statement statement = connection.createStatement(); Statement otherStatement = null; try { otherStatement = connection.createStatement(); stopProxy(); otherStatement.execute("SELECT 1"); } catch (SQLException e) { assertTrue(otherStatement.isClosed()); assertTrue(connection.isClosed()); try { statement.execute("SELECT 1"); } catch (SQLException ee) { assertTrue(statement.isClosed()); assertEquals("must be an SQLState 08000 exception", "08000", ee.getSQLState()); } } } } @Test public void closeOnCompletion() throws SQLException { Statement statement = sharedConnection.createStatement(); assertFalse(statement.isCloseOnCompletion()); try (ResultSet rs = statement.executeQuery("SELECT 1")) { statement.closeOnCompletion(); assertTrue(statement.isCloseOnCompletion()); assertFalse(statement.isClosed()); } assertTrue(statement.isClosed()); } @Test public void testFractionalTimeBatch() throws SQLException { Assume.assumeTrue(doPrecisionTest); createTable("testFractionalTimeBatch", "tt TIMESTAMP(6)"); Timestamp currTime = new Timestamp(System.currentTimeMillis()); try (PreparedStatement preparedStatement = sharedConnection.prepareStatement( "INSERT INTO testFractionalTimeBatch (tt) values (?)")) { for (int i = 0; i < 2; i++) { preparedStatement.setTimestamp(1, currTime); preparedStatement.addBatch(); } preparedStatement.executeBatch(); } try (Statement statement = sharedConnection.createStatement()) { try (ResultSet resultSet = statement.executeQuery("SELECT * from testFractionalTimeBatch")) { assertTrue(resultSet.next()); assertEquals(resultSet.getTimestamp(1).getNanos(), currTime.getNanos()); } } } }