Implementation of DBUpgrade

This commit is contained in:
Ziver Koc 2015-12-08 21:51:18 +01:00
parent 3aece9551b
commit 3f3333a72d

View file

@ -1,9 +1,14 @@
package zutil.db; package zutil.db;
import zutil.db.handler.ListSQLResult; import zutil.db.handler.ListSQLResult;
import zutil.db.handler.SimpleSQLResult;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -47,12 +52,14 @@ public class DBUpgradeHandler {
- setTransactionSuccessful - setTransactionSuccessful
*/ */
try { try {
logger.fine("Starting upgrade transaction...");
target.exec("BEGIN IMMEDIATE TRANSACTION"); target.exec("BEGIN IMMEDIATE TRANSACTION");
upgradeCreateTabels(); upgradeCreateTabels();
upgradeDropTables();
upgradeAlterTables(); upgradeAlterTables();
upgradeDeleteTables();
logger.fine("Committing upgrade transaction...");
target.exec("COMMIT TRANSACTION"); target.exec("COMMIT TRANSACTION");
} catch(SQLException e){ } catch(SQLException e){
try { try {
@ -65,7 +72,6 @@ public class DBUpgradeHandler {
} }
private void upgradeCreateTabels() throws SQLException { private void upgradeCreateTabels() throws SQLException {
List<String> refTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>()); List<String> refTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>());
List<String> targetTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>()); List<String> targetTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>());
@ -73,17 +79,100 @@ public class DBUpgradeHandler {
for(String table : refTables){ for(String table : refTables){
if(!targetTables.contains(table)){ if(!targetTables.contains(table)){
logger.fine("Creating new table: "+ table); logger.fine("Creating new table: "+ table);
// Get reference create sql
PreparedStatement stmt = reference.getPreparedStatement("SELECT sql FROM sqlite_master WHERE name == ?");
stmt.setString(1, table);
String sql = DBConnection.exec(stmt, new SimpleSQLResult<String>());
// Execute sql on target
target.exec(sql);
}
}
}
private void upgradeDropTables() throws SQLException {
List<String> refTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>());
List<String> targetTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>());
for(String table : targetTables){
if(!refTables.contains(table)){
logger.fine("Dropping table: ");
PreparedStatement stmt = target.getPreparedStatement("DROP TABLE ?");
stmt.setString(1, table);
DBConnection.exec(stmt);
} }
} }
} }
private void upgradeAlterTables() throws SQLException { private void upgradeAlterTables() throws SQLException {
logger.fine("Altering table: "); List<String> refTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>());
//RAGMA table_info([tablename]); List<String> targetTables = reference.exec("SELECT name FROM sqlite_master WHERE type='table';", new ListSQLResult<String>());
for(String table : targetTables){
if(refTables.contains(table)){
// Get reference structure
PreparedStatement stmt = reference.getPreparedStatement("PRAGMA table_info(?)");
stmt.setString(1, table);
List<DBColumn> refStruct = DBConnection.exec(stmt, new TableStructureResultHandler());
// Get target structure
stmt = target.getPreparedStatement("PRAGMA table_info(?)");
stmt.setString(1, table);
List<DBColumn> targetStruct = DBConnection.exec(stmt, new TableStructureResultHandler());
// Check existing columns
for(DBColumn column : refStruct) {
if(!targetStruct.contains(column)) {
logger.fine("Adding column '" + column.name + "' to table: " + table);
stmt = target.getPreparedStatement("ALTER TABLE ? ADD COLUMN ? ? ?");
stmt.setString(1, table); // Table name
stmt.setString(2, column.name); // Column name
stmt.setString(2, column.type); // Column type
stmt.setString(2, ""+// Column constraints
(column.defaultValue != null ? " DEFAULT '"+column.defaultValue+"'" : "")+
(column.notNull ? " NOT NULL" : "")+
(column.publicKey ? " PRIMARY KEY" : "")
);
DBConnection.exec(stmt);
}
}
// Check unnecessary columns
for(DBColumn column : targetStruct) {
if(!refStruct.contains(column)) {
logger.warning("Unable to drop column: '" + column.name + "' from table: "+ table +" (SQLite does not support dropping columns)");
}
}
}
}
} }
private void upgradeDeleteTables() throws SQLException { private static class DBColumn{
logger.fine("Deleting table: "); String name;
String type;
boolean notNull;
String defaultValue;
boolean publicKey;
public boolean equals(Object obj){
return obj instanceof DBColumn &&
name.equals(((DBColumn)obj).name);
}
}
private static class TableStructureResultHandler implements SQLResultHandler<List<DBColumn>>{
@Override
public List<DBColumn> handleQueryResult(Statement stmt, ResultSet result) throws SQLException {
ArrayList<DBColumn> list = new ArrayList<>();
while (result.next()){
DBColumn column = new DBColumn();
column.name = result.getString("name");
column.type = result.getString("type");
column.notNull = result.getBoolean("notnull");
column.defaultValue = result.getString("dflt_value");
column.publicKey = result.getBoolean("pk");
list.add(column);
}
return list;
}
} }
} }