All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.DBDifference Maven / Gradle / Ivy

There is a newer version: shw-air-terminal-vertical-1.0.57
Show newest version
/**
 * 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); } } }