Package net.sourceforge.squirrel_sql.plugins.dbcopy

Source Code of net.sourceforge.squirrel_sql.plugins.dbcopy.CopyExecutor

/*
* Copyright (C) 2005 Rob Manning
* manningr@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package net.sourceforge.squirrel_sql.plugins.dbcopy;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.sourceforge.squirrel_sql.client.session.ISession;
import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory;
import net.sourceforge.squirrel_sql.fw.dialects.DialectUtils;
import net.sourceforge.squirrel_sql.fw.dialects.UserCancelledOperationException;
import net.sourceforge.squirrel_sql.fw.dialects.CreateScriptPreferences;
import net.sourceforge.squirrel_sql.fw.sql.IDatabaseObjectInfo;
import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData;
import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
import net.sourceforge.squirrel_sql.fw.sql.PrimaryKeyInfo;
import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
import net.sourceforge.squirrel_sql.fw.sql.SQLUtilities;
import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo;
import net.sourceforge.squirrel_sql.fw.util.StringManager;
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.AnalysisEvent;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.CopyEvent;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.CopyTableListener;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.ErrorEvent;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.RecordEvent;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.StatementEvent;
import net.sourceforge.squirrel_sql.plugins.dbcopy.event.TableEvent;
import net.sourceforge.squirrel_sql.plugins.dbcopy.prefs.DBCopyPreferenceBean;
import net.sourceforge.squirrel_sql.plugins.dbcopy.prefs.PreferencesManager;
import net.sourceforge.squirrel_sql.plugins.dbcopy.util.DBUtil;

import org.hibernate.MappingException;

/**
* This is the class that performs the table copy using database connections
* to two different database schemas. 
*/
public class CopyExecutor extends I18NBaseObject {

    /** the class that provides out session information */
    SessionInfoProvider prov = null;
   
    /** the source session.  This comes from prov */
    ISession sourceSession = null;
   
    /** the destination session.  This comes from prov */
    ISession destSession = null;
   
    /** the thread we do the work in */
    private Thread execThread = null;
   
    /** what value did autocommit have in dest connection when we received it */
    private boolean originalAutoCommitValue = true;
   
    /** what value does autocommit have in dest connection now */
    private boolean currentAutoCommitValue = true;   
   
    /** the user's preferences */
    private static DBCopyPreferenceBean prefs =
                                            PreferencesManager.getPreferences();   
   
    /** Logger for this class. */
    private final static ILogger log =
                         LoggerController.createLogger(CopyExecutor.class);
   
    /** Internationalized strings for this class. */
    private static final StringManager s_stringMgr =
        StringManagerFactory.getStringManager(CopyExecutor.class);
   
    /** the list of ITableInfos that represent the user's last selection. */
    private ArrayList<ITableInfo> selectedTableInfos = null;   
   
    /** the CopyTableListeners that have registered with this class */
    private ArrayList<CopyTableListener> listeners =
        new ArrayList<CopyTableListener>();
   
    /** whether or not the user cancelled the copy operation */
    private volatile boolean cancelled = false;   
   
    /** impl that gives us feedback from the user */
    private UICallbacks pref = null;
   
    /** the start time in millis that the copy operation began */
    private long start = 0;
   
    /** the finish time in millis that the copy operation began */
    private long end = 0;
   
    /**
     * Constructor.
     *
     * @param p the provider of information regarding what to copy where.
     */
    public CopyExecutor(SessionInfoProvider p) {
        prov = p;
        sourceSession = prov.getCopySourceSession();
        destSession = prov.getCopyDestSession();
    }
   
    /**
     * Starts the thread that executes the copy operation.
     */
    public void execute() {
        Runnable runnable = new Runnable() {
            public void run() {
                _execute();
            }
        };
        execThread = new Thread(runnable);
        execThread.setName("DBCopy Executor Thread");
        execThread.start();
    }

    /**
     * Cancels the copy operation.
     */
    public void cancel() {
        cancelled = true;
        execThread.interrupt();       
    }
   
    /**
     * Performs the table copy operation.
     */
    private void _execute() {
        start = System.currentTimeMillis();
        boolean encounteredException = false;
        ISQLConnection destConn = destSession.getSQLConnection();
        if (!analyzeTables()) {
            return;
        }
        setupAutoCommit(destConn);
        IDatabaseObjectInfo[] sourceObjs = prov.getSourceSelectedDatabaseObjects();
        int[] counts = getTableCounts();
        sendCopyStarted(counts);
        String destSchema = prov.getDestSelectedDatabaseObject().getSimpleName();
        String destCatalog = prov.getDestSelectedDatabaseObject().getCatalogName();
        for (int i = 0; i < sourceObjs.length; i++) {
            if (false == sourceObjs[i] instanceof ITableInfo) {
                continue;
            }
            ITableInfo sourceTI = (ITableInfo)sourceObjs[i];
            sendTableCopyStarted(sourceTI, i+1);
            try {
                int destTableCount = DBUtil.getTableCount(destSession,
                                                          destCatalog,
                                                          destSchema,
                                                          sourceTI.getSimpleName(),
                                                          DialectFactory.DEST_TYPE);
                if (destTableCount == -1) {
                    createTable(sourceTI);
                }
                if (destTableCount > 0) {
                    try {
                        String t = sourceTI.getSimpleName();
                        if (pref.appendRecordsToExisting(t)) {
                            /* Do nothing */
                        } else if (pref.deleteTableData(sourceTI.getSimpleName())) {
                            // Yes || Yes to all
                            DBUtil.deleteDataInExistingTable(destSession,
                                                             destCatalog,
                                                             destSchema,
                                                             sourceTI.getSimpleName());
                        } else {
                            continue; // skip this table, try the next.
                        }
                       
                    } catch (UserCancelledOperationException e) {
                        cancelled = true;
                        break;
                    }
                }
               
                copyTable(sourceTI, counts[i]);
               
                if (i == sourceObjs.length - 1 && !cancelled) {
                    // We just copied the last table.  Now it is safe to copy the
                    // constraints.(Well, that is, if all FK dependencies are met
                    // in the group of tables being copied.
                    // TODO: new feature could be to examine table list for FK's
                    // in tables not in the list then prompt the user to add
                    // those missing tables to the list.
                    copyConstraints(sourceObjs);
                }
                if (!cancelled) {
                    sendTableCopyFinished(sourceTI, i+1);
                    sleep(prefs.getTableDelayMillis());
                }
            } catch (SQLException e) {
                encounteredException = true;
                sendErrorEvent(ErrorEvent.SQL_EXCEPTION_TYPE, e);
                break;
            } catch (MappingException e) {
                encounteredException = true;
                sendErrorEvent(ErrorEvent.MAPPING_EXCEPTION_TYPE, e);
                break;
            } catch (UserCancelledOperationException e) {
                cancelled = true;
                break;
            } catch (Exception e) {
                encounteredException = true;
                sendErrorEvent(ErrorEvent.GENERIC_EXCEPTION, e);
                break;
            }
        }       
        restoreAutoCommit(destConn);
        if (cancelled) {
            sendErrorEvent(ErrorEvent.USER_CANCELLED_EXCEPTION_TYPE);
            return;
        }
        if (encounteredException) {
            return;
        }        
        end = System.currentTimeMillis();
       
        ISession session = prov.getCopyDestSession();
        session.getSchemaInfo().reload(prov.getDestSelectedDatabaseObject());
        session.getSchemaInfo().fireSchemaInfoUpdate();

        notifyCopyFinished();
    }
   
    /**
     * Registers the specified listener to receive copy events from this class.
     *
     * @param listener
     */
    public void addListener(CopyTableListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener cannot be null");
        }
        listeners.add(listener);
    }
   
    /**
     * Causes the current thread to sleep for the amount of time specified if
     * sleepTime > 0.  No effect for sleepTime <= 0.
     *
     * @param sleepTime time in milliseconds to make the current thread sleep.
     */
    private void sleep(long sleepTime) {
        boolean shouldSleep = prefs.isDelayBetweenObjects();
        if (!shouldSleep || sleepTime <= 0) {
            return;
        }
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            // Do Nothing
        }
    }
   
    /**
     * For all selected tables, loop through their columns and see if the column
     * name can be used as a column name in the destination database.  This
     * method will send an error event if a table has any column names that
     * cannot be used in the destination database.  This method just returns
     * true if the user preference is not to test column names. 
     *
     * @return true if the tables can be created in the destination database;
     *         false is returned otherwise.
     */
    private boolean analyzeTables() {       
        boolean result = true;
        if (!prefs.isTestColumnNames()) {
            return true;
        }
        if (DBUtil.sameDatabaseType(prov.getCopySourceSession(),
                                    prov.getCopyDestSession()))
        {
            // No need to check column name validity when source and dest are
            // of the same type of database.
            return true;
        }
        sendAnalysisStarted();
        try {
            IDatabaseObjectInfo[] dbObjs = prov.getSourceSelectedDatabaseObjects();       
            for (int tableIdx = 0; tableIdx < dbObjs.length; tableIdx++) {
                ITableInfo ti = (ITableInfo)dbObjs[tableIdx];
                sendAnalyzingTable(ti, tableIdx);
                DBUtil.validateColumnNames(ti, prov);
            }
        } catch (MappingException e) {
            sendErrorEvent(ErrorEvent.MAPPING_EXCEPTION_TYPE, e);
            result = false;
        } catch (UserCancelledOperationException e) {
            sendErrorEvent(ErrorEvent.USER_CANCELLED_EXCEPTION_TYPE, e);
            result = false;
        }
        return result;
    }       

   
    /**
     * Setup the auto-commit setting on the specified connection to
     * the user's preference.
     *
     * @param con
     */
    private void setupAutoCommit(ISQLConnection con) {
        boolean autoCommitPref = prefs.isAutoCommitEnabled();
        try {
            originalAutoCommitValue = con.getAutoCommit();
            currentAutoCommitValue = originalAutoCommitValue;
            if (autoCommitPref != originalAutoCommitValue) {
                con.setAutoCommit(autoCommitPref);
                currentAutoCommitValue = autoCommitPref;
            }
        } catch (SQLException e) {
            // Don't fool around with manual commit later.
            currentAutoCommitValue = true;
            sendErrorEvent(ErrorEvent.SETUP_AUTO_COMMIT_TYPE, e);
        }
   
    }
   
    /**
     * Restore the auto-commit setting on the specified connection to the
     * whatever it was previous to our manipulation
     *
     * @param con
     */
    private void restoreAutoCommit(ISQLConnection con) {
        if (originalAutoCommitValue == currentAutoCommitValue) {
            return;
        }
        try {
            con.setAutoCommit(originalAutoCommitValue);
        } catch (SQLException e) {
            sendErrorEvent(ErrorEvent.RESTORE_AUTO_COMMIT_TYPE, e);                     
        }
    }   
   
    private int[] getTableCounts() {
        int[] result = null;
       
        ISession sourceSession = prov.getCopySourceSession();
        IDatabaseObjectInfo[] dbObjs = prov.getSourceSelectedDatabaseObjects();
        if (dbObjs != null) {
            result = new int[dbObjs.length];
            selectedTableInfos = new ArrayList<ITableInfo>();
            for (int i = 0; i < dbObjs.length; i++) {
                if (false == dbObjs[i] instanceof ITableInfo) {
                    continue;
                }         
                try {
                    ITableInfo ti = (ITableInfo) dbObjs[i];
                    selectedTableInfos.add(ti);
                    // This doesn't appear to work for PROGRESS RDBMS
                    //result[i] = DBUtil.getTableCount(con, ti.getSimpleName());
                    result[i] =
                        DBUtil.getTableCount(sourceSession,
                                             ti.getCatalogName(),
                                             ti.getSchemaName(),
                                             ti.getSimpleName(),
                                             DialectFactory.SOURCE_TYPE);
                } catch (Exception e) {
                    log.error("",e);
                    result[i] = 0;
                }
            }          
        }
        return result;
    }
   
    private void sendAnalysisStarted() {
        AnalysisEvent event = new AnalysisEvent(prov);
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.tableAnalysisStarted(event);
        }
    }
   
    private void sendAnalyzingTable(ITableInfo ti, int number) {
        TableEvent event = new TableEvent(prov);
        event.setTableCount(prov.getSourceSelectedDatabaseObjects().length);
        event.setTableNumber(number);
        Iterator<CopyTableListener> i = listeners.iterator();
        event.setTableName(ti.getSimpleName());
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.analyzingTable(event);
        }               
    }
   
    private void sendCopyStarted(int[] tableCounts) {
        CopyEvent event = new CopyEvent(prov);
        event.setTableCounts(tableCounts);
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.copyStarted(event);
        }       
    }
   
    private void sendTableCopyStarted(ITableInfo ti, int number) {
        TableEvent event = new TableEvent(prov);
        event.setTableNumber(number);
        event.setTableCount(prov.getSourceSelectedDatabaseObjects().length);
        event.setTableName(ti.getSimpleName());
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.tableCopyStarted(event);
        }
    }

    private void sendTableCopyFinished(ITableInfo ti, int number) {
        TableEvent event = new TableEvent(prov);
        event.setTableNumber(number);
        event.setTableCount(prov.getSourceSelectedDatabaseObjects().length);
        event.setTableName(ti.getSimpleName());
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.tableCopyFinished(event);
        }
    }   
   
    /**
     * Send an error event message to all CopyTableListeners
     * @param type the type of the ErrorEvent.
     */
    private void sendErrorEvent(int type) {
        sendErrorEvent(type, null);
    }

    /**
     * Send an error event message to all CopyTableListeners
     * @param type the type of the ErrorEvent.
     * @param e the exception that was encountered.
     */   
    private void sendErrorEvent(int type, Exception e) {
        ErrorEvent event = new ErrorEvent(prov, type);
        event.setException(e);
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.handleError(event);
        }       
    }
   
    private void sendRecordEvent(int number, int count) {
        RecordEvent event = new RecordEvent(prov, number, count);
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.recordCopied(event);
        }
    }
   
    private void sendStatementEvent(String sql, String[] vals) {
        StatementEvent event =
            new StatementEvent(sql, StatementEvent.INSERT_RECORD_TYPE);
        event.setBindValues(vals);
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.statementExecuted(event);
        }       
    }
   
    private void notifyCopyFinished() {
        int seconds = (int)getElapsedSeconds();
        Iterator<CopyTableListener> i = listeners.iterator();
        while (i.hasNext()) {
            CopyTableListener listener = i.next();
            listener.copyFinished(seconds);
        }
    }
   
    /**
     *
     * @return
     */
    private long getElapsedSeconds() {
        long result = 1;
        double elapsed = end - start;
        if (elapsed > 1000) {
            result = Math.round(elapsed / 1000);
        }
        return result;
    }
   
    /**
     *
     * @param sourceTableInfo
     * @param sourceTableCount
     * @throws MappingException
     * @throws SQLException
     */
    private void copyTable(ITableInfo sourceTableInfo, int sourceTableCount)
        throws MappingException, SQLException, UserCancelledOperationException
    {
        PreparedStatement insertStmt = null;
        ResultSet rs = null;
        if (cancelled) {
            return;
        }
        if (!PreferencesManager.getPreferences().isCopyData()) {
            return;
        }
        ISQLConnection sourceConn = prov.getCopySourceSession().getSQLConnection();
        ISQLConnection destConn = prov.getCopyDestSession().getSQLConnection();
        SQLDatabaseMetaData sourceMetaData = sourceConn.getSQLMetaData();
        SQLDatabaseMetaData destMetaData = destConn.getSQLMetaData();
        try {
            String destSchema =
                prov.getDestSelectedDatabaseObject().getSimpleName();           
            ITableInfo destTableInfo =
                DBUtil.getTableInfo(prov.getCopyDestSession(),
                                    destSchema,
                                    sourceTableInfo.getSimpleName());
           
            TableColumnInfo[] sourceInfos = sourceMetaData.getColumnInfo(sourceTableInfo);
            TableColumnInfo[] destInfos = destMetaData.getColumnInfo(destTableInfo);
           
            destInfos = sort(sourceInfos,
                             destInfos,
                             sourceTableInfo.getQualifiedName(),
                             destTableInfo.getQualifiedName());
           
            String sourceColList = DBUtil.getColumnList(sourceInfos);
            String destColList = DBUtil.getColumnList(destInfos);
           
            String selectSQL = DBUtil.getSelectQuery(prov,
                                                     sourceColList,
                                                     sourceTableInfo);
            String insertSQL = DBUtil.getInsertSQL(prov, destColList,
                                                   sourceTableInfo,
                                                   destInfos.length);
            insertStmt = destConn.prepareStatement(insertSQL);
           
            int count = 1;
            int commitCount = prefs.getCommitCount();
            int columnCount = destInfos.length;
            String[] bindVarVals = new String[columnCount];
                       
            boolean foundLOBType = false;
            // Loop through source records...
            DBUtil.setLastStatement(selectSQL);
            rs = DBUtil.executeQuery(prov.getCopySourceSession(), selectSQL);
            DBUtil.setLastStatement(insertSQL);
            boolean isMysql = DialectFactory.isMySQL(destSession.getMetaData());
            boolean isSourceOracle =
                DialectFactory.isOracle(sourceSession.getMetaData());
            boolean isDestOracle = DialectFactory.isOracle(destSession.getMetaData());
            while (rs.next() && !cancelled) {
                // MySQL driver gets unhappy when we use the same
                // PreparedStatement to bind null and non-null LOB variables
                // without clearing the parameters first.
                if (isMysql && foundLOBType)
                {
                    insertStmt.clearParameters();
                }
                StringBuilder lastStmtValuesBuffer = new StringBuilder();
                lastStmtValuesBuffer.append("\n(Bind variable values: ");
                for (int i = 0; i < columnCount; i++) {

                    int sourceColType = sourceInfos[i].getDataType();
                    // If source column is type 1111 (OTHER), try to use the
                    // column type name to find a type that isn't 1111.
                    sourceColType = DBUtil.replaceOtherDataType(sourceInfos[i], prov.getCopySourceSession());
                    sourceColType = getDateReplacement(sourceColType,
                                                       isSourceOracle);
                   
                    int destColType   = destInfos[i].getDataType();
                    // If source column is type 1111 (OTHER), try to use the
                    // column type name to find a type that isn't 1111.
                    destColType = DBUtil.replaceOtherDataType(destInfos[i], prov.getCopyDestSession());
                    destColType = getDateReplacement(destColType, isDestOracle);
                   
                   
                    String bindVal = DBUtil.bindVariable(insertStmt,
                                                         sourceColType,
                                                         destColType,
                                                         i+1,
                                                         rs);
                    bindVarVals[i] = bindVal;
                    lastStmtValuesBuffer.append(bindVal);
                    if (i + 1 < columnCount) {
                        lastStmtValuesBuffer.append(", ");
                    }
                    if (isLOBType(destColType)) {
                      foundLOBType = true;
                    }
                }               
                lastStmtValuesBuffer.append(")");
                DBUtil.setLastStatementValues(lastStmtValuesBuffer.toString());
                sendStatementEvent(insertSQL, bindVarVals);
                insertStmt.executeUpdate();
                sendRecordEvent(count, sourceTableCount);
                count++;
                if (!currentAutoCommitValue) {
                    if ((count % commitCount) == 0) {
                        commitConnection(destConn);
                    }
                }
                sleep(prefs.getRecordDelayMillis());
            }
        } finally {
            SQLUtilities.closeResultSet(rs);
            SQLUtilities.closeStatement(insertStmt);
            if (!currentAutoCommitValue) {
                commitConnection(destConn);
            }
        }
    }
   
    /**
     * This will return a TIMESTAMP type when the specified type is a DATE and
     * isOracle is true.  This is done so that Oracle dates that have a time
     * component, will have the time component copied correctly.
     * 
     * @param session
     * @param type
     * @param isOracle
     * @return
     */
    private int getDateReplacement(int type, boolean isOracle)
    {
        int result = type;
        if (isOracle && type == java.sql.Types.DATE) {
            result = java.sql.Types.TIMESTAMP;
        }
        return result;
    }
   
    /**
     * Returns a boolean value indicating whether or not the specific column
     * type is a binary or LOB column.
     * @param columnType the JDBC type.
     *
     * @return true if the specified type is LOB; false otherwise.
     */
    private boolean isLOBType(int columnType) {
        if (columnType == Types.BLOB
            || columnType == Types.CLOB
                || columnType == Types.LONGVARBINARY
                || columnType == Types.BINARY)
        {
            return true;
        }
        return false;
    }
   
    /**
     * Sorts the specified destInfos array based on the order of the sourceInfos
     * array.  Not a very efficient algorthim, but it gets the job done.
     * TODO: rewrite this using Collections sorting capability.
     *
     * @param sourceInfos
     * @param destInfos
     * @param sourceTableName
     * @param destTableName
     * @return a re-ordered version of the specified destInfos array
     * @throws MappingException if the arrays differ in length or column names.
     */
    private TableColumnInfo[] sort(TableColumnInfo[] sourceInfos,
                                   TableColumnInfo[] destInfos,
                                   String sourceTableName,
                                   String destTableName)
        throws MappingException
    {
        if (sourceInfos.length != destInfos.length) {
            //i18n[CopyExecutor.tablecolmismatch=Column count for table {0} in
            //source database is {1}, but column count for table {2} in
            //destination database is {3}
            String msg =
                s_stringMgr.getString("CopyExecutor.tablecolmismatch",
                                      new Object[] {
                                              sourceTableName,
                                              Integer.valueOf(sourceInfos.length),
                                              destTableName,
                                              Integer.valueOf(destInfos.length)});
            throw new MappingException(msg);
        }
        ArrayList<TableColumnInfo> result = new ArrayList<TableColumnInfo>();
       
        for (int sourceIdx = 0; sourceIdx < sourceInfos.length; sourceIdx++) {
            TableColumnInfo sourceInfo = sourceInfos[sourceIdx];
            // trim the column name in case of HADB
            String sourceColumnName = sourceInfo.getColumnName().trim();
            boolean found = false;
            int destIdx = 0;
            while (!found && destIdx < destInfos.length) {
                TableColumnInfo destInfo = destInfos[destIdx];
                // trim the column name in case of HADB
                String destColumnName = destInfo.getColumnName().trim();
                if (destColumnName.equalsIgnoreCase(sourceColumnName)) {
                    result.add(destInfo);
                    found = true;
                }
                destIdx++;
            }
            if (!found) {
                throw new MappingException("Destination table "+destTableName+
                                    " doesn't appear to have a column named "+
                                    sourceInfo.getColumnName());
            }
        }
        return result.toArray(new TableColumnInfo[destInfos.length]);
    }
   
    /**
     * Commit the specified Connection and log any SQLExceptions that might
     * occur.
     *
     * @param connection
     */
    private void commitConnection(ISQLConnection connection) {
        try {
            connection.commit();
        } catch (SQLException e) {
            log.error("Failed to commit connection - "+connection, e);
        }
    }
   
    /**
     * Copies the foreign key constraints.  Primary keys are created in the table
     * create statement, since some databases don't support adding primary keys
     * after table creation. This will have no effect when using Axion as the
     * source database.
     * 
     * @param sourceConn
     * @param destConn
     * @param ti
     * @throws SQLException
     */
    private void copyConstraints(IDatabaseObjectInfo[] dbObjs)
        throws SQLException, UserCancelledOperationException
    {
        if (!prefs.isCopyForeignKeys()
            || DialectFactory.isAxion(prov.getCopySourceSession().getMetaData())) {
            return;
        }
        ISQLConnection destConn = prov.getCopyDestSession().getSQLConnection();
        for (int i = 0; i < dbObjs.length; i++) {
            ITableInfo ti = (ITableInfo) dbObjs[i];
            Set<String> fkStmts =
                DBUtil.getForeignKeySQL(prov, ti, selectedTableInfos);
            Iterator<String> it = fkStmts.iterator();
            while (it.hasNext()) {
                String fkSQL = it.next();
                DBUtil.setLastStatementValues("");
                try {
                    DBUtil.executeUpdate(destConn, fkSQL, true);
                } catch (SQLException e) {
                    log.error("Unexpected exception while attempting to " +
                              "create FK constraint using sql = "+fkSQL, e);
                }
            }          
        }
    }   
   
    private void createTable(ITableInfo ti)
        throws SQLException, UserCancelledOperationException, MappingException
    {
        if (cancelled) {
            return;
        }
        ISQLConnection destCon = prov.getCopyDestSession().getSQLConnection();
        String createTableSql = DBUtil.getCreateTableSql(prov, ti);
        DBUtil.executeUpdate(destCon, createTableSql, true);
       
        if (prefs.isCommitAfterTableDefs() && !currentAutoCommitValue) {
            commitConnection(destCon);
        }
       
        if (prefs.isCopyIndexDefs()) {
            Collection<String> indices = null;
            ISQLDatabaseMetaData sqlmd = sourceSession.getMetaData();
            if (prefs.isCopyPrimaryKeys()) {
                PrimaryKeyInfo[] pkList = sqlmd.getPrimaryKey(ti);
                List<PrimaryKeyInfo> pkList2 = Arrays.asList(pkList);
                indices = DialectUtils.createIndexes(ti, sqlmd, pkList2, new CreateScriptPreferences());
            } else {
                indices = DialectUtils.createIndexes(ti, sqlmd, null, new CreateScriptPreferences());
            }
            Iterator<String> i = indices.iterator();
            while (i.hasNext()) {
                String createIndicesSql = i.next();
                DBUtil.executeUpdate(destCon, createIndicesSql, true);
            }
        }
    }

    /**
     * @param pref The pref to set.
     */
    public void setPref(UICallbacks pref) {
        this.pref = pref;
    }

    /**
     * @return Returns the pref.
     */
    public UICallbacks getPref() {
        return pref;
    }   
   
}
TOP

Related Classes of net.sourceforge.squirrel_sql.plugins.dbcopy.CopyExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.