Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* ADempiere contribution
* Author: Karsten Thiemann, [email protected]
* Compiere/Adempiere migration script generation.
*/
package oracle;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Vector;
/**
* Class to compare two oracle compiere/adempiere databases. It creates a sql
* script to upgrade the first db to the second. Please read the readme.txt
* before you use it!
*
* @author Karsten Thiemann, [email protected]
*
*/
public class DBDifference {
// global setting - please adjust them to your needs...
/** name of first database - the one you want to migrate (old compiere) */
private static final String DB1_NAME = "c253a";
/** url of first database - check servername and port */
private static final String DB1_URL = "jdbc:oracle:thin:@meitner:1521:";
/** user name of first database - should be compiere */
private static final String DB1_USER = "compiere";
/** password first database */
private static final String DB1_PASSWD = "compiere";
/** name of second database - the migration target (adempiere) */
private static final String DB2_NAME = "c253b";
/** user name of second database - should be adempiere or compiere */
private static final String DB2_USER = "compiere";
/** password second database */
private static final String DB2_PASSWD = "compiere";
/** url of second database - check servername and port */
private static final String DB2_URL = "jdbc:oracle:thin:@meitner:1521:";
/**
* id of the (custom)clients admin role. If not null access to new
* forms/windows is added
*/
private static final String AD_ROLE_ID = "1000000";
/**
* id of the (custom) client. If not null access to new forms/windows is
* added
*/
private static final String AD_CLIENT_ID = "1000000";
/** time format used for AD_* entries */
private static final String TIME_FORMAT = "RRRR-MM-DD";
// global variables - no need to edit them...
/** new tables to create */
private Vector
m_newTables = new Vector
();
/** tables with additional columns */
private Vector
m_changedTables = new Vector
();
/** tables missing in DB2 */
private Vector
m_tablesToDrop = new Vector
();
/** new views to create */
private Vector m_newViews = new Vector();
/** changed views */
private Vector m_changedViews = new Vector();
/** new constraints */
private Vector m_newConstraints = new Vector();
/** constraints missing in db2 if not a customization you can drop them */
private Vector m_constraintsToDrop = new Vector();
/** new lines for AD_Tables */
private Vector m_newTableEntry = new Vector();
/** changed lines for AD_Tables */
private Vector m_alterADEntry = new Vector();
/** deleted lines for AD_Tables */
private Vector m_deleteADEntry = new Vector();
/** new functions/procedure statements to create */
private Vector m_newFunctionStatements = new Vector();
/** new index statements to create */
private Vector m_newIndexStatements = new Vector();
/** drop index statements */
private Vector m_dropIndexStatements = new Vector();
/** functions/procedure statements to drop */
private Vector m_dropFunctionStatements = new Vector();
/** triggers to drop */
private Vector m_dropTriggerStatements = new Vector();
/** unappliable statements */
private Vector m_unappliableStatements = new Vector();
private Statement stmtdb1 = null;
private Statement stmtdb2 = null;
private Connection con1 = null;
private Connection con2 = null;
/**
* Main method...
*
* @param args
*/
public static void main(String[] args) {
new DBDifference().showDifference();
}
/**
* Compares the two databases and prints out the sql statements and hints to
* update the first db to the second.
*
* @param db1
* name of first database (working db)
* @param db2
* name of second database (reference db)
*/
public void showDifference() {
try {
con1 = getConnection(DB1_NAME, DB1_USER, DB1_PASSWD, DB1_URL);
con1.setAutoCommit(false);
con2 = getConnection(DB2_NAME, DB2_USER, DB2_PASSWD, DB2_URL);
con2.setAutoCommit(false);
stmtdb1 = con1.createStatement();
stmtdb2 = con2.createStatement();
System.out.println("compare tables ...");
compareTables();
System.out.println("compare constraints ...");
compareConstraints();
System.out.println("compare views ...");
compareViews();
System.out.println("compare functions/procedures ...");
compareFunctionsAndProcedures();
System.out.println("drop triggers ...");
dropTriggers();
System.out.println("compare ad_elements ...");
compareADElements();
System.out.println("compare indexes ...");
compareIndexes();
sortAndPrintSQL();
stmtdb1.close();
stmtdb2.close();
con1.close();
con2.close();
System.out.println("done.");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Newer compiere dbs don't use triggers. So just create drop statements.
*
* @throws SQLException
*/
private void dropTriggers() throws SQLException {
String sql = "select trigger_name from user_triggers order by trigger_name";
ResultSet rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
m_dropTriggerStatements.add("DROP " + rs.getString("TRIGGER_NAME") + ";");
}
rs.close();
}
/**
* Compare indexes.
*
* @throws SQLException
*/
private void compareIndexes() throws SQLException {
final Vector indexNamesDB1 = new Vector();
final Vector indexNamesDB2 = new Vector();
String sql = "select index_name, uniqueness, table_name from user_indexes "
+ " where index_type='NORMAL' and index_name not like 'SYS_%' and index_name not like 'BIN$%'";
ResultSet rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
indexNamesDB1.add(rs.getString("INDEX_NAME"));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
indexNamesDB2.add(rs.getString("INDEX_NAME"));
}
rs.close();
final Vector newIndexes = getNewElements(indexNamesDB1, indexNamesDB2);
for (int i = 0; i < newIndexes.size(); i++) {
if (!newIndexes.get(i).endsWith("KEY")) {
// key indexes are generated by oracle when you create the table
createNewIndexEntry(newIndexes.get(i));
}
}
// drop indexes not found in db2
final Vector missingIndexes = getMissingElements(indexNamesDB1, indexNamesDB2);
for (int i = 0; i < missingIndexes.size(); i++) {
if (!missingIndexes.get(i).endsWith("KEY")) {
//unable to drop key indexes - they are dropped if table is dropped
m_dropIndexStatements.add("DROP INDEX " + missingIndexes.get(i) + ";");
}
}
// find changed index
for (int i = 0; i < indexNamesDB2.size(); i++) {
if (indexNamesDB1.contains(indexNamesDB2.get(i))) {
// index found in both dbs, test for changes
// get columns for index
final Vector columnNames1 = new Vector();
final Vector columnNames2 = new Vector();
sql = "select column_name from user_ind_columns where index_name='"
+ indexNamesDB2.get(i) + "' order by column_position";
rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
columnNames1.add(rs.getString("COLUMN_NAME"));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
columnNames2.add(rs.getString("COLUMN_NAME"));
}
rs.close();
// simple comparison - just compare the length...
if (columnNames1.size() != columnNames2.size()) {
if (!indexNamesDB2.get(i).endsWith("KEY")) {
// cant drop key indexes...
m_dropIndexStatements.add("DROP INDEX " + indexNamesDB2.get(i) + ";");
createNewIndexEntry(indexNamesDB2.get(i));
}
}
}
}
}
/**
* Creates create index statements for the giving indexName and adds them to
* the global m_newIndexStatements Vector.
*
* @param newIndexes
* @param i
* @throws SQLException
*/
private void createNewIndexEntry(String indexName) throws SQLException {
ResultSet rs;
String unique = "";
String tableName = "";
rs = stmtdb2
.executeQuery("select table_name, uniqueness from user_indexes where index_name='"
+ indexName + "'");
if (rs.next()) {
tableName = rs.getString("TABLE_NAME");
unique = rs.getString("UNIQUENESS");
if (unique.equals("NONUNIQUE")) {
unique = "";
}
}
rs.close();
String createStatement = "CREATE " + unique + " INDEX " + indexName + " ON " + tableName
+ " (";
// get columns for index
rs = stmtdb2.executeQuery("select column_name from user_ind_columns where index_name='"
+ indexName + "' order by column_position");
int k = 0;
while (rs.next()) {
if (k != 0) {
createStatement += " ,";
}
createStatement += rs.getString("COLUMN_NAME");
k++;
}
rs.close();
createStatement += ");";
m_newIndexStatements.add(createStatement);
}
/**
* Compares the functions and procedures of the two dbs.
*
* @throws SQLException
*/
private void compareFunctionsAndProcedures() throws SQLException {
final Vector functionNamesDB1 = new Vector();
final Vector functionNamesDB2 = new Vector();
// user_procedures holds functions and procedures...
String sql = "select object_name from user_procedures order by object_name";
ResultSet rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
functionNamesDB1.add(rs.getString("OBJECT_NAME"));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
functionNamesDB2.add(rs.getString("OBJECT_NAME"));
}
rs.close();
// compare existing functions
for (int i = 0; i < functionNamesDB2.size(); i++) {
if (functionNamesDB1.contains(functionNamesDB2.get(i))) {
sql = "select text from user_source where name='" + functionNamesDB2.get(i) + "'";
rs = stmtdb1.executeQuery(sql);
String text1 = "";
String text2 = "";
if (rs.next()) {
text1 = rs.getString("TEXT");
}
rs.close();
rs = stmtdb2.executeQuery(sql);
if (rs.next()) {
text2 = rs.getString("TEXT");
}
rs.close();
if (!text2.equals(text1)) {
// changed function
System.out.println("FUNCTION OR PROCEDURE " + functionNamesDB2.get(i)
+ " HAS CHANGED - please check it for customizations");
rs = stmtdb2.executeQuery("select text from user_source where name='"
+ functionNamesDB2.get(i) + "'");
String createStatement = "create or replace ";
while (rs.next()) {
createStatement += rs.getString("TEXT");
}
m_newFunctionStatements.add(createStatement);
}
}
}
System.out.println("searching new functions/procedures ...");
final Vector newFunctions = getNewElements(functionNamesDB1, functionNamesDB2);
for (int i = 0; i < newFunctions.size(); i++) {
rs = stmtdb2.executeQuery("select text from user_source where name='"
+ newFunctions.get(i) + "'");
String createStatement = " CREATE OR REPLACE ";
while (rs.next()) {
createStatement += rs.getString("TEXT");
}
m_newFunctionStatements.add(createStatement);
}
final Vector missingFunctions = getMissingElements(functionNamesDB1,
functionNamesDB2);
for (int i = 0; i < missingFunctions.size(); i++) {
m_dropFunctionStatements.add(" DROP FUNCTION " + missingFunctions.get(i) + ";");
}
}
/**
* Compares the views of the two dbs.
*
* @throws SQLException
*/
private void compareViews() throws SQLException {
final Vector viewsDB1 = new Vector();
final Vector viewsDB2 = new Vector();
String sql = "select view_name, text from user_views where view_name not like 'BIN$%'";
ResultSet rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
viewsDB1.add(new View(rs.getString("VIEW_NAME"), rs.getString("TEXT")));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
viewsDB2.add(new View(rs.getString("VIEW_NAME"), rs.getString("TEXT")));
}
rs.close();
// find new views
for (int i = 0; i < viewsDB2.size(); i++) {
String name = viewsDB2.get(i).getName();
String text = viewsDB2.get(i).getText();
boolean found = false;
boolean identical = false;
for (int j = 0; j < viewsDB1.size(); j++) {
if (name.equals(viewsDB1.get(j).getName())) {
found = true;
if (text.equals(viewsDB1.get(j).getText())) {
identical = true;
}
break;
}
}
if (!found) {
// add view to new views
m_newViews.add(viewsDB2.get(i));
} else if (!identical) {
// add view to changed views
m_changedViews.add(viewsDB2.get(i));
}
}
// find views missing in db2 - no need to drop them
for (int i = 0; i < viewsDB1.size(); i++) {
String name = viewsDB1.get(i).getName();
boolean found = false;
for (int j = 0; j < viewsDB2.size(); j++) {
if (name.equals(viewsDB2.get(j).getName())) {
found = true;
break;
}
}
if (!found) {
System.out.println();
System.out.println("THE VIEW " + name
+ " DOESN'T EXIST IN NEW DB - but no need to drop them...");
System.out.println();
}
}
}
/**
* Compares the tables of the two dbs.
*
* @throws SQLException
*/
private void compareTables() throws SQLException {
final Vector tableNamesDB1 = new Vector();
final Vector tableNamesDB2 = new Vector();
String sql = "select table_name from user_tables where table_name not like 'BIN$%'";
ResultSet rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
tableNamesDB1.add(rs.getString("TABLE_NAME"));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
tableNamesDB2.add(rs.getString("TABLE_NAME"));
}
rs.close();
System.out.println("searching new tables ...");
final Vector newTables = getNewElements(tableNamesDB1, tableNamesDB2);
for (int i = 0; i < newTables.size(); i++) {
final String tableName = newTables.get(i);
final Table table = new Table(tableName);
sql = "select * from user_tab_columns where table_name='" + tableName + "'";
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
Column column = new Column(rs);
table.addColumn(column);
}
rs.close();
m_newTables.add(table);
//createEntriesForTable(tableName);
}
System.out.println("searching missing tables ...");
final Vector missingTables = getMissingElements(tableNamesDB1, tableNamesDB2);
for (int i = 0; i < missingTables.size(); i++) {
final Table table = new Table(missingTables.get(i));
m_tablesToDrop.add(table);
}
System.out.println("searching changed tables ...");
addChangedTablesToGlobalVector(tableNamesDB1, tableNamesDB2);
}
/**
* Searches for changed tables and adds them to the global m_changedTables
* Vector.
*
* @param tableNamesDB1
* @param tableNamesDB2
* @throws SQLException
*/
private void addChangedTablesToGlobalVector(Vector tableNamesDB1,
Vector tableNamesDB2) throws SQLException {
final PreparedStatement stmtGetColumNamesForTable1 = con1
.prepareStatement("select column_name from user_tab_columns where table_name=?");
final PreparedStatement stmtGetColumNamesForTable2 = con2
.prepareStatement("select column_name from user_tab_columns where table_name=?");
final PreparedStatement stmtGetColumDetailsDB1 = con1
.prepareStatement("select * from user_tab_columns where column_name=? and table_name=?");
final PreparedStatement stmtGetColumDetailsDB2 = con2
.prepareStatement("select * from user_tab_columns where column_name=? and table_name=?");
Iterator iter = tableNamesDB2.iterator();
while (iter.hasNext()) {
String tableName = (String) iter.next();
if (tableNamesDB1.contains(tableName)) {
// get all column names for this table
final Vector columnNamesDB1 = new Vector();
final Vector columnNamesDB2 = new Vector();
stmtGetColumNamesForTable1.setString(1, tableName);
stmtGetColumNamesForTable2.setString(1, tableName);
ResultSet rs = stmtGetColumNamesForTable1.executeQuery();
while (rs.next()) {
columnNamesDB1.add(rs.getString("COLUMN_NAME"));
}
rs.close();
rs = stmtGetColumNamesForTable2.executeQuery();
while (rs.next()) {
columnNamesDB2.add(rs.getString("COLUMN_NAME"));
}
rs.close();
// search for new columns in existing tables
final Vector addedColumns = getNewElements(columnNamesDB1, columnNamesDB2);
if (addedColumns.size() != 0) {
final Table table = new Table(tableName);
for (int i = 0; i < addedColumns.size(); i++) {
stmtGetColumDetailsDB2.setString(1, addedColumns.get(i));
stmtGetColumDetailsDB2.setString(2, tableName);
rs = stmtGetColumDetailsDB2.executeQuery();
while (rs.next()) {
final Column column = new Column(rs);
if (!column.isNullable() && column.getDefaultValue() == null) {
// search for sensible default value and set it
column.setTmpDefaultValue(getTempDefaultValueForColumn(tableName,
column));
}
table.addColumnToAdd(column);
}
rs.close();
}
m_changedTables.add(table);
}
// search for missing columns in existing tables
final Vector missingColumns = getMissingElements(columnNamesDB1,
columnNamesDB2);
if (missingColumns.size() != 0) {
final Table table = new Table(tableName);
for (int i = 0; i < missingColumns.size(); i++) {
table.addColumnToDrop(new Column(missingColumns.get(i)));
}
m_changedTables.add(table);
}
// find changed columns
Table changedTable = null;
for (int i = 0; i < columnNamesDB1.size(); i++) {
String colName = columnNamesDB1.get(i);
if (columnNamesDB2.contains(colName)) {
// column with that name exists in both dbs
stmtGetColumDetailsDB1.setString(1, colName);
stmtGetColumDetailsDB1.setString(2, tableName);
stmtGetColumDetailsDB2.setString(1, colName);
stmtGetColumDetailsDB2.setString(2, tableName);
Column colDB1 = null;
Column colDB2 = null;
rs = stmtGetColumDetailsDB1.executeQuery();
if (rs.next()) {
colDB1 = new Column(rs);
}
rs.close();
rs = stmtGetColumDetailsDB2.executeQuery();
if (rs.next()) {
colDB2 = new Column(rs);
}
rs.close();
if (!colDB1.equals(colDB2)) {
if (changedTable == null) {
changedTable = new Table(tableName);
}
if (!colDB2.isNullable() && colDB2.getDefaultValue() == null) {
// search for sensible default value and set it
colDB2.setTmpDefaultValue(getTempDefaultValueForColumn(tableName,
colDB2));
}
colDB2.setNullHasChanged(colDB2.isNullable() != colDB1.isNullable());
final String def1 = colDB1.getDefaultValue();
final String def2 = colDB2.getDefaultValue();
if (def1 == null && def2 == null) {
colDB2.setDefaultHasChanged(false);
} else if (def1 != null && def2 != null) {
colDB2.setDefaultHasChanged(!def1.equals(def2));
} else {
colDB2.setDefaultHasChanged(true);
}
changedTable.addColumnToModify(colDB2);
}
}
}
if (changedTable != null) {
m_changedTables.add(changedTable);
}
}
}
stmtGetColumNamesForTable1.close();
stmtGetColumNamesForTable2.close();
stmtGetColumDetailsDB1.close();
stmtGetColumDetailsDB2.close();
}
/**
* Returns a sensible (applieable) value for the given table and column. The
* value can be used as a default value for the column. It is used to
* add/modify columns with not null state to tables with existing data.
*
* @param tableName
* @param column
* @return
* @throws SQLException
*/
private String getTempDefaultValueForColumn(String tableName, Column column)
throws SQLException {
String retValue = null;
// test if it is a foreign key
String sql = "select col2.Table_Name, col2.Column_Name from User_Cons_Columns col "
+ "inner join user_constraints con on (col.Constraint_Name=con.Constraint_Name) "
+ "inner join User_Cons_Columns col2 on (con.R_Constraint_Name=col2.Constraint_Name) "
+ "where col.table_name='" + tableName + "' and con.constraint_type='R' "
+ "and col.Column_Name='" + column.getColumnName() + "'";
ResultSet rs = stmtdb2.executeQuery(sql);
String fkTableName = "";
String fkColumnName = "";
if (rs.next()) {
fkTableName = rs.getString("Table_Name");
fkColumnName = rs.getString("Column_Name");
}
rs.close();
if (!"".equals(fkColumnName) && !"".equals(fkTableName)) {
try {
// foreign key found - try to get a value from the old db
// may be an error if fkColumn is new
sql = "select max(" + fkColumnName + ") from " + fkTableName;
rs = stmtdb1.executeQuery(sql);
if (rs.next()) {
retValue = rs.getString(1);
}
rs.close();
} catch (SQLException e) {
// fkColumn doesn't exist in db1
System.out.println("foreign key column missing in db1: " + fkColumnName
+ " - table: " + fkTableName);
}
}
if (retValue == null) {
// no foreign key - check for column type
if (column.isNumberType()) {
retValue = "-1";
} else if (column.isStringType()) {
retValue = "'N'";
}
}
return retValue;
}
/**
* Returns a Vector containing the Strings found in objNamesDB1 but not in
* objNamesDB2. This could be deleted tables, columns etc. or
* customizations.
*
* @param objNamesDB1
* @param objNamesDB2
* @return
*/
private Vector getMissingElements(Vector objNamesDB1, Vector objNamesDB2) {
Vector missingElements = new Vector();
Iterator iter = objNamesDB1.iterator();
while (iter.hasNext()) {
String name = (String) iter.next();
if (!objNamesDB2.contains(name)) {
missingElements.add(name);
}
}
return missingElements;
}
/**
* Returns a Vector containing the Strings found in objNamesDB2 but not in
* objNamesDB1.
*
* @param objNamesDB1
* @param objNamesDB2
* @return
*/
private Vector getNewElements(Vector objNamesDB1, Vector objNamesDB2) {
Vector newElements = new Vector();
Iterator iter = objNamesDB2.iterator();
while (iter.hasNext()) {
String name = (String) iter.next();
if (!objNamesDB1.contains(name)) {
newElements.add(name);
}
}
return newElements;
}
/**
* Sorts the generated sql statements by applying them to db1 and prints the
* sorted statement list.
*
* @throws SQLException
*/
private void sortAndPrintSQL() throws SQLException {
final Vector statements = new Vector(1000, 500);
final Vector sortedStatements = new Vector(1000, 500);
for (int i = 0; i < m_newTables.size(); i++) {
statements.add(m_newTables.get(i).getCreateStatement());
}
for (int i = 0; i < m_changedTables.size(); i++) {
if (m_changedTables.get(i).isAlterAdd()) {
statements.add(m_changedTables.get(i).getAlterAddStatement());
} else if (m_changedTables.get(i).isAlterDrop()) {
statements.add(m_changedTables.get(i).getAlterDropStatement());
} else if (m_changedTables.get(i).isAlterModify()) {
statements.add(m_changedTables.get(i).getAlterModifyStatement());
}
}
for (int i = 0; i < m_constraintsToDrop.size(); i++) {
statements.add(m_constraintsToDrop.get(i).getDropString());
}
for (int i = 0; i < m_newConstraints.size(); i++) {
statements.add(m_newConstraints.get(i).getAlterTableString());
}
Vector tempVector = sortStatements(statements);
for (int i = 0; i < tempVector.size(); i++) {
sortedStatements.add(tempVector.get(i));
}
// new data
sortedStatements.add("COMMIT;");
sortedStatements.add("SET DEFINE OFF;");
statements.clear();
for (int i = 0; i < m_newTableEntry.size(); i++) {
statements.add(m_newTableEntry.get(i).replaceAll("\n", " "));
}
tempVector = sortStatements(statements);
for (int i = 0; i < tempVector.size(); i++) {
sortedStatements.add(tempVector.get(i));
}
// changed data
sortedStatements.add("COMMIT;");
sortedStatements.add("SET DEFINE OFF;");
statements.clear();
for (int i = 0; i < m_alterADEntry.size(); i++) {
statements.add(m_alterADEntry.get(i).replaceAll("\n", " "));
}
tempVector = sortStatements(statements);
for (int i = 0; i < tempVector.size(); i++) {
sortedStatements.add(tempVector.get(i));
}
// data to delete
sortedStatements.add("COMMIT;");
sortedStatements.add("SET DEFINE OFF;");
statements.clear();
for (int i = 0; i < m_deleteADEntry.size(); i++) {
statements.add(m_deleteADEntry.get(i).replaceAll("\n", " "));
}
tempVector = sortStatements(statements);
for (int i = 0; i < tempVector.size(); i++) {
sortedStatements.add(tempVector.get(i));
}
System.out.println();
System.out.println("---------------------------");
System.out.println("-- SCRIPT STARTS HERE!");
System.out.println("---------------------------");
System.out.println("-- UNABLE TO APPLY THESE STATEMENTS - START");
for (int i = 0; i < m_unappliableStatements.size(); i++) {
System.out.println(m_unappliableStatements.get(i));
}
System.out.println("-- UNABLE TO APPLY THESE STATEMENTS - END");
System.out.println();
System.out.println("-- NEW/CHANGED TABLES - NEW/CHANGED AD_ENTRIES");
for (int i = 0; i < sortedStatements.size(); i++) {
System.out.println(sortedStatements.get(i));
}
// no sorting needed
System.out.println();
System.out.println("-- NEW VIEWS");
for (int i = 0; i < m_newViews.size(); i++) {
System.out.println(m_newViews.get(i).getCreateStatement());
}
System.out.println();
System.out
.println("-- CHANGED VIEWS - but check them first - don't overwrite your customizations...");
for (int i = 0; i < m_changedViews.size(); i++) {
System.out.println(m_changedViews.get(i).getCreateStatement());
}
System.out.println();
System.out.println("-- NEW OR CHANGED FUNCTIONS/PROCEDURES");
for (int i = 0; i < m_newFunctionStatements.size(); i++) {
System.out.println(m_newFunctionStatements.get(i));
}
System.out.println();
System.out.println("-- DROP FUNCTIONS/PROCEDURES");
for (int i = 0; i < m_dropFunctionStatements.size(); i++) {
System.out.println(m_dropFunctionStatements.get(i));
}
System.out.println();
System.out.println("-- DROP TRIGGERS");
for (int i = 0; i < m_dropTriggerStatements.size(); i++) {
System.out.println(m_dropTriggerStatements.get(i));
}
System.out.println();
System.out.println("-- DROP INDEXES");
for (int i = 0; i < m_dropIndexStatements.size(); i++) {
System.out.println(m_dropIndexStatements.get(i));
}
System.out.println();
System.out.println("-- NEW OR CHANGED INDEXES");
for (int i = 0; i < m_newIndexStatements.size(); i++) {
System.out.println(m_newIndexStatements.get(i));
}
System.out.println();
System.out.println("-- PLEASE CHECK THE SEQUENCES BY HAND - USE:");
System.out.println("-- select * from user_sequences;");
System.out.println();
System.out.println(getUpdateVersionStatement());
System.out.println("COMMIT;");
}
/**
* Sorts the given statements by applying them to db1. Returns a Vector
* containing the sorted statements.
*
* @param statements
* @param sortedStatements
*/
private Vector sortStatements(final Vector statements) {
final Vector sortedStatements = new Vector(1000, 500);
int maxTries = statements.size();
int attempt = 0;
while (statements.size() != 0 && attempt <= maxTries) {
final String statement = statements.firstElement();
try {
// there may be not null workaround, and we need to preserve the
// sequence
String[] stmts = statement.split(Table.STATEMENT_SEPARATOR);
for (int j = 0; j < stmts.length; j++) {
if (!"".equals(stmts[j])) {
stmtdb1.executeUpdate(stmts[j].substring(0, stmts[j].lastIndexOf(';')));
}
}
sortedStatements.add(statement.replaceAll(Table.STATEMENT_SEPARATOR, ""));
statements.remove(0);
maxTries = statements.size();
attempt = 0;
} catch (SQLException e) {
System.out.println(e.getMessage());
statements.remove(0);
statements.add(statement);
}
attempt++;
}
if (statements.size() != 0) {
for (int i = 0; i < statements.size(); i++) {
m_unappliableStatements.add(statements.get(i));
}
}
return sortedStatements;
}
/**
* Prints out the generated sql statements to the console. Old version.
*
* @deprecated
*/
private void printSQL() {
System.out.println();
System.out
.println("-- please replace all PA_Measure/PA_MeasureCalc related entries with the following lines");
System.out.println("and place them at the end of the alter tables section");
System.out.println(getHardcodedStuff());
System.out.println();
System.out.println("-- end of the PA_Measure/PA_MeasureCalc replacement lines");
System.out.println();
System.out.println("-- USE THE FOLLOWING LINES FOR YOUR MIGRATION SCRIPT:");
System.out.println("-- INSERT TABLES");
for (int i = 0; i < m_newTables.size(); i++) {
System.out.println(m_newTables.get(i).getCreateStatement());
}
System.out.println();
System.out.println("-- ALTER TABLES");
for (int i = 0; i < m_changedTables.size(); i++) {
if (m_changedTables.get(i).isAlterAdd()) {
System.out.println(m_changedTables.get(i).getAlterAddStatement());
}
}
System.out.println("-- PLEASE CHECK THE ADD/MODIFY STATEMENTS:");
System.out.println("-- If you find a 'BEWARE' first check if the table has some data");
System.out.println("-- if not, you can ignort the 'BEWARE', if the table has data");
System.out.println("-- you might have to set a temporary default value for the column");
System.out.println("-- (if not all rows have a value for the modied column)");
System.out.println("-- Sample: ALTER TABLE TEST ADD ( columnname NOT NULL);");
System.out
.println("-- first set default value (for existing data), than remove it (for new data)");
System.out
.println("-- change to: ALTER TABLE TEST ADD ( columnname DEFAULT 'tempDefault' NOT NULL);");
System.out.println("-- ALTER TABLE TEST MODIFY ( columnname NULL);");
System.out.println("-- ALTER TABLE TEST MODIFY ( columnname NOT NULL);");
System.out.println();
System.out.println("-- FOR MODIFY STATEMENTS");
System.out.println("-- just set a value for all existing rows");
System.out.println();
System.out.println("-- Sample: ALTER TABLE TEST MODIFY ( columnname not null);");
System.out.println("-- insert an update statement before the alter statement");
System.out.println("-- insert before: UPDATE TEST SET columnname 'myDefault';");
for (int i = 0; i < m_changedTables.size(); i++) {
if (m_changedTables.get(i).isAlterModify()) {
System.out.println(m_changedTables.get(i).getAlterModifyStatement());
}
}
System.out.println("-- PLEASE CHECK THE FOLLOWING COLUMNS - DON'T DROP CUSTOMIZATIONS");
for (int i = 0; i < m_changedTables.size(); i++) {
if (m_changedTables.get(i).isAlterDrop()) {
System.out.println(m_changedTables.get(i).getAlterDropStatement());
}
}
System.out.println();
System.out.println("-- DROP TABLES - but check them first - don't drop customizations...");
for (int i = 0; i < m_tablesToDrop.size(); i++) {
System.out.println(m_tablesToDrop.get(i).getDropStatement());
}
System.out.println();
System.out.println();
System.out.println("-- PUT THE FOLLOWING LINES INTO A NEW FILE");
System.out.println();
System.out.println();
System.out.println("-- DROP CONSTRAINTS");
for (int i = 0; i < m_constraintsToDrop.size(); i++) {
System.out.println(m_constraintsToDrop.get(i).getDropString());
}
System.out.println();
System.out.println("-- ADD/RECREATE CONSTRAINTS");
for (int i = m_newConstraints.size() - 1; i >= 0; i--) {
System.out.println(m_newConstraints.get(i).getAlterTableString());
}
System.out.println();
System.out.println();
System.out.println("-- PUT THE FOLLOWING LINES INTO A NEW FILE");
System.out.println();
System.out.println();
System.out.println("-- NEW AD_* ENTRIES AND ROWS OF ADDED TABLES");
System.out.println();
System.out.println("SET DEFINE OFF;");
System.out.println();
Collections.sort(m_newTableEntry, new AD_Comparator());
for (int i = 0; i < m_newTableEntry.size(); i++) {
System.out.println(m_newTableEntry.get(i).replaceAll("\n", " "));
}
System.out.println();
System.out.println("-- CHANGED AD_* ENTRIES");
Collections.sort(m_alterADEntry);
for (int i = 0; i < m_alterADEntry.size(); i++) {
System.out.println(m_alterADEntry.get(i).replaceAll("\n", " "));
}
System.out.println();
System.out.println();
System.out.println("-- PUT THE FOLLOWING LINES INTO A NEW FILE");
System.out.println();
System.out.println();
System.out.println("-- NEW VIEWS");
for (int i = 0; i < m_newViews.size(); i++) {
System.out.println(m_newViews.get(i).getCreateStatement());
}
System.out.println();
System.out
.println("-- CHANGED VIEWS - but check them first - don't overwrite your customizations...");
for (int i = 0; i < m_changedViews.size(); i++) {
System.out.println(m_changedViews.get(i).getCreateStatement());
}
System.out.println();
System.out.println("-- NEW OR CHANGED FUNCTIONS/PROCEDURES");
for (int i = 0; i < m_newFunctionStatements.size(); i++) {
System.out.println(m_newFunctionStatements.get(i));
}
System.out.println();
System.out.println("-- DROP FUNCTIONS/PROCEDURES");
for (int i = 0; i < m_dropFunctionStatements.size(); i++) {
System.out.println(m_dropFunctionStatements.get(i));
}
System.out.println();
System.out.println("-- DROP TRIGGERS - BUT DON'T DELETE CUSTOMIZATIONS");
for (int i = 0; i < m_dropTriggerStatements.size(); i++) {
System.out.println(m_dropTriggerStatements.get(i));
}
System.out.println();
System.out.println("-- DROP INDEXES - BUT DON'T DELETE CUSTOMIZATIONS");
for (int i = 0; i < m_dropIndexStatements.size(); i++) {
System.out.println(m_dropIndexStatements.get(i));
}
System.out.println();
System.out.println("-- NEW OR CHANGED INDEXES");
for (int i = 0; i < m_newIndexStatements.size(); i++) {
System.out.println(m_newIndexStatements.get(i));
}
System.out.println();
System.out.println("-- PLEASE CHECK THE SEQUENCES BY HAND - USE:");
System.out.println("-- select * from user_sequences;");
System.out.println();
System.out.println(getUpdateVersionStatement());
System.out.println("COMMIT;");
}
/**
* Compares the constraint, if there are differences drop the old and create
* a new one.
*
* @param name
* @param stat1
* @param stat2
* @throws SQLException
*/
private void compareConstraints() throws SQLException {
final Vector constraintsDB1 = new Vector();
final Vector constraintsDB2 = new Vector();
// get all constrains but not the U(nique) and SYS_* ones
// SYS_* constraints - name is autocreated for the not null and check
// constraints without name
// They are handled by the alter table statements
String sql = "select * from user_constraints where constraint_name not like 'SYS_%' and constraint_name not like 'BIN%' and constraint_type != 'U'";
ResultSet rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
constraintsDB1.add(new Constraint(rs.getString("CONSTRAINT_NAME"), rs
.getString("TABLE_NAME")));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
constraintsDB2.add(new Constraint(rs.getString("CONSTRAINT_NAME"), rs
.getString("TABLE_NAME")));
}
rs.close();
// find missing constraints - don't delete them might be customizations,
// just alert them
System.out.println("searching constraints to drop...");
Vector constraintsToDrop = new Vector();
Vector duplicatedConstraints = new Vector();
for (int i = 0; i < constraintsDB1.size(); i++) {
String n1 = constraintsDB1.get(i).getName();
boolean found = false;
for (int j = 0; j < constraintsDB2.size(); j++) {
String n2 = constraintsDB2.get(j).getName();
if (n2.equals(n1)) {
found = true;
break;
}
}
if (!found) {
// constraint in db1 but not found in db2
constraintsToDrop.add(constraintsDB1.get(i));
} else {
// check for changes
duplicatedConstraints.add(constraintsDB1.get(i));
}
}
for (int i = 0; i < constraintsToDrop.size(); i++) {
m_constraintsToDrop.add(constraintsToDrop.get(i));
}
System.out.println("searching new constraints...");
// find new constraints
for (int i = 0; i < constraintsDB2.size(); i++) {
String n2 = constraintsDB2.get(i).getName();
boolean found = false;
for (int j = 0; j < constraintsDB1.size(); j++) {
String n1 = constraintsDB1.get(j).getName();
if (n2.equals(n1)) {
found = true;
break;
}
}
if (!found) {
m_newConstraints.add(createNewConstraint(constraintsDB2.get(i).getName()));
}
}
// old version
for (int i = 0; i < duplicatedConstraints.size(); i++) {
String name = duplicatedConstraints.get(i).getName();
sql = "select Constraint_Type, Table_Name,"
+ "Search_Condition, R_Constraint_Name, Delete_Rule"
+ " from User_Constraints where Constraint_Name='" + name + "'";
String sqlColumn = "select * from User_Cons_Columns where Constraint_Name='" + name
+ "'";
rs = stmtdb2.executeQuery(sql);
String tableName2 = "";
String constraintType2 = "";
String condition2 = "";
String rConstraintName2 = "";
String deleteRule2 = "";
String column2 = "";
if (rs.next()) {
constraintType2 = rs.getString("Constraint_Type");
tableName2 = rs.getString("Table_Name");
condition2 = rs.getString("Search_Condition");
rConstraintName2 = rs.getString("R_Constraint_Name");
deleteRule2 = rs.getString("Delete_Rule");
}
rs.close();
rs = stmtdb2.executeQuery(sqlColumn);
if (rs.next()) {
column2 = rs.getString("Column_Name");
}
rs.close();
rs = stmtdb1.executeQuery(sql);
String tableName1 = "";
String constraintType1 = "";
String condition1 = "";
String rConstraintName1 = "";
String deleteRule1 = "";
String column1 = "";
if (rs.next()) {
constraintType1 = rs.getString("Constraint_Type");
tableName1 = rs.getString("Table_Name");
condition1 = rs.getString("Search_Condition");
rConstraintName1 = rs.getString("R_Constraint_Name");
deleteRule1 = rs.getString("Delete_Rule");
}
rs.close();
rs = stmtdb1.executeQuery(sqlColumn);
if (rs.next()) {
column1 = rs.getString("Column_Name");
}
rs.close();
if (condition1 == null) {
condition1 = "";
}
if (rConstraintName1 == null) {
rConstraintName1 = "";
}
if (deleteRule1 == null) {
deleteRule1 = "";
}
if (column1 == null) {
column1 = "";
}
if (condition2 == null) {
condition2 = "";
}
if (rConstraintName2 == null) {
rConstraintName2 = "";
}
if (deleteRule2 == null) {
deleteRule2 = "";
}
if (column2 == null) {
column2 = "";
}
if (tableName1.equals(tableName2) && constraintType1.equals(constraintType2)
&& condition1.equals(condition2) && rConstraintName1.equals(rConstraintName2)
&& deleteRule1.equals(deleteRule2) && column1.equals(column2)) {
// seems to be equal...
} else {
m_constraintsToDrop.add(duplicatedConstraints.get(i));
m_newConstraints.add(createNewConstraint(name));
}
}
addMissingSysConstraints();
}
/**
* Creates check constrains found in db2 but not in db1 and adds them to the
* global m_newConstraints Vector.
*/
private void addMissingSysConstraints() {
String sql2 = "";
final Vector newConstraintNames = new Vector();
try {
String sql = "select * from user_constraints where constraint_name like 'SYS_%' and constraint_type='C'";
ResultSet rs2 = stmtdb2.executeQuery(sql);
while (rs2.next()) {
final String searchCondition = rs2.getString("SEARCH_CONDITION");
if (searchCondition == null) {
continue;
} else if (searchCondition.toUpperCase().indexOf("IS NOT NULL") != -1) {
// not null constraints are handled by alter table
continue;
}
final String tableName = rs2.getString("TABLE_NAME");
sql2 = "select * from user_constraints where table_name='" + tableName
+ "' and search_condition is not null";
ResultSet rs1 = stmtdb1.executeQuery(sql2);
boolean found = false;
while (rs1.next()) {
if (searchCondition.equals(rs1.getString("SEARCH_CONDITION"))) {
found = true;
continue;
}
}
rs1.close();
if (!found) {
newConstraintNames.add(rs2.getString("CONSTRAINT_NAME"));
}
}
rs2.close();
for (int i = 0; i < newConstraintNames.size(); i++) {
m_newConstraints.add(createNewConstraint(newConstraintNames.get(i)));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(sql2);
}
}
/**
* Creates a new constraint from the data found for the constraint with the
* given name in db2.
*
* @param stmtdb2
* @param name
* @throws SQLException
*/
private Constraint createNewConstraint(String name) throws SQLException {
ResultSet rs = stmtdb2.executeQuery("select Constraint_Type, Table_Name,"
+ "Search_Condition, R_Constraint_Name, Delete_Rule"
+ " from User_Constraints where Constraint_Name='" + name + "'");
String tableName = "";
String constraintType = "";
String condition = "";
String rConstraintName = "";
String deleteRule = "";
String column = "";
if (rs.next()) {
constraintType = rs.getString("Constraint_Type");
tableName = rs.getString("Table_Name");
condition = rs.getString("Search_Condition");
rConstraintName = rs.getString("R_Constraint_Name");
deleteRule = rs.getString("Delete_Rule");
}
rs.close();
if (constraintType.equals(Constraint.FOREIGN_KEY)) {
Constraint refConstraint = null;
rs = stmtdb2.executeQuery("select * from User_Cons_Columns where Constraint_Name='"
+ name + "'");
if (rs.next()) {
column = rs.getString("Column_Name");
}
rs.close();
rs = stmtdb2.executeQuery("select * from User_Cons_Columns where Constraint_Name='"
+ rConstraintName + "'");
if (rs.next()) {
String refColumn = rs.getString("Column_Name");
String refTableName = rs.getString("Table_Name");
refConstraint = new Constraint(rConstraintName, refTableName);
refConstraint.addColumnName(refColumn);
refConstraint.setDeleteRule(deleteRule);
}
rs.close();
Constraint c = new Constraint(name, tableName);
c.setType(Constraint.FOREIGN_KEY);
c.addColumnName(column);
c.setRConstraint(refConstraint);
c.addColumnName(column);
c.setDeleteRule(deleteRule);
return (c);
} else if (constraintType.equals(Constraint.PRIMARY_KEY)) {
rs = stmtdb2.executeQuery("select * from User_Cons_Columns where Constraint_Name='"
+ name + "'");
Constraint c = new Constraint(name, tableName);
c.setType(Constraint.PRIMARY_KEY);
c.setDeleteRule(deleteRule);
while (rs.next()) {
c.addColumnName(rs.getString("Column_Name"));
}
rs.close();
return (c);
} else if (constraintType.equals(Constraint.CHECK)) {
rs = stmtdb2.executeQuery("select * from User_Cons_Columns where Constraint_Name='"
+ name + "'");
if (rs.next()) {
column = rs.getString("Column_Name");
}
rs.close();
Constraint c = new Constraint(name, tableName);
c.setType(Constraint.CHECK);
c.addColumnName(column);
c.setCheckCondition(condition);
c.setDeleteRule(deleteRule);
return (c);
}
return null;
}
/**
* Compares the data in the AD_% tables. Looks for new elements only.
*
* @param stmtdb1
* @param stmtdb2
* @throws SQLException
*/
private void compareADElements() throws SQLException {
final String TABLE_DOES_NOT_EXITST = "ORA-00942";
final Vector adTableNames2 = new Vector();
String sql = "select table_name from user_tables";// where table_name like 'AD_%'";
ResultSet rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
final String tableName = rs.getString("TABLE_NAME");
if (tableName.endsWith("_TRL")) {
continue;
}
adTableNames2.add(tableName);
}
rs.close();
for (int i = 0; i < adTableNames2.size(); i++) {
String tableName = adTableNames2.get(i);
boolean addClientAccess = false;
if (tableName.equals("AD_WINDOW_ACCESS") || tableName.equals("AD_PROCESS_ACCESS")
|| tableName.equals("AD_FORM_ACCESS")) {
addClientAccess = true;
}
// get all column names
final Vector columns1 = new Vector();
final Vector columns2 = new Vector();
sql = "select * from user_tab_columns where table_name='" + tableName
+ "' order by column_id";
rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
columns1.add(new Column(rs));
}
rs.close();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
columns2.add(new Column(rs));
}
rs.close();
// get keycolumns for table
sql = "select col.column_name from user_constraints constr "
+ "inner join User_Cons_Columns col ON (col.constraint_name = constr.constraint_name) "
+ "where constr.constraint_type='P' and constr.table_name = '" + tableName
+ "'";
final Vector keycolumns = new Vector();
rs = stmtdb2.executeQuery(sql);
// create select statement for table
sql = "select * from " + tableName + " where ";
if (rs.next()) {
sql += rs.getString("COLUMN_NAME");
sql += " <1000000 ";
keycolumns.add(rs.getString("COLUMN_NAME"));
} else {
// no keyColumn found
System.out.println("Please check table " + tableName
+ " for new data and add it by hand");
continue;
}
while (rs.next()) {
sql += " and " + rs.getString("COLUMN_NAME");
sql += " <1000000 ";
keycolumns.add(rs.getString("COLUMN_NAME"));
}
rs.close();
Vector dataElements1 = new Vector();
Vector dataElements2 = new Vector();
try {
// get data from db1 and db2 and compare them...
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
final ADDataElement data = new ADDataElement();
for (int j = 0; j < columns2.size(); j++) {
final String colName = columns2.get(j).getColumnName();
data.addColumnAndValue(colName, rs.getString(colName));
}
dataElements2.add(data);
}
rs.close();
// error if new colums was added and is key column...
rs = stmtdb1.executeQuery(sql);
while (rs.next()) {
final ADDataElement data = new ADDataElement();
for (int j = 0; j < columns1.size(); j++) {
final String colName = columns1.get(j).getColumnName();
data.addColumnAndValue(colName, rs.getString(colName));
}
dataElements1.add(data);
}
rs.close();
// got all data - lets compare them (will take some time...)
// new entry? search for data with same keyValues
//TODO: drop entries missing in db2...
try {
//find elements to drop
for(int j = 0; j < dataElements1.size(); j++) {
boolean found = false;
final ADDataElement data1 = dataElements1.get(j);
sql = "select * from " + tableName + " where ";
for (int m = 0; m < keycolumns.size(); m++) {
if (m != 0) {
sql += " and ";
}
sql += keycolumns.get(m) + "=" + data1.getValueForColumn(keycolumns.get(m));
}
rs = stmtdb2.executeQuery(sql);
if (rs.next()) {
found = true;
}
rs.close();
if(!found){
//data exist in db1 but no longer in db2 - delete it
createDeleteTableEntry(tableName, data1, keycolumns, columns1);
}
}
} catch (SQLException e1) {
// if keyColumns have changed...
System.out.println(e1.getMessage() + " - on searching data to drop for table: " + tableName);
}
for (int j = 0; j < dataElements2.size(); j++) {
boolean found = false;
final ADDataElement data2 = dataElements2.get(j);
sql = "select * from " + tableName + " where ";
for (int m = 0; m < keycolumns.size(); m++) {
if (m != 0) {
sql += " and ";
}
sql += keycolumns.get(m) + "=" + data2.getValueForColumn(keycolumns.get(m));
}
rs = stmtdb1.executeQuery(sql);
if (rs.next()) {
found = true;
}
rs.close();
if (!found) {
createNewTableEntry(tableName, data2, keycolumns, columns2);
if (addClientAccess && AD_CLIENT_ID != null && AD_ROLE_ID != null) {
data2.setValueForColumn("AD_CLIENT_ID", AD_CLIENT_ID);
data2.setValueForColumn("AD_ROLE_ID", AD_ROLE_ID);
createNewTableEntry(tableName, data2, keycolumns, columns2);
}
} else {
// could be changed...
// compare Strings and Numbers but not Dates like
// created/updated
// because they are changed every version...
sql = "select * from " + tableName + " where ";
boolean and = false;
for (int m = 0; m < columns2.size(); m++) {
if (!columns1.contains(columns2.get(m))) {
// column added in db2
continue;
}
String value = data2.getValueForColumn(columns2.get(m).getColumnName());
if (value != null && value.indexOf('\'') != -1) {
value = value.replaceAll("'", "''");
}
if (and) {
sql += " and ";
}
if (value == null) {
sql += columns2.get(m).getColumnName() + " is null ";
and = true;
continue;
}
if (columns2.get(m).isStringType()) {
sql += columns2.get(m).getColumnName() + "='" + value + "'";
and = true;
} else if (columns2.get(m).isNumberType()) {
sql += columns2.get(m).getColumnName() + "="
+ data2.getValueForColumn(columns2.get(m).getColumnName());
and = true;
} else {
and = false;
}
}
try {
found = false;
// System.out.println(sql);
rs = stmtdb1.executeQuery(sql);
if (rs.next()) {
found = true;
}
rs.close();
if (!found) {
updateADEntry(tableName, data2, keycolumns, columns2);
}
} catch (SQLException e) {
// corrupt sql statement because sometimes Strings
// contains '
if (e.getMessage().startsWith("ORA-00933")
|| e.getMessage().startsWith("ORA-01722")) {
// we could miss some changed ad elements but
// never mind...
;
} else {
System.out.println(e.getMessage() + ":");
System.out.println(sql);
}
}
}
}
} catch (SQLException e) {
if (e.getMessage().startsWith(TABLE_DOES_NOT_EXITST)) {
// new ad_* table, add all elements from db2
for (int j = 0; j < dataElements2.size(); j++) {
createNewTableEntry(tableName, dataElements2.get(j), keycolumns, columns2);
}
} else {
System.out.println(e.getMessage() + " - for table " + tableName);
}
}
}
}
/**
* Creates a delete from table statement for the given entry and adds it to the
* global m_deleteADEntry Vector.
* @param tableName
* @param data1
* @param keycolumns
* @param columns1
*/
private void createDeleteTableEntry(String tableName, ADDataElement data1, Vector keycolumns, Vector columns1) {
String alterStatement = "DELETE FROM " + tableName + " WHERE ";
boolean and = false;
for (int i = 0; i < columns1.size(); i++) {
final Column column = columns1.get(i);
final String columnName = column.getColumnName();
if (keycolumns.contains(columnName)) {
if (and) {
alterStatement += " AND ";
}
and = true;
if (data1.getValueForColumn(columnName) == null) {
alterStatement += column.getColumnName() + " is null ";
continue;
}
alterStatement += column.getColumnName() + "=";
if (column.isStringType()) {
alterStatement += "'"
+ data1.getValueForColumn(columnName).replaceAll("'", "''") + "'";
} else {
alterStatement += data1.getValueForColumn(columnName);
}
}
}
alterStatement += ";";
m_deleteADEntry.add(alterStatement);
}
/**
* Creates an update statement for the AD_* entry identified by the given
* tableName, ADDataElement and keycolumns. And adds them to the global
* m_alterADEntry Vector.
*
* @param tableName
* @param data2
* @param keycolumns
* @param columns2
*/
private void updateADEntry(String tableName, ADDataElement data2, Vector keycolumns,
Vector columns2) {
String alterStatement = "UPDATE " + tableName + " SET ";
boolean comma = false;
for (int i = 0; i < columns2.size(); i++) {
final Column column = columns2.get(i);
if (!keycolumns.contains(column.getColumnName())
&& !"DATE".equals(column.getDataType())) {
if (comma) {
alterStatement += ",";
}
comma = true;
final String columnName = column.getColumnName();
alterStatement += column.getColumnName() + "=";
if (column.isStringType()) {
if (data2.getValueForColumn(columnName) == null) {
alterStatement += "null";
continue;
}
alterStatement += "'"
+ data2.getValueForColumn(columnName).replaceAll("'", "''") + "'";
} else {
alterStatement += data2.getValueForColumn(columnName);
}
}
}
alterStatement += " WHERE ";
boolean and = false;
for (int i = 0; i < columns2.size(); i++) {
final Column column = columns2.get(i);
final String columnName = column.getColumnName();
if (keycolumns.contains(columnName)) {
if (and) {
alterStatement += " AND ";
}
and = true;
if (data2.getValueForColumn(columnName) == null) {
alterStatement += column.getColumnName() + " is null ";
continue;
}
alterStatement += column.getColumnName() + "=";
if (column.isStringType()) {
alterStatement += "'"
+ data2.getValueForColumn(columnName).replaceAll("'", "''") + "'";
} else {
alterStatement += data2.getValueForColumn(columnName);
}
}
}
alterStatement += ";";
m_alterADEntry.add(alterStatement);
}
/**
* Creates an insert statement for the data identified by the given
* tableName, keyColumnName and keyColumValue and adds them to the global
* m_newTableEntry Vector. It's a row in an AD_% table found in db2 but not
* in db1 or a row of a new table.
*
* @param tableName
* @param data2
* @param keyColumnNames2
* @throws SQLException
*/
private void createNewTableEntry(String tableName, ADDataElement data2,
Vector keyColumnNames2, Vector columns) throws SQLException {
String insertStatement = "INSERT INTO " + tableName + "(";
for (int i = 0; i < columns.size(); i++) {
if (i != 0) {
insertStatement += ",";
}
insertStatement += columns.get(i).getColumnName();
}
insertStatement += ")values(";
for (int i = 0; i < columns.size(); i++) {
if (i != 0) {
insertStatement += ",";
}
// get the column (type/name) for the actual dataelement
String type = columns.get(i).getDataType();
String columnName = columns.get(i).getColumnName();
int precision = columns.get(i).getDataPrecision();
int scale = columns.get(i).getDataScale();
if (data2.getValueForColumn(columnName) == null) {
insertStatement += "null";
} else {
if (type.equals("BLOB")) {
// I'm not shure but I think just do it with ''
insertStatement += "'"
+ data2.getValueForColumn(columnName).replaceAll("'", "''") + "'";
} else if (type.equals("RAW")) {
// I don't know.... //TODO
} else if (type.equals("CLOB")) {
insertStatement += "'"
+ data2.getValueForColumn(columnName).replaceAll("'", "''") + "'";
} else if (type.equals("CHAR") || type.equals("NCHAR") || type.equals("NVARCHAR2")
|| type.equals("VARCHAR2")) {
insertStatement += "'"
+ data2.getValueForColumn(columnName).replaceAll("'", "''") + "'";
} else if (type.equals("DATE")) {
String date = data2.getValueForColumn(columnName);
if (date.indexOf(' ') != -1) {
date = date.substring(0, date.indexOf(' '));
}
insertStatement += "to_date('" + date + "','" + TIME_FORMAT + "')";
} else if (type.equals("NUMBER")) {
if (scale == 0) {
insertStatement += data2.getValueForColumn(columnName);
} else {
insertStatement += data2.getValueForColumn(columnName);
}
}
}
}
insertStatement += ");";
m_newTableEntry.add(insertStatement);
}
/**
* Creates insert statements for every row of the given table and adds them
* to the global m_newTableEntry Vector.
*
* @param tableName
* @throws SQLException
*/
private void createEntriesForTable(String tableName) throws SQLException {
// get all column names
final Vector columns2 = new Vector();
String sql = "select * from user_tab_columns where table_name='" + tableName
+ "' order by column_id";
ResultSet rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
columns2.add(new Column(rs));
}
rs.close();
// get keycolumns for table
sql = "select col.column_name from user_constraints constr "
+ "inner join User_Cons_Columns col ON (col.constraint_name = constr.constraint_name) "
+ "where constr.constraint_type='P' and constr.table_name = '" + tableName + "'";
final Vector keycolumns = new Vector();
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
keycolumns.add(rs.getString("COLUMN_NAME"));
}
rs.close();
// create select statement for table
sql = "select * from " + tableName;
Vector dataElements2 = new Vector();
// get data from db2
rs = stmtdb2.executeQuery(sql);
while (rs.next()) {
final ADDataElement data = new ADDataElement();
for (int i = 0; i < columns2.size(); i++) {
final String colName = columns2.get(i).getColumnName();
data.addColumnAndValue(colName, rs.getString(colName));
}
dataElements2.add(data);
}
rs.close();
for (int i = 0; i < dataElements2.size(); i++) {
try {
createNewTableEntry(tableName, dataElements2.get(i), keycolumns, columns2);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* Some tables cannot be created the normal way because of to many
* constraints. This code is tested for 253b.
*
* @deprecated
* @return
*/
private String getHardcodedStuff() {
StringBuffer buffer = new StringBuffer();
buffer = buffer
.append("-- BEWARE: ALL ENTRIES IN PA_MEASURE AND PA_MEASURECALC ARE DELETED \n")
.append("DELETE FROM PA_MEASURE;\n")
.append("DELETE FROM PA_MEASURECALC;\n")
.append("\n")
.append(" ALTER TABLE PA_MEASURECALC \n")
.append(" ADD ( AD_TABLE_ID NUMBER(10,0) NOT NULL ENABLE, \n")
.append(" KEYCOLUMN NVARCHAR2(60) NOT NULL ENABLE, \n")
.append(" ENTITYTYPE VARCHAR2(4 BYTE) NOT NULL ENABLE\n")
.append(" ) ;\n")
.append("\n")
.append("-- INSERTING into PA_MEASURECALC \n")
.append(
"INSERT INTO PA_MEASURECALC (PA_MEASURECALC_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,SELECTCLAUSE,WHERECLAUSE,DATECOLUMN,ORGCOLUMN,BPARTNERCOLUMN,PRODUCTCOLUMN,AD_TABLE_ID,KEYCOLUMN,ENTITYTYPE) values (100,0,0,'Y',to_date('26.04.01','DD.MM.RR'),0,to_date('01.01.06','DD.MM.RR'),100,'Invoiced Net Revenue','Invoiced net revenue, without tax and charges','SELECT SUM(il.LineNetAmt) \n")
.append("FROM RV_C_Invoice C_Invoice\n")
.append(
" INNER JOIN RV_C_InvoiceLine il ON (C_Invoice.C_Invoice_ID=il.C_Invoice_ID)','WHERE C_Invoice.IsSOTrx=''Y'' AND C_Invoice.Processed=''Y''','C_Invoice.DateInvoiced','C_Invoice.AD_Org_ID','C_Invoice.C_BPartner_ID','il.M_Product_ID',318,'C_Invoice.C_Invoice_ID','D');\n")
.append(
"INSERT INTO PA_MEASURECALC (PA_MEASURECALC_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,SELECTCLAUSE,WHERECLAUSE,DATECOLUMN,ORGCOLUMN,BPARTNERCOLUMN,PRODUCTCOLUMN,AD_TABLE_ID,KEYCOLUMN,ENTITYTYPE) values (101,0,0,'Y',to_date('26.04.01','DD.MM.RR'),0,to_date('01.01.06','DD.MM.RR'),100,'Invoiced Gross Revenue','Invoice gross amount including tax; Does not allow selection by product (Category)','SELECT SUM(GrandTotal) \n")
.append(
"FROM RV_C_Invoice C_Invoice','WHERE IsSOTrx=''Y'' AND Processed=''Y''','DateInvoiced','AD_Org_ID','C_BPartner_ID',null,318,'C_Invoice_ID','D');\n")
.append(
"INSERT INTO PA_MEASURECALC (PA_MEASURECALC_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,SELECTCLAUSE,WHERECLAUSE,DATECOLUMN,ORGCOLUMN,BPARTNERCOLUMN,PRODUCTCOLUMN,AD_TABLE_ID,KEYCOLUMN,ENTITYTYPE) values (102,0,0,'Y',to_date('26.04.01','DD.MM.RR'),0,to_date('01.01.06','DD.MM.RR'),100,'Invoiced Sales Margin','Difference between Limit and Actual price','SELECT SUM((il.PriceActual-il.PriceLimit)*QtyInvoiced) \n")
.append("FROM RV_C_Invoice C_Invoice\n")
.append(
" INNER JOIN RV_C_InvoiceLine il ON (C_Invoice.C_Invoice_ID=il.C_Invoice_ID)','WHERE C_Invoice.IsSOTrx=''Y'' AND C_Invoice.Processed=''Y''','C_Invoice.DateInvoiced','C_Invoice.AD_Org_ID','C_Invoice.C_BPartner_ID','il.M_Product_ID',318,'C_Invoice.C_Invoice_ID','D');\n")
.append(
"INSERT INTO PA_MEASURECALC (PA_MEASURECALC_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,SELECTCLAUSE,WHERECLAUSE,DATECOLUMN,ORGCOLUMN,BPARTNERCOLUMN,PRODUCTCOLUMN,AD_TABLE_ID,KEYCOLUMN,ENTITYTYPE) values (103,0,0,'Y',to_date('26.04.01','DD.MM.RR'),0,to_date('25.12.05','DD.MM.RR'),100,'Number of Customers','Number of (new) customers','SELECT COUNT(*) \n")
.append(
"FROM C_BPartner','WHERE IsCustomer=''Y''','Created','AD_Org_ID','C_BPartner_ID',null,291,'C_BPartner_ID','D');\n")
.append(
"INSERT INTO PA_MEASURECALC (PA_MEASURECALC_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,SELECTCLAUSE,WHERECLAUSE,DATECOLUMN,ORGCOLUMN,BPARTNERCOLUMN,PRODUCTCOLUMN,AD_TABLE_ID,KEYCOLUMN,ENTITYTYPE) values (104,0,0,'Y',to_date('25.12.05','DD.MM.RR'),100,to_date('01.01.06','DD.MM.RR'),100,'Invoiced Paid Quantities','Invoiced paid quantities','SELECT SUM(il.QtyInvoiced) \n")
.append("FROM RV_C_Invoice C_Invoice\n")
.append(
" INNER JOIN RV_C_InvoiceLine il ON (C_Invoice.C_Invoice_ID=il.C_Invoice_ID)','WHERE C_Invoice.IsSOTrx=''Y'' AND C_Invoice.Processed=''Y'' AND C_Invoice.IsPaid=''Y''\n")
.append(
"','C_Invoice.DateInvoiced','C_Invoice.AD_Org_ID','C_Invoice.C_BPartner_ID','il.M_Product_ID',318,'C_Invoice.C_Invoice_ID','D');\n")
.append(
"INSERT INTO PA_MEASURECALC (PA_MEASURECALC_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,SELECTCLAUSE,WHERECLAUSE,DATECOLUMN,ORGCOLUMN,BPARTNERCOLUMN,PRODUCTCOLUMN,AD_TABLE_ID,KEYCOLUMN,ENTITYTYPE) values (105,0,0,'Y',to_date('01.01.06','DD.MM.RR'),100,to_date('01.01.06','DD.MM.RR'),100,'Open Invoice Amount','Open Invoice Amount in Accounting Currency','SELECT COALESCE(SUM(currencyBase(invoiceOpen(C_Invoice_ID, C_InvoicePaySchedule_ID),C_Currency_ID, DateAcct, AD_Client_ID, AD_Org_ID)),0)\n")
.append(
"FROM C_Invoice_v C_Invoice','WHERE IsSOTrx=''Y'' AND Processed=''Y''','DateInvoiced','AD_Org_ID','C_BPartner_ID',null,318,'C_Invoice_ID','D');\n")
.append("\n")
.append("\n")
.append(" ALTER TABLE PA_MEASURE \n")
.append(" ADD ( PA_BENCHMARK_ID NUMBER(10,0), \n")
.append(" PA_RATIO_ID NUMBER(10,0), \n")
.append(" PA_HIERARCHY_ID NUMBER(10,0), \n")
.append(" MEASUREDATATYPE CHAR(1 BYTE) NOT NULL ENABLE, \n")
.append(" R_REQUESTTYPE_ID NUMBER(10,0), \n")
.append(" C_PROJECTTYPE_ID NUMBER(10,0)\n")
.append(" ) ;\n")
.append(" \n")
.append(" ALTER TABLE PA_MEASURE\n")
.append(" ADD CONSTRAINT PABENCHMARK_PAMEASURE FOREIGN KEY (PA_BENCHMARK_ID)\n")
.append(" REFERENCES PA_BENCHMARK (PA_BENCHMARK_ID); \n")
.append(" ALTER TABLE PA_MEASURE\n")
.append(" ADD CONSTRAINT PAHIERARCHY_PAMEASURE FOREIGN KEY (PA_HIERARCHY_ID)\n")
.append(" REFERENCES PA_HIERARCHY (PA_HIERARCHY_ID); \n")
.append(" ALTER TABLE PA_MEASURE\n")
.append(" ADD CONSTRAINT PARATIO_PAMEASURE FOREIGN KEY (PA_RATIO_ID)\n")
.append(" REFERENCES PA_RATIO (PA_RATIO_ID);\n")
.append(" \n")
.append("-- INSERTING into PA_MEASURE \n")
.append(
"INSERT INTO PA_MEASURE (PA_MEASURE_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,MEASURETYPE,MANUALACTUAL,MANUALNOTE,CALCULATIONCLASS,PA_MEASURECALC_ID,PA_BENCHMARK_ID,PA_RATIO_ID,PA_HIERARCHY_ID,MEASUREDATATYPE,R_REQUESTTYPE_ID,C_PROJECTTYPE_ID) values (102,11,0,'Y',to_date('01.01.06','DD.MM.RR'),100,to_date('01.01.06','DD.MM.RR'),100,'Open Invoice Amount',null,'C',0,null,null,105,null,null,null,'S',null,null);\n")
.append(
"INSERT INTO PA_MEASURE (PA_MEASURE_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,MEASURETYPE,MANUALACTUAL,MANUALNOTE,CALCULATIONCLASS,PA_MEASURECALC_ID,PA_BENCHMARK_ID,PA_RATIO_ID,PA_HIERARCHY_ID,MEASUREDATATYPE,R_REQUESTTYPE_ID,C_PROJECTTYPE_ID) values (103,11,0,'Y',to_date('20.01.06','DD.MM.RR'),100,to_date('20.01.06','DD.MM.RR'),100,'Service Requests (Time)',null,'Q',0,null,null,null,null,null,null,'T',101,null);\n")
.append(
"INSERT INTO PA_MEASURE (PA_MEASURE_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,MEASURETYPE,MANUALACTUAL,MANUALNOTE,CALCULATIONCLASS,PA_MEASURECALC_ID,PA_BENCHMARK_ID,PA_RATIO_ID,PA_HIERARCHY_ID,MEASUREDATATYPE,R_REQUESTTYPE_ID,C_PROJECTTYPE_ID) values (104,11,0,'Y',to_date('20.01.06','DD.MM.RR'),100,to_date('20.01.06','DD.MM.RR'),100,'Service Requests (Status)',null,'Q',0,null,null,null,null,null,null,'S',101,null);\n")
.append(
"INSERT INTO PA_MEASURE (PA_MEASURE_ID,AD_CLIENT_ID,AD_ORG_ID,ISACTIVE,CREATED,CREATEDBY,UPDATED,UPDATEDBY,NAME,DESCRIPTION,MEASURETYPE,MANUALACTUAL,MANUALNOTE,CALCULATIONCLASS,PA_MEASURECALC_ID,PA_BENCHMARK_ID,PA_RATIO_ID,PA_HIERARCHY_ID,MEASUREDATATYPE,R_REQUESTTYPE_ID,C_PROJECTTYPE_ID) values (101,11,0,'Y',to_date('25.12.05','DD.MM.RR'),100,to_date('26.12.05','DD.MM.RR'),101,'Invoices Gross Revenue',null,'C',0,null,null,101,null,null,null,'T',null,null);\n")
.append("\n");
return buffer.toString();
}
/**
* Returns the update statement to set the db version to the one needed for
* 253b. You need to change this if the target db is not 253b.
*
* @return
*/
private String getUpdateVersionStatement() {
return "UPDATE AD_SYSTEM SET VERSION='2006-01-20';";
}
/**
* Erzeugt eine Connection zur Auftrags-Datenbank.
*
* @return Connection
* @throws ClassNotFoundException
* @throws SQLException
*/
private Connection getConnection(String dbName, String username, String password, String url)
throws ClassNotFoundException, SQLException {
Connection connection;
// Load the JDBC driver
String driverName = "oracle.jdbc.OracleDriver";
Class.forName(driverName);
url = url + dbName;
connection = DriverManager.getConnection(url, username, password);
return connection;
}
/**
* Comparator for insert statements. Sorts AD_* entries.
*
* @author Karsten Thiemann, [email protected]
* @deprecated
*/
private class AD_Comparator implements Comparator {
String[] reihenfolge = new String[] { "AD_ELEMENT(", "AD_WINDOW(", "AD_WINDOW_ACCESS(",
"AD_TABLE(", "AD_REFERENCE(", "AD_VAL_RULE(", "AD_REPORTVIEW(", "AD_PROCESS(",
"AD_PROCESS_ACCESS(", "AD_PROCESS_PARA(", "AD_PINSTANCE(", "AD_PINSTANCE_PARA(",
"AD_COLUMN(", "AD_TAB(", "AD_FIELD(", "AD_FORM(", "AD_FORM_ACCESS(", "AD_MENU(",
"AD_PRINTFORMAT(", "AD_PRINTFORMATITEM(", "AD_MESSAGE(", "AD_REF_LIST(",
"AD_TREE(", "AD_TREENODE(", "AD_TREENODEMM(", };
public int compare(Object arg1, Object arg2) {
if (!(arg1 instanceof String && arg2 instanceof String)) {
return 0;
}
final String str1 = (String) arg1;
final String str2 = (String) arg2;
int prio1 = 100;
int prio2 = 100;
for (int i = 0; i < reihenfolge.length; i++) {
if (str1.startsWith("INSERT INTO " + reihenfolge[i])) {
prio1 = i;
break;
}
}
for (int i = 0; i < reihenfolge.length; i++) {
if (str2.startsWith("INSERT INTO " + reihenfolge[i])) {
prio2 = i;
break;
}
}
if (prio1 != prio2) {
if (prio1 < prio2) {
return -1;
} else {
return 1;
}
} else
return str1.compareTo(str2);
}
}
}