diff --git a/.gitignore b/.gitignore
index d6c3350..866120e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,5 @@ target
*.iws
.idea
*.externalToolBuilders
+*.bak
+*.tmp
diff --git a/pom.xml b/pom.xml
index ceb71a5..9e4dd57 100644
--- a/pom.xml
+++ b/pom.xml
@@ -276,12 +276,12 @@
- commons-lang
- commons-lang
- [2.0,)
+ org.apache.commons
+ commons-lang3
+ [3.0,)
compile
-
+
commons-logging
commons-logging
diff --git a/src/main/java/com/tacitknowledge/util/migration/DistributedMigrationProcess.java b/src/main/java/com/tacitknowledge/util/migration/DistributedMigrationProcess.java
index 7980955..b76ff59 100644
--- a/src/main/java/com/tacitknowledge/util/migration/DistributedMigrationProcess.java
+++ b/src/main/java/com/tacitknowledge/util/migration/DistributedMigrationProcess.java
@@ -436,9 +436,16 @@ public final LinkedHashMap getMigrationTasksWithLaunchers() throws MigrationExce
if (log.isDebugEnabled())
{
Iterator launchers = subLauncher.getContexts().keySet().iterator();
- String systemName = ((JdbcMigrationContext) launchers.next()).getSystemName();
- log.debug("\tMigration+Launcher binder found subtask " + task.getName()
+ if (!launchers.hasNext()) {
+ log.debug("\tMigration+Launcher binder found subtask " + task.getName()
+ + " with no contexts defined");
+
+ } else {
+ JdbcMigrationContext next = (JdbcMigrationContext) launchers.next();
+ String systemName = next.getSystemName();
+ log.debug("\tMigration+Launcher binder found subtask " + task.getName()
+ " for launcher context " + systemName);
+ }
}
// store the task, related to its launcher
diff --git a/src/main/java/com/tacitknowledge/util/migration/MigrationRunnerFactory.java b/src/main/java/com/tacitknowledge/util/migration/MigrationRunnerFactory.java
index 440ff9c..4d85561 100644
--- a/src/main/java/com/tacitknowledge/util/migration/MigrationRunnerFactory.java
+++ b/src/main/java/com/tacitknowledge/util/migration/MigrationRunnerFactory.java
@@ -15,7 +15,7 @@
package com.tacitknowledge.util.migration;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -35,23 +35,24 @@ public class MigrationRunnerFactory
public static MigrationRunnerStrategy getMigrationRunnerStrategy(String strategy)
{
- log.info("Strategy received '" + strategy + "'");
if (StringUtils.isBlank(strategy))
{
+ log.info("No migration strategy specified. Using default: '" + DEFAULT_MIGRATION_STRATEGY + "'");
return new OrderedMigrationRunnerStrategy();
}
try
{
+ log.info("Using specified migration strategy: '" + strategy + "'");
Class c = Class.forName(strategy.trim());
MigrationRunnerStrategy runnerStrategy = (MigrationRunnerStrategy) c.newInstance();
return runnerStrategy;
}
catch (Exception e)
{
- throw new IllegalArgumentException("Strategy selected " + strategy + " cannot be instantiated ", e);
+ throw new IllegalArgumentException("Specified strategy (" + strategy + ") cannot be instantiated ", e);
}
diff --git a/src/main/java/com/tacitknowledge/util/migration/MissingPatchMigrationRunnerStrategy.java b/src/main/java/com/tacitknowledge/util/migration/MissingPatchMigrationRunnerStrategy.java
index 44f9d33..6dfef07 100644
--- a/src/main/java/com/tacitknowledge/util/migration/MissingPatchMigrationRunnerStrategy.java
+++ b/src/main/java/com/tacitknowledge/util/migration/MissingPatchMigrationRunnerStrategy.java
@@ -15,7 +15,7 @@
package com.tacitknowledge.util.migration;
-import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang3.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -38,6 +38,7 @@ public boolean shouldMigrationRun(int migrationLevel, PatchInfoStore patchInfoSt
throw new IllegalArgumentException("Patch Info Store should not be null");
}
+ // This is the crux of this migration strategy. As long as a patch has not yet been executed, it can be.
return !patchInfoStore.isPatchApplied(migrationLevel);
}
diff --git a/src/main/java/com/tacitknowledge/util/migration/OrderedMigrationRunnerStrategy.java b/src/main/java/com/tacitknowledge/util/migration/OrderedMigrationRunnerStrategy.java
index cafe706..6091d8b 100644
--- a/src/main/java/com/tacitknowledge/util/migration/OrderedMigrationRunnerStrategy.java
+++ b/src/main/java/com/tacitknowledge/util/migration/OrderedMigrationRunnerStrategy.java
@@ -34,6 +34,7 @@ public class OrderedMigrationRunnerStrategy implements MigrationRunnerStrategy
{
public boolean shouldMigrationRun(int migrationLevel, PatchInfoStore patchInfoStore) throws MigrationException
{
+ // This is the crux of this migration strategy. Only patches with a patch level higher than the highest one executed so far are eligible to be excuted.
return migrationLevel > patchInfoStore.getPatchLevel();
}
diff --git a/src/main/java/com/tacitknowledge/util/migration/jdbc/AutoPatchSupport.java b/src/main/java/com/tacitknowledge/util/migration/jdbc/AutoPatchSupport.java
index fdaed71..081fdd3 100644
--- a/src/main/java/com/tacitknowledge/util/migration/jdbc/AutoPatchSupport.java
+++ b/src/main/java/com/tacitknowledge/util/migration/jdbc/AutoPatchSupport.java
@@ -51,6 +51,7 @@ public class AutoPatchSupport
*/
public AutoPatchSupport(String systemName) throws MigrationException
{
+ //TODO should be injected
this(new JdbcMigrationLauncherFactoryLoader().createFactory(), systemName);
}
diff --git a/src/main/java/com/tacitknowledge/util/migration/jdbc/DatabaseType.java b/src/main/java/com/tacitknowledge/util/migration/jdbc/DatabaseType.java
index 045ba27..d79f1bf 100644
--- a/src/main/java/com/tacitknowledge/util/migration/jdbc/DatabaseType.java
+++ b/src/main/java/com/tacitknowledge/util/migration/jdbc/DatabaseType.java
@@ -19,6 +19,9 @@
import java.io.InputStream;
import java.util.Properties;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
/**
* Defines a type of database (e.g. oracle or postgres. This
* is used to help define the SQL that is used to update the patch table and as a hint
@@ -51,6 +54,8 @@
*/
public class DatabaseType
{
+ private static Log log = LogFactory.getLog(DatabaseType.class);
+
/**
* The SQL statements and properties that are unique to this database flavor.
*/
@@ -89,6 +94,16 @@ public DatabaseType(String databaseType)
// this is okay, in this class, migration.properties is only used to override SQL
}
this.databaseType = databaseType;
+ log.debug("AutoPatch instantiated and loaded with properties per " + databasePropertiesFilename);
+ if (isMultipleStatementsSupported())
+ {
+ log.debug("AutoPatch thinks that Multiple SQL Statements can be executed at once.");
+ }
+ else
+ {
+ log.debug("AutoPatch thinks that Multiple SQL Statements must be executed separately.");
+ }
+
}
protected Properties loadProperties(String propertiesFilename, ClassLoader loader)
diff --git a/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncher.java b/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncher.java
index ed52e41..b6491a8 100644
--- a/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncher.java
+++ b/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncher.java
@@ -766,11 +766,13 @@ public void rollbackSuccessful(RollbackableMigrationTask task, int rollbackLevel
public void setMigrationStrategy(String migrationStrategy)
{
+ log.debug("Setting migration strategy to: "+migrationStrategy+ " (was: "+this.migrationStrategy+")");
this.migrationStrategy = migrationStrategy;
}
public String getMigrationStrategy()
{
+ log.debug("Get-accessor says migration strategy is: "+migrationStrategy);
return migrationStrategy;
}
}
diff --git a/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncherFactory.java b/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncherFactory.java
index b261b51..7a4204e 100644
--- a/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncherFactory.java
+++ b/src/main/java/com/tacitknowledge/util/migration/jdbc/JdbcMigrationLauncherFactory.java
@@ -20,7 +20,7 @@
import com.tacitknowledge.util.migration.MigrationListener;
import com.tacitknowledge.util.migration.jdbc.util.ConfigurationUtil;
import com.tacitknowledge.util.migration.jdbc.util.NonPooledDataSource;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -123,6 +123,7 @@ public JdbcMigrationLauncher createMigrationLauncher(String systemName)
public JdbcMigrationLauncher createMigrationLauncher(ServletContextEvent sce)
throws MigrationException
{
+ log.info("Creating JdbcMigrationLauncher for web-application.");
JdbcMigrationLauncher launcher = getJdbcMigrationLauncher();
configureFromServletContext(launcher, sce);
return launcher;
@@ -139,6 +140,14 @@ public JdbcMigrationLauncher createMigrationLauncher(ServletContextEvent sce)
private void configureFromServletContext(JdbcMigrationLauncher launcher,
ServletContextEvent sce) throws MigrationException
{
+ log.debug("Configuring launcher from Servlet Context (web.xml)");
+
+ String migrationStrategy = sce.getServletContext().getInitParameter("migration.strategy");
+ log.debug("Servlet Container says migration.strategy = "+migrationStrategy);
+ if (!StringUtils.isBlank(migrationStrategy)) {
+ launcher.setMigrationStrategy(migrationStrategy);
+ }
+
String readOnly = sce.getServletContext().getInitParameter("migration.readonly");
launcher.setReadOnly(false);
if ("true".equals(readOnly))
@@ -155,6 +164,7 @@ private void configureFromServletContext(JdbcMigrationLauncher launcher,
}
String patchPath = ConfigurationUtil.getRequiredParam("migration.patchpath", sce, this);
+ log.debug("migration.patchpath (required) = "+patchPath);
launcher.setPatchPath(patchPath);
String postPatchPath = sce.getServletContext().getInitParameter("migration.postpatchpath");
diff --git a/src/main/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTask.java b/src/main/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTask.java
index e778235..6282cbc 100644
--- a/src/main/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTask.java
+++ b/src/main/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTask.java
@@ -20,7 +20,7 @@
import com.tacitknowledge.util.migration.MigrationTaskSupport;
import com.tacitknowledge.util.migration.jdbc.util.SqlUtil;
import com.tacitknowledge.util.migration.jdbc.util.SybaseUtil;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/src/main/java/com/tacitknowledge/util/migration/jdbc/StandaloneMigrationLauncher.java b/src/main/java/com/tacitknowledge/util/migration/jdbc/StandaloneMigrationLauncher.java
index 2e20da2..87e65d3 100644
--- a/src/main/java/com/tacitknowledge/util/migration/jdbc/StandaloneMigrationLauncher.java
+++ b/src/main/java/com/tacitknowledge/util/migration/jdbc/StandaloneMigrationLauncher.java
@@ -19,7 +19,7 @@
import com.tacitknowledge.util.migration.MigrationException;
import com.tacitknowledge.util.migration.jdbc.util.ConfigurationUtil;
import com.tacitknowledge.util.migration.jdbc.util.MigrationUtil;
-import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.picocontainer.PicoContainer;
diff --git a/src/test/java/com/tacitknowledge/util/migration/DistributedMigrationProcessTest.java b/src/test/java/com/tacitknowledge/util/migration/DistributedMigrationProcessTest.java
index 5b6cab6..a71f082 100644
--- a/src/test/java/com/tacitknowledge/util/migration/DistributedMigrationProcessTest.java
+++ b/src/test/java/com/tacitknowledge/util/migration/DistributedMigrationProcessTest.java
@@ -222,7 +222,7 @@ public void testDoRollbacksActionMockingAsIfOrderedStrategyWereUsed() throws Mig
boolean forceRollback=false;
int rollbacksApplied = distributedMigrationProcess.doRollbacks(patchInfoStoreMock,rollbackLevels,migrationContextMock,forceRollback);
- assertEquals("Two rollbacks should be applied", 3, rollbacksApplied);
+ assertEquals("Rollbacks should have been applied", 3, rollbacksApplied);
}
}
diff --git a/src/test/java/com/tacitknowledge/util/migration/MigrationRunnerFactoryTest.java b/src/test/java/com/tacitknowledge/util/migration/MigrationRunnerFactoryTest.java
new file mode 100644
index 0000000..c3ce459
--- /dev/null
+++ b/src/test/java/com/tacitknowledge/util/migration/MigrationRunnerFactoryTest.java
@@ -0,0 +1,40 @@
+package com.tacitknowledge.util.migration;
+
+import junit.framework.TestCase;
+
+public class MigrationRunnerFactoryTest extends TestCase
+{
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ public void testGetMigrationRunnerStrategy_Default()
+ {
+ MigrationRunnerStrategy strategy = MigrationRunnerFactory.getMigrationRunnerStrategy("");
+ assertEquals("com.tacitknowledge.util.migration.OrderedMigrationRunnerStrategy",strategy.getClass().getName());
+ }
+
+ public void testGetMigrationRunnerStrategy_MissingPatchMigrationRunnerStrategy()
+ {
+ MigrationRunnerStrategy strategy = MigrationRunnerFactory.getMigrationRunnerStrategy("com.tacitknowledge.util.migration.MissingPatchMigrationRunnerStrategy");
+ assertEquals("com.tacitknowledge.util.migration.MissingPatchMigrationRunnerStrategy",strategy.getClass().getName());
+ }
+
+ public void testGetMigrationRunnerStrategy_NoSuchStrategy()
+ {
+ try
+ {
+ MigrationRunnerFactory.getMigrationRunnerStrategy("com.tacitknowledge.util.migration.NoSuchStrategy");
+ fail("MigrationRunnerFactory.getMigrationRunnerStrategy() Should have raised an IllegalArgumentException");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ }
+
+
+}
diff --git a/src/test/java/com/tacitknowledge/util/migration/jdbc/DistributedJdbcMigrationLauncherFactoryTest.java b/src/test/java/com/tacitknowledge/util/migration/jdbc/DistributedJdbcMigrationLauncherFactoryTest.java
index 971f280..7864327 100644
--- a/src/test/java/com/tacitknowledge/util/migration/jdbc/DistributedJdbcMigrationLauncherFactoryTest.java
+++ b/src/test/java/com/tacitknowledge/util/migration/jdbc/DistributedJdbcMigrationLauncherFactoryTest.java
@@ -206,7 +206,7 @@ public void testDistributedReadOnlyMode() throws Exception
log.debug("got exception: " + me.getMessage());
}
- currentPatchLevel = 8;
+ currentPatchLevel = 13;
// need to mock the patch info stores to return the expected patch levels
setReportedPatchLevel(controlledSystems.values(), currentPatchLevel);
diff --git a/src/test/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTaskTest.java b/src/test/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTaskTest.java
index 9dc83b8..19264d7 100644
--- a/src/test/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTaskTest.java
+++ b/src/test/java/com/tacitknowledge/util/migration/jdbc/SqlScriptMigrationTaskTest.java
@@ -20,8 +20,10 @@
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.Properties;
import javax.sql.DataSource;
@@ -41,290 +43,354 @@
*
* @author Scott Askew (scott@tacitknowledge.com)
*/
-public class SqlScriptMigrationTaskTest extends JDBCTestCaseAdapter
-{
- private static Log log = LogFactory.getLog(SqlScriptMigrationTaskTest.class);
- /**
- * The task to test.
- */
- private SqlScriptMigrationTask task = null;
-
- /**
- * The JDBCMigrationConteext used for testing
- */
- private DataSourceMigrationContext context = new DataSourceMigrationContext();
-
- /**
- * {@inheritDoc}
- */
- protected void setUp() throws Exception
- {
- super.setUp();
-
- MockConnection conn = getJDBCMockObjectFactory().getMockConnection();
-
- context = new DataSourceMigrationContext();
- context.setDataSource(new ConnectionWrapperDataSource(conn));
- context.setSystemName("milestone");
- context.setDatabaseType(new DatabaseType("postgres"));
- }
-
- /**
- * Test doing a migration (with the connection silently succeeding)
- *
- * @throws IOException
- * if the test patch file doesn't load correctly
- */
- public void testMigrate() throws IOException
- {
- InputStream is = getClass().getResourceAsStream(
- "test/patch0003_third_patch.sql");
- task = new SqlScriptMigrationTask("test", 1, is);
- is.close();
-
- try
- {
- task.migrate(context);
- } catch (MigrationException me)
- {
- log.info("Unexpected exception", me);
- fail("unexpected exception");
+public class SqlScriptMigrationTaskTest extends JDBCTestCaseAdapter {
+ private static Log log = LogFactory.getLog(SqlScriptMigrationTaskTest.class);
+ /**
+ * The task to test.
+ */
+ private SqlScriptMigrationTask task = null;
+
+ /**
+ * The JDBCMigrationConteext used for testing
+ */
+ private DataSourceMigrationContext context = new DataSourceMigrationContext();
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ MockConnection conn = getJDBCMockObjectFactory().getMockConnection();
+
+ context = new DataSourceMigrationContext();
+ context.setDataSource(new ConnectionWrapperDataSource(conn));
+ context.setSystemName("milestone");
+ context.setDatabaseType(new DatabaseType("postgres"));
+ }
+
+ /**
+ * Test doing a migration (with the connection silently succeeding)
+ *
+ * @throws IOException
+ * if the test patch file doesn't load correctly
+ */
+ public void testMigrate() throws IOException {
+ InputStream is = getClass().getResourceAsStream("test/patch0003_third_patch.sql");
+ task = new SqlScriptMigrationTask("test", 1, is);
+ is.close();
+
+ try {
+ task.migrate(context);
+ } catch (MigrationException me) {
+ log.info("Unexpected exception", me);
+ fail("unexpected exception");
+ }
+ }
+
+ public void testLevel() throws Exception {
+ SqlScriptMigrationTaskSource source = new SqlScriptMigrationTaskSource();
+ List tasks = null;
+ MigrationTaskSupport task = null;
+ try {
+ tasks = source.getMigrationTasks(this.getClass().getPackage().getName() + ".test");
+
+ task = findTaskByLevel(tasks, 1);
+ assertEquals("patch0001.sql", task.getName());
+
+ task = findTaskByLevel(tasks, 2);
+ assertEquals("patch0002_second_patch.sql", task.getName());
+
+ task = findTaskByLevel(tasks, 3);
+ assertEquals("patch0003_third_patch.sql", task.getName());
+ } catch (Exception e) {
+ log.info("Unexpected exception", e);
+ fail();
+ }
+ }
+
+ private MigrationTaskSupport findTaskByLevel(List tasks, int level) {
+ for (Iterator iterator = tasks.iterator(); iterator.hasNext();) {
+ MigrationTaskSupport task = (MigrationTaskSupport) iterator.next();
+ if (task.getLevel() == level) {
+ return task;
+ }
+ }
+ return null;
+
+ }
+
+ /**
+ * Ensures that a rollback script is correctly read from disk and then
+ * executed.
+ *
+ * @throws IOException
+ */
+ public void testRollback() throws IOException {
+ SqlScriptMigrationTaskSource source = new SqlScriptMigrationTaskSource();
+ List tasks = null;
+ try {
+ tasks = source.getMigrationTasks(this.getClass().getPackage().getName() + ".test");
+ // patches 1 & 3 have rollbacks (2 & 4 do not)
+ MigrationTaskSupport task = findTaskByLevel(tasks, 3);
+ if (task.isRollbackSupported())
+ task.down(context);
+ else
+ fail("Rollback should be supported for task " + task.getName());
+ } catch (Exception e) {
+ log.info("Unexpected exception", e);
+ fail();
+ }
+ }
+
+ /**
+ * Ensures that isRollbackSupported returns false if there is no rollback
+ * script.
+ *
+ * @throws IOException
+ */
+ public void testIsRollbackSupported() throws IOException {
+ SqlScriptMigrationTaskSource source = new SqlScriptMigrationTaskSource();
+ List tasks = null;
+ int[] SQL_PATCHES_WITH_NO_ROLLBACK = { 2, 13 };
+
+ try {
+ tasks = source.getMigrationTasks(this.getClass().getPackage().getName() + ".test");
+
+ for (Iterator i = tasks.iterator(); i.hasNext();) {
+ RollbackableMigrationTask rollbackableTask = (RollbackableMigrationTask) i.next();
+ if (Arrays.binarySearch(SQL_PATCHES_WITH_NO_ROLLBACK, rollbackableTask.getLevel()) > -1)
+ assertFalse(rollbackableTask.isRollbackSupported());
+ else
+ assertTrue(rollbackableTask.isRollbackSupported());
+
+ }
+
+ } catch (Exception e) {
+ log.info("Unexpected exception", e);
+ fail();
+ }
}
- }
-
- /**
- * Ensures that a rollback script is correctly read from disk and then executed.
- *
- * @throws IOException
- */
- public void testRollback() throws IOException
- {
- SqlScriptMigrationTaskSource source = new SqlScriptMigrationTaskSource();
- List tasks = null;
- try
- {
- tasks = source.getMigrationTasks(this.getClass().getPackage()
- .getName()
- + ".test");
- MigrationTaskSupport task = (MigrationTaskSupport)tasks.get(2);
-
- if(task.isRollbackSupported())
- task.down(context);
- else
- fail("Rollback should be supported for this task");
- } catch (Exception e)
- {
- log.info("Unexpected exception", e);
- fail();
+
+ /**
+ * Ensures that the task can correctly parse multiple SQL statements from a
+ * single file, with embedded comments.
+ *
+ * @throws IOException
+ * if an unexpected error occurs while attempting to read the
+ * test SQL patch file; it's a system resource, so this
+ * shouldn't happen
+ */
+ public void testParsingMultipleStatement_ProcessedSingly() throws IOException {
+ // patch0001.sql contains 3 statements, each with a closing semicolon
+ InputStream is = getClass().getResourceAsStream("test/patch0001.sql");
+ task = new SqlScriptMigrationTask("test", 1, is);
+ is.close();
+
+ // For Oracle, the statements are processed separately
+ context.setDatabaseType(new DatabaseType("oracle"));
+ List statements = task.getSqlStatements(context);
+ assertEquals(3, statements.size());
+ assertEquals("insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),2, 'SYSA', 3)", statements.get(0).toString());
+ assertEquals("insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),3, 'SYSA', 3)", statements.get(1).toString());
+ assertEquals("insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_--id_seq;'),4, 'SYSA', 3)", statements.get(2).toString());
+
+ }
+
+ public void testParsingMultipleStatement_ProcessedTogether() throws IOException {
+ // patch0001.sql contains 3 statements, each with a closing semicolon
+ InputStream is = getClass().getResourceAsStream("test/patch0001.sql");
+ task = new SqlScriptMigrationTask("test", 1, is);
+ is.close();
+
+ // For Postgres, the statements are processed together as one. (Same for
+ // MySQL, normally, but another test has a forced-override of the
+ // supportsMultipleStatements for MySQL, so we can't rely on it being
+ // correct here.)
+ String databaseType = "postgres";
+ context.setDatabaseType(new DatabaseType(databaseType));
+
+ assertTrue(context.getDatabaseType().isMultipleStatementsSupported());
+ List statementsl = task.getSqlStatements(context);
+ assertEquals(1, statementsl.size());
+ assertEquals("\n insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),2, 'SYSA', 3); \n\n"
+ + "// Testing\n" + "insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),3, 'SYSA', 3);\n\n"
+ + " -- This is a comment\n" + "insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_--id_seq;'),4, 'SYSA', 3);\n \n" + " \n", statementsl
+ .get(0).toString());
+
+ }
+
+ public void testParsingSingleStatement_NoSemicolon() throws IOException {
+ // patch0002_second_patch.sql contains a single statement with no
+ // closing semicolon
+ InputStream is = getClass().getResourceAsStream("test/patch0002_second_patch.sql");
+ task = new SqlScriptMigrationTask("test", 1, is);
+ is.close();
+
+ context.setDatabaseType(new DatabaseType("oracle"));
+ List l = task.getSqlStatements(context);
+ assertEquals(1, l.size());
+ assertEquals("insert into user_role_assoc (user_role_id, application_user_id, "
+ + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),2, 'SYSA', 3)", l.get(0).toString());
+ }
+
+ /**
+ * Make sure that if we can do one big statement, it correctly does one big
+ * statement
+ *
+ * @exception IOException
+ * if an unexpected error happens while reading test SQL
+ */
+ public void testParsingSingleStatement() throws IOException {
+ InputStream is = getClass().getResourceAsStream("test/patch0003_third_patch.sql");
+ task = new SqlScriptMigrationTask("test", 1, is);
+ is.close();
+
+ List l = task.getSqlStatements(context);
+ assertEquals(1, l.size());
+ assertEquals("select * from dual;\nselect * from dual;\n", l.get(0).toString());
}
- }
-
- /**
- * Ensures that isRollbackSupported returns false if there is no
- * rollback script.
- *
- * @throws IOException
- */
- public void testIsRollbackSupported() throws IOException
- {
- SqlScriptMigrationTaskSource source = new SqlScriptMigrationTaskSource();
- List tasks = null;
- try
- {
- tasks = source.getMigrationTasks(this.getClass().getPackage()
- .getName()
- + ".test");
-
- for(Iterator i=tasks.iterator(); i.hasNext();) {
- //patch with ID 2 has no rollback
- RollbackableMigrationTask rollbackableTask = (RollbackableMigrationTask) i.next();
- if(rollbackableTask.getLevel().equals(Integer.valueOf(2)))
- assertFalse(rollbackableTask.isRollbackSupported());
- else
- assertTrue(rollbackableTask.isRollbackSupported());
-
- }
-
- } catch (Exception e)
- {
- log.info("Unexpected exception", e);
- fail();
+
+ /**
+ * See that the name and toString are the same, given a file name to load
+ *
+ * @exception IOException
+ * if an unexpected error happens while reading test SQL
+ */
+ public void testTaskName() throws IOException {
+ InputStream is = getClass().getResourceAsStream("test/patch0003_third_patch.sql");
+ task = new SqlScriptMigrationTask("patch0003_third_patch", 1, is);
+ is.close();
+ assertEquals("patch0003_third_patch", task.toString());
}
- }
-
- /**
- * Ensures that the task can correctly parse multiple SQL statements from a
- * single file, with embedded comments.
- *
- * @throws IOException
- * if an unexpected error occurs while attempting to read
- * the test SQL patch file; it's a system resource, so this
- * shouldn't happen
- */
- public void testParsingMultipleStatement() throws IOException
- {
- InputStream is = getClass().getResourceAsStream(
- "test/patch0001.sql");
- task = new SqlScriptMigrationTask("test", 1, is);
- is.close();
-
- context.setDatabaseType(new DatabaseType("oracle"));
- List l = task.getSqlStatements(context);
- assertEquals(3, l.size());
- assertEquals(
- "insert into user_role_assoc (user_role_id, application_user_id, "
- + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),2, 'SYSA', 3)",
- l.get(0).toString());
- assertEquals(
- "insert into user_role_assoc (user_role_id, application_user_id, "
- + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),3, 'SYSA', 3)",
- l.get(1).toString());
- assertEquals(
- "insert into user_role_assoc (user_role_id, application_user_id, "
- + "role_code, project_id) \n\t\t\tvalues (nextval('role_--id_seq;'),4, 'SYSA', 3)",
- l.get(2).toString());
-
- is = getClass().getResourceAsStream("test/patch0002_second_patch.sql");
- task = new SqlScriptMigrationTask("test", 1, is);
- is.close();
-
- l = task.getSqlStatements(context);
- assertEquals(1, l.size());
- assertEquals(
- "insert into user_role_assoc (user_role_id, application_user_id, "
- + "role_code, project_id) \n\t\t\tvalues (nextval('role_id_seq'),2, 'SYSA', 3)",
- l.get(0).toString());
- }
-
- /**
- * Make sure that if we can do one big statement, it correctly does one big
- * statement
- *
- * @exception IOException
- * if an unexpected error happens while reading test SQL
- */
- public void testParsingSingleStatement() throws IOException
- {
- InputStream is = getClass().getResourceAsStream(
- "test/patch0003_third_patch.sql");
- task = new SqlScriptMigrationTask("test", 1, is);
- is.close();
-
- List l = task.getSqlStatements(context);
- assertEquals(1, l.size());
- assertEquals("select * from dual;\nselect * from dual;\n", l.get(0)
- .toString());
- }
-
- /**
- * See that the name and toString are the same, given a file name to load
- *
- * @exception IOException
- * if an unexpected error happens while reading test SQL
- */
- public void testTaskName() throws IOException
- {
- InputStream is = getClass().getResourceAsStream(
- "test/patch0003_third_patch.sql");
- task = new SqlScriptMigrationTask("patch0003_third_patch", 1, is);
- is.close();
- assertEquals("patch0003_third_patch", task.toString());
- }
-
- /**
- * Tests that sybase tsql statements are parsed correctly
- *
- * @throws IOException
- * if an unexpected error occurs.
- */
- public void testParsesSybaseTSql() throws IOException
- {
- InputStream is = getClass().getResourceAsStream("test/sybase_tsql.sql");
- assertNotNull(is);
- task = new SqlScriptMigrationTask("sybase_tsql.sql", 1, is);
-
- MockDatabaseType dbType = new MockDatabaseType("sybase");
- dbType.setMultipleStatementsSupported(false);
- context.setDatabaseType(dbType);
- List statements = task.getSqlStatements(context);
- assertEquals(8, statements.size());
- }
-
- /**
- * Test that sybase database patches are committed when illegal multi
- * statement transaction commands are used.
- *
- * @throws IOException
- * if an unexpected error occurs
- * @throws MigrationException
- * if an unexpected error occurs
- * @throws SQLException
- * if an unexpected error occurs
- */
- public void testSybasePatchesCommitsOnEveryStatement() throws IOException,
- MigrationException, SQLException
- {
- InputStream is = getClass().getResourceAsStream("test/sybase_tsql.sql");
- assertNotNull(is);
- task = new SqlScriptMigrationTask("sybase_tsql.sql", 1, is);
-
- MockDatabaseType dbType = new MockDatabaseType("sybase");
- dbType.setMultipleStatementsSupported(false);
- context.setDatabaseType(dbType);
- int numStatements = task.getSqlStatements(context).size();
-
- // setup mocks to verify commits are called
- MockControl dataSourceControl = MockControl
- .createControl(DataSource.class);
- DataSource dataSource = (DataSource) dataSourceControl.getMock();
- context.setDataSource(dataSource);
-
- MockControl connectionControl = MockControl
- .createControl(Connection.class);
- Connection connection = (Connection) connectionControl.getMock();
-
- dataSourceControl.expectAndReturn(dataSource.getConnection(),
- connection);
-
- MockControl statementControl = MockControl
- .createControl(Statement.class);
- Statement statement = (Statement) statementControl.getMock();
- statement.execute("");
- statementControl.setMatcher(MockControl.ALWAYS_MATCHER);
- statementControl.setReturnValue(true, MockControl.ONE_OR_MORE);
- statementControl.expectAndReturn(statement.isClosed(), false, MockControl.ONE_OR_MORE);
- statement.close();
- statementControl.setVoidCallable(MockControl.ONE_OR_MORE);
-
- connectionControl.expectAndReturn(connection.isClosed(), false,
- MockControl.ONE_OR_MORE);
- connectionControl.expectAndReturn(connection.createStatement(),
- statement, numStatements);
- connectionControl.expectAndReturn(connection.getAutoCommit(), false,
- MockControl.ONE_OR_MORE);
- connection.commit();
- /*
- * Magic Number 4 derived from the assumption that the fixture sql
- * contains only one statement that is not allowed in a multi statement
- * transaction: commit at beginning of migrate method commit prior to
- * running the command not allowed in multi statement transaction to
- * clear the transaction state. commit after running the multi statement
- * transaction to clear transaction state for upcoming statements.
- * commit at end of migrate method once all statements executed.
+
+ /**
+ * Tests that sybase tsql statements are parsed correctly
*
- * Therefore, if you add more illegal statements to the fixture, add 2
- * more commit call's for each illegal statement.
+ * @throws IOException
+ * if an unexpected error occurs.
*/
- connectionControl.setVoidCallable(4);
+ public void testParsesSybaseTSql() throws IOException {
+ // sybase_tsql.sql contains multiple statements separated by "GO"
+ // keywords. GO must be on a line by itself, but it is case insensitive
+ // and leading and trailing whitespace is allowed.
+ InputStream is = getClass().getResourceAsStream("test/sybase_tsql.sql");
+ assertNotNull(is);
+ task = new SqlScriptMigrationTask("sybase_tsql.sql", 1, is);
+
+ MockDatabaseType dbType = new MockDatabaseType("sybase");
+ dbType.setMultipleStatementsSupported(false);
+ context.setDatabaseType(dbType);
+ List statements = task.getSqlStatements(context);
+ assertEquals(8, statements.size());
+ assertEquals("/* just some sane sql at first */\n" + " \n" + "\n" + "PRINT 'Creating photo table'",
+ statements.get(0).toString());
+ assertEquals("/* will this table name screw up the parser looking for GO delimiter :)? */\n"
+ + "create table gogo\n" + "(\n" + "id numeric(14,0) NOT NULL\n" + "value varchar(32)\n" + ")",
+ statements.get(7).toString());
+ }
- dataSourceControl.replay();
- connectionControl.replay();
- statementControl.replay();
+ /**
+ * Tests that multiple DDL statements are parsed correctly (when the
+ * MultipleStatementsSupported property is forced to FALSE).
+ *
+ * @throws IOException
+ * if an unexpected error occurs.
+ */
+ public void testParsesDDL() throws IOException {
+ // some_lengthy_DDL_statements.sql contains multiple DDL statements that
+ // end with semicolons.
+ InputStream is = getClass().getResourceAsStream("test/some_lengthy_DDL_statements.sql");
+ assertNotNull(is);
+ task = new SqlScriptMigrationTask("some_lengthy_DDL_statements.sql", 1, is);
+
+ MockDatabaseType dbType = new MockDatabaseType("mysql");
+ dbType.setMultipleStatementsSupported(false);
+ context.setDatabaseType(dbType);
+ List statements = task.getSqlStatements(context);
+ assertEquals(13, statements.size());
+ assertEquals("CREATE TABLE `ref_country` ( \n" + " `isoCode` varchar(10) NOT NULL DEFAULT '', \n"
+ + " `perceivedCorruption` decimal(9,2) DEFAULT NULL, \n"
+ + " `currency` char(3) NOT NULL DEFAULT 'USD', \n" + " PRIMARY KEY (`isoCode`) \n"
+ + " ) ENGINE=InnoDB DEFAULT CHARSET=latin1", statements.get(0).toString());
+ assertEquals("UPDATE provider_registration_request a\n"
+ + " JOIN ref_state rs on a.state = rs.isoCode and a.country = rs.countryCode\n"
+ + " SET countrySubdivision = concat(country,'-',state)\n" + " WHERE state is not null \n"
+ + " AND countrySubdivision is null", statements.get(12).toString());
+ }
- // run tests
- task.migrate(context);
- dataSourceControl.verify();
- connectionControl.verify();
- }
+ /**
+ * Test that sybase database patches are committed when illegal multi
+ * statement transaction commands are used.
+ *
+ * @throws IOException
+ * if an unexpected error occurs
+ * @throws MigrationException
+ * if an unexpected error occurs
+ * @throws SQLException
+ * if an unexpected error occurs
+ */
+ public void testSybasePatchesCommitsOnEveryStatement() throws IOException, MigrationException, SQLException {
+ InputStream is = getClass().getResourceAsStream("test/sybase_tsql.sql");
+ assertNotNull(is);
+ task = new SqlScriptMigrationTask("sybase_tsql.sql", 1, is);
+
+ MockDatabaseType dbType = new MockDatabaseType("sybase");
+ dbType.setMultipleStatementsSupported(false);
+ context.setDatabaseType(dbType);
+ int numStatements = task.getSqlStatements(context).size();
+
+ // setup mocks to verify commits are called
+ MockControl dataSourceControl = MockControl.createControl(DataSource.class);
+ DataSource dataSource = (DataSource) dataSourceControl.getMock();
+ context.setDataSource(dataSource);
+
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+
+ dataSourceControl.expectAndReturn(dataSource.getConnection(), connection);
+
+ MockControl statementControl = MockControl.createControl(Statement.class);
+ Statement statement = (Statement) statementControl.getMock();
+ statement.execute("");
+ statementControl.setMatcher(MockControl.ALWAYS_MATCHER);
+ statementControl.setReturnValue(true, MockControl.ONE_OR_MORE);
+ statementControl.expectAndReturn(statement.isClosed(), false, MockControl.ONE_OR_MORE);
+ statement.close();
+ statementControl.setVoidCallable(MockControl.ONE_OR_MORE);
+
+ connectionControl.expectAndReturn(connection.isClosed(), false, MockControl.ONE_OR_MORE);
+ connectionControl.expectAndReturn(connection.createStatement(), statement, numStatements);
+ connectionControl.expectAndReturn(connection.getAutoCommit(), false, MockControl.ONE_OR_MORE);
+ connection.commit();
+ /*
+ * Magic Number 4 derived from the assumption that the fixture sql
+ * contains only one statement that is not allowed in a multi statement
+ * transaction: commit at beginning of migrate method commit prior to
+ * running the command not allowed in multi statement transaction to
+ * clear the transaction state. commit after running the multi statement
+ * transaction to clear transaction state for upcoming statements.
+ * commit at end of migrate method once all statements executed.
+ *
+ * Therefore, if you add more illegal statements to the fixture, add 2
+ * more commit call's for each illegal statement.
+ */
+ connectionControl.setVoidCallable(4);
+
+ dataSourceControl.replay();
+ connectionControl.replay();
+ statementControl.replay();
+
+ // run tests
+ task.migrate(context);
+ dataSourceControl.verify();
+ connectionControl.verify();
+ }
}
diff --git a/src/test/java/com/tacitknowledge/util/migration/tasks/normal/TestMigrationTask2.java b/src/test/java/com/tacitknowledge/util/migration/tasks/normal/TestMigrationTask2.java
index 1d83808..ab4cfc6 100644
--- a/src/test/java/com/tacitknowledge/util/migration/tasks/normal/TestMigrationTask2.java
+++ b/src/test/java/com/tacitknowledge/util/migration/tasks/normal/TestMigrationTask2.java
@@ -30,7 +30,7 @@ public class TestMigrationTask2 extends BaseTestMigrationTask
private static Integer patchLevelOverride = new Integer(5);
/**
- * Creates a new TestMigrationTask3.
+ * Creates a new TestMigrationTask2.
*/
public TestMigrationTask2()
{
diff --git a/src/test/resources/com/tacitknowledge/util/migration/jdbc/test/some_lengthy_DDL_statements.sql b/src/test/resources/com/tacitknowledge/util/migration/jdbc/test/some_lengthy_DDL_statements.sql
new file mode 100644
index 0000000..59fc8b6
--- /dev/null
+++ b/src/test/resources/com/tacitknowledge/util/migration/jdbc/test/some_lengthy_DDL_statements.sql
@@ -0,0 +1,208 @@
+CREATE TABLE `ref_country` (
+ `isoCode` varchar(10) NOT NULL DEFAULT '',
+ `perceivedCorruption` decimal(9,2) DEFAULT NULL,
+ `currency` char(3) NOT NULL DEFAULT 'USD',
+ PRIMARY KEY (`isoCode`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+CREATE TABLE `ref_country_subdivision` (
+ `isoCode` varchar(10) NOT NULL,
+ `countryCode` varchar(10) NOT NULL,
+ PRIMARY KEY (`isoCode`,`countryCode`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `ref_state` (
+ `isoCode` char(10) NOT NULL,
+ `countryCode` char(2) NOT NULL,
+ PRIMARY KEY (`isoCode`,`countryCode`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `accounts` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(50) NOT NULL,
+ `createdBy` int(11) DEFAULT NULL,
+ `creationDate` datetime DEFAULT NULL,
+ `updatedBy` int(11) DEFAULT NULL,
+ `updateDate` datetime DEFAULT NULL,
+ `status` varchar(15) NOT NULL DEFAULT 'Pending',
+ `address` varchar(50) DEFAULT NULL,
+ `address2` varchar(50) DEFAULT NULL,
+ `address3` varchar(50) DEFAULT NULL,
+ `city` varchar(35) DEFAULT NULL,
+ `state` varchar(10) DEFAULT NULL,
+ `zip` varchar(15) DEFAULT NULL,
+ `country` varchar(25) DEFAULT NULL,
+ `phone` varchar(30) DEFAULT NULL,
+ `phone2` varchar(35) DEFAULT NULL,
+ `fax` varchar(30) DEFAULT NULL,
+ `contactID` mediumint(9) DEFAULT NULL,
+ `email` varchar(50) DEFAULT NULL,
+ `web_URL` varchar(50) DEFAULT NULL,
+ `nameIndex` varchar(50) DEFAULT NULL,
+ `reason` varchar(100) DEFAULT NULL,
+ `description` text,
+ `needsIndexing` tinyint(4) unsigned NOT NULL DEFAULT '1',
+ `parentID` int(11) DEFAULT NULL,
+ `currencyCode` char(3) DEFAULT 'USD',
+ `locale` varchar(5) DEFAULT 'en',
+ `timezone` varchar(50) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `name` (`name`),
+ KEY `nameIndex` (`nameIndex`)
+ ) ENGINE=InnoDB AUTO_INCREMENT=33517 DEFAULT CHARSET=latin1;
+
+CREATE TABLE `provider_audit` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `creationDate` datetime DEFAULT NULL,
+ `createdBy` int(11) DEFAULT NULL,
+ `updateDate` datetime DEFAULT NULL,
+ `updatedBy` int(11) DEFAULT NULL,
+ `expiresDate` datetime DEFAULT NULL,
+ `effectiveDate` datetime DEFAULT NULL,
+ `assignedDate` datetime DEFAULT NULL,
+ `scheduledDate` datetime DEFAULT NULL,
+ `lastRecalculation` date DEFAULT NULL,
+ `score` tinyint(3) DEFAULT '0',
+ `contact` varchar(50) DEFAULT NULL,
+ `phone` varchar(25) DEFAULT NULL,
+ `phone2` varchar(255) DEFAULT NULL,
+ `address` varchar(50) DEFAULT NULL,
+ `address2` varchar(50) DEFAULT NULL,
+ `city` varchar(35) DEFAULT NULL,
+ `state` varchar(10) DEFAULT NULL,
+ `zip` varchar(10) DEFAULT NULL,
+ `country` varchar(50) DEFAULT NULL,
+ `latitude` float NOT NULL DEFAULT '0',
+ `longitude` float NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB AUTO_INCREMENT=761716 DEFAULT CHARSET=latin1
+
+CREATE TABLE `provider_info` (
+ `id` int(11) NOT NULL,
+ `description` text,
+ `secondContact` varchar(50) DEFAULT NULL,
+ `secondPhone` varchar(50) DEFAULT NULL,
+ `secondEmail` varchar(50) DEFAULT NULL,
+ `billingContact` varchar(50) DEFAULT NULL,
+ `billingPhone` varchar(50) DEFAULT NULL,
+ `billingEmail` varchar(50) DEFAULT NULL,
+ `billingAddress` varchar(50) DEFAULT NULL,
+ `billingCity` varchar(35) DEFAULT NULL,
+ `billingState` varchar(10) DEFAULT NULL,
+ `billingCountrySubdivision` varchar(10) DEFAULT NULL,
+ `billingZip` varchar(10) DEFAULT NULL,
+ `billingCountry` varchar(25) DEFAULT NULL,
+ `membershipDate` date DEFAULT NULL,
+ `paymentMethod` varchar(20) DEFAULT 'CreditCard',
+ `paymentMethodStatus` varchar(20) DEFAULT NULL,
+ `renew` tinyint(4) DEFAULT '1',
+ `lastUpgradeDate` date DEFAULT NULL,
+ `balance` decimal(9,2) DEFAULT '0.00',
+ `needsRecalculation` tinyint(4) NOT NULL DEFAULT '1',
+ `lastRecalculation` datetime DEFAULT NULL,
+ `ccOnFile` tinyint(4) NOT NULL DEFAULT '0',
+ `ccExpiration` date DEFAULT NULL,
+ `ccEmail` varchar(50) DEFAULT NULL,
+ `showInDirectory` tinyint(4) DEFAULT '1',
+ PRIMARY KEY (`id`),
+ CONSTRAINT `FK_contractor_info` FOREIGN KEY (`id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=latin1
+
+CREATE TABLE `provider_registration_request` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `createdBy` int(11) DEFAULT NULL,
+ `updatedBy` int(11) DEFAULT NULL,
+ `creationDate` datetime DEFAULT NULL,
+ `updateDate` datetime DEFAULT NULL,
+ `requestedByID` mediumint(9) NOT NULL,
+ `requestedByUser` varchar(20) DEFAULT NULL,
+ `status` varchar(30) NOT NULL DEFAULT 'Active',
+ `contact` varchar(30) NOT NULL,
+ `phone` varchar(20) DEFAULT NULL,
+ `email` varchar(50) DEFAULT NULL,
+ `address` varchar(100) DEFAULT NULL,
+ `city` varchar(50) DEFAULT NULL,
+ `state` varchar(10) DEFAULT NULL,
+ `zip` varchar(10) DEFAULT NULL,
+ `country` char(2) DEFAULT NULL,
+ `deadline` date DEFAULT NULL,
+ `lastContactedBy` mediumint(9) DEFAULT NULL,
+ `lastContactDate` datetime DEFAULT NULL,
+ `contactCountByEmail` tinyint(4) unsigned NOT NULL DEFAULT '0',
+ `contactCountByPhone` tinyint(4) unsigned NOT NULL DEFAULT '0',
+ `notes` text,
+ `holdDate` date DEFAULT NULL,
+ `reasonForRegistration` varchar(500) DEFAULT NULL,
+ `reasonForDecline` varchar(500) DEFAULT NULL,
+ `closedOnDate` date DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `NameRequestedByIDUnique` (`name`,`requestedByID`),
+ KEY `status` (`status`,`country`,`state`)
+ ) ENGINE=InnoDB AUTO_INCREMENT=7465 DEFAULT CHARSET=latin1
+
+
+
+ALTER TABLE `accounts`
+ ADD COLUMN `countrySubdivision` varchar(10) COLLATE latin1_swedish_ci NULL after `state`,
+ CHANGE `zip` `zip` varchar(15) COLLATE latin1_swedish_ci NULL after `countrySubdivision`,
+ CHANGE `country` `country` varchar(25) COLLATE latin1_swedish_ci NULL after `zip`,
+ CHANGE `phone` `phone` varchar(30) COLLATE latin1_swedish_ci NULL after `country`,
+ CHANGE `phone2` `phone2` varchar(35) COLLATE latin1_swedish_ci NULL after `phone`,
+ CHANGE `fax` `fax` varchar(30) COLLATE latin1_swedish_ci NULL after `phone2`,
+ CHANGE `contactID` `contactID` mediumint(9) NULL after `fax`,
+ CHANGE `email` `email` varchar(50) COLLATE latin1_swedish_ci NULL after `contactID`,
+ CHANGE `web_URL` `web_URL` varchar(50) COLLATE latin1_swedish_ci NULL after `email`,
+ CHANGE `nameIndex` `nameIndex` varchar(50) COLLATE latin1_swedish_ci NULL after `web_URL`,
+ CHANGE `reason` `reason` varchar(100) COLLATE latin1_swedish_ci NULL after `nameIndex`,
+ CHANGE `description` `description` text COLLATE latin1_swedish_ci NULL after `reason`,
+ CHANGE `needsIndexing` `needsIndexing` tinyint(4) unsigned NOT NULL DEFAULT '1' after `description`,
+ CHANGE `parentID` `parentID` int(11) NULL after `needsIndexing`,
+ CHANGE `currencyCode` `currencyCode` char(3) COLLATE latin1_swedish_ci NULL DEFAULT 'USD' after `parentID`,
+ CHANGE `locale` `locale` varchar(5) COLLATE latin1_swedish_ci NULL DEFAULT 'en' after `currencyCode`,
+ CHANGE `timezone` `timezone` varchar(50) COLLATE latin1_swedish_ci NULL after `locale`, COMMENT='';
+
+ALTER TABLE `provider_audit`
+ CHANGE `state` `state` varchar(10) COLLATE latin1_swedish_ci NULL after `city`,
+ ADD COLUMN `countrySubdivision` varchar(10) COLLATE latin1_swedish_ci NULL after `state`,
+ CHANGE `zip` `zip` varchar(10) COLLATE latin1_swedish_ci NULL after `countrySubdivision`,
+ CHANGE `country` `country` varchar(50) COLLATE latin1_swedish_ci NULL after `zip`,
+ CHANGE `latitude` `latitude` float NOT NULL DEFAULT '0' after `country`,
+ CHANGE `longitude` `longitude` float NOT NULL DEFAULT '0' after `latitude`;
+
+ALTER TABLE `provider_info`
+ ADD COLUMN `billingCountrySubdivision` varchar(10) COLLATE latin1_swedish_ci NULL after `billingState`;
+
+ALTER TABLE `provider_registration_request`
+ ADD COLUMN `countrySubdivision` varchar(10) COLLATE latin1_swedish_ci NULL after `state`;
+
+ALTER TABLE `provider_info`
+ ADD CONSTRAINT `FK_provider_info`
+ FOREIGN KEY (`id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE;
+
+
+
+UPDATE accounts a
+ JOIN ref_state rs on a.state = rs.isoCode and a.country = rs.countryCode
+ SET countrySubdivision = concat(country,'-',state)
+ WHERE state is not null
+ AND countrySubdivision is null;
+
+UPDATE provider_audit a
+ JOIN ref_state rs on a.state = rs.isoCode and a.country = rs.countryCode
+ SET countrySubdivision = concat(country,'-',state)
+ WHERE a.state is not null
+ AND a.countrySubdivision is null;
+
+UPDATE provider_info a
+ JOIN ref_state rs on a.billingState = rs.isoCode and a.billingCountry = rs.countryCode
+ SET billingCountrySubdivision = concat(billingCountry,'-',billingState)
+ WHERE a.billingState is not null
+ AND a.billingCountrySubdivision is null;
+
+UPDATE provider_registration_request a
+ JOIN ref_state rs on a.state = rs.isoCode and a.country = rs.countryCode
+ SET countrySubdivision = concat(country,'-',state)
+ WHERE state is not null
+ AND countrySubdivision is null;
+