diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java index 2d187e505..1266fdac6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java @@ -528,9 +528,25 @@ private void setTypeDefinition(DTV dtv) { if (userProvidesPrecision) { param.typeDefinition = SSType.DECIMAL.toString() + "(" + valueLength + "," + scale + ")"; } - } else - param.typeDefinition = SSType.DECIMAL.toString() + "(" + SQLServerConnection.maxDecimalPrecision - + "," + scale + ")"; + } else { + BigDecimal bigDecimal = null; + if (dtv.getJavaType() == JavaType.BIGDECIMAL + && null != (bigDecimal = (BigDecimal) dtv.getSetterValue())) { + + String[] plainValueArray = bigDecimal.abs().toPlainString().split("\\."); + param.typeDefinition = SSType.DECIMAL.toString() + "(" + + // Precision + (plainValueArray.length == 2 ? plainValueArray[0].length() + + plainValueArray[1].length() : plainValueArray[0].length()) + + "," + + // Scale + (plainValueArray.length == 2 ? plainValueArray[1].length() : 0) + ")"; + + } else { + param.typeDefinition = SSType.DECIMAL.toString() + "(" + + SQLServerConnection.maxDecimalPrecision + "," + scale + ")"; + } + } break; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java index 7b069bba3..5264d6ef9 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java @@ -7,11 +7,11 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.fail; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.StringReader; import java.math.BigDecimal; +import java.math.RoundingMode; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; @@ -78,19 +78,19 @@ public class TCAttentionHandling { + " It is particularly long so that we will get a multipacket TDS response back from the server." + " This is a test string." + " This is a test string." + " This is a test string." + " This is a test string." + " This is a test string." + " This is a test string."; - String tableName = RandomUtil.getIdentifier("TCAttentionHandling"); + String tableName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("TCAttentionHandling")); @BeforeEach public void init() throws Exception { try (Connection con = getConnection()) { con.setAutoCommit(false); try (Statement stmt = con.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 INT, col2 VARCHAR(" + TEST_STRING.length() + "))"); + TestUtils.dropTableIfExists(tableName, stmt); + stmt.executeUpdate( + "CREATE TABLE " + tableName + " (col1 INT, col2 VARCHAR(" + TEST_STRING.length() + "))"); for (int i = 0; i < NUM_TABLE_ROWS; i++) - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1, col2) VALUES (" + i + ", '" + TEST_STRING + "')"); + stmt.executeUpdate( + "INSERT INTO " + tableName + " (col1, col2) VALUES (" + i + ", '" + TEST_STRING + "')"); } con.commit(); } @@ -99,7 +99,7 @@ public void init() throws Exception { @AfterEach public void terminate() throws Exception { try (Statement stmt = connection.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); } } @@ -112,8 +112,7 @@ public void terminate() throws Exception { public void testCancelBeforeExecute() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { stmt.cancel(); - try (ResultSet rs = stmt - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { int numSelectedRows = 0; while (rs.next()) ++numSelectedRows; @@ -134,8 +133,8 @@ public void testCancelBeforeExecute() throws Exception { */ @Test public void testErrorInRequest() throws Exception { - try (Connection con = getConnection(); PreparedStatement ps = con.prepareStatement( - "UPDATE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " SET col2 = ? WHERE col1 = ?")) { + try (Connection con = getConnection(); PreparedStatement ps = con + .prepareStatement("UPDATE " + tableName + " SET col2 = ? WHERE col1 = ?")) { ps.setString(1, TEST_STRING); for (int i = 0; i < MIN_TABLE_ROWS; i++) { ps.setInt(2, i); @@ -219,8 +218,7 @@ public void testCancelLongResponse() throws Exception { } try (ResultSet rs = stmt.executeQuery( - "SELECT " + "a.col1, a.col2 FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " a CROSS JOIN " + AbstractSQLGenerator.escapeIdentifier(tableName) + " b")) { + "SELECT " + "a.col1, a.col2 FROM " + tableName + " a CROSS JOIN " + tableName + " b")) { // Scan the first MIN_TABLE_ROWS rows int numSelectedRows = 0; @@ -297,8 +295,8 @@ public void testCancelBlockedResponse() throws Exception { // and leave it non-responsive for now... conLock.setAutoCommit(false); try (Statement stmtLock = conLock.createStatement()) { - stmtLock.executeUpdate("UPDATE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " SET col2 = 'New Value!' WHERE col1 = " + (NUM_TABLE_ROWS - MIN_TABLE_ROWS)); + stmtLock.executeUpdate("UPDATE " + tableName + " SET col2 = 'New Value!' WHERE col1 = " + + (NUM_TABLE_ROWS - MIN_TABLE_ROWS)); try (Connection con = getConnection()) { // In SQL Azure, both ALLOW_SNAPSHOT_ISOLATION and READ_COMMITTED_SNAPSHOT options @@ -325,8 +323,7 @@ public void testCancelBlockedResponse() throws Exception { try (Statement stmt = con.createStatement(SQLServerResultSet.TYPE_SS_DIRECT_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { ((SQLServerStatement) stmt).setResponseBuffering("adaptive"); - try (ResultSet rs = stmt.executeQuery( - "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { // Time how long it takes for execution to be cancelled... long elapsedMillis = -System.currentTimeMillis(); @@ -389,8 +386,8 @@ public void testCancelBlockedResponsePS() throws Exception { // and leave it non-responsive for now... conLock.setAutoCommit(false); try (Statement stmtLock = conLock.createStatement()) { - stmtLock.executeUpdate("UPDATE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " SET col2 = 'New Value!' WHERE col1 = " + (NUM_TABLE_ROWS - MIN_TABLE_ROWS)); + stmtLock.executeUpdate("UPDATE " + tableName + " SET col2 = 'New Value!' WHERE col1 = " + + (NUM_TABLE_ROWS - MIN_TABLE_ROWS)); try (Connection con = getConnection()) { // In SQL Azure, both ALLOW_SNAPSHOT_ISOLATION and READ_COMMITTED_SNAPSHOT options @@ -413,8 +410,7 @@ public void testCancelBlockedResponsePS() throws Exception { // // Need to use adaptive response buffering when executing the statement. // Otherwise, we would block in executeQuery()... - try (PreparedStatement stmt = con.prepareStatement( - "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName), + try (PreparedStatement stmt = con.prepareStatement("SELECT * FROM " + tableName, SQLServerResultSet.TYPE_SS_DIRECT_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { ((SQLServerStatement) stmt).setResponseBuffering("adaptive"); try (ResultSet rs = stmt.executeQuery()) { @@ -484,8 +480,8 @@ public void testCancelBlockedCursoredResponse() throws Exception { // and leave it non-responsive for now... conLock.setAutoCommit(false); try (Statement stmtLock = conLock.createStatement()) { - stmtLock.executeUpdate("UPDATE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " SET col2 = 'New Value!' WHERE col1 = " + (NUM_TABLE_ROWS - MIN_TABLE_ROWS)); + stmtLock.executeUpdate("UPDATE " + tableName + " SET col2 = 'New Value!' WHERE col1 = " + + (NUM_TABLE_ROWS - MIN_TABLE_ROWS)); try (Connection con = getConnection()) { // In SQL Azure, both ALLOW_SNAPSHOT_ISOLATION and READ_COMMITTED_SNAPSHOT options @@ -503,8 +499,7 @@ public void testCancelBlockedCursoredResponse() throws Exception { con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); } - try (PreparedStatement stmt = con.prepareStatement( - "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName), + try (PreparedStatement stmt = con.prepareStatement("SELECT * FROM " + tableName, SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { // Start up a thread to cancel the following SELECT after 3 seconds of blocking. @@ -565,8 +560,7 @@ public void testCancelBlockedCursoredResponse() throws Exception { public void testCancelAfterResponse() throws Exception { int numSelectedRows; try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - try (ResultSet rs = stmt - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { numSelectedRows = 0; while (rs.next()) ++numSelectedRows; @@ -578,8 +572,7 @@ public void testCancelAfterResponse() throws Exception { stmt.cancel(); // Verify that the query can be re-executed without error - try (ResultSet rs = stmt - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { numSelectedRows = 0; while (rs.next()) ++numSelectedRows; @@ -697,8 +690,7 @@ void start(final Connection con) { final Runnable runner = new Runnable() { public void run() { - try (ResultSet rs = stmt.executeQuery( - "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { while (rs.next()) ++numExecuteSuccesses; @@ -862,8 +854,10 @@ public void testCloseOnCompletion() throws Exception { @Nested public class TCStatement { - private final String table1Name = RandomUtil.getIdentifier("TCStatement1"); - private final String table2Name = RandomUtil.getIdentifier("TCStatement2"); + private final String table1Name = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCStatement1")); + private final String table2Name = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCStatement2")); /** * test statement.closeOnCompltetion method @@ -927,14 +921,13 @@ public void testConsecutiveQueries() throws SQLException { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table1Name), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table2Name), stmt); + TestUtils.dropTableIfExists(table1Name, stmt); + TestUtils.dropTableIfExists(table2Name, stmt); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(table1Name) + " (col1 INT)"); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(table2Name) + " (col1 INT)"); + stmt.executeUpdate("CREATE TABLE " + table1Name + " (col1 INT)"); + stmt.executeUpdate("CREATE TABLE " + table2Name + " (col1 INT)"); - try (ResultSet rs = stmt.executeQuery( - "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(table2Name))) {} catch (Exception e) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + table2Name)) {} catch (Exception e) { assertEquals(stmt.isClosed(), true, TestResource.getResource("R_statementShouldBeClosed")); } } @@ -1062,8 +1055,8 @@ public void testLargeMaxRows() throws Exception { public void terminate() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement();) { try { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table1Name), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table2Name), stmt); + TestUtils.dropTableIfExists(table1Name, stmt); + TestUtils.dropTableIfExists(table2Name, stmt); } catch (SQLException e) {} } } @@ -1071,7 +1064,7 @@ public void terminate() throws Exception { @Nested public class TCStatementCallable { - String procName = RandomUtil.getIdentifier("p1"); + String procName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("p1")); /** * Tests CallableStatementMethods on jdbc41 @@ -1085,10 +1078,10 @@ public void testJdbc41CallableStatementMethods() throws Exception { try (Connection conn = getConnection(); Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { - String query = "create procedure " + AbstractSQLGenerator.escapeIdentifier(procName) - + " @col1Value varchar(512) OUTPUT," + " @col2Value int OUTPUT," + " @col3Value float OUTPUT," - + " @col4Value decimal(10,5) OUTPUT," + " @col5Value uniqueidentifier OUTPUT," - + " @col6Value xml OUTPUT," + " @col7Value varbinary(max) OUTPUT," + " @col8Value text OUTPUT," + String query = "CREATE PROCEDURE " + procName + " @col1Value varchar(512) OUTPUT," + + " @col2Value int OUTPUT," + " @col3Value float OUTPUT," + " @col4Value decimal(10,5) OUTPUT," + + " @col5Value uniqueidentifier OUTPUT," + " @col6Value xml OUTPUT," + + " @col7Value varbinary(max) OUTPUT," + " @col8Value text OUTPUT," + " @col9Value ntext OUTPUT," + " @col10Value varbinary(max) OUTPUT," + " @col11Value date OUTPUT," + " @col12Value time OUTPUT," + " @col13Value datetime2 OUTPUT," + " @col14Value datetimeoffset OUTPUT," + " @col15Value decimal(10,10) OUTPUT," @@ -1105,8 +1098,7 @@ public void testJdbc41CallableStatementMethods() throws Exception { // Test JDBC 4.1 methods for CallableStatement try (CallableStatement cstmt = conn - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) - + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}")) { + .prepareCall("{call " + procName + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}")) { cstmt.registerOutParameter(1, java.sql.Types.VARCHAR); cstmt.registerOutParameter(2, java.sql.Types.INTEGER); cstmt.registerOutParameter("col3Value", java.sql.Types.FLOAT); @@ -1219,7 +1211,7 @@ public void testJdbc41CallableStatementMethods() throws Exception { public void terminate() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { try { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(procName), stmt); + TestUtils.dropProcedureIfExists(procName, stmt); } catch (SQLException e) { fail(e.getMessage()); } @@ -1230,8 +1222,10 @@ public void terminate() throws Exception { @Nested public class TCStatementParam { - private final String tableName = RandomUtil.getIdentifier("TCStatementParam"); - private final String procName = RandomUtil.getIdentifier("TCStatementParam"); + private final String tableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCStatementParam")); + private final String procName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCStatementParam")); /** * @@ -1249,7 +1243,7 @@ public void testStatementOutParamGetsTwice() throws Exception { log.fine("testStatementOutParamGetsTwice threw: " + e.getMessage()); } - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + stmt.executeUpdate("CREATE PROCEDURE " + procName + " ( @p2_smallint smallint, @p3_smallint_out smallint OUTPUT) AS SELECT @p3_smallint_out=@p2_smallint RETURN @p2_smallint + 1"); try (ResultSet rs = stmt.getResultSet()) { @@ -1261,8 +1255,7 @@ public void testStatementOutParamGetsTwice() throws Exception { } } - try (CallableStatement cstmt = con - .prepareCall("{ ? = CALL " + AbstractSQLGenerator.escapeIdentifier(procName) + " (?,?)}")) { + try (CallableStatement cstmt = con.prepareCall("{ ? = CALL " + procName + " (?,?)}")) { cstmt.registerOutParameter(1, Types.INTEGER); cstmt.setObject(2, Short.valueOf("32"), Types.SMALLINT); cstmt.registerOutParameter(3, Types.SMALLINT); @@ -1290,11 +1283,10 @@ public void testStatementOutParamGetsTwice() throws Exception { @Tag(Constants.xAzureSQLDW) public void testStatementOutManyParamGetsTwiceRandomOrder() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + stmt.executeUpdate("CREATE PROCEDURE " + procName + " ( @p2_smallint smallint, @p3_smallint_out smallint OUTPUT, @p4_smallint smallint OUTPUT, @p5_smallint_out smallint OUTPUT) AS SELECT @p3_smallint_out=@p2_smallint, @p5_smallint_out=@p4_smallint RETURN @p2_smallint + 1"); - try (CallableStatement cstmt = con.prepareCall( - "{ ? = CALL " + AbstractSQLGenerator.escapeIdentifier(procName) + " (?,?, ?, ?)}")) { + try (CallableStatement cstmt = con.prepareCall("{ ? = CALL " + procName + " (?,?, ?, ?)}")) { cstmt.registerOutParameter(1, Types.INTEGER); cstmt.setObject(2, Short.valueOf("32"), Types.SMALLINT); cstmt.registerOutParameter(3, Types.SMALLINT); @@ -1324,11 +1316,10 @@ public void testStatementOutManyParamGetsTwiceRandomOrder() throws Exception { @Tag(Constants.xAzureSQLDW) public void testStatementOutParamGetsTwiceInOut() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + stmt.executeUpdate("CREATE PROCEDURE " + procName + " ( @p2_smallint smallint, @p3_smallint_out smallint OUTPUT) AS SELECT @p3_smallint_out=@p3_smallint_out +1 RETURN @p2_smallint + 1"); - try (CallableStatement cstmt = con - .prepareCall("{ ? = CALL " + AbstractSQLGenerator.escapeIdentifier(procName) + " (?,?)}")) { + try (CallableStatement cstmt = con.prepareCall("{ ? = CALL " + procName + " (?,?)}")) { cstmt.registerOutParameter(1, Types.INTEGER); cstmt.setObject(2, Short.valueOf("1"), Types.SMALLINT); cstmt.setObject(3, Short.valueOf("100"), Types.SMALLINT); @@ -1356,20 +1347,15 @@ public void testResultSetParams() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { - stmt.executeUpdate("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 int, col2 text, col3 int identity(1,1))"); - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 'hello')"); - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 'hi')"); - String query = "create procedure " + AbstractSQLGenerator.escapeIdentifier(procName) - + " @col1Value int, @col2Value varchar(512) OUTPUT AS BEGIN SELECT * from " - + AbstractSQLGenerator.escapeIdentifier(tableName) - + " where col1=@col1Value SET @col2Value='hi' END"; + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 int, col2 text, col3 int identity(1,1))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0, 'hello')"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0, 'hi')"); + String query = "CREATE PROCEDURE " + procName + + " @col1Value int, @col2Value varchar(512) OUTPUT AS BEGIN SELECT * FROM " + tableName + + " WHERE col1=@col1Value SET @col2Value='hi' END"; stmt.execute(query); - try (CallableStatement cstmt = con - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?, ?)}")) { + try (CallableStatement cstmt = con.prepareCall("{CALL " + procName + "(?, ?)}")) { cstmt.setInt(1, 0); cstmt.registerOutParameter(2, java.sql.Types.VARCHAR); try (ResultSet rs = cstmt.executeQuery()) { @@ -1392,20 +1378,15 @@ public void testResultSetNullParams() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { - stmt.executeUpdate("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 int, col2 text, col3 int identity(1,1))"); - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 'hello')"); - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 'hi')"); - String query = "create procedure " + AbstractSQLGenerator.escapeIdentifier(procName) - + " @col1Value int, @col2Value varchar(512) OUTPUT AS BEGIN SELECT * from " - + AbstractSQLGenerator.escapeIdentifier(tableName) - + " where col1=@col1Value SET @col2Value='hi' END"; + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 int, col2 text, col3 int identity(1,1))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0, 'hello')"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0, 'hi')"); + String query = "CREATE PROCEDURE " + procName + + " @col1Value int, @col2Value varchar(512) OUTPUT AS BEGIN SELECT * FROM " + tableName + + " WHERE col1=@col1Value SET @col2Value='hi' END"; stmt.execute(query); - try (CallableStatement cstmt = con - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?, ?)}")) { + try (CallableStatement cstmt = con.prepareCall("{CALL " + procName + "(?, ?)}")) { cstmt.setInt(1, 0); try { cstmt.getInt(2); @@ -1425,28 +1406,188 @@ public void testResultSetNullParams() throws Exception { public void testFailedToResumeTransaction() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - stmt.executeUpdate("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 int)"); - stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0)"); - stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(1)"); - stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(2)"); - stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(3)"); - try (PreparedStatement ps = con.prepareStatement("BEGIN TRAN " + "Insert into " - + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(4) " + "ROLLBACK")) {} + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 int)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(1)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(2)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(3)"); + try (PreparedStatement ps = con + .prepareStatement("BEGIN TRAN " + "INSERT INTO " + tableName + " VALUES(4) " + "ROLLBACK")) {} con.setAutoCommit(false); - try (PreparedStatement ps2 = con.prepareStatement( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values('a')")) { + try (PreparedStatement ps2 = con.prepareStatement("INSERT INTO " + tableName + " VALUES('a')")) { try { ps2.execute(); } catch (SQLException e) {} try { - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(4)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(4)"); } catch (SQLException ex) {} } } } + /** + * Tests result of math operation in prepared statement using subtraction + * + * @throws SQLException + * when an error occurs + */ + @Test + public void testMathBigDecimalSubtraction() throws SQLException { + try (Connection con = getConnection(); Statement stmt = con.createStatement()) { + stmt.executeUpdate("CREATE TABLE " + tableName + " (test_column decimal(10,5))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(99999.12345)"); + try (PreparedStatement pstmt = con.prepareStatement("SELECT (test_column - ?), " + + "(test_column - ?), (test_column - ?), (test_column - ?) FROM " + tableName)) { + BigDecimal value1 = new BigDecimal("1.5"); + pstmt.setObject(1, value1); + BigDecimal value2 = new BigDecimal("0"); + pstmt.setObject(2, value2); + BigDecimal value3 = new BigDecimal("99999.12345"); + pstmt.setObject(3, value3); + BigDecimal value4 = new BigDecimal("99999.2"); + pstmt.setObject(4, value4); + + BigDecimal base = new BigDecimal("99999.12345"); + BigDecimal expected1 = base.subtract(value1); + BigDecimal expected2 = base.subtract(value2); + BigDecimal expected3 = base.subtract(value3); + BigDecimal expected4 = base.subtract(value4); + + try (ResultSet rs = pstmt.executeQuery()) { + rs.next(); + assertEquals(expected1, rs.getObject(1)); + assertEquals(expected2, rs.getObject(2)); + assertEquals(expected3, rs.getObject(3)); + assertEquals(expected4, rs.getObject(4)); + } + } + } + } + + /** + * Tests result of math operation in prepared statement using addition + * + * @throws SQLException + * when an error occurs + */ + @Test + public void testMathBigDecimalAddition() throws SQLException { + try (Connection con = getConnection(); Statement stmt = con.createStatement()) { + stmt.executeUpdate("CREATE TABLE " + tableName + " (test_column decimal(10,5))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(99999.12345)"); + try (PreparedStatement pstmt = con.prepareStatement("SELECT (test_column + ?), " + + "(test_column + ?), (test_column + ?), (test_column + ?) FROM " + tableName)) { + BigDecimal value1 = new BigDecimal("1.5"); + pstmt.setObject(1, value1); + BigDecimal value2 = new BigDecimal("0"); + pstmt.setObject(2, value2); + BigDecimal value3 = new BigDecimal("99999.12345"); + pstmt.setObject(3, value3); + BigDecimal value4 = new BigDecimal("99999.2"); + pstmt.setObject(4, value4); + + BigDecimal base = new BigDecimal("99999.12345"); + BigDecimal expected1 = base.add(value1); + BigDecimal expected2 = base.add(value2); + BigDecimal expected3 = base.add(value3); + BigDecimal expected4 = base.add(value4); + + try (ResultSet rs = pstmt.executeQuery()) { + rs.next(); + assertEquals(expected1, rs.getObject(1)); + assertEquals(expected2, rs.getObject(2)); + assertEquals(expected3, rs.getObject(3)); + assertEquals(expected4, rs.getObject(4)); + } + } + } + } + + /** + * Tests result of math operation in prepared statement using multiplication + * + * @throws SQLException + * when an error occurs + */ + @Test + public void testMathBigDecimalMultiplication() throws SQLException { + try (Connection con = getConnection(); Statement stmt = con.createStatement()) { + stmt.executeUpdate("CREATE TABLE " + tableName + " (test_column decimal(10,5))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(99999.12345)"); + try (PreparedStatement pstmt = con.prepareStatement("SELECT (test_column * ?), " + + "(test_column * ?), (test_column * ?), (test_column * ?) FROM " + tableName)) { + BigDecimal value1 = new BigDecimal("1.5"); + pstmt.setObject(1, value1); + BigDecimal value2 = new BigDecimal("0"); + pstmt.setObject(2, value2); + BigDecimal value3 = new BigDecimal("99999.12345"); + pstmt.setObject(3, value3); + BigDecimal value4 = new BigDecimal("99999.2"); + pstmt.setObject(4, value4); + + BigDecimal base = new BigDecimal("99999.12345"); + BigDecimal expected1 = base.multiply(value1); + BigDecimal expected2 = base.multiply(value2); + BigDecimal expected3 = base.multiply(value3); + BigDecimal expected4 = base.multiply(value4); + + try (ResultSet rs = pstmt.executeQuery()) { + rs.next(); + assertEquals(expected1, rs.getObject(1)); + assertEquals(expected2, rs.getObject(2)); + assertEquals(expected3, rs.getObject(3)); + assertEquals(expected4, rs.getObject(4)); + } + } + } + } + + /** + * Tests result of math operation in prepared statement using division + * + * @throws SQLException + * when an error occurs + */ + @Test + public void testMathBigDecimalDivision() throws SQLException { + try (Connection con = getConnection(); Statement stmt = con.createStatement()) { + stmt.executeUpdate("CREATE TABLE " + tableName + " (test_column decimal(10,5))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(99999.12345)"); + try (PreparedStatement pstmt = con.prepareStatement("select (test_column / ?), " + + "(test_column / ?), (test_column / ?), (test_column / ?) FROM " + tableName)) { + + /* + * Division has some unique properties in sql server math operations. + * Notably in this case we cannot compare a result with an infinite trailing decimal + * and the returned value has an expanded precision. + */ + BigDecimal value1 = new BigDecimal("1.5"); + pstmt.setObject(1, value1); + BigDecimal value2 = new BigDecimal("0.1"); + pstmt.setObject(2, value2); + BigDecimal value3 = new BigDecimal("99999.12345"); + pstmt.setObject(3, value3); + BigDecimal value4 = new BigDecimal("1"); + pstmt.setObject(4, value4); + + BigDecimal base = new BigDecimal("99999.12345"); + BigDecimal expected1 = base.divide(value1, RoundingMode.HALF_UP); + BigDecimal expected2 = base.divide(value2, RoundingMode.HALF_UP); + BigDecimal expected3 = base.divide(value3, RoundingMode.HALF_UP); + BigDecimal expected4 = base.divide(value4, RoundingMode.HALF_UP); + + try (ResultSet rs = pstmt.executeQuery()) { + rs.next(); + assertEquals(0, expected1.compareTo((BigDecimal) rs.getObject(1))); + assertEquals(0, expected2.compareTo((BigDecimal) rs.getObject(2))); + assertEquals(0, expected3.compareTo((BigDecimal) rs.getObject(3))); + assertEquals(0, expected4.compareTo((BigDecimal) rs.getObject(4))); + } + } + } + } + /** * * @throws Exception @@ -1457,18 +1598,14 @@ public void testResultSetErrors() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { - stmt.executeUpdate("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 int, col2 text, col3 int identity(1,1))"); - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 'hello')"); - stmt.executeUpdate( - "Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 'hi')"); - String query = "create procedure " + AbstractSQLGenerator.escapeIdentifier(procName) - + " @col1Value int, @col2Value varchar(512) OUTPUT AS BEGIN SELECT * from somenonexistenttable where col1=@col1Value SET @col2Value='hi' END"; + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 int, col2 text, col3 int identity(1,1))"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0, 'hello')"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0, 'hi')"); + String query = "CREATE PROCEDURE " + procName + + " @col1Value int, @col2Value varchar(512) OUTPUT AS BEGIN SELECT * FROM somenonexistenttable WHERE col1=@col1Value SET @col2Value='hi' END"; stmt.execute(query); - try (CallableStatement cstmt = con - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?, ?)}")) { + try (CallableStatement cstmt = con.prepareCall("{CALL " + procName + "(?, ?)}")) { cstmt.setInt(1, 0); cstmt.registerOutParameter(2, Types.VARCHAR); @@ -1487,15 +1624,13 @@ public void testResultSetErrors() throws Exception { public void testRowError() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - stmt.executeUpdate("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (ROWID int IDENTITY, col1 int)"); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0)"); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(1)"); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(2)"); - stmt.execute( - "create procedure " + AbstractSQLGenerator.escapeIdentifier(procName) + " @col1Value int AS " - + " BEGIN " + " SELECT col1 FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " WITH (UPDLOCK) WHERE (col1 = @col1Value) ORDER BY ROWID" + " END"); + stmt.executeUpdate("CREATE TABLE " + tableName + " (ROWID int IDENTITY, col1 int)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(0)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(1)"); + stmt.executeUpdate("INSERT INTO " + tableName + " VALUES(2)"); + stmt.execute("CREATE PROCEDURE " + procName + " @col1Value int AS " + " BEGIN " + + " SELECT col1 FROM " + tableName + + " WITH (UPDLOCK) WHERE (col1 = @col1Value) ORDER BY ROWID" + " END"); // For the test, lock each row in the table, one by one, for update // on one connection and, on another connection, verify that the @@ -1511,8 +1646,7 @@ public void testRowError() throws Exception { // locking it for update. try (Connection testConn1 = getConnection()) { testConn1.setAutoCommit(false); - try (CallableStatement cstmt = testConn1 - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?)}")) { + try (CallableStatement cstmt = testConn1.prepareCall("{CALL " + procName + "(?)}")) { cstmt.setInt(1, row); // enable isCloseOnCompletion @@ -1536,8 +1670,7 @@ public void testRowError() throws Exception { stmt2.executeUpdate("SET LOCK_TIMEOUT 0"); try (CallableStatement cstmt2 = testConn2.prepareCall( - "SELECT col1 FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " WITH (UPDLOCK) ORDER BY ROWID")) { + "SELECT col1 FROM " + tableName + " WITH (UPDLOCK) ORDER BY ROWID")) { // Verify that the result set can be closed after // the lock timeout error @@ -1576,15 +1709,16 @@ public void testRowError() throws Exception { @AfterEach public void terminate() throws SQLException { try (Statement stmt = connection.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(procName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); + TestUtils.dropProcedureIfExists(procName, stmt); } } } @Nested public class TCSparseColumnSetAndNBCROW { - private final String tableName = RandomUtil.getIdentifier("TCStatementSparseColumnSetAndNBCROW"); + private final String tableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCStatementSparseColumnSetAndNBCROW")); private Connection createConnectionAndPopulateData() throws Exception { SQLServerDataSource ds = new SQLServerDataSource(); @@ -1596,9 +1730,9 @@ private Connection createConnectionAndPopulateData() throws Exception { Statement stmt = con.createStatement(); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + stmt.executeUpdate("CREATE TABLE " + tableName + "(col1_int int IDENTITY(1,1), col2_varchar varchar(200), col3_varchar varchar(20) SPARSE NULL, col4_smallint smallint SPARSE NULL, col5_xml XML COLUMN_SET FOR ALL_SPARSE_COLUMNS, col6_nvarcharMax NVARCHAR(MAX), col7_varcharMax VARCHAR(MAX))"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " DEFAULT VALUES"); + stmt.executeUpdate("INSERT INTO " + tableName + " DEFAULT VALUES"); assertTrue(con != null, "connection is null"); return con; @@ -1608,7 +1742,7 @@ private Connection createConnectionAndPopulateData() throws Exception { public void terminate() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { try { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); } catch (SQLException e) { fail(e.getMessage()); } @@ -1632,7 +1766,7 @@ public void testNBCROWNullsForLOBs() throws Exception { try (Connection con = createConnectionAndPopulateData()) { Statement stmt = con.createStatement(); String selectQuery = "SELECT col1_int, col2_varchar, col3_varchar, col4_smallint, col5_xml, col6_nvarcharMax, col7_varcharMax FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName); + + tableName; try (ResultSet rs = stmt.executeQuery(selectQuery)) { rs.next(); @@ -1665,7 +1799,7 @@ public void testSparseColumnSetValues() throws Exception { try (Connection con = createConnectionAndPopulateData(); Statement stmt = con.createStatement()) { String selectQuery = "SELECT col1_int, col2_varchar, col3_varchar, col4_smallint, col5_xml, col6_nvarcharMax, col7_varcharMax FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName); + + tableName; try (ResultSet rs = stmt.executeQuery(selectQuery)) { rs.next(); @@ -1705,7 +1839,7 @@ public void testSparseColumnSetIndex() throws Exception { try (Connection con = createConnectionAndPopulateData(); Statement stmt = con.createStatement()) { String selectQuery = "SELECT col1_int, col2_varchar, col3_varchar, col4_smallint, col5_xml, col6_nvarcharMax, col7_varcharMax FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName); + + tableName; try (ResultSet rs = stmt.executeQuery(selectQuery)) { rs.next(); @@ -1745,7 +1879,7 @@ public void testSparseColumnSetForException() throws Exception { SQLServerResultSetMetaData rsmd; try (Connection con = createConnectionAndPopulateData(); Statement stmt = con.createStatement()) { - String selectQuery = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName); + String selectQuery = "SELECT * FROM " + tableName; try (ResultSet rs = stmt.executeQuery(selectQuery)) { rs.next(); rsmd = (SQLServerResultSetMetaData) rs.getMetaData(); @@ -1757,8 +1891,7 @@ public void testSparseColumnSetForException() throws Exception { stmt.close(); rsmd.isSparseColumnSet(1); } - try (ResultSet rs = con.createStatement() - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = con.createStatement().executeQuery("SELECT * FROM " + tableName)) { rsmd = (SQLServerResultSetMetaData) rs.getMetaData(); con.close(); rsmd.isSparseColumnSet(1); @@ -1786,11 +1919,10 @@ public void testNBCRowForAllNulls() throws Exception { try (Connection con = ds.getConnection(); Statement stmt = con.createStatement()) { try { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); } catch (SQLException e) {} - String createTableQuery = "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + "(col1 int IDENTITY(1,1)"; + String createTableQuery = "CREATE TABLE " + tableName + "(col1 int IDENTITY(1,1)"; int noOfColumns = 128; for (int i = 2; i <= noOfColumns; i++) { @@ -1798,10 +1930,8 @@ public void testNBCRowForAllNulls() throws Exception { } createTableQuery += ")"; stmt.executeUpdate(createTableQuery); - stmt.executeUpdate( - "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " DEFAULT VALUES"); - try (ResultSet rs = stmt - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + stmt.executeUpdate("INSERT INTO " + tableName + " DEFAULT VALUES"); + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { rs.next(); // test that all columns except the first one are null @@ -1841,12 +1971,11 @@ public void testNBCROWWithRandomAccess() throws Exception { try (Statement stmt = con.createStatement()) { try { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); } catch (SQLException e) {} // construct a query to create a table with 100 columns - String createTableQuery = "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + "(col1 int IDENTITY(1,1)"; + String createTableQuery = "CREATE TABLE " + tableName + "(col1 int IDENTITY(1,1)"; for (int i = 2; i <= noOfColumns; i++) { createTableQuery = createTableQuery + ", col" + i + " int"; @@ -1854,7 +1983,7 @@ public void testNBCROWWithRandomAccess() throws Exception { createTableQuery += ")"; stmt.executeUpdate(createTableQuery); - stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + stmt.executeUpdate("TRUNCATE TABLE " + tableName); // randomly generate columns whose values would be set to a non null value nonNullColumns = new ArrayList<>(); @@ -1870,7 +1999,7 @@ public void testNBCROWWithRandomAccess() throws Exception { } // construct the insert query - String insertQuery = "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + "("; + String insertQuery = "INSERT INTO " + tableName + "("; String values = " VALUES("; for (int i = 1; i < nonNullColumns.size(); i++) { insertQuery = insertQuery + "col" + nonNullColumns.get(i); @@ -1887,8 +2016,7 @@ public void testNBCROWWithRandomAccess() throws Exception { // if there are no non-null columns if (nonNullColumns.size() == 1) - insertQuery = "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " DEFAULT VALUES"; + insertQuery = "INSERT INTO " + tableName + " DEFAULT VALUES"; log.fine("INSEER Query:" + insertQuery); // populate the table by executing the insert query @@ -1898,8 +2026,7 @@ public void testNBCROWWithRandomAccess() throws Exception { } try (Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) { // Try accessing rows and columns randomly for 10 times for (int j = 0; j < 10; j++) { @@ -2098,10 +2225,14 @@ public void testClosedConnection() throws Exception { public class TCUpdateCountWithTriggers { private static final int NUM_ROWS = 3; - private final String tableName = RandomUtil.getIdentifier("TCUpdateCountWithTriggersTable1"); - private final String table2Name = RandomUtil.getIdentifier("TCUpdateCountWithTriggersTable2"); - private final String sprocName = RandomUtil.getIdentifier("TCUpdateCountWithTriggersProc"); - private final String triggerName = RandomUtil.getIdentifier("TCUpdateCountWithTriggersTrigger"); + private final String tableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCUpdateCountWithTriggersTable1")); + private final String table2Name = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCUpdateCountWithTriggersTable2")); + private final String sprocName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCUpdateCountWithTriggersProc")); + private final String triggerName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCUpdateCountWithTriggersTrigger")); @BeforeEach public void setup() throws Exception { @@ -2111,35 +2242,25 @@ public void setup() throws Exception { try { stmt.executeUpdate("if EXISTS (SELECT * FROM sys.triggers where name = '" - + TestUtils.escapeSingleQuotes((triggerName)) + "') drop trigger " - + AbstractSQLGenerator.escapeIdentifier(triggerName)); + + TestUtils.escapeSingleQuotes((triggerName)) + "') drop trigger " + triggerName); } catch (SQLException e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } - stmt.executeUpdate( - "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 INT )"); + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 INT )"); for (int i = 0; i < NUM_ROWS; i++) - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1) VALUES (" + i + ")"); + stmt.executeUpdate("INSERT INTO " + tableName + " (col1) VALUES (" + i + ")"); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(table2Name) - + " (NAME VARCHAR(100), col2 int identity(1,1) )"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(table2Name) - + " (NAME) VALUES ('BLAH')"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(table2Name) - + " (NAME) VALUES ('FNORD')"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(table2Name) - + " (NAME) VALUES ('EEEP')"); + stmt.executeUpdate("CREATE TABLE " + table2Name + " (NAME VARCHAR(100), col2 int identity(1,1) )"); + stmt.executeUpdate("INSERT INTO " + table2Name + " (NAME) VALUES ('BLAH')"); + stmt.executeUpdate("INSERT INTO " + table2Name + " (NAME) VALUES ('FNORD')"); + stmt.executeUpdate("INSERT INTO " + table2Name + " (NAME) VALUES ('EEEP')"); - stmt.executeUpdate("Create Procedure " + AbstractSQLGenerator.escapeIdentifier(sprocName) + " AS " - + "Begin " + " Update " + AbstractSQLGenerator.escapeIdentifier(table2Name) + " SET " - + " NAME = 'Update' Where NAME = 'TEST' " + "Return 0 " + "End"); + stmt.executeUpdate("Create Procedure " + sprocName + " AS " + "Begin " + " Update " + table2Name + + " SET " + " NAME = 'Update' Where NAME = 'TEST' " + "Return 0 " + "End"); - stmt.executeUpdate("CREATE Trigger " + AbstractSQLGenerator.escapeIdentifier(triggerName) + " ON " - + AbstractSQLGenerator.escapeIdentifier(tableName) + " FOR DELETE AS " + "Begin " - + "Declare @l_retstat Integer " + "Execute @l_retstat = " - + AbstractSQLGenerator.escapeIdentifier(sprocName) + " " + "If (@l_retstat <> 0) " - + "Begin " + " Rollback Transaction " + "End " + "End"); + stmt.executeUpdate("CREATE Trigger " + triggerName + " ON " + tableName + " FOR DELETE AS " + + "Begin " + "Declare @l_retstat Integer " + "Execute @l_retstat = " + sprocName + " " + + "If (@l_retstat <> 0) " + "Begin " + " Rollback Transaction " + "End " + "End"); } con.commit(); @@ -2155,8 +2276,7 @@ public void setup() throws Exception { public void testLastUpdateCountTrue() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount=true"); - PreparedStatement ps = con.prepareStatement( - "DELETE FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE col1 = ?")) { + PreparedStatement ps = con.prepareStatement("DELETE FROM " + tableName + " WHERE col1 = ?")) { ps.setInt(1, 1); int updateCount = ps.executeUpdate(); @@ -2175,8 +2295,7 @@ public void testLastUpdateCountTrue() throws Exception { public void testLastUpdateCountFalse() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount=false"); - PreparedStatement ps = con.prepareStatement( - "DELETE FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE col1 = ?")) { + PreparedStatement ps = con.prepareStatement("DELETE FROM " + tableName + " WHERE col1 = ?")) { ps.setInt(1, 1); int updateCount = ps.executeUpdate(); @@ -2195,10 +2314,9 @@ public void testLastUpdateCountFalse() throws Exception { public void testPreparedStatementInsertExecInsert() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount=true"); - PreparedStatement ps = con.prepareStatement("INSERT INTO " - + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1) VALUES (" + (NUM_ROWS + 1) - + "); " + "EXEC " + AbstractSQLGenerator.escapeIdentifier(sprocName) + "; " + "UPDATE " - + AbstractSQLGenerator.escapeIdentifier(table2Name) + " SET NAME = 'FISH'")) { + PreparedStatement ps = con + .prepareStatement("INSERT INTO " + tableName + " (col1) VALUES (" + (NUM_ROWS + 1) + "); " + + "EXEC " + sprocName + "; " + "UPDATE " + table2Name + " SET NAME = 'FISH'")) { int updateCount = ps.executeUpdate(); @@ -2218,10 +2336,8 @@ public void testStatementInsertExecInsert() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount=true"); Statement stmt = con.createStatement()) { - int updateCount = stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1) VALUES (" + (NUM_ROWS + 1) + "); " + "EXEC " - + AbstractSQLGenerator.escapeIdentifier(sprocName) + "; " + "UPDATE " - + AbstractSQLGenerator.escapeIdentifier(table2Name) + " SET NAME = 'FISH'"); + int updateCount = stmt.executeUpdate("INSERT INTO " + tableName + " (col1) VALUES (" + (NUM_ROWS + 1) + + "); " + "EXEC " + sprocName + "; " + "UPDATE " + table2Name + " SET NAME = 'FISH'"); // updateCount should be from the INSERT, // which should have affected 1 (new) row in AbstractSQLGenerator.escapeIdentifier(tableName). @@ -2232,9 +2348,9 @@ public void testStatementInsertExecInsert() throws Exception { @AfterEach public void terminate() throws SQLException { try (Statement stmt = connection.createStatement();) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table2Name), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(sprocName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); + TestUtils.dropTableIfExists(table2Name, stmt); + TestUtils.dropProcedureIfExists(sprocName, stmt); } } } @@ -2242,8 +2358,9 @@ public void terminate() throws SQLException { @Nested @Tag(Constants.xAzureSQLDW) public class TCUpdateCountAfterRaiseError { - private final String tableName = RandomUtil.getIdentifier("TCUpdateCountAfterRaiseError"); - private final String triggerName = tableName + "Trigger"; + private final String tableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCUpdateCountAfterRaiseError")); + private final String triggerName = AbstractSQLGenerator.escapeIdentifier("Trigger"); private final int NUM_ROWS = 3; private final String errorMessage50001InSqlAzure = "Error 50001, severity 17, state 1 was raised, but no message with that error number was found in sys.messages. If error is larger than 50000, make sure the user-defined message is added using sp_addmessage."; @@ -2253,11 +2370,9 @@ public void setup() throws Exception { con.setAutoCommit(false); try (Statement stmt = con.createStatement()) { TestUtils.dropTriggerIfExists(triggerName, stmt); - stmt.executeUpdate( - "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 INT )"); + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 INT )"); for (int i = 0; i < NUM_ROWS; i++) - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1) VALUES (" + i + ")"); + stmt.executeUpdate("INSERT INTO " + tableName + " (col1) VALUES (" + i + ")"); // Skip adding message for 50001 if the target server is SQL Azure, because SQL Azure does not // support @@ -2274,10 +2389,9 @@ public void setup() throws Exception { } } - stmt.executeUpdate("CREATE TRIGGER " + AbstractSQLGenerator.escapeIdentifier(triggerName) + " ON " - + AbstractSQLGenerator.escapeIdentifier(tableName) + " FOR INSERT AS BEGIN DELETE FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName) - + " WHERE col1 = 1 RAISERROR(50001, 17, 1) END"); + stmt.executeUpdate( + "CREATE TRIGGER " + triggerName + " ON " + tableName + " FOR INSERT AS BEGIN DELETE FROM " + + tableName + " WHERE col1 = 1 RAISERROR(50001, 17, 1) END"); } con.commit(); } @@ -2291,11 +2405,8 @@ public void setup() throws Exception { @Test public void testUpdateCountAfterRaiseError() throws Exception { - try (Connection con = getConnection(); - PreparedStatement pstmt = con - .prepareStatement("UPDATE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " SET col1 = 5 WHERE col1 = 2 RAISERROR(50001, 17, 1) SELECT * FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (Connection con = getConnection(); PreparedStatement pstmt = con.prepareStatement("UPDATE " + tableName + + " SET col1 = 5 WHERE col1 = 2 RAISERROR(50001, 17, 1) SELECT * FROM " + tableName)) { // enable isCloseOnCompletion try { @@ -2348,8 +2459,7 @@ public void testUpdateCountAfterRaiseError() throws Exception { public void testUpdateCountAfterErrorInTriggerLastUpdateCountFalse() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount = false"); - PreparedStatement pstmt = con.prepareStatement( - "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (5)")) { + PreparedStatement pstmt = con.prepareStatement("INSERT INTO " + tableName + " VALUES (5)")) { int updateCount = pstmt.executeUpdate(); assertEquals(updateCount, 1, "First result: should have been 1 row deleted"); @@ -2377,8 +2487,7 @@ public void testUpdateCountAfterErrorInTriggerLastUpdateCountFalse() throws Exce result = pstmt.getMoreResults(); assertEquals(result, false, "Third result: wrong result type; update count expected"); assertEquals(pstmt.getUpdateCount(), 1, "Third result: wrong number of rows inserted"); - try (ResultSet rs = con.createStatement() - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = con.createStatement().executeQuery("SELECT * FROM " + tableName)) { int rowCount = 0; while (rs.next()) ++rowCount; @@ -2397,8 +2506,7 @@ public void testUpdateCountAfterErrorInTriggerLastUpdateCountFalse() throws Exce public void testUpdateCountAfterErrorInTriggerLastUpdateCountTrue() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount = true"); - PreparedStatement pstmt = con.prepareStatement( - "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (5)")) { + PreparedStatement pstmt = con.prepareStatement("INSERT INTO " + tableName + " VALUES (5)")) { try { pstmt.executeUpdate(); @@ -2427,8 +2535,7 @@ public void testUpdateCountAfterErrorInTriggerLastUpdateCountTrue() throws Excep assertEquals(pstmt.getUpdateCount(), 1, "Second result: wrong number of rows inserted"); } - try (ResultSet rs = con.createStatement() - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = con.createStatement().executeQuery("SELECT * FROM " + tableName)) { int rowCount = 0; while (rs.next()) ++rowCount; @@ -2441,7 +2548,7 @@ public void testUpdateCountAfterErrorInTriggerLastUpdateCountTrue() throws Excep public void terminate() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement();) { try { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); } catch (SQLException e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } @@ -2452,7 +2559,7 @@ public void terminate() throws Exception { @Nested @Tag(Constants.xAzureSQLDW) public class TCNocount { - private final String tableName = RandomUtil.getIdentifier("TCNoCount"); + private final String tableName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("TCNoCount")); private static final int NUM_ROWS = 3; @@ -2468,11 +2575,9 @@ public void setup() throws Exception { } catch (Exception e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } - stmt.executeUpdate( - "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 INT )"); + stmt.executeUpdate("CREATE TABLE " + tableName + " (col1 INT )"); for (int i = 0; i < NUM_ROWS; i++) - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1) VALUES (" + i + ")"); + stmt.executeUpdate("INSERT INTO " + tableName + " (col1) VALUES (" + i + ")"); assertEquals(stmt.isClosed(), false, TestResource.getResource("R_statementShouldBeOpened")); } @@ -2491,9 +2596,8 @@ public void testNoCountWithExecute() throws Exception { try (Connection con = PrepUtil.getConnection(connectionString + ";lastUpdateCount = true"); Statement stmt = con.createStatement();) { - boolean isResultSet = stmt - .execute("set nocount on\n" + "insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) - + "(col1) values(" + (NUM_ROWS + 1) + ")\n" + "select 1"); + boolean isResultSet = stmt.execute("set nocount on\n" + "insert into " + tableName + "(col1) values(" + + (NUM_ROWS + 1) + ")\n" + "select 1"); assertEquals(true, isResultSet, "execute() said first result was an update count"); @@ -2513,7 +2617,7 @@ public void testNoCountWithExecute() throws Exception { public void terminate() throws Exception { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { try { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(tableName, stmt); } catch (SQLException e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); }