From 8254117929bddb014868094fccc088d4c288c4df Mon Sep 17 00:00:00 2001 From: Mahendra Chavan Date: Wed, 4 Dec 2024 10:55:40 +0530 Subject: [PATCH 01/10] Issue#2550 - Fixed getGeneratedKeys functionality for execute API --- .../sqlserver/jdbc/SQLServerStatement.java | 10 +- .../microsoft/sqlserver/jdbc/StreamDone.java | 6 +- .../jdbc/unit/statement/StatementTest.java | 318 ++++++++++++++++++ 3 files changed, 331 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index ab9e9fbe2..01b236867 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -1601,9 +1601,15 @@ boolean onDone(TDSReader tdsReader) throws SQLServerException { if (null != procedureName) return false; + //For Insert, we must fetch additional TDS_DONE token that comes with the actual update count + if (doneToken.cmdIsInsert() && (-1 != doneToken.getUpdateCount()) && EXECUTE == executeMethod) { + return true; + } + // Always return all update counts from statements executed through Statement.execute() - if (EXECUTE == executeMethod) - return false; + if (EXECUTE == executeMethod) { + return false; + } // Statement.executeUpdate() may or may not return this update count depending on the // setting of the lastUpdateCount connection property: diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java b/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java index 319c9ad6c..a2982f938 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java @@ -231,8 +231,12 @@ final long getUpdateCount() { } } + final boolean cmdIsInsert() { + return (CMD_INSERT == curCmd); + } + final boolean cmdIsDMLOrDDL() { - switch (curCmd) { + switch (curCmd) { case CMD_INSERT: case CMD_BULKINSERT: case CMD_DELETE: 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 9c814916d..f2bb85277 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 @@ -24,6 +24,7 @@ import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; +import java.util.List; import java.util.Random; import java.util.UUID; import java.util.concurrent.Executors; @@ -2692,4 +2693,321 @@ public void terminate() throws Exception { } } } + + + @Nested + @Tag(Constants.xAzureSQLDW) + public class TCGenKeys { + private final String tableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeys")); + private final String idTableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeysIDs")); + + private final String triggerName = AbstractSQLGenerator.escapeIdentifier("Trigger"); + private final int NUM_ROWS = 3; + + @BeforeEach + public void setup() throws Exception { + try (Connection con = getConnection()) { + con.setAutoCommit(false); + try (Statement stmt = con.createStatement()) { + TestUtils.dropTriggerIfExists(triggerName, stmt); + stmt.executeUpdate("CREATE TABLE " + tableName + " (ID int NOT NULL IDENTITY(1,1) PRIMARY KEY, NAME varchar(32));"); + + stmt.executeUpdate("CREATE TABLE " + idTableName + "(ID int NOT NULL IDENTITY(1,1) PRIMARY KEY);"); + + stmt.executeUpdate("CREATE TRIGGER " + triggerName + " ON " + tableName + " FOR INSERT AS INSERT INTO " + idTableName + " DEFAULT VALUES;"); + + for (int i = 0; i < NUM_ROWS; i++) { + stmt.executeUpdate("INSERT INTO " + tableName + " (NAME) VALUES ('test')"); + } + + } + con.commit(); + } + } + + /** + * Tests executeUpdate for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testExecuteUpdateInsertAndGenKeys() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + stmt.executeUpdate(sql, List.of("ID").toArray(String[]::new)); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "id should have been 4, but received : " + id); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testExecuteInsertAndGenKeys() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + stmt.execute(sql, List.of("ID").toArray(String[]::new)); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "generated key should have been 4"); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Insert followed by select + * + * @throws Exception + */ + @Test + public void testExecuteInsertAndSelect() throws Exception { + + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("INSERT INTO " + tableName +" (NAME) VALUES('test') SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 1"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + + /** + * Tests execute for Merge followed by select + * + * @throws Exception + */ + @Test + public void testExecuteMergeAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("MERGE INTO " + tableName + " AS target USING (VALUES ('test1')) AS source (name) ON target.name = source.name WHEN NOT MATCHED THEN INSERT (name) VALUES ('test1'); SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 1"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Insert multiple rows followed by select + * + * @throws Exception + */ + @Test + public void testExecuteInsertManyRowsAndSelect() throws Exception { + try (Connection con = getConnection()) { + try (Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("INSERT INTO " + tableName + " SELECT NAME FROM " + tableName + " SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 3, "update count should have been 6"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute two Inserts followed by select + * + * @throws Exception + */ + @Test + public void testExecuteTwoInsertsRowsAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("INSERT INTO " + tableName + " (NAME) VALUES('test') INSERT INTO " + tableName + " (NAME) VALUES('test') SELECT NAME from " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 2"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + + /** + * Tests execute for Update followed by select + * + * @throws Exception + */ + @Test + public void testExecuteUpdAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("UPDATE " + tableName +" SET NAME = 'test' SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 3, "update count should have been 3"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Update followed by select + * + * @throws Exception + */ + @Test + public void testExecuteDelAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("DELETE FROM " + tableName +" WHERE ID = 1 SELECT NAME FROM " + tableName + " WHERE ID = 2"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 1"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + @AfterEach + public void terminate() throws Exception { + try (Connection con = getConnection(); Statement stmt = con.createStatement()) { + try { + TestUtils.dropTriggerIfExists(triggerName, stmt); + TestUtils.dropTableIfExists(idTableName, stmt); + TestUtils.dropTableIfExists(tableName, stmt); + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + } + } + + } From 59259bfca5edf580d104a0104ab75f30aa06e8e7 Mon Sep 17 00:00:00 2001 From: Mahendra Chavan Date: Thu, 5 Dec 2024 00:04:29 +0530 Subject: [PATCH 02/10] Adapted the test for working with jdk8 --- .../jdbc/unit/statement/StatementTest.java | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) 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 f2bb85277..f872359a9 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 @@ -24,6 +24,7 @@ import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.UUID; @@ -2734,20 +2735,22 @@ public void setup() throws Exception { */ @Test public void testExecuteUpdateInsertAndGenKeys() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; - stmt.executeUpdate(sql, List.of("ID").toArray(String[]::new)); - try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { - if (generatedKeys.next()) { - int id = generatedKeys.getInt(1); - assertEquals(id, 4, "id should have been 4, but received : " + id); - } - } - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + List lst = Arrays.asList("ID"); + String[] arr = lst.toArray(new String[0]); + stmt.executeUpdate(sql, arr); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "id should have been 4, but received : " + id); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } } /** @@ -2757,20 +2760,22 @@ public void testExecuteUpdateInsertAndGenKeys() throws Exception { */ @Test public void testExecuteInsertAndGenKeys() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; - stmt.execute(sql, List.of("ID").toArray(String[]::new)); - try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { - if (generatedKeys.next()) { - int id = generatedKeys.getInt(1); - assertEquals(id, 4, "generated key should have been 4"); - } - } - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + List lst = Arrays.asList("ID"); + String[] arr = lst.toArray(new String[0]); + stmt.execute(sql, arr); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "generated key should have been 4"); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } } /** From ad365ca7f70d1628ac345544aa0b7e084bc7abae Mon Sep 17 00:00:00 2001 From: Mahendra Chavan Date: Thu, 5 Dec 2024 00:06:05 +0530 Subject: [PATCH 03/10] Fixed indenetation --- .../jdbc/unit/statement/StatementTest.java | 633 +++++++++--------- 1 file changed, 316 insertions(+), 317 deletions(-) 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 f872359a9..86437173b 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 @@ -2696,323 +2696,322 @@ public void terminate() throws Exception { } - @Nested - @Tag(Constants.xAzureSQLDW) - public class TCGenKeys { - private final String tableName = AbstractSQLGenerator - .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeys")); - private final String idTableName = AbstractSQLGenerator - .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeysIDs")); - - private final String triggerName = AbstractSQLGenerator.escapeIdentifier("Trigger"); - private final int NUM_ROWS = 3; - - @BeforeEach - public void setup() throws Exception { - try (Connection con = getConnection()) { - con.setAutoCommit(false); - try (Statement stmt = con.createStatement()) { - TestUtils.dropTriggerIfExists(triggerName, stmt); - stmt.executeUpdate("CREATE TABLE " + tableName + " (ID int NOT NULL IDENTITY(1,1) PRIMARY KEY, NAME varchar(32));"); - - stmt.executeUpdate("CREATE TABLE " + idTableName + "(ID int NOT NULL IDENTITY(1,1) PRIMARY KEY);"); - - stmt.executeUpdate("CREATE TRIGGER " + triggerName + " ON " + tableName + " FOR INSERT AS INSERT INTO " + idTableName + " DEFAULT VALUES;"); - - for (int i = 0; i < NUM_ROWS; i++) { - stmt.executeUpdate("INSERT INTO " + tableName + " (NAME) VALUES ('test')"); - } - - } - con.commit(); - } - } - - /** - * Tests executeUpdate for Insert followed by getGenerateKeys - * - * @throws Exception - */ - @Test - public void testExecuteUpdateInsertAndGenKeys() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; - List lst = Arrays.asList("ID"); - String[] arr = lst.toArray(new String[0]); - stmt.executeUpdate(sql, arr); - try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { - if (generatedKeys.next()) { - int id = generatedKeys.getInt(1); - assertEquals(id, 4, "id should have been 4, but received : " + id); - } - } - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /** - * Tests execute for Insert followed by getGenerateKeys - * - * @throws Exception - */ - @Test - public void testExecuteInsertAndGenKeys() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; - List lst = Arrays.asList("ID"); - String[] arr = lst.toArray(new String[0]); - stmt.execute(sql, arr); - try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { - if (generatedKeys.next()) { - int id = generatedKeys.getInt(1); - assertEquals(id, 4, "generated key should have been 4"); - } - } - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /** - * Tests execute for Insert followed by select - * - * @throws Exception - */ - @Test - public void testExecuteInsertAndSelect() throws Exception { - - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - boolean retval = stmt.execute("INSERT INTO " + tableName +" (NAME) VALUES('test') SELECT NAME FROM " + tableName + " WHERE ID = 1"); - do { - if (retval == false) { - int count = stmt.getUpdateCount(); - if (count == -1) { - // no more results - break; - } else { - assertEquals(count, 1, "update count should have been 1"); - } - } else { - // process ResultSet - try (ResultSet rs = stmt.getResultSet()) { - if (rs.next()) { - String val = rs.getString(1); - assertEquals(val, "test", "read value should have been 'test'"); - } - } - } - retval = stmt.getMoreResults(); - } while (true); - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - - /** - * Tests execute for Merge followed by select - * - * @throws Exception - */ - @Test - public void testExecuteMergeAndSelect() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - boolean retval = stmt.execute("MERGE INTO " + tableName + " AS target USING (VALUES ('test1')) AS source (name) ON target.name = source.name WHEN NOT MATCHED THEN INSERT (name) VALUES ('test1'); SELECT NAME FROM " + tableName + " WHERE ID = 1"); - do { - if (retval == false) { - int count = stmt.getUpdateCount(); - if (count == -1) { - // no more results - break; - } else { - assertEquals(count, 1, "update count should have been 1"); - } - } else { - // process ResultSet - try (ResultSet rs = stmt.getResultSet()) { - if (rs.next()) { - String val = rs.getString(1); - assertEquals(val, "test", "read value should have been 'test'"); - } - } - - } - retval = stmt.getMoreResults(); - } while (true); - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /** - * Tests execute for Insert multiple rows followed by select - * - * @throws Exception - */ - @Test - public void testExecuteInsertManyRowsAndSelect() throws Exception { - try (Connection con = getConnection()) { - try (Statement stmt = con.createStatement()) { - boolean retval = stmt.execute("INSERT INTO " + tableName + " SELECT NAME FROM " + tableName + " SELECT NAME FROM " + tableName + " WHERE ID = 1"); - do { - if (retval == false) { - int count = stmt.getUpdateCount(); - if (count == -1) { - // no more results - break; - } else { - assertEquals(count, 3, "update count should have been 6"); - } - } else { - // process ResultSet - try (ResultSet rs = stmt.getResultSet()) { - if (rs.next()) { - String val = rs.getString(1); - assertEquals(val, "test", "read value should have been 'test'"); - } - } - - } - retval = stmt.getMoreResults(); - } while (true); - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /** - * Tests execute two Inserts followed by select - * - * @throws Exception - */ - @Test - public void testExecuteTwoInsertsRowsAndSelect() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - boolean retval = stmt.execute("INSERT INTO " + tableName + " (NAME) VALUES('test') INSERT INTO " + tableName + " (NAME) VALUES('test') SELECT NAME from " + tableName + " WHERE ID = 1"); - do { - if (retval == false) { - int count = stmt.getUpdateCount(); - if (count == -1) { - // no more results - break; - } else { - assertEquals(count, 1, "update count should have been 2"); - } - } else { - // process ResultSet - try (ResultSet rs = stmt.getResultSet()) { - if (rs.next()) { - String val = rs.getString(1); - assertEquals(val, "test", "read value should have been 'test'"); - } - } - - } - retval = stmt.getMoreResults(); - } while (true); - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - - /** - * Tests execute for Update followed by select - * - * @throws Exception - */ - @Test - public void testExecuteUpdAndSelect() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - boolean retval = stmt.execute("UPDATE " + tableName +" SET NAME = 'test' SELECT NAME FROM " + tableName + " WHERE ID = 1"); - do { - if (retval == false) { - int count = stmt.getUpdateCount(); - if (count == -1) { - // no more results - break; - } else { - assertEquals(count, 3, "update count should have been 3"); - } - } else { - // process ResultSet - try (ResultSet rs = stmt.getResultSet()) { - if (rs.next()) { - String val = rs.getString(1); - assertEquals(val, "test", "read value should have been 'test'"); - } - } - } - retval = stmt.getMoreResults(); - } while (true); - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /** - * Tests execute for Update followed by select - * - * @throws Exception - */ - @Test - public void testExecuteDelAndSelect() throws Exception { - try (Connection con = getConnection()) { - try(Statement stmt = con.createStatement()) { - boolean retval = stmt.execute("DELETE FROM " + tableName +" WHERE ID = 1 SELECT NAME FROM " + tableName + " WHERE ID = 2"); - do { - if (retval == false) { - int count = stmt.getUpdateCount(); - if (count == -1) { - // no more results - break; - } else { - assertEquals(count, 1, "update count should have been 1"); - } - } else { - // process ResultSet - try (ResultSet rs = stmt.getResultSet()) { - if (rs.next()) { - String val = rs.getString(1); - assertEquals(val, "test", "read value should have been 'test'"); - } - } - } - retval = stmt.getMoreResults(); - } while (true); - } - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - @AfterEach - public void terminate() throws Exception { - try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - try { - TestUtils.dropTriggerIfExists(triggerName, stmt); - TestUtils.dropTableIfExists(idTableName, stmt); - TestUtils.dropTableIfExists(tableName, stmt); - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - } - } + @Nested + @Tag(Constants.xAzureSQLDW) + public class TCGenKeys { + private final String tableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeys")); + private final String idTableName = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeysIDs")); + + private final String triggerName = AbstractSQLGenerator.escapeIdentifier("Trigger"); + private final int NUM_ROWS = 3; + + @BeforeEach + public void setup() throws Exception { + try (Connection con = getConnection()) { + con.setAutoCommit(false); + try (Statement stmt = con.createStatement()) { + TestUtils.dropTriggerIfExists(triggerName, stmt); + stmt.executeUpdate("CREATE TABLE " + tableName + " (ID int NOT NULL IDENTITY(1,1) PRIMARY KEY, NAME varchar(32));"); + + stmt.executeUpdate("CREATE TABLE " + idTableName + "(ID int NOT NULL IDENTITY(1,1) PRIMARY KEY);"); + + stmt.executeUpdate("CREATE TRIGGER " + triggerName + " ON " + tableName + " FOR INSERT AS INSERT INTO " + idTableName + " DEFAULT VALUES;"); + + for (int i = 0; i < NUM_ROWS; i++) { + stmt.executeUpdate("INSERT INTO " + tableName + " (NAME) VALUES ('test')"); + } + + } + con.commit(); + } + } + + /** + * Tests executeUpdate for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testExecuteUpdateInsertAndGenKeys() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + List lst = Arrays.asList("ID"); + String[] arr = lst.toArray(new String[0]); + stmt.executeUpdate(sql, arr); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "id should have been 4, but received : " + id); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testExecuteInsertAndGenKeys() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + List lst = Arrays.asList("ID"); + String[] arr = lst.toArray(new String[0]); + stmt.execute(sql, arr); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "generated key should have been 4"); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Insert followed by select + * + * @throws Exception + */ + @Test + public void testExecuteInsertAndSelect() throws Exception { + + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("INSERT INTO " + tableName +" (NAME) VALUES('test') SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 1"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + + /** + * Tests execute for Merge followed by select + * + * @throws Exception + */ + @Test + public void testExecuteMergeAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("MERGE INTO " + tableName + " AS target USING (VALUES ('test1')) AS source (name) ON target.name = source.name WHEN NOT MATCHED THEN INSERT (name) VALUES ('test1'); SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 1"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + /** + * Tests execute for Insert multiple rows followed by select + * + * @throws Exception + */ + @Test + public void testExecuteInsertManyRowsAndSelect() throws Exception { + try (Connection con = getConnection()) { + try (Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("INSERT INTO " + tableName + " SELECT NAME FROM " + tableName + " SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 3, "update count should have been 6"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute two Inserts followed by select + * + * @throws Exception + */ + @Test + public void testExecuteTwoInsertsRowsAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("INSERT INTO " + tableName + " (NAME) VALUES('test') INSERT INTO " + tableName + " (NAME) VALUES('test') SELECT NAME from " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 2"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + + /** + * Tests execute for Update followed by select + * + * @throws Exception + */ + @Test + public void testExecuteUpdAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("UPDATE " + tableName +" SET NAME = 'test' SELECT NAME FROM " + tableName + " WHERE ID = 1"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 3, "update count should have been 3"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests execute for Update followed by select + * + * @throws Exception + */ + @Test + public void testExecuteDelAndSelect() throws Exception { + try (Connection con = getConnection()) { + try(Statement stmt = con.createStatement()) { + boolean retval = stmt.execute("DELETE FROM " + tableName +" WHERE ID = 1 SELECT NAME FROM " + tableName + " WHERE ID = 2"); + do { + if (retval == false) { + int count = stmt.getUpdateCount(); + if (count == -1) { + // no more results + break; + } else { + assertEquals(count, 1, "update count should have been 1"); + } + } else { + // process ResultSet + try (ResultSet rs = stmt.getResultSet()) { + if (rs.next()) { + String val = rs.getString(1); + assertEquals(val, "test", "read value should have been 'test'"); + } + } + } + retval = stmt.getMoreResults(); + } while (true); + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + @AfterEach + public void terminate() throws Exception { + try (Connection con = getConnection(); Statement stmt = con.createStatement()) { + try { + TestUtils.dropTriggerIfExists(triggerName, stmt); + TestUtils.dropTableIfExists(idTableName, stmt); + TestUtils.dropTableIfExists(tableName, stmt); + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + } + } } From 700153d9621c4e9ce212eb131c25bba187305bb3 Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 12 Dec 2024 10:07:22 +0530 Subject: [PATCH 04/10] Enable thre new TCGenKeys tests for AzureDW --- .../microsoft/sqlserver/jdbc/unit/statement/StatementTest.java | 1 - 1 file changed, 1 deletion(-) 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 86437173b..3df079450 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 @@ -2697,7 +2697,6 @@ public void terminate() throws Exception { @Nested - @Tag(Constants.xAzureSQLDW) public class TCGenKeys { private final String tableName = AbstractSQLGenerator .escapeIdentifier(RandomUtil.getIdentifier("TCInsertWithGenKeys")); From 286367b5e830f0c37a115a0aaffbaa1b869200ed Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 19 Dec 2024 10:54:08 +0530 Subject: [PATCH 05/10] Incorporated review comments. --- .../com/microsoft/sqlserver/jdbc/SQLServerStatement.java | 2 +- .../java/com/microsoft/sqlserver/jdbc/StreamDone.java | 4 ---- .../sqlserver/jdbc/unit/statement/StatementTest.java | 9 +++------ 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index 01b236867..972c3b35b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -1602,7 +1602,7 @@ boolean onDone(TDSReader tdsReader) throws SQLServerException { return false; //For Insert, we must fetch additional TDS_DONE token that comes with the actual update count - if (doneToken.cmdIsInsert() && (-1 != doneToken.getUpdateCount()) && EXECUTE == executeMethod) { + if ((StreamDone.CMD_INSERT == doneToken.getCurCmd()) && (-1 != doneToken.getUpdateCount()) && EXECUTE == executeMethod) { return true; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java b/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java index a2982f938..ede354260 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/StreamDone.java @@ -231,10 +231,6 @@ final long getUpdateCount() { } } - final boolean cmdIsInsert() { - return (CMD_INSERT == curCmd); - } - final boolean cmdIsDMLOrDDL() { switch (curCmd) { case CMD_INSERT: 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 3df079450..620a6aaa3 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 @@ -2713,15 +2713,12 @@ public void setup() throws Exception { try (Statement stmt = con.createStatement()) { TestUtils.dropTriggerIfExists(triggerName, stmt); stmt.executeUpdate("CREATE TABLE " + tableName + " (ID int NOT NULL IDENTITY(1,1) PRIMARY KEY, NAME varchar(32));"); - stmt.executeUpdate("CREATE TABLE " + idTableName + "(ID int NOT NULL IDENTITY(1,1) PRIMARY KEY);"); - - stmt.executeUpdate("CREATE TRIGGER " + triggerName + " ON " + tableName + " FOR INSERT AS INSERT INTO " + idTableName + " DEFAULT VALUES;"); - + stmt.executeUpdate("CREATE TRIGGER " + triggerName + " ON " + tableName + + " FOR INSERT AS INSERT INTO " + idTableName + " DEFAULT VALUES;"); for (int i = 0; i < NUM_ROWS; i++) { stmt.executeUpdate("INSERT INTO " + tableName + " (NAME) VALUES ('test')"); } - } con.commit(); } @@ -3012,5 +3009,5 @@ public void terminate() throws Exception { } } } - + } From c9faea57015ea9ab44075da2c74d3ca6ae5f8da0 Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 19 Dec 2024 11:02:09 +0530 Subject: [PATCH 06/10] Incorporated review comments --- .../sqlserver/jdbc/unit/statement/StatementTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 620a6aaa3..5ac771118 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 @@ -2786,7 +2786,7 @@ public void testExecuteInsertAndSelect() throws Exception { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("INSERT INTO " + tableName +" (NAME) VALUES('test') SELECT NAME FROM " + tableName + " WHERE ID = 1"); do { - if (retval == false) { + if (!retval) { int count = stmt.getUpdateCount(); if (count == -1) { // no more results @@ -2823,7 +2823,7 @@ public void testExecuteMergeAndSelect() throws Exception { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("MERGE INTO " + tableName + " AS target USING (VALUES ('test1')) AS source (name) ON target.name = source.name WHEN NOT MATCHED THEN INSERT (name) VALUES ('test1'); SELECT NAME FROM " + tableName + " WHERE ID = 1"); do { - if (retval == false) { + if (!retval) { int count = stmt.getUpdateCount(); if (count == -1) { // no more results @@ -2860,7 +2860,7 @@ public void testExecuteInsertManyRowsAndSelect() throws Exception { try (Statement stmt = con.createStatement()) { boolean retval = stmt.execute("INSERT INTO " + tableName + " SELECT NAME FROM " + tableName + " SELECT NAME FROM " + tableName + " WHERE ID = 1"); do { - if (retval == false) { + if (!retval) { int count = stmt.getUpdateCount(); if (count == -1) { // no more results @@ -2897,7 +2897,7 @@ public void testExecuteTwoInsertsRowsAndSelect() throws Exception { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("INSERT INTO " + tableName + " (NAME) VALUES('test') INSERT INTO " + tableName + " (NAME) VALUES('test') SELECT NAME from " + tableName + " WHERE ID = 1"); do { - if (retval == false) { + if (!retval) { int count = stmt.getUpdateCount(); if (count == -1) { // no more results @@ -2935,7 +2935,7 @@ public void testExecuteUpdAndSelect() throws Exception { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("UPDATE " + tableName +" SET NAME = 'test' SELECT NAME FROM " + tableName + " WHERE ID = 1"); do { - if (retval == false) { + if (!retval) { int count = stmt.getUpdateCount(); if (count == -1) { // no more results @@ -2971,7 +2971,7 @@ public void testExecuteDelAndSelect() throws Exception { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("DELETE FROM " + tableName +" WHERE ID = 1 SELECT NAME FROM " + tableName + " WHERE ID = 2"); do { - if (retval == false) { + if (!retval) { int count = stmt.getUpdateCount(); if (count == -1) { // no more results From 18c96b5e5be227f821b8debf23bc84356143c571 Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 19 Dec 2024 11:35:20 +0530 Subject: [PATCH 07/10] Incorporated review comments --- .../jdbc/unit/statement/StatementTest.java | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) 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 5ac771118..81c29583a 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 @@ -2730,7 +2730,7 @@ public void setup() throws Exception { * @throws Exception */ @Test - public void testExecuteUpdateInsertAndGenKeys() throws Exception { + public void testExecuteUpdateInsertAndGenKeys() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; @@ -2755,7 +2755,7 @@ public void testExecuteUpdateInsertAndGenKeys() throws Exception { * @throws Exception */ @Test - public void testExecuteInsertAndGenKeys() throws Exception { + public void testExecuteInsertAndGenKeys() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; @@ -2780,7 +2780,7 @@ public void testExecuteInsertAndGenKeys() throws Exception { * @throws Exception */ @Test - public void testExecuteInsertAndSelect() throws Exception { + public void testExecuteInsertAndSelect() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { @@ -2818,7 +2818,7 @@ public void testExecuteInsertAndSelect() throws Exception { * @throws Exception */ @Test - public void testExecuteMergeAndSelect() throws Exception { + public void testExecuteMergeAndSelect() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("MERGE INTO " + tableName + " AS target USING (VALUES ('test1')) AS source (name) ON target.name = source.name WHEN NOT MATCHED THEN INSERT (name) VALUES ('test1'); SELECT NAME FROM " + tableName + " WHERE ID = 1"); @@ -2855,7 +2855,7 @@ public void testExecuteMergeAndSelect() throws Exception { * @throws Exception */ @Test - public void testExecuteInsertManyRowsAndSelect() throws Exception { + public void testExecuteInsertManyRowsAndSelect() { try (Connection con = getConnection()) { try (Statement stmt = con.createStatement()) { boolean retval = stmt.execute("INSERT INTO " + tableName + " SELECT NAME FROM " + tableName + " SELECT NAME FROM " + tableName + " WHERE ID = 1"); @@ -2892,7 +2892,7 @@ public void testExecuteInsertManyRowsAndSelect() throws Exception { * @throws Exception */ @Test - public void testExecuteTwoInsertsRowsAndSelect() throws Exception { + public void testExecuteTwoInsertsRowsAndSelect() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("INSERT INTO " + tableName + " (NAME) VALUES('test') INSERT INTO " + tableName + " (NAME) VALUES('test') SELECT NAME from " + tableName + " WHERE ID = 1"); @@ -2930,7 +2930,7 @@ public void testExecuteTwoInsertsRowsAndSelect() throws Exception { * @throws Exception */ @Test - public void testExecuteUpdAndSelect() throws Exception { + public void testExecuteUpdAndSelect() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("UPDATE " + tableName +" SET NAME = 'test' SELECT NAME FROM " + tableName + " WHERE ID = 1"); @@ -2966,7 +2966,7 @@ public void testExecuteUpdAndSelect() throws Exception { * @throws Exception */ @Test - public void testExecuteDelAndSelect() throws Exception { + public void testExecuteDelAndSelect() { try (Connection con = getConnection()) { try(Statement stmt = con.createStatement()) { boolean retval = stmt.execute("DELETE FROM " + tableName +" WHERE ID = 1 SELECT NAME FROM " + tableName + " WHERE ID = 2"); @@ -2997,15 +2997,13 @@ public void testExecuteDelAndSelect() throws Exception { } @AfterEach - public void terminate() throws Exception { + public void terminate() { try (Connection con = getConnection(); Statement stmt = con.createStatement()) { - try { - TestUtils.dropTriggerIfExists(triggerName, stmt); - TestUtils.dropTableIfExists(idTableName, stmt); - TestUtils.dropTableIfExists(tableName, stmt); - } catch (SQLException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } + TestUtils.dropTriggerIfExists(triggerName, stmt); + TestUtils.dropTableIfExists(idTableName, stmt); + TestUtils.dropTableIfExists(tableName, stmt); + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } } } From a65116ea9e13131b5b8d2466b3123af2812b686f Mon Sep 17 00:00:00 2001 From: machavan Date: Mon, 20 Jan 2025 19:10:47 +0530 Subject: [PATCH 08/10] Add a test for PreparedStatement --- .../jdbc/unit/statement/StatementTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) 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 81c29583a..7e7c7ab1d 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 @@ -2749,6 +2749,31 @@ public void testExecuteUpdateInsertAndGenKeys() { } } + /** + * Tests executeUpdate using PreparedStatement for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testPrepStmtExecuteUpdateInsertAndGenKeys() { + try (Connection con = getConnection()) { + String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; + List lst = Arrays.asList("ID"); + String[] arr = lst.toArray(new String[0]); + try(PreparedStatement stmt = con.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS)) { + stmt.executeUpdate(); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "id should have been 4, but received : " + id); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + /** * Tests execute for Insert followed by getGenerateKeys * From 596aafc9aa95f97d7b1d370e6fd9cac788201bf9 Mon Sep 17 00:00:00 2001 From: machavan Date: Tue, 21 Jan 2025 19:19:19 +0530 Subject: [PATCH 09/10] Adding a fix and test case for issue # 2587 --- .../jdbc/SQLServerPreparedStatement.java | 2 +- .../sqlserver/jdbc/SQLServerStatement.java | 31 ++++++++++++++----- .../jdbc/unit/statement/StatementTest.java | 25 +++++++++++++-- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 244cfb696..f05f01f33 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -705,7 +705,7 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE if (EXECUTE_QUERY == executeMethod && null == resultSet) { SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_noResultset"), null, true); - } else if (EXECUTE_UPDATE == executeMethod && null != resultSet) { + } else if ((EXECUTE_UPDATE == executeMethod) && (null != resultSet) && !bRequestedGeneratedKeys) { SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_resultsetGeneratedForUpdate"), null, false); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index 972c3b35b..3faa0ebb3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -2363,17 +2363,27 @@ public final ResultSet getGeneratedKeys() throws SQLServerException { if (null == autoGeneratedKeys) { long orgUpd = updateCount; + // + //A case of SET NOCOUNT ON and GENERATED KEYS requested + //where we may not have received update count but would have already read the resultset + //so directly consume it. + // + if ((executeMethod != EXECUTE_QUERY) && bRequestedGeneratedKeys && (resultSet != null)) { + autoGeneratedKeys = resultSet; + updateCount = orgUpd; + } else { - // Generated keys are returned in a ResultSet result right after the update count. - // Try to get that ResultSet. If there are no more results after the update count, - // or if the next result isn't a ResultSet, then something is wrong. - if (!getNextResult(true) || null == resultSet) { - SQLServerException.makeFromDriverError(connection, this, - SQLServerException.getErrString("R_statementMustBeExecuted"), null, false); + // Generated keys are returned in a ResultSet result right after the update count. + // Try to get that ResultSet. If there are no more results after the update count, + // or if the next result isn't a ResultSet, then something is wrong. + if (!getNextResult(true) || null == resultSet) { + SQLServerException.makeFromDriverError(connection, this, + SQLServerException.getErrString("R_statementMustBeExecuted"), null, false); + } + autoGeneratedKeys = resultSet; + updateCount = orgUpd; } - autoGeneratedKeys = resultSet; - updateCount = orgUpd; } loggerExternal.exiting(getClassNameLogging(), "getGeneratedKeys", autoGeneratedKeys); return autoGeneratedKeys; @@ -2622,6 +2632,11 @@ SQLServerColumnEncryptionKeyStoreProvider getColumnEncryptionKeyStoreProvider( lock.unlock(); } } + + protected void setAutoGeneratedKey(SQLServerResultSet rs) { + autoGeneratedKeys = rs; + } + } 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 7e7c7ab1d..072ea706b 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 @@ -2758,8 +2758,29 @@ public void testExecuteUpdateInsertAndGenKeys() { public void testPrepStmtExecuteUpdateInsertAndGenKeys() { try (Connection con = getConnection()) { String sql = "INSERT INTO " + tableName + " (NAME) VALUES('test')"; - List lst = Arrays.asList("ID"); - String[] arr = lst.toArray(new String[0]); + try(PreparedStatement stmt = con.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS)) { + stmt.executeUpdate(); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "id should have been 4, but received : " + id); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** + * Tests executeUpdate using PreparedStatement for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testPrepStmtNoCountExecuteUpdateInsertAndGenKeys() { + try (Connection con = getConnection()) { + String sql = "SET NOCOUNT ON; INSERT INTO " + tableName + " (NAME) VALUES('test')"; try(PreparedStatement stmt = con.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS)) { stmt.executeUpdate(); try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { From 978d8f3a4a113742aedda5d5dcf1dac82f7c9d04 Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 23 Jan 2025 10:16:21 +0530 Subject: [PATCH 10/10] Added a new test for execute API with set no count --- .../jdbc/unit/statement/StatementTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) 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 072ea706b..959837f0a 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 @@ -2795,6 +2795,30 @@ public void testPrepStmtNoCountExecuteUpdateInsertAndGenKeys() { } } + /** + * Tests executeUpdate using PreparedStatement for Insert followed by getGenerateKeys + * + * @throws Exception + */ + @Test + public void testPrepStmtNoCountExecuteInsertAndGenKeys() { + try (Connection con = getConnection()) { + String sql = "SET NOCOUNT ON; INSERT INTO " + tableName + " (NAME) VALUES('test')"; + try(PreparedStatement stmt = con.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS)) { + stmt.execute(); + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + int id = generatedKeys.getInt(1); + assertEquals(id, 4, "id should have been 4, but received : " + id); + } + } + } + } catch (SQLException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /** * Tests execute for Insert followed by getGenerateKeys *