/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.util.databasechange; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import org.openmrs.util.DatabaseUtil; import org.openmrs.util.OpenmrsConstants; import liquibase.change.custom.CustomTaskChange; import liquibase.database.Database; import liquibase.database.jvm.JdbcConnection; import liquibase.exception.CustomChangeException; import liquibase.exception.DatabaseException; import liquibase.exception.SetupException; import liquibase.exception.ValidationErrors; import liquibase.resource.ResourceAccessor; /** * This changeset creates provider accounts for orderers that have no providers accounts, and then * converts the orderer from being users to providers */ public class ConvertOrderersToProviders implements CustomTaskChange { @Override public void execute(Database database) throws CustomChangeException { JdbcConnection connection = (JdbcConnection) database.getConnection(); try { List<List<Object>> usersAndProviders = getUsersAndProviders(connection); convertOrdererToProvider(connection, usersAndProviders); } catch (Exception e) { throw new CustomChangeException(e); } } private List<List<Object>> getUsersAndProviders(JdbcConnection connection) throws CustomChangeException, SQLException { //Should only match on current users that are orderers final String query = "SELECT u.user_id AS userId, p.provider_id AS providerId FROM users u, provider p" + " WHERE u.person_id = p.person_id AND u.user_id IN (select orderer from orders)"; return DatabaseUtil.executeSQL(connection.getUnderlyingConnection(), query, true); } private void convertOrdererToProvider(JdbcConnection connection, List<List<Object>> usersAndProviders) throws CustomChangeException, SQLException, DatabaseException { final int batchSize = 1000; int index = 0; PreparedStatement updateStatement = null; Statement statement = connection.createStatement(); Boolean autoCommit = null; try { autoCommit = connection.getAutoCommit(); connection.setAutoCommit(false); updateStatement = connection.prepareStatement("UPDATE orders SET orderer = ? WHERE orderer = ?"); boolean supportsBatchUpdate = connection.getMetaData().supportsBatchUpdates(); for (List<Object> row : usersAndProviders) { updateStatement.setInt(1, (Integer) row.get(1)); updateStatement.setInt(2, (Integer) row.get(0)); if (supportsBatchUpdate) { updateStatement.addBatch(); index++; if (index % batchSize == 0) { updateStatement.executeBatch(); } } else { updateStatement.executeUpdate(); } } if (supportsBatchUpdate) { updateStatement.executeBatch(); } //Set the orderer for orders with null orderer to Unknown Provider statement.execute("UPDATE orders SET orderer = " + "(SELECT provider_id FROM provider WHERE uuid =" + "(SELECT property_value FROM global_property WHERE property = '" + "" + OpenmrsConstants.GP_UNKNOWN_PROVIDER_UUID + "')) " + "WHERE orderer IS NULL"); connection.commit(); } catch (DatabaseException e) { handleError(connection, e); } catch (SQLException e) { handleError(connection, e); } finally { if (autoCommit != null) { connection.setAutoCommit(autoCommit); } if (updateStatement != null) { updateStatement.close(); } if (statement != null) { statement.close(); } } } @Override public String getConfirmationMessage() { return "Finished converting orders.orderer from user_id to provider_id"; } @Override public void setUp() throws SetupException { } @Override public void setFileOpener(ResourceAccessor resourceAccessor) { } @Override public ValidationErrors validate(Database database) { return null; } private void handleError(JdbcConnection connection, Exception e) throws DatabaseException, CustomChangeException { connection.rollback(); throw new CustomChangeException(e); } }