Author: [EMAIL PROTECTED]
Date: Mon Sep 29 08:11:22 2008
New Revision: 2724
Added:
trunk/src/ca/sqlpower/architect/swingui/action/SQLQueryAction.java
trunk/src/ca/sqlpower/architect/swingui/query/
trunk/src/ca/sqlpower/architect/swingui/query/ExecuteActionListener.java
trunk/src/ca/sqlpower/architect/swingui/query/QueryDialog.java
trunk/src/ca/sqlpower/architect/swingui/query/SQLQueryEntryPanel.java
Modified:
trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java
Log:
Added a new SQL querying tool. This is the initial commit and more changes
will follow.
Modified: trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java Mon Sep 29
08:11:22 2008
@@ -100,6 +100,7 @@
import ca.sqlpower.architect.swingui.action.ProjectSettingsAction;
import ca.sqlpower.architect.swingui.action.RedoAction;
import ca.sqlpower.architect.swingui.action.ReverseRelationshipAction;
+import ca.sqlpower.architect.swingui.action.SQLQueryAction;
import ca.sqlpower.architect.swingui.action.SQLRunnerAction;
import ca.sqlpower.architect.swingui.action.SearchReplaceAction;
import ca.sqlpower.architect.swingui.action.SelectAllAction;
@@ -190,6 +191,7 @@
private Action exportDDLAction;
private Action compareDMAction;
private Action dataMoverAction;
+ private Action sqlQueryAction;
/**
* Closes all sessions and terminates the JVM.
@@ -201,6 +203,7 @@
};
+
/**
* This constructor is used by the session implementation. To obtain an
* Architect Frame, you have to create an
@@ -381,6 +384,7 @@
compareDMAction = new CompareDMAction(session,comapareDMDialog);
dataMoverAction = new DataMoverAction(this, session);
+ sqlQueryAction = new SQLQueryAction(session);
deleteSelectedAction = new DeleteSelectedAction(session);
createIdentifyingRelationshipAction = new
CreateRelationshipAction(session, true, playpen.getCursorManager());
@@ -608,7 +612,7 @@
toolsMenu.add(exportDDLAction);
toolsMenu.add(compareDMAction);
toolsMenu.add(new SQLRunnerAction(session));
-
+ toolsMenu.add(sqlQueryAction);
toolsMenu.add(dataMoverAction);
menuBar.add(toolsMenu);
Added: trunk/src/ca/sqlpower/architect/swingui/action/SQLQueryAction.java
==============================================================================
--- (empty file)
+++ trunk/src/ca/sqlpower/architect/swingui/action/SQLQueryAction.java Mon
Sep 29 08:11:22 2008
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui.action;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import ca.sqlpower.architect.swingui.ArchitectSwingSession;
+import ca.sqlpower.architect.swingui.query.QueryDialog;
+
+/**
+ * An action that opens a SQLQuery panel.
+ */
+public class SQLQueryAction extends AbstractArchitectAction {
+
+ private final ArchitectSwingSession session;
+
+ public SQLQueryAction(ArchitectSwingSession session) {
+ super(session, "SQL Query...", "A tool for executing SQL
queries.");
+ this.session = session;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ JDialog sqlQueryDialog = new
JDialog(session.getArchitectFrame(), "SQL Query");
+ JPanel sqlQueryPanel = new QueryDialog(session);
+ sqlQueryDialog.setContentPane(new JScrollPane(sqlQueryPanel));
+ sqlQueryDialog.pack();
+ sqlQueryDialog.setVisible(true);
+
+
+ }
+
+}
Added:
trunk/src/ca/sqlpower/architect/swingui/query/ExecuteActionListener.java
==============================================================================
--- (empty file)
+++
trunk/src/ca/sqlpower/architect/swingui/query/ExecuteActionListener.java
Mon Sep 29 08:11:22 2008
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui.query;
+
+import java.sql.ResultSet;
+
+/**
+ * A listener for executing queries in a [EMAIL PROTECTED] SQLQueryEntryPanel}.
+ */
+public interface ExecuteActionListener {
+
+ public void sqlQueryExecuted(ResultSet rs);
+
+}
Added: trunk/src/ca/sqlpower/architect/swingui/query/QueryDialog.java
==============================================================================
--- (empty file)
+++ trunk/src/ca/sqlpower/architect/swingui/query/QueryDialog.java Mon Sep
29 08:11:22 2008
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui.query;
+
+import java.awt.BorderLayout;
+import java.sql.ResultSet;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.table.TableModel;
+import javax.swing.tree.TreeModel;
+
+import org.apache.log4j.Logger;
+
+import ca.sqlpower.architect.ArchitectException;
+import ca.sqlpower.architect.swingui.ArchitectSwingSession;
+import ca.sqlpower.architect.swingui.DBTree;
+import ca.sqlpower.swingui.table.ResultSetTableFactory;
+import ca.sqlpower.swingui.table.ResultSetTableModel;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+/**
+ * This is like DBVisualizer, only not. It'll be different, I promise,
trust me....
+ */
+public class QueryDialog extends JPanel {
+
+ private static Logger logger = Logger.getLogger(QueryDialog.class);
+
+ /**
+ * The table showing the result set. This can only be created when we
get
+ * an actual ResultSet to avoid NPEs.
+ */
+ private JTable resultSetTable;
+
+ /**
+ * The scroll pane that contains the JTable displaying the results of
the
+ * SQL query.
+ */
+ private JScrollPane tableScrollPane;
+
+ /**
+ * The text area attached to the table that users can type into for
filtering
+ * the table.
+ */
+ private JTextArea tableFilterTextArea;
+
+ private final DBTree dbTree;
+
+ private SQLQueryEntryPanel queryEntryPanel;
+
+ /**
+ * Creates and displays the window for executing SQL queries.
+ */
+ public QueryDialog(ArchitectSwingSession session) {
+
+ try {
+ dbTree = new DBTree(session);
+ } catch (ArchitectException e) {
+ throw new RuntimeException(e);
+ }
+ TreeModel model = session.getSourceDatabases().getModel();
+ dbTree.setModel(model);
+
+ queryEntryPanel = new SQLQueryEntryPanel(session, dbTree);
+ queryEntryPanel.addExecuteAction(new ExecuteActionListener() {
+
+ public void sqlQueryExecuted(ResultSet rs) {
+ TableModel newModel = new ResultSetTableModel(rs);
+ if (resultSetTable == null) {
+ resultSetTable =
ResultSetTableFactory.createResultSetJTableWithSearch(rs,
tableFilterTextArea.getDocument());
+ tableScrollPane.getViewport().add(resultSetTable);
+ }
+ resultSetTable.setModel(newModel);
+ resultSetTable.createDefaultColumnsFromModel();
+ }});
+ buildUI(session);
+ }
+
+ private void buildUI(ArchitectSwingSession session) {
+
+ JSplitPane queryPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+ queryPane.add(queryEntryPanel, JSplitPane.TOP);
+
+ tableFilterTextArea = new JTextArea();
+ FormLayout tableAreaLayout = new FormLayout("pref, 10dlu,
pref:grow", "pref, 10dlu, fill:max(100dlu;pref):grow");
+ DefaultFormBuilder tableAreaBuilder = new
DefaultFormBuilder(tableAreaLayout);
+ tableAreaBuilder.setDefaultDialogBorder();
+ tableAreaBuilder.append("Filter");
+ tableAreaBuilder.append(tableFilterTextArea);
+ tableAreaBuilder.nextLine();
+ tableAreaBuilder.nextLine();
+ resultSetTable = null;
+ tableScrollPane = new JScrollPane();
+ tableAreaBuilder.append(tableScrollPane, 3);
+
+ queryPane.add(tableAreaBuilder.getPanel(), JSplitPane.BOTTOM);
+ JSplitPane treePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+
+ treePane.add(new JScrollPane(dbTree), JSplitPane.LEFT);
+ treePane.add(queryPane, JSplitPane.RIGHT);
+
+ setLayout(new BorderLayout());
+ add(treePane, BorderLayout.CENTER);
+ }
+
+}
Added: trunk/src/ca/sqlpower/architect/swingui/query/SQLQueryEntryPanel.java
==============================================================================
--- (empty file)
+++ trunk/src/ca/sqlpower/architect/swingui/query/SQLQueryEntryPanel.java
Mon Sep 29 08:11:22 2008
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui.query;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.KeyStroke;
+
+import org.apache.log4j.Logger;
+
+import ca.sqlpower.architect.ArchitectException;
+import ca.sqlpower.architect.SQLObject;
+import ca.sqlpower.architect.SQLTable;
+import ca.sqlpower.architect.swingui.ArchitectSwingSession;
+import ca.sqlpower.architect.swingui.DBTree;
+import ca.sqlpower.architect.swingui.DnDTreePathTransferable;
+import ca.sqlpower.sql.CachedRowSet;
+import ca.sqlpower.sql.SPDataSource;
+import ca.sqlpower.swingui.SPSUtils;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+/**
+ * This JPanel contains a text area to enter SQL script into and execute
it.
+ */
+public class SQLQueryEntryPanel extends JPanel {
+
+ private static Logger logger =
Logger.getLogger(SQLQueryEntryPanel.class);
+
+ private static final String EXECUTE_QUERY_ACTION = "Execute Query";
+
+ /**
+ * This QueryDropListener Listens to the SQLObjects being dragged onto
the
+ * QueryTextArea from a DBTree. When an object is dragged onto the
text area
+ * the object's name will be entered at the caret position.
+ */
+ private class QueryDropListener implements DropTargetListener {
+
+ private DBTree dbTree;
+
+ public QueryDropListener(DBTree dbtree) {
+ this.dbTree = dbtree;
+ }
+
+ public void dragEnter(DropTargetDragEvent dtde) {
+ logger.debug("we are in dragEnter");
+
+ }
+
+ public void dragExit(DropTargetEvent dte) {
+ logger.debug("we are in dragExit");
+
+ }
+
+ public void dragOver(DropTargetDragEvent dtde) {
+ logger.debug("we are in dragOver");
+
+ }
+
+ public void drop(DropTargetDropEvent dtde) {
+ DataFlavor[] flavours =
dtde.getTransferable().getTransferDataFlavors();
+ DataFlavor bestFlavour = null;
+ for (int i = 0; i < flavours.length; i++) {
+ if (flavours[i] != null) {
+ bestFlavour = flavours[i];
+ break;
+ }
+ }
+ try {
+ ArrayList paths = (ArrayList)
dtde.getTransferable().getTransferData(bestFlavour);
+ Iterator it = paths.iterator();
+ while(it.hasNext()) {
+ Object oo =
DnDTreePathTransferable.getNodeForDnDPath((SQLObject)
dbTree.getModel().getRoot(), (int[])it.next());
+ if (oo instanceof SQLTable) {
+ SQLTable table = ((SQLTable) oo);
+ StringBuffer buffer = new StringBuffer();
+ if (!table.getCatalogName().equals("")) {
+ buffer.append(table.getCatalogName());
+ buffer.append(".");
+ }
+ if(!table.getSchemaName().equals("")) {
+ buffer.append(table.getSchemaName());
+ buffer.append(".");
+ }
+ buffer.append(table.getPhysicalName());
+ queryArea.insert(buffer.toString(),
queryArea.getCaretPosition());
+ } else if (oo instanceof SQLObject) {
+ queryArea.insert(((SQLObject)
oo).getPhysicalName(), queryArea.getCaretPosition());
+ } else {
+ logger.error("Unknown object dropped in
PlayPen: "+oo);
+ }
+ }
+ dtde.dropComplete(true);
+ } catch (UnsupportedFlavorException e) {
+ logger.error(e);
+ dtde.rejectDrop();
+ } catch (IOException e) {
+ logger.error(e);
+ dtde.rejectDrop();
+ } catch (ArchitectException e) {
+ logger.error(e);
+ dtde.rejectDrop();
+ }
+ }
+
+ public void dropActionChanged(DropTargetDragEvent dtde) {
+ logger.debug("we are in dropActionChange");
+
+ }
+
+ }
+
+ /**
+ * The action for executing and displaying a user's query.
+ */
+ private final AbstractAction executeAction = new
AbstractAction("Execute") {
+ public void actionPerformed(ActionEvent e) {
+ logger.debug("Starting execute action.");
+ SPDataSource ds = (SPDataSource)databases.getSelectedItem();
+ if (ds == null) {
+ return;
+ }
+ Connection con = null;
+ Statement stmt = null;
+ ResultSet rs = null;
+ try {
+ con = ds.createConnection();
+ stmt = con.createStatement();
+ rs = stmt.executeQuery(queryArea.getText());
+ CachedRowSet rowSet = new CachedRowSet();
+ rowSet.populate(rs);
+
+ for (ExecuteActionListener listener : executeListeners) {
+ listener.sqlQueryExecuted(rowSet);
+ }
+
+ } catch (SQLException ex) {
+ SPSUtils.showExceptionDialogNoReport(getParent(), "Could
not query the database", ex);
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (SQLException ex) {
+ ex.printStackTrace();
+ }
+ }
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException ex) {
+ ex.printStackTrace();
+ }
+ }
+ if (con != null) {
+ try {
+ con.close();
+ } catch (SQLException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * The text area users can enter SQL queries to get data from the
database.
+ */
+ private final JTextArea queryArea;
+
+ /**
+ * A combo box of available connections the user have specified. The
selected
+ * one will have the query run on it when the user hits the execute
button.
+ */
+ private final JComboBox databases;
+
+ private DropTarget dt;
+
+ private List<ExecuteActionListener> executeListeners;
+
+ public SQLQueryEntryPanel(ArchitectSwingSession session, DBTree
dbTree) {
+ this(session);
+
+ dt = new DropTarget(queryArea, new QueryDropListener(dbTree));
+ }
+
+ public SQLQueryEntryPanel(ArchitectSwingSession session) {
+ super();
+
+ executeListeners = new ArrayList<ExecuteActionListener>();
+ queryArea = new JTextArea();
+ databases = new
JComboBox(session.getContext().getConnections().toArray());
+
+ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
+ KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())
+ , EXECUTE_QUERY_ACTION);
+ getActionMap().put(EXECUTE_QUERY_ACTION, executeAction);
+
+ buildUI();
+ }
+
+ private void buildUI() {
+ FormLayout textAreaLayout = new FormLayout("max(250dlu;pref):grow,
10dlu, pref", "fill:max(100dlu;pref):grow, pref, pref");
+ DefaultFormBuilder textAreaBuilder = new
DefaultFormBuilder(textAreaLayout, this);
+ textAreaBuilder.setDefaultDialogBorder();
+ textAreaBuilder.append(new JScrollPane(queryArea), 3);
+ textAreaBuilder.nextLine();
+ textAreaBuilder.append(databases);
+
+ textAreaBuilder.append(new JButton(executeAction));
+ textAreaBuilder.nextLine();
+ textAreaBuilder.append("");
+ textAreaBuilder.append(new JButton(new AbstractAction("Clear"){
+ public void actionPerformed(ActionEvent arg0) {
+ queryArea.setText("");
+ }}));
+ }
+
+ public void addExecuteAction(ExecuteActionListener l) {
+ executeListeners.add(l);
+ }
+
+ public void removeExecuteAction(ExecuteActionListener l) {
+ executeListeners.remove(l);
+ }
+
+}