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

net.sourceforge.squirrel_sql.client.session.action.DeleteTablesCommand Maven / Gradle / Ivy

package net.sourceforge.squirrel_sql.client.session.action;

/*
 * Copyright (C) 2006 Rob Manning
 * [email protected]
 *
 * 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
 */
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;

import net.sourceforge.squirrel_sql.client.gui.IProgressCallBackFactory;
import net.sourceforge.squirrel_sql.client.gui.ProgressCallBackFactory;
import net.sourceforge.squirrel_sql.client.session.IObjectTreeAPI;
import net.sourceforge.squirrel_sql.client.session.ISession;
import net.sourceforge.squirrel_sql.client.session.SQLExecuterTask;
import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory;
import net.sourceforge.squirrel_sql.fw.gui.GUIUtils;
import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
import net.sourceforge.squirrel_sql.fw.sql.ProgressCallBack;
import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
import net.sourceforge.squirrel_sql.fw.sql.SQLUtilities;
import net.sourceforge.squirrel_sql.fw.util.ICommand;
import net.sourceforge.squirrel_sql.fw.util.StringManager;
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
import net.sourceforge.squirrel_sql.fw.util.Utilities;
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;

/**
 * @version $Id: DeleteTablesCommand.java,v 1.9 2008-10-11 22:55:54 manningr Exp $
 * @author Rob Manning
 */
public class DeleteTablesCommand implements ICommand
{
	/** Logger for this class. */
	private final ILogger s_log = LoggerController.createLogger(DeleteTablesCommand.class);

	/** Internationalized strings for this class */
	private static final StringManager s_stringMgr =
		StringManagerFactory.getStringManager(DeleteTablesCommand.class);

	static interface i18n
	{

		// i18n[DeleteTablesCommand.progressDialogTitle=Analyzing tables to delete]
		String PROGRESS_DIALOG_TITLE = s_stringMgr.getString("DeleteTablesCommand.progressDialogTitle");

		// i18n[DeleteTablesCommand.loadingPrefix=Analyzing table:]
		String LOADING_PREFIX = s_stringMgr.getString("DeleteTablesCommand.loadingPrefix");

	}

	/** Current session. */
	private final ISession _session;

	/** Tables that have records to be deleted. */
	private final List _tables;

	/**
	 * A set of materialized view names in the same schema as the table(s) being deleted
	 */
	private HashSet matViewLookup = null;

	/** API for the current tree. */
	private IObjectTreeAPI _tree;

	private IProgressCallBackFactory progressCallBackFactory = new ProgressCallBackFactory();
	
	/**
	 * Ctor.
	 * 
	 * @param session
	 *           Current session..
	 * @param tables
	 *           Array of IDatabaseObjectInfo objects representing the tables to be deleted.
	 * @throws IllegalArgumentException
	 *            Thrown if a null ISession passed.
	 */
	public DeleteTablesCommand(IObjectTreeAPI tree, List tables)
	{
		super();
		if (tree == null) { throw new IllegalArgumentException("ISession == null"); }
		if (tables == null) { throw new IllegalArgumentException("IDatabaseObjectInfo[] == null"); }

		_session = tree.getSession();
		_tree = tree;
		_tables = tables;
	}

	/**
	 * Delete records from the selected tables in the object tree.
	 */
	public void execute()
	{		
		ProgressCallBack cb =
			progressCallBackFactory.create(_session.getApplication().getMainFrame(), 
				i18n.PROGRESS_DIALOG_TITLE, _tables.size());
			
		cb.setLoadingPrefix(i18n.LOADING_PREFIX);
		DeleteExecuter executer = new DeleteExecuter(cb);
		_session.getApplication().getThreadPool().addTask(executer);
	}

	private class DeleteExecuter implements Runnable
	{

		ProgressCallBack _cb = null;

		public DeleteExecuter(ProgressCallBack cb)
		{
			Utilities.checkNull("DeleteExecuter.init", "cb", cb);
			_cb = cb;
		}

		public void run()
		{
			final SQLDatabaseMetaData md = _session.getSQLConnection().getSQLMetaData();
			List orderedTables = _tables;
			try
			{
				orderedTables = SQLUtilities.getDeletionOrder(_tables, md, _cb);
			}
			catch (Exception e)
			{
				s_log.error("Unexpected exception while attempting to order tables", e);
			} finally {
				GUIUtils.processOnSwingEventThread(new Runnable()
				{
					public void run()				
					{
						_cb.setVisible(false);
					}
				});
			}
			final String sqlSep = _session.getQueryTokenizer().getSQLStatementSeparator();
			String cascadeClause = null;
			try
			{
				cascadeClause = md.getCascadeClause();
			}
			catch (SQLException e)
			{
				s_log.error("Unexpected exception while attempting to get cascade clause", e);
			}
			final StringBuilder buf = new StringBuilder();
			for (ITableInfo ti : orderedTables)
			{
				// Can't delete records in snapshots (Oracle materialized views)
				if (isMaterializedView(ti, _session))
				{
					continue;
				}
				buf.append("DELETE FROM ").append(ti.getQualifiedName());
				if (cascadeClause != null && !cascadeClause.equals(""))
				{
					buf.append(" ").append(cascadeClause);
				}
				buf.append(" ").append(sqlSep).append(" ").append('\n');
			}
			if (buf.length() == 0) { return; }
			SQLExecuterTask executer = new SQLExecuterTask(_session, buf.toString(), null);

			// Execute the sql synchronously
			executer.run();			

			GUIUtils.processOnSwingEventThread(new Runnable()
			{
				public void run()				
				{
					_tree.refreshSelectedNodes();
				}
			});
		}
	}

	/**
	 * Returns a boolean value indicating whether or not the specified table info is not only a table, but also
	 * a materialized view.
	 * 
	 * @param ti
	 * @param session
	 * @return
	 */
	private boolean isMaterializedView(ITableInfo ti, ISession session)
	{
		if (!DialectFactory.isOracle(session.getMetaData()))
		{
			// Only Oracle supports materialized views directly.
			return false;
		}
		if (matViewLookup == null)
		{
			initMatViewLookup(session, ti.getSchemaName());
		}
		return matViewLookup.contains(ti.getSimpleName());
	}

	private void initMatViewLookup(ISession session, String schema)
	{
		matViewLookup = new HashSet();
		// There is no good way using JDBC metadata to tell if the table is a
		// materialized view. So, we need to query the data dictionary to find
		// that out. Get all table names whose comment indicates that they are
		// a materialized view.
		String sql =
			"SELECT TABLE_NAME FROM ALL_TAB_COMMENTS " + "where COMMENTS like 'snapshot%' " + "and OWNER = ? ";

		PreparedStatement stmt = null;
		ResultSet rs = null;
		try
		{
			stmt = session.getSQLConnection().prepareStatement(sql);
			stmt.setString(1, schema);
			rs = stmt.executeQuery();
			if (rs.next())
			{
				String tableName = rs.getString(1);
				matViewLookup.add(tableName);
			}
		}
		catch (SQLException e)
		{
			s_log.error("Unexpected exception while attempting to find mat. views " + "in schema: " + schema, e);
		}
		finally
		{
			SQLUtilities.closeResultSet(rs, true);
		}

	}

	public void setProgressCallBackFactory(IProgressCallBackFactory progressCallBackFactory)
	{
		this.progressCallBackFactory = progressCallBackFactory;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy