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);
+    }
+
+}

Reply via email to