Skip to content

Commit

Permalink
Add configuration to back up tables before db migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanrdoherty committed Apr 30, 2024
1 parent a640c5b commit a5a6e87
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -107,6 +108,12 @@ public Collection<Object[]> toValues(StepData obj) {
}
return values;
}

@Override
public List<String> getTableNamesForBackup(String schema) {
// no backup needed; creating a new table in this writer
return Collections.emptyList();
}
}

private AtomicInteger _numParams = new AtomicInteger(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ public interface TableRowUpdaterPlugin<T extends TableRow> {
* when all processing is complete to allow the plugin to dump those statistics.
*/
void dumpStatistics();

/**
* Whether to back up tables that may be written to before processing begins
*
* @return true if backup should be performed
*/
default boolean isPerformTableBackup() {
return false;
}
}

/**
Expand Down Expand Up @@ -125,6 +134,16 @@ public interface TableRowWriter<T extends TableRow> {
*/
void tearDown(WdkModel wdkModel) throws Exception;

/**
* Returns a list of table names (including schema prefix) whose rows may be overwritten
* by this writer. Plugin will decide whether backup is actually performed. The
* schema value passed in will be empty or will have a '.' as the last character. It
* is the user schema configured in the WDK model created for this update
*
* @return list of tables
*/
List<String> getTableNamesForBackup(String schema);

/**
* Provides parameterized SQL to write a single record. This SQL will be converted to a
* PreparedStatement, then executed as a batch update operation using the SQL types and values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import javax.sql.DataSource;

Expand All @@ -30,6 +35,7 @@
import org.gusdb.fgputil.db.runner.SQLRunner;
import org.gusdb.fgputil.db.runner.SQLRunner.ArgumentBatch;
import org.gusdb.fgputil.db.runner.SQLRunner.ResultSetHandler;
import org.gusdb.fgputil.db.runner.SQLRunnerException;
import org.gusdb.fgputil.runtime.GusHome;
import org.gusdb.wdk.model.WdkModel;
import org.gusdb.wdk.model.fix.table.TableRowInterfaces.RowResult;
Expand Down Expand Up @@ -217,6 +223,18 @@ private ExitStatus run() {
DatabaseInstance userDb = _wdkModel.getUserDb();
RecordQueue<T> recordQueue = new RecordQueue<>();

// back up tables if requested
if (_plugin.isPerformTableBackup()) {
// collect table names from writers and remove duplicates
String userSchema = getUserSchema(_wdkModel);
Set<String> tables = _writers.stream()
.map(writer -> writer.getTableNamesForBackup(userSchema))
.flatMap(Collection::stream)
.collect(Collectors.toSet());
// create backup tables
backUpTables(userDb.getDataSource(), tables);
}

// create and start threads that will listen to queue and pull off records to process
for (int i = 0; i < NUM_THREADS; i++) {
RowHandler<T> thread = new RowHandler<>(i + 1, recordQueue, _plugin, _writers, _wdkModel);
Expand Down Expand Up @@ -275,6 +293,21 @@ private ExitStatus run() {
return ExitStatus.SUCCESS;
}

private void backUpTables(DataSource ds, Set<String> tables) {
try {
String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
for (String table : tables) {
String bkTable = table + "_bk_" + timestamp;
String sql = "create table " + bkTable + " as (select * from " + table + ")";
LOG.info("Creating backup table " + bkTable + " from " + table);
new SQLRunner(ds, sql, "table-backup").executeStatement();
}
}
catch (SQLRunnerException e) {
throw new RuntimeException("Could not create backup table", e.getCause());
}
}

private void setUpDatabase() throws Exception {
_factory.setUp(_wdkModel);
for (TableRowWriter<T> writer : _writers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;
import java.util.List;

import org.gusdb.fgputil.ListBuilder;
import org.gusdb.fgputil.db.platform.DBPlatform;
Expand Down Expand Up @@ -37,6 +38,11 @@ public AnalysisRow newTableRow(ResultSet rs, DBPlatform platform) throws SQLExce
return new AnalysisRow(rs, platform);
}

@Override
public List<String> getTableNamesForBackup(String schema) {
return List.of(_schema + ".analysis");
}

@Override
public String getWriteSql(String schema) {
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.gusdb.wdk.model.fix.table.edaanalysis.plugins;

import org.gusdb.wdk.model.fix.table.TableRowInterfaces.RowResult;
import org.gusdb.wdk.model.fix.table.edaanalysis.AbstractAnalysisUpdater;
import org.gusdb.wdk.model.fix.table.edaanalysis.AnalysisRow;

public class NoOpBackupPlugin extends AbstractAnalysisUpdater {

@Override
public RowResult<AnalysisRow> processRecord(AnalysisRow nextRow) throws Exception {
return new RowResult<>(nextRow);
}

@Override
public void dumpStatistics() {
// nothing to do
}

@Override
public boolean isPerformTableBackup() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public class StepDataWriter implements TableRowWriter<StepData> {
mapToList(new ListBuilder<String>().addAll(UPDATE_COLS).add(STEP_ID).toList(),
key -> SQLTYPES.get(key)).toArray(new Integer[COLS.length]);

@Override
public List<String> getTableNamesForBackup(String schema) {
return List.of(schema + "steps");
}

@Override
public String getWriteSql(String schema) {
return "update " + schema + "steps set " + UPDATE_COLS_TEXT + " where " + STEP_ID + " = ?";
Expand Down

0 comments on commit a5a6e87

Please sign in to comment.