diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
index b9313a29b3d..83ee05de03a 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
@@ -43,6 +43,14 @@
classes
+
+
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java
index 0b800dbb344..514f2fc959f 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java
@@ -50,7 +50,7 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet indexes = metadata.getIndexInfo(null, null, theTableName, false, true);
+ ResultSet indexes = metadata.getIndexInfo(connection.getCatalog(), connection.getSchema(), theTableName, false, true);
Set indexNames = new HashSet<>();
while (indexes.next()) {
@@ -78,7 +78,7 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet indexes = metadata.getIndexInfo(null, null, theTableName, false, false);
+ ResultSet indexes = metadata.getIndexInfo(connection.getCatalog(), connection.getSchema(), theTableName, false, false);
while (indexes.next()) {
String indexName = indexes.getString("INDEX_NAME");
@@ -107,7 +107,9 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet indexes = metadata.getColumns(null, null, null, null);
+ String catalog = connection.getCatalog();
+ String schema = connection.getSchema();
+ ResultSet indexes = metadata.getColumns(catalog, schema, theTableName, null);
while (indexes.next()) {
@@ -158,7 +160,7 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet indexes = metadata.getCrossReference(null, null, theTableName, null, null, theForeignTable);
+ ResultSet indexes = metadata.getCrossReference(connection.getCatalog(), connection.getSchema(), theTableName, connection.getCatalog(), connection.getSchema(), theForeignTable);
Set columnNames = new HashSet<>();
while (indexes.next()) {
@@ -194,7 +196,7 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet indexes = metadata.getColumns(null, null, null, null);
+ ResultSet indexes = metadata.getColumns(connection.getCatalog(), connection.getSchema(), theTableName, null);
Set columnNames = new HashSet<>();
while (indexes.next()) {
@@ -223,7 +225,7 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet tables = metadata.getTables(null, null, null, null);
+ ResultSet tables = metadata.getTables(connection.getCatalog(), connection.getSchema(), null, null);
Set columnNames = new HashSet<>();
while (tables.next()) {
@@ -254,7 +256,7 @@ public class JdbcUtils {
DatabaseMetaData metadata;
try {
metadata = connection.getMetaData();
- ResultSet tables = metadata.getColumns(null, null, null, null);
+ ResultSet tables = metadata.getColumns(connection.getCatalog(), connection.getSchema(), theTableName, theColumnName);
while (tables.next()) {
String tableName = toUpperCase(tables.getString("TABLE_NAME"), Locale.US);
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/Migrator.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/Migrator.java
index 60792b73811..43753507426 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/Migrator.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/Migrator.java
@@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.migrate;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
public class Migrator {
@@ -40,6 +41,7 @@ public class Migrator {
private DriverTypeEnum.ConnectionProperties myConnectionProperties;
private int myChangesCount;
private boolean myDryRun;
+ private List myExecutedStatements = new ArrayList<>();
public int getChangesCount() {
return myChangesCount;
@@ -74,7 +76,7 @@ public class Migrator {
myConnectionProperties = myDriverType.newConnectionProperties(myConnectionUrl, myUsername, myPassword);
try {
- for (BaseTask next : myTasks) {
+ for (BaseTask> next : myTasks) {
next.setDriverType(myDriverType);
next.setConnectionProperties(myConnectionProperties);
next.setDryRun(myDryRun);
@@ -85,12 +87,33 @@ public class Migrator {
}
myChangesCount += next.getChangesCount();
+ myExecutedStatements.addAll(next.getExecutedStatements());
}
} finally {
myConnectionProperties.close();
}
ourLog.info("Finished migration of {} tasks", myTasks.size());
+
+ if (myDryRun) {
+ StringBuilder statementBuilder = new StringBuilder();
+ String lastTable = null;
+ for (BaseTask.ExecutedStatement next : myExecutedStatements) {
+ if (!Objects.equals(lastTable, next.getTableName())) {
+ statementBuilder.append("\n\n-- Table: ").append(next.getTableName()).append("\n");
+ lastTable = next.getTableName();
+ }
+
+ statementBuilder.append(next.getSql()).append(";\n");
+
+ for (Object nextArg : next.getArguments()) {
+ statementBuilder.append(" -- Arg: ").append(nextArg).append("\n");
+ }
+ }
+
+ ourLog.info("SQL that would be executed:\n\n***********************************\n{}***********************************", statementBuilder);
+ }
+
}
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java
index ca1a7545538..b194d1e973f 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java
@@ -46,9 +46,22 @@ public class AddColumnTask extends BaseTableColumnTypeTask {
nullable = "";
}
- String sql = "alter table " + getTableName() + " add column " + getColumnName() + " " + type + " " + nullable;
+ String sql = "";
+ switch (getDriverType()) {
+ case DERBY_EMBEDDED:
+ case MARIADB_10_1:
+ case MYSQL_5_7:
+ case POSTGRES_9_4:
+ sql = "alter table " + getTableName() + " add column " + getColumnName() + " " + type + " " + nullable;
+ break;
+ case MSSQL_2012:
+ case ORACLE_12C:
+ sql = "alter table " + getTableName() + " add " + getColumnName() + " " + type + " " + nullable;
+ break;
+ }
+
ourLog.info("Adding column {} of type {} to table {}", getColumnName(), type, getTableName());
- executeSql(sql);
+ executeSql(getTableName(), sql);
}
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddForeignKeyTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddForeignKeyTask.java
index a49d4808e41..4affdcd4ad0 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddForeignKeyTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddForeignKeyTask.java
@@ -83,7 +83,7 @@ public class AddForeignKeyTask extends BaseTableColumnTask {
try {
- executeSql(sql);
+ executeSql(getTableName(), sql);
} catch (Exception e) {
if (e.toString().contains("already exists")) {
ourLog.warn("Index {} already exists", myConstraintName);
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIndexTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIndexTask.java
index f5e40556901..dac17bb52de 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIndexTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIndexTask.java
@@ -67,12 +67,13 @@ public class AddIndexTask extends BaseTableTask {
return;
}
- String unique = myUnique ? "UNIQUE " : "";
+ String unique = myUnique ? "unique " : "";
String columns = String.join(", ", myColumns);
- String sql = "CREATE " + unique + " INDEX " + myIndexName + " ON " + getTableName() + "(" + columns + ")";
+ String sql = "create " + unique + "index " + myIndexName + " on " + getTableName() + "(" + columns + ")";
+ String tableName = getTableName();
try {
- executeSql(sql);
+ executeSql(tableName, sql);
} catch (Exception e) {
if (e.toString().contains("already exists")) {
ourLog.warn("Index {} already exists", myIndexName);
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java
index 57a1cb481a4..9fdaefafe18 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java
@@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -38,11 +38,13 @@ public class ArbitrarySqlTask extends BaseTask {
private static final Logger ourLog = LoggerFactory.getLogger(ArbitrarySqlTask.class);
private final String myDescription;
+ private final String myTableName;
private List myTask = new ArrayList<>();
private int myBatchSize = 1000;
private String myExecuteOnlyIfTableExists;
- public ArbitrarySqlTask(String theDescription) {
+ public ArbitrarySqlTask(String theTableName, String theDescription) {
+ myTableName = theTableName;
myDescription = theDescription;
}
@@ -104,7 +106,6 @@ public class ArbitrarySqlTask extends BaseTask {
@Override
public void execute() {
if (isDryRun()) {
- logDryRunSql(mySql);
return;
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java
index b5963b63010..9ba2f97895d 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java
@@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -28,6 +28,10 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
public abstract class BaseTask {
@@ -37,6 +41,7 @@ public abstract class BaseTask {
private String myDescription;
private int myChangesCount;
private boolean myDryRun;
+ private List myExecutedStatements = new ArrayList<>();
public boolean isDryRun() {
return myDryRun;
@@ -56,29 +61,36 @@ public abstract class BaseTask {
return (T) this;
}
+ public List getExecutedStatements() {
+ return myExecutedStatements;
+ }
+
public int getChangesCount() {
return myChangesCount;
}
- public void executeSql(@Language("SQL") String theSql, Object... theArguments) {
- if (isDryRun()) {
- logDryRunSql(theSql);
- return;
+ /**
+ * @param theTableName This is only used for logging currently
+ * @param theSql The SQL statement
+ * @param theArguments The SQL statement arguments
+ */
+ public void executeSql(String theTableName, @Language("SQL") String theSql, Object... theArguments) {
+ if (isDryRun() == false) {
+ Integer changes = getConnectionProperties().getTxTemplate().execute(t -> {
+ JdbcTemplate jdbcTemplate = getConnectionProperties().newJdbcTemplate();
+ int changesCount = jdbcTemplate.update(theSql, theArguments);
+ ourLog.info("SQL \"{}\" returned {}", theSql, changesCount);
+ return changesCount;
+ });
+
+ myChangesCount += changes;
}
- Integer changes = getConnectionProperties().getTxTemplate().execute(t -> {
- JdbcTemplate jdbcTemplate = getConnectionProperties().newJdbcTemplate();
- int changesCount = jdbcTemplate.update(theSql, theArguments);
- ourLog.info("SQL \"{}\" returned {}", theSql, changesCount);
- return changesCount;
- });
-
- myChangesCount += changes;
-
+ captureExecutedStatement(theTableName, theSql, theArguments);
}
- protected void logDryRunSql(@Language("SQL") String theSql) {
- ourLog.info("WOULD EXECUTE SQL: {}", theSql);
+ protected void captureExecutedStatement(String theTableName, @Language("SQL") String theSql, Object[] theArguments) {
+ myExecutedStatements.add(new ExecutedStatement(theTableName, theSql, theArguments));
}
public DriverTypeEnum.ConnectionProperties getConnectionProperties() {
@@ -108,4 +120,28 @@ public abstract class BaseTask {
}
public abstract void execute() throws SQLException;
+
+ public static class ExecutedStatement {
+ private final String mySql;
+ private final List