Search in sources :

Example 26 with BatchUpdateException

use of java.sql.BatchUpdateException in project mssql-jdbc by Microsoft.

the class SQLServerPreparedStatement method executeBatch.

public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQLTimeoutException {
    loggerExternal.entering(getClassNameLogging(), "executeBatch");
    if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) {
        loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString());
    }
    checkClosed();
    discardLastExecutionResults();
    int[] updateCounts;
    if (batchParamValues == null)
        updateCounts = new int[0];
    else
        try {
            // OUT or INOUT are present, the entire batch fails.
            for (Parameter[] paramValues : batchParamValues) {
                for (Parameter paramValue : paramValues) {
                    if (paramValue.isOutput()) {
                        throw new BatchUpdateException(SQLServerException.getErrString("R_outParamsNotPermittedinBatch"), null, 0, null);
                    }
                }
            }
            PrepStmtBatchExecCmd batchCommand = new PrepStmtBatchExecCmd(this);
            executeStatement(batchCommand);
            updateCounts = new int[batchCommand.updateCounts.length];
            for (int i = 0; i < batchCommand.updateCounts.length; ++i) updateCounts[i] = (int) batchCommand.updateCounts[i];
            // Transform the SQLException into a BatchUpdateException with the update counts.
            if (null != batchCommand.batchException) {
                throw new BatchUpdateException(batchCommand.batchException.getMessage(), batchCommand.batchException.getSQLState(), batchCommand.batchException.getErrorCode(), updateCounts);
            }
        } finally {
            batchParamValues = null;
        }
    loggerExternal.exiting(getClassNameLogging(), "executeBatch", updateCounts);
    return updateCounts;
}
Also used : BatchUpdateException(java.sql.BatchUpdateException)

Example 27 with BatchUpdateException

use of java.sql.BatchUpdateException in project openmrs-core by openmrs.

the class DuplicateEncounterRoleNameChangeSet method execute.

/**
 * Method to perform validation and resolution of duplicate EncounterRole names
 */
@Override
public void execute(Database database) throws CustomChangeException {
    JdbcConnection connection = (JdbcConnection) database.getConnection();
    Map<String, HashSet<Integer>> duplicates = new HashMap<>();
    Statement stmt = null;
    PreparedStatement pStmt = null;
    ResultSet rs = null;
    Boolean initialAutoCommit = null;
    try {
        initialAutoCommit = connection.getAutoCommit();
        // set auto commit mode to false for UPDATE action
        connection.setAutoCommit(false);
        stmt = connection.createStatement();
        rs = stmt.executeQuery("SELECT * FROM encounter_role INNER JOIN (SELECT name FROM encounter_role GROUP BY name HAVING count(name) > 1) dup ON encounter_role.name = dup.name");
        Integer id;
        String name;
        while (rs.next()) {
            id = rs.getInt("encounter_role_id");
            name = rs.getString("name");
            if (duplicates.get(name) == null) {
                HashSet<Integer> results = new HashSet<>();
                results.add(id);
                duplicates.put(name, results);
            } else {
                HashSet<Integer> results = duplicates.get(name);
                results.add(id);
            }
        }
        for (Object o : duplicates.entrySet()) {
            Map.Entry pairs = (Map.Entry) o;
            HashSet values = (HashSet) pairs.getValue();
            List<Integer> ids = new ArrayList<Integer>(values);
            int duplicateNameId = 1;
            for (int i = 1; i < ids.size(); i++) {
                String newName = pairs.getKey() + "_" + duplicateNameId;
                List<List<Object>> duplicateResult;
                boolean duplicateName;
                Connection con = DatabaseUpdater.getConnection();
                do {
                    String sqlValidatorString = "select * from encounter_role where name = '" + newName + "'";
                    duplicateResult = DatabaseUtil.executeSQL(con, sqlValidatorString, true);
                    if (!duplicateResult.isEmpty()) {
                        duplicateNameId += 1;
                        newName = pairs.getKey() + "_" + duplicateNameId;
                        duplicateName = true;
                    } else {
                        duplicateName = false;
                    }
                } while (duplicateName);
                pStmt = connection.prepareStatement("update encounter_role set name = ?, changed_by = ?, date_changed = ? where encounter_role_id = ?");
                if (!duplicateResult.isEmpty()) {
                    pStmt.setString(1, newName);
                }
                pStmt.setString(1, newName);
                pStmt.setInt(2, DatabaseUpdater.getAuthenticatedUserId());
                Calendar cal = Calendar.getInstance();
                Date date = new Date(cal.getTimeInMillis());
                pStmt.setDate(3, date);
                pStmt.setInt(4, ids.get(i));
                duplicateNameId += 1;
                pStmt.executeUpdate();
            }
        }
    } catch (BatchUpdateException e) {
        log.warn("Error generated while processsing batch insert", e);
        try {
            log.debug("Rolling back batch", e);
            connection.rollback();
        } catch (Exception rbe) {
            log.warn("Error generated while rolling back batch insert", e);
        }
        // marks the changeset as a failed one
        throw new CustomChangeException("Failed to update one or more duplicate EncounterRole names", e);
    } catch (Exception e) {
        throw new CustomChangeException(e);
    } finally {
        // set auto commit to its initial state
        try {
            connection.commit();
            if (initialAutoCommit != null) {
                connection.setAutoCommit(initialAutoCommit);
            }
        } catch (DatabaseException e) {
            log.warn("Failed to set auto commit to ids initial state", e);
        }
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                log.warn("Failed to close the resultset object");
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                log.warn("Failed to close the select statement used to identify duplicate EncounterRole object names");
            }
        }
        if (pStmt != null) {
            try {
                pStmt.close();
            } catch (SQLException e) {
                log.warn("Failed to close the prepared statement used to update duplicate EncounterRole object names");
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) CustomChangeException(liquibase.exception.CustomChangeException) JdbcConnection(liquibase.database.jvm.JdbcConnection) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) BatchUpdateException(java.sql.BatchUpdateException) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Calendar(java.util.Calendar) Connection(java.sql.Connection) JdbcConnection(liquibase.database.jvm.JdbcConnection) PreparedStatement(java.sql.PreparedStatement) Date(java.sql.Date) BatchUpdateException(java.sql.BatchUpdateException) CustomChangeException(liquibase.exception.CustomChangeException) SetupException(liquibase.exception.SetupException) SQLException(java.sql.SQLException) DatabaseException(liquibase.exception.DatabaseException) HashMap(java.util.HashMap) Map(java.util.Map) DatabaseException(liquibase.exception.DatabaseException)

Example 28 with BatchUpdateException

use of java.sql.BatchUpdateException in project mssql-jdbc by Microsoft.

the class BatchExecuteWithErrorsTest method Repro47239.

/**
 * Batch test
 *
 * @throws SQLException
 */
@Test
@DisplayName("Batch Test")
public void Repro47239() throws SQLException {
    String tableN = RandomUtil.getIdentifier("t_Repro47239");
    final String tableName = AbstractSQLGenerator.escapeIdentifier(tableN);
    final String insertStmt = "INSERT INTO " + tableName + " VALUES (999, 'HELLO', '4/12/1994')";
    final String error16 = "RAISERROR ('raiserror level 16',16,42)";
    final String select = "SELECT 1";
    final String dateConversionError = "insert into " + tableName + " values (999999, 'Hello again', 'asdfasdf')";
    String warning;
    String error;
    String severe;
    con = DriverManager.getConnection(connectionString);
    if (DBConnection.isSqlAzure(con)) {
        // SQL Azure will throw exception for "raiserror WITH LOG", so the following RAISERROR statements have not "with log" option
        warning = "RAISERROR ('raiserror level 4',4,1)";
        error = "RAISERROR ('raiserror level 11',11,1)";
        // On SQL Azure, raising FATAL error by RAISERROR() is not supported and there is no way to
        // cut the current connection by a statement inside a SQL batch.
        // Details: Although one can simulate a fatal error (that cuts the connections) by dropping the database,
        // this simulation cannot be written entirely in TSQL (because it needs a new connection),
        // and thus it cannot be put into a TSQL batch and it is useless here.
        // So we have to skip the last scenario of this test case, i.e. "Test Severe (connection-closing) errors"
        // It is worthwhile to still execute the first 5 test scenarios of this test case, in order to have best test coverage.
        // this is a dummy statement that never being executed on SQL Azure
        severe = "--Not executed when testing against SQL Azure";
    } else {
        warning = "RAISERROR ('raiserror level 4',4,1) WITH LOG";
        error = "RAISERROR ('raiserror level 11',11,1) WITH LOG";
        severe = "RAISERROR ('raiserror level 20',20,1) WITH LOG";
    }
    con.close();
    int[] actualUpdateCounts;
    int[] expectedUpdateCounts;
    String actualExceptionText;
    // SQL Server 2005 driver
    try {
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    } catch (ClassNotFoundException e1) {
        fail(e1.toString());
    }
    Connection conn = DriverManager.getConnection(connectionString);
    Statement stmt = conn.createStatement();
    try {
        stmt.executeUpdate("drop table " + tableName);
    } catch (Exception ignored) {
    }
    stmt.executeUpdate("create table " + tableName + " (c1_int int, c2_varchar varchar(20), c3_date datetime, c4_int int identity(1,1) primary key)");
    // Regular Statement batch update
    expectedUpdateCounts = new int[] { 1, -2, 1, -2, 1, -2 };
    Statement batchStmt = conn.createStatement();
    batchStmt.addBatch(insertStmt);
    batchStmt.addBatch(warning);
    batchStmt.addBatch(insertStmt);
    batchStmt.addBatch(warning);
    batchStmt.addBatch(insertStmt);
    batchStmt.addBatch(warning);
    try {
        actualUpdateCounts = batchStmt.executeBatch();
        actualExceptionText = "";
    } catch (BatchUpdateException bue) {
        actualUpdateCounts = bue.getUpdateCounts();
        actualExceptionText = bue.getMessage();
        if (log.isLoggable(Level.FINE)) {
            log.fine("BatchUpdateException occurred. Message:" + actualExceptionText);
        }
    } finally {
        batchStmt.close();
    }
    if (log.isLoggable(Level.FINE)) {
        log.fine("UpdateCounts:");
    }
    for (int updateCount : actualUpdateCounts) {
        log.fine("" + updateCount + ",");
    }
    log.fine("");
    assertTrue(Arrays.equals(actualUpdateCounts, expectedUpdateCounts), "Test interleaved inserts and warnings");
    expectedUpdateCounts = new int[] { -3, 1, 1, 1 };
    stmt.addBatch(error);
    stmt.addBatch(insertStmt);
    stmt.addBatch(insertStmt);
    stmt.addBatch(insertStmt);
    try {
        actualUpdateCounts = stmt.executeBatch();
        actualExceptionText = "";
    } catch (BatchUpdateException bue) {
        actualUpdateCounts = bue.getUpdateCounts();
        actualExceptionText = bue.getMessage();
    }
    log.fine("UpdateCounts:");
    for (int updateCount : actualUpdateCounts) {
        log.fine("" + updateCount + ",");
    }
    log.fine("");
    assertTrue(Arrays.equals(actualUpdateCounts, expectedUpdateCounts), "Test error followed by inserts");
    // 50280
    expectedUpdateCounts = new int[] { 1, -3 };
    stmt.addBatch(insertStmt);
    stmt.addBatch(error16);
    try {
        actualUpdateCounts = stmt.executeBatch();
        actualExceptionText = "";
    } catch (BatchUpdateException bue) {
        actualUpdateCounts = bue.getUpdateCounts();
        actualExceptionText = bue.getMessage();
    }
    for (int updateCount : actualUpdateCounts) {
        log.fine("" + updateCount + ",");
    }
    log.fine("");
    assertTrue(Arrays.equals(actualUpdateCounts, expectedUpdateCounts), "Test insert followed by non-fatal error (50280)");
    // Test "soft" errors
    conn.setAutoCommit(false);
    stmt.addBatch(select);
    stmt.addBatch(insertStmt);
    stmt.addBatch(select);
    stmt.addBatch(insertStmt);
    try {
        stmt.executeBatch();
        assertEquals(true, false, "Soft error test: executeBatch unexpectedly succeeded");
    } catch (BatchUpdateException bue) {
        assertEquals("A result set was generated for update.", bue.getMessage(), "Soft error test: wrong error message in BatchUpdateException");
        assertEquals(Arrays.equals(bue.getUpdateCounts(), new int[] { -3, 1, -3, 1 }), true, "Soft error test: wrong update counts in BatchUpdateException");
    }
    conn.rollback();
    // Defect 128801: Rollback (with conversion error) should throw SQLException
    stmt.addBatch(dateConversionError);
    stmt.addBatch(insertStmt);
    stmt.addBatch(insertStmt);
    stmt.addBatch(insertStmt);
    try {
        stmt.executeBatch();
    } catch (BatchUpdateException bue) {
        assertThat(bue.getMessage(), containsString("Syntax error converting date"));
    // CTestLog.CompareStartsWith(bue.getMessage(), "Syntax error converting date", "Transaction rollback with conversion error threw wrong
    // BatchUpdateException");
    } catch (SQLException e) {
        assertThat(e.getMessage(), containsString("Conversion failed when converting date"));
    // CTestLog.CompareStartsWith(e.getMessage(), "Conversion failed when converting date", "Transaction rollback with conversion error threw
    // wrong SQLException");
    }
    conn.setAutoCommit(true);
    // It is worthwhile to still execute the first 5 test scenarios of this test case, in order to have best test coverage.
    if (!DBConnection.isSqlAzure(conn)) {
        // Test Severe (connection-closing) errors
        stmt.addBatch(error);
        stmt.addBatch(insertStmt);
        stmt.addBatch(warning);
        // TODO Removed until ResultSet refactoring task (45832) is complete.
        // stmt.addBatch(select); // error: select not permitted in batch
        stmt.addBatch(insertStmt);
        stmt.addBatch(severe);
        stmt.addBatch(insertStmt);
        stmt.addBatch(insertStmt);
        try {
            stmt.executeBatch();
            assertEquals(false, true, "Test fatal errors batch execution succeeded (should have failed)");
        } catch (BatchUpdateException bue) {
            assertEquals(false, true, "Test fatal errors returned BatchUpdateException rather than SQLException");
        } catch (SQLException e) {
            actualExceptionText = e.getMessage();
            if (actualExceptionText.endsWith("reset")) {
                assertTrue(actualExceptionText.equalsIgnoreCase("Connection reset"), "Test fatal errors");
            } else {
                assertTrue(actualExceptionText.equalsIgnoreCase("raiserror level 20"), "Test fatal errors");
            }
        }
    }
    try {
        stmt.executeUpdate("drop table " + tableName);
    } catch (Exception ignored) {
    }
    stmt.close();
    conn.close();
}
Also used : SQLException(java.sql.SQLException) Statement(java.sql.Statement) Connection(java.sql.Connection) DBConnection(com.microsoft.sqlserver.testframework.DBConnection) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) BatchUpdateException(java.sql.BatchUpdateException) SQLException(java.sql.SQLException) BatchUpdateException(java.sql.BatchUpdateException) Test(org.junit.jupiter.api.Test) AbstractTest(com.microsoft.sqlserver.testframework.AbstractTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 29 with BatchUpdateException

use of java.sql.BatchUpdateException in project mssql-jdbc by Microsoft.

the class PreparedStatementTest method testStatementPooling.

/**
 * Test handling of statement pooling for prepared statements.
 *
 * @throws SQLException
 */
@Test
@Tag("slow")
public void testStatementPooling() throws SQLException {
    // Test % handle re-use
    try (SQLServerConnection con = (SQLServerConnection) DriverManager.getConnection(connectionString)) {
        String query = String.format("/*statementpoolingtest_re-use_%s*/SELECT TOP(1) * FROM sys.tables;", UUID.randomUUID().toString());
        con.setStatementPoolingCacheSize(10);
        boolean[] prepOnFirstCalls = { false, true };
        for (boolean prepOnFirstCall : prepOnFirstCalls) {
            con.setEnablePrepareOnFirstPreparedStatementCall(prepOnFirstCall);
            int[] queryCounts = { 10, 20, 30, 40 };
            for (int queryCount : queryCounts) {
                String[] queries = new String[queryCount];
                for (int i = 0; i < queries.length; ++i) {
                    queries[i] = String.format("%s--%s--%s--%s", query, i, queryCount, prepOnFirstCall);
                }
                int testsWithHandleReuse = 0;
                final int testCount = 500;
                for (int i = 0; i < testCount; ++i) {
                    Random random = new Random();
                    int queryNumber = random.nextInt(queries.length);
                    try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(queries[queryNumber])) {
                        pstmt.execute();
                        // Grab handle-reuse before it would be populated if initially created.
                        if (0 < pstmt.getPreparedStatementHandle())
                            testsWithHandleReuse++;
                        // Make sure handle is updated.
                        pstmt.getMoreResults();
                    }
                }
                System.out.println(String.format("Prep on first call: %s Query count:%s: %s of %s (%s)", prepOnFirstCall, queryCount, testsWithHandleReuse, testCount, (double) testsWithHandleReuse / (double) testCount));
            }
        }
    }
    try (SQLServerConnection con = (SQLServerConnection) DriverManager.getConnection(connectionString)) {
        // Test behvaior with statement pooling.
        con.setStatementPoolingCacheSize(10);
        this.executeSQL(con, "IF NOT EXISTS (SELECT * FROM sys.messages WHERE message_id = 99586) EXEC sp_addmessage 99586, 16, 'Prepared handle GAH!';");
        // Test with missing handle failures (fake).
        this.executeSQL(con, "CREATE TABLE #update1 (col INT);INSERT #update1 VALUES (1);");
        this.executeSQL(con, "CREATE PROC #updateProc1 AS UPDATE #update1 SET col += 1; IF EXISTS (SELECT * FROM #update1 WHERE col % 5 = 0) RAISERROR(99586,16,1);");
        try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement("#updateProc1")) {
            for (int i = 0; i < 100; ++i) {
                try {
                    assertSame(1, pstmt.executeUpdate());
                } catch (SQLException e) {
                    // Since the original "Could not find prepared statement with handle" error does not terminate the execution after it.
                    if (!e.getMessage().contains("Prepared handle GAH")) {
                        throw e;
                    }
                }
            }
        }
        // although executeUpdate() throws exception, update operation should be executed successfully.
        try (ResultSet rs = con.createStatement().executeQuery("select * from #update1")) {
            rs.next();
            assertSame(101, rs.getInt(1));
        }
        // Test batching with missing handle failures (fake).
        this.executeSQL(con, "IF NOT EXISTS (SELECT * FROM sys.messages WHERE message_id = 99586) EXEC sp_addmessage 99586, 16, 'Prepared handle GAH!';");
        this.executeSQL(con, "CREATE TABLE #update2 (col INT);INSERT #update2 VALUES (1);");
        this.executeSQL(con, "CREATE PROC #updateProc2 AS UPDATE #update2 SET col += 1; IF EXISTS (SELECT * FROM #update2 WHERE col % 5 = 0) RAISERROR(99586,16,1);");
        try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement("#updateProc2")) {
            for (int i = 0; i < 100; ++i) {
                pstmt.addBatch();
            }
            int[] updateCounts = null;
            try {
                updateCounts = pstmt.executeBatch();
            } catch (BatchUpdateException e) {
                // Since the original "Could not find prepared statement with handle" error does not terminate the execution after it.
                if (!e.getMessage().contains("Prepared handle GAH")) {
                    throw e;
                }
            }
            // since executeBatch() throws exception, it does not return anthing. So updateCounts is still null.
            assertSame(null, updateCounts);
            // although executeBatch() throws exception, update operation should be executed successfully.
            try (ResultSet rs = con.createStatement().executeQuery("select * from #update2")) {
                rs.next();
                assertSame(101, rs.getInt(1));
            }
        }
    }
    try (SQLServerConnection con = (SQLServerConnection) DriverManager.getConnection(connectionString)) {
        // Test behvaior with statement pooling.
        con.setDisableStatementPooling(false);
        con.setStatementPoolingCacheSize(10);
        String lookupUniqueifier = UUID.randomUUID().toString();
        String query = String.format("/*statementpoolingtest_%s*/SELECT * FROM sys.tables;", lookupUniqueifier);
        // Execute statement first, should create cache entry WITHOUT handle (since sp_executesql was used).
        try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(query)) {
            // sp_executesql
            pstmt.execute();
            // Make sure handle is updated.
            pstmt.getMoreResults();
            assertSame(0, pstmt.getPreparedStatementHandle());
        }
        // Execute statement again, should now create handle.
        int handle = 0;
        try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(query)) {
            // sp_prepexec
            pstmt.execute();
            // Make sure handle is updated.
            pstmt.getMoreResults();
            handle = pstmt.getPreparedStatementHandle();
            assertNotSame(0, handle);
        }
        // Execute statement again and verify same handle was used.
        try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(query)) {
            // sp_execute
            pstmt.execute();
            // Make sure handle is updated.
            pstmt.getMoreResults();
            assertNotSame(0, pstmt.getPreparedStatementHandle());
            assertSame(handle, pstmt.getPreparedStatementHandle());
        }
        // Execute new statement with different SQL text and verify it does NOT get same handle (should now fall back to using sp_executesql).
        SQLServerPreparedStatement outer = null;
        try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(query + ";")) {
            outer = pstmt;
            // sp_executesql
            pstmt.execute();
            // Make sure handle is updated.
            pstmt.getMoreResults();
            assertSame(0, pstmt.getPreparedStatementHandle());
            assertNotSame(handle, pstmt.getPreparedStatementHandle());
        }
        try {
            System.out.println(outer.getPreparedStatementHandle());
            fail("Error for invalid use of getPreparedStatementHandle() after statement close expected.");
        } catch (Exception e) {
        // Good!
        }
    }
}
Also used : SQLException(java.sql.SQLException) SQLServerPreparedStatement(com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement) BatchUpdateException(java.sql.BatchUpdateException) SQLException(java.sql.SQLException) SQLServerConnection(com.microsoft.sqlserver.jdbc.SQLServerConnection) Random(java.util.Random) ResultSet(java.sql.ResultSet) BatchUpdateException(java.sql.BatchUpdateException) Test(org.junit.jupiter.api.Test) AbstractTest(com.microsoft.sqlserver.testframework.AbstractTest) Tag(org.junit.jupiter.api.Tag)

Example 30 with BatchUpdateException

use of java.sql.BatchUpdateException in project openmrs-core by openmrs.

the class ConceptValidatorChangeSet method runBatchUpdate.

/**
 * Executes all the changes to the concept names as a batch update.
 *
 * @param connection The database connection
 */
private void runBatchUpdate(JdbcConnection connection) {
    PreparedStatement pStmt = null;
    try {
        connection.setAutoCommit(false);
        pStmt = connection.prepareStatement("UPDATE concept_name SET locale = ?, concept_name_type = ?, locale_preferred = ?, voided = ?, date_voided = ?, void_reason = ?, voided_by = ? WHERE concept_name_id = ?");
        Integer userId = DatabaseUpdater.getAuthenticatedUserId();
        // is we have no authenticated user(for API users), set as Daemon
        if (userId == null || userId < 1) {
            userId = getInt(connection, "SELECT min(user_id) FROM users");
            // leave it as null rather than setting it to 0
            if (userId < 1) {
                userId = null;
            }
        }
        for (ConceptName conceptName : updatedConceptNames) {
            pStmt.setString(1, conceptName.getLocale().toString());
            pStmt.setString(2, (conceptName.getConceptNameType() != null) ? conceptName.getConceptNameType().toString() : null);
            pStmt.setBoolean(3, conceptName.getLocalePreferred());
            pStmt.setBoolean(4, conceptName.getVoided());
            pStmt.setDate(5, conceptName.getVoided() ? new Date(System.currentTimeMillis()) : null);
            pStmt.setString(6, conceptName.getVoidReason());
            // "Not all databases allow for a non-typed Null to be sent to the backend", so we can't use setInt
            pStmt.setObject(7, (conceptName.getVoided() && userId != null) ? userId : null, Types.INTEGER);
            pStmt.setInt(8, conceptName.getConceptNameId());
            pStmt.addBatch();
        }
        try {
            int[] updateCounts = pStmt.executeBatch();
            for (int updateCount : updateCounts) {
                if (updateCount > -1) {
                    log.debug("Successfully executed: updateCount=" + updateCount);
                } else if (updateCount == Statement.SUCCESS_NO_INFO) {
                    log.debug("Successfully executed; No Success info");
                } else if (updateCount == Statement.EXECUTE_FAILED) {
                    log.warn("Failed to execute update");
                }
            }
            log.debug("Committing updates...");
            connection.commit();
        } catch (BatchUpdateException be) {
            log.warn("Error generated while processsing batch update", be);
            int[] updateCounts = be.getUpdateCounts();
            for (int updateCount : updateCounts) {
                if (updateCount > -1) {
                    log.warn("Executed with exception: updateCount=" + updateCount);
                } else if (updateCount == Statement.SUCCESS_NO_INFO) {
                    log.warn("Executed with exception; No Success info");
                } else if (updateCount == Statement.EXECUTE_FAILED) {
                    log.warn("Failed to execute update with exception");
                }
            }
            try {
                log.warn("Rolling back batch", be);
                connection.rollback();
            } catch (Exception rbe) {
                log.warn("Error generated while rolling back batch update", be);
            }
        }
    } catch (SQLException | DatabaseException e) {
        log.warn("Error generated", e);
    } finally {
        // reset to auto commit mode
        try {
            connection.setAutoCommit(true);
        } catch (DatabaseException e) {
            log.warn("Failed to reset auto commit back to true", e);
        }
        if (pStmt != null) {
            try {
                pStmt.close();
            } catch (SQLException e) {
                log.warn("Failed to close the prepared statement object");
            }
        }
    }
}
Also used : SQLException(java.sql.SQLException) ConceptName(org.openmrs.ConceptName) PreparedStatement(java.sql.PreparedStatement) DatabaseException(liquibase.exception.DatabaseException) Date(java.sql.Date) BatchUpdateException(java.sql.BatchUpdateException) CustomChangeException(liquibase.exception.CustomChangeException) SetupException(liquibase.exception.SetupException) SQLException(java.sql.SQLException) DatabaseException(liquibase.exception.DatabaseException) BatchUpdateException(java.sql.BatchUpdateException)

Aggregations

BatchUpdateException (java.sql.BatchUpdateException)103 SQLException (java.sql.SQLException)39 PreparedStatement (java.sql.PreparedStatement)33 Statement (java.sql.Statement)22 ArrayList (java.util.ArrayList)19 Test (org.junit.Test)19 Connection (java.sql.Connection)17 Test (org.testng.annotations.Test)17 BaseTest (util.BaseTest)17 SerializedBatchUpdateException (util.SerializedBatchUpdateException)17 ResultSet (java.sql.ResultSet)13 List (java.util.List)12 CallableStatement (java.sql.CallableStatement)8 HashSet (java.util.HashSet)8 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)7 HashMap (java.util.HashMap)6 Map (java.util.Map)5 CustomChangeException (liquibase.exception.CustomChangeException)5 DatabaseException (liquibase.exception.DatabaseException)5 SetupException (liquibase.exception.SetupException)5