Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle initializing >1 system in patches table. #40

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
* <ul>
* <li>patches.create - DDL that creates the patches table</li>
* <li>level.create - SQL that inserts a new patch level record for the system</li>
* <li>level.count - SQL that counts patches for the system</li>
* <li>level.read - SQL that selects the current patch level of the system</li>
* <li>level.update - SQL that updates the current patch level of the system</li>
* <li>lock.read - Returns 'T' if the system patch lock is in use, 'F' otherwise</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,6 @@ public void createPatchStoreIfNeeded() throws MigrationException
}
stmt.execute();
context.commit();

// We don't yet have a patch record for this system; create one
createSystemPatchRecord();
}
catch (SQLException sqle)
{
Expand All @@ -150,6 +147,20 @@ public void createPatchStoreIfNeeded() throws MigrationException
{
SqlUtil.close(conn, stmt, rs);
}

try {
// We don't yet have a patch record for this system; create one
createSystemPatchRecord();
}
catch (Exception ex)
{
throw new MigrationException("Unexpected exception while creating system record.", ex);
}
finally
{
SqlUtil.close(conn, stmt, rs);
}

}

/**
Expand Down Expand Up @@ -361,14 +372,26 @@ private void createSystemPatchRecord() throws MigrationException, SQLException
String systemName = context.getSystemName();
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{
conn = context.getConnection();
stmt = conn.prepareStatement(getSql("level.create"));
stmt = conn.prepareStatement(getSql("level.count"));
stmt.setString(1, systemName);
stmt.execute();
context.commit();
log.info("Created patch record for " + systemName);
rs = stmt.executeQuery();
rs.next();
if (rs.getInt(1) == 0)
{
SqlUtil.close(null, stmt, null);
stmt = conn.prepareStatement(getSql("level.create"));
stmt.setString(1, systemName);
stmt.execute();
context.commit();
log.info("Created patch record for " + systemName);
} else
{
log.debug("Patch record already existed for " + systemName);
}
}
catch (SQLException e)
{
Expand All @@ -377,7 +400,7 @@ private void createSystemPatchRecord() throws MigrationException, SQLException
}
finally
{
SqlUtil.close(conn, stmt, null);
SqlUtil.close(conn, stmt, rs);
}
}

Expand All @@ -402,7 +425,7 @@ private boolean updatePatchLock(boolean lock) throws MigrationException
stmt = conn.prepareStatement(getSql(sqlkey));
if (log.isDebugEnabled())
{
log.debug("Updating patch table lock: " + getSql(sqlkey));
log.debug("Updating patch table lock for system " + context.getSystemName() + ": " + getSql(sqlkey));
}
stmt.setString(1, context.getSystemName());
if (lock)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ patches.create=CREATE TABLE patches ( \

# Validates that a record exists for a given system
level.create=INSERT INTO patches (system_name, patch_level) VALUES ( ?, 0)
level.count=SELECT COUNT(*) FROM patches WHERE system_name = ?
level.table.exists=SELECT patch_level FROM patches WHERE system_name = ?
level.read=SELECT MAX(patch_level) FROM patches WHERE system_name = ?
level.rollback=DELETE FROM patches WHERE patch_level = ? and system_name = ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ patches.create=CREATE TABLE IF NOT EXISTS patches ( \

# Validates that a record exists for a given system
level.create=INSERT INTO patches (system_name, patch_level) VALUES ( ?, 0 )
level.count=SELECT COUNT(*) FROM patches WHERE system_name = ?
level.table.exists=SELECT patch_level FROM patches WHERE system_name = ?
level.read=SELECT MAX(patch_level) FROM patches WHERE system_name = ?
level.rollback=DELETE FROM patches WHERE patch_level = ? and system_name = ?
Expand All @@ -21,4 +22,4 @@ patches.all=SELECT patch_level FROM patches WHERE system_name = ?
# the system is currently locked.
lock.read=SELECT patch_in_progress FROM patches WHERE system_name = ? AND ( patch_in_progress <> 'F' OR patch_level in ( SELECT MAX(patch_level) FROM patches WHERE system_name = ? ))
lock.obtain=UPDATE patches SET patch_in_progress = 'T' WHERE system_name = ? AND patch_in_progress = 'F' AND patch_level in ( SELECT max_patch_level FROM (SELECT MAX(patch_level) AS max_patch_level FROM patches WHERE system_name = ? ) AS tmptable )
lock.release=UPDATE patches SET patch_in_progress = 'F' WHERE system_name = ? AND patch_in_progress <> 'F'
lock.release=UPDATE patches SET patch_in_progress = 'F' WHERE system_name = ? AND patch_in_progress <> 'F'
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ patches.create=CREATE TABLE tk_patches (\

# Validates that a record exists for a given system
level.create=INSERT INTO tk_patches (system_name, patch_level) VALUES ( ?, 0 )
level.count=SELECT COUNT(*) FROM tk_patches WHERE system_name = ?
level.table.exists=SELECT patch_level FROM tk_patches WHERE system_name = ?
level.read=SELECT MAX(patch_level) FROM tk_patches WHERE system_name = ?
level.rollback=DELETE FROM tk_patches WHERE patch_level = ? and system_name = ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ patches.create=CREATE TABLE patches ( \

# Validates that a record exists for a given system
level.create=INSERT INTO patches (system_name, patch_level) VALUES ( ?, 0 )
level.count=SELECT COUNT(*) FROM patches WHERE system_name = ?
level.table.exists=SELECT patch_level FROM patches WHERE system_name = ?
level.read=SELECT MAX(patch_level) FROM patches WHERE system_name = ?
level.rollback=DELETE FROM patches WHERE patch_level = ? and system_name = ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ patches.create=CREATE TABLE patches ( \

# Validates that a record exists for a given system
level.create=INSERT INTO patches (system_name, patch_level) VALUES ( ?, 0)
level.count=SELECT COUNT(*) FROM patches WHERE system_name = ?
level.table.exists=SELECT patch_level FROM patches WHERE system_name = ?
level.read=SELECT MAX(patch_level) FROM patches WHERE system_name = ?
level.rollback=DELETE FROM patches WHERE patch_level = ? and system_name = ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ patches.create=CREATE TABLE patches (\

# Validates that a record exists for a given system
level.create=INSERT INTO patches (system_name, patch_level) VALUES ( ?, 0 )
level.count=SELECT COUNT(*) FROM patches WHERE system_name = ?
level.table.exists=SELECT patch_level FROM patches WHERE system_name = ?
level.read=SELECT MAX(patch_level) FROM patches WHERE system_name = ?
level.rollback=DELETE FROM patches WHERE patch_level = ? and system_name = ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
package com.tacitknowledge.util.migration.jdbc;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.BooleanUtils;
import org.easymock.MockControl;

import com.mockrunner.jdbc.JDBCTestCaseAdapter;
Expand Down Expand Up @@ -115,6 +117,7 @@ public void testCreatePatchesTable() throws Exception
PreparedStatementResultSetHandler h = conn.getPreparedStatementResultSetHandler();
h.prepareThrowsSQLException(table.getSql("level.table.exists"));

setupLevelCreatedMock(h, false);
table.createPatchStoreIfNeeded();

commonVerifications();
Expand Down Expand Up @@ -193,6 +196,18 @@ public void testGetPatchLevel() throws Exception
verifyPreparedStatementNotPresent(table.getSql("level.create"));
}

/**
* Adds a result set to a data source mock to simulate existence of a patch level record.
*
* @param handler prepared statement handler
* @param levelExists controls what the mock returns for whether a level was already created or not
*/
private void setupLevelCreatedMock(PreparedStatementResultSetHandler handler, Boolean levelExists) {
MockResultSet rs = handler.createResultSet();
handler.prepareResultSet(table.getSql("level.count"), rs);
rs.addRow(new Integer[] {BooleanUtils.toInteger(levelExists)});
}

/**
* Validates that <code>getPatchLevel</code> works on a new system.
*
Expand All @@ -206,6 +221,7 @@ public void testGetPatchLevelFirstTime() throws Exception
// empty result set
handler.prepareResultSet(table.getSql("level.read"), rs);
handler.prepareThrowsSQLException(table.getSql("level.table.exists"));
setupLevelCreatedMock(handler, false);

int i = table.getPatchLevel();

Expand All @@ -227,6 +243,7 @@ public void testUpdatePatchLevel() throws Exception
MockResultSet rs = handler.createResultSet();
rs.addRow(new Integer[]{new Integer(12)});
handler.prepareResultSet(table.getSql("level.read"), rs, new String[]{"milestone"});
setupLevelCreatedMock(handler, true);

table.updatePatchLevel(13);

Expand All @@ -251,6 +268,7 @@ public void testIsPatchTableNotLocked() throws Exception
MockResultSet rs = handler.createResultSet();
rs.addRow(new String[]{"F"});
handler.prepareResultSet(table.getSql("lock.read"), rs, new String[]{"milestone", "milestone"});
setupLevelCreatedMock(handler, true);

assertFalse(table.isPatchStoreLocked());
commonVerifications();
Expand All @@ -272,6 +290,7 @@ public void testIsPatchTableLocked() throws Exception
MockResultSet rs = handler.createResultSet();
rs.addRow(new String[]{"T"});
handler.prepareResultSet(table.getSql("lock.read"), rs, new String[]{"milestone", "milestone"});
setupLevelCreatedMock(handler, true);

assertTrue(table.isPatchStoreLocked());
commonVerifications();
Expand All @@ -292,6 +311,7 @@ public void testLockPatchTableWhenAlreadyLocked() throws Exception
// Return a non-empty set in response to the patch lock query
handler = conn.getPreparedStatementResultSetHandler();
handler.prepareUpdateCount(table.getSql("lock.obtain"), 0, new String[] {"milestone", "milestone"});
setupLevelCreatedMock(handler, true);

try
{
Expand Down Expand Up @@ -322,7 +342,7 @@ public void testLockPatchTableWhenNotAlreadyLocked() throws Exception
// Test-specific setup
// Return an empty set in response to the patch lock query
handler = conn.getPreparedStatementResultSetHandler();
MockResultSet rs = handler.createResultSet();
setupLevelCreatedMock(handler, true);
handler.prepareUpdateCount(table.getSql("lock.obtain"), 1, new String[] {"milestone", "milestone"});

table.lockPatchStore();
Expand Down Expand Up @@ -407,6 +427,48 @@ public void testPatchRetrievesSetWithPatchesApplied () throws SQLException, Migr
verifyPreparedStatementPresent(table.getSql("patches.all"));
}

public void testSecondSystemInitialized () throws Exception, SQLException, MigrationException {
String systemName = "milestone";
// setup test like testGetPatchLevelFirstTime
handler = conn.getPreparedStatementResultSetHandler();
MockResultSet rs = handler.createResultSet();
// empty result set
handler.prepareResultSet(table.getSql("level.read"), rs, Arrays.asList(systemName));
handler.prepareThrowsSQLException(table.getSql("level.table.exists"));
setupLevelCreatedMock(handler, false);

int i = table.getPatchLevel();

assertEquals(0, i);
commonVerifications();
verifyPreparedStatementPresent(table.getSql("level.create"));
verifyPreparedStatementParameter(table.getSql("level.create"), 1, systemName);

// Test-specific setup
// setup a second system backed by the same database table and verify that it is initialized properly
systemName = "orders";
DataSourceMigrationContext context2 = new DataSourceMigrationContext();
context2.setDataSource(new ConnectionWrapperDataSource(conn));
context2.setSystemName(systemName);
context2.setDatabaseType(new DatabaseType("hsqldb"));
PatchTable table2 = new PatchTable(context2);

// clear the exception from above which caused the database table to be created
handler.clearThrowsSQLException();
// clear out prepared statements since one is for "patches.create"
handler.clearPreparedStatements();
// simulate the table existing (since it was created by the first system)
rs = handler.createResultSet();
handler.prepareResultSet(table2.getSql("level.table.exists"), rs, Arrays.asList(systemName));
rs = handler.createResultSet();
handler.prepareResultSet(table2.getSql("level.read"), rs, Arrays.asList(systemName));

i = table2.getPatchLevel();
assertEquals(0, i);
verifyPreparedStatementNotPresent(table2.getSql("patches.create"));
verifyPreparedStatementPresent(table2.getSql("level.create"));
verifyPreparedStatementParameter(table2.getSql("level.create"), 1, systemName);
}

private void commonVerifications()
{
Expand Down