Source Code Cross Referenced for QueryBuilder.java in  » IDE-Netbeans » db » org » netbeans » modules » db » sql » visualeditor » querybuilder » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » db » org.netbeans.modules.db.sql.visualeditor.querybuilder 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.netbeans.modules.db.sql.visualeditor.querybuilder;
0042:
0043:        import java.awt.Component;
0044:        import java.awt.Cursor;
0045:        import java.awt.event.ActionEvent;
0046:        import java.awt.event.KeyEvent;
0047:        import java.awt.event.KeyListener;
0048:        import java.awt.datatransfer.Clipboard;
0049:        import java.awt.datatransfer.ClipboardOwner;
0050:        import java.awt.datatransfer.Transferable;
0051:
0052:        import javax.swing.JComponent;
0053:        import javax.swing.ImageIcon;
0054:        import javax.swing.JOptionPane;
0055:        import javax.swing.SwingUtilities;
0056:        import javax.swing.AbstractAction;
0057:        import javax.swing.KeyStroke;
0058:        import javax.swing.InputMap;
0059:        import javax.swing.ActionMap;
0060:        import javax.swing.JFrame;
0061:        import javax.swing.RepaintManager;
0062:        import javax.swing.text.DefaultEditorKit;
0063:
0064:        import java.sql.ResultSet;
0065:        import java.sql.SQLException;
0066:        import java.sql.PreparedStatement;
0067:        import java.sql.ParameterMetaData;
0068:        import java.sql.Connection;
0069:
0070:        import java.util.ArrayList;
0071:        import java.util.List;
0072:
0073:        import java.util.logging.Level;
0074:        import org.netbeans.api.db.explorer.ConnectionManager;
0075:        import org.netbeans.modules.db.sql.visualeditor.QueryEditorUILogger;
0076:
0077:        import org.openide.NotifyDescriptor;
0078:        import org.openide.DialogDisplayer;
0079:        import org.openide.actions.DeleteAction;
0080:        import org.openide.nodes.Node;
0081:        import org.openide.util.HelpCtx;
0082:        import org.openide.util.NbBundle;
0083:        import org.openide.util.actions.ActionPerformer;
0084:        import org.openide.util.actions.SystemAction;
0085:        import org.openide.windows.TopComponent;
0086:        import org.openide.windows.WindowManager;
0087:
0088:        import org.netbeans.modules.db.sql.visualeditor.querymodel.ColumnProvider;
0089:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Column;
0090:        import org.netbeans.modules.db.sql.visualeditor.querymodel.JoinTable;
0091:        import org.netbeans.modules.db.sql.visualeditor.querymodel.OrderBy;
0092:        import org.netbeans.modules.db.sql.visualeditor.parser.ParseException;
0093:        import org.netbeans.modules.db.sql.visualeditor.parser.TokenMgrError;
0094:
0095:        import org.netbeans.modules.db.sql.visualeditor.api.VisualSQLEditorMetaData;
0096:        import org.netbeans.modules.db.sql.visualeditor.api.VisualSQLEditor;
0097:
0098:        import org.netbeans.modules.db.sql.visualeditor.Log;
0099:
0100:        import org.netbeans.api.db.explorer.DatabaseConnection;
0101:        import org.netbeans.api.db.sql.support.SQLIdentifiers;
0102:        import org.openide.util.Exceptions;
0103:
0104:        /**
0105:         * The top-level class for the QueryBuilder.
0106:         *
0107:         * This is the class that gets invoked from outside, to create QueryBuilder
0108:         * instances.  It also handles communication between the QueryBuilder panes and the
0109:         * data source (RowSet, Connection), including retrieving metadata, executing
0110:         * queries, and retrieving result sets.
0111:         *
0112:         * @author  Sanjay Dhamankar, Jim Davidson, then hacked apart, chewed up, by jfbrown, but still needs more!
0113:         */
0114:        public class QueryBuilder extends TopComponent implements 
0115:                ClipboardOwner, KeyListener, ColumnProvider {
0116:
0117:            // Provide package access on these, for use by other classes in the Query Builder
0118:
0119:            QueryBuilderPane _queryBuilderPane;
0120:            QueryModel _queryModel;
0121:            boolean _updateModel = true;
0122:            boolean _graphicsEnabled = true;
0123:
0124:            // Used to delay updating text pane until all changes have been made
0125:            boolean _updateText = true;
0126:            SQLIdentifiers.Quoter quoter;
0127:
0128:            // Private variables
0129:            private String lastQuery;
0130:
0131:            // the boolean below is used to determine if we need to store the query in the 
0132:            // backing file. The first time that generateText is called, we avoid saving
0133:            // the query in the backing file as this unnecessarily sets the save buttons ON.
0134:            private boolean firstTimeGenerateText = true;
0135:
0136:            private String _parseErrorMessage = null;
0137:            private boolean DEBUG = false;
0138:            private DatabaseConnection dbconn;
0139:            private String statement;
0140:            private QueryBuilderMetaData qbMetaData;
0141:            // private VisualSQLEditorMetaData         metaDataCache = null ;
0142:            private VisualSQLEditor vse;
0143:            private SQLException lastException = null;
0144:
0145:            /**
0146:             * Static factory method, added for access from RowSet
0147:             * @Return a QueryBuilder instance, either new or retrieved from the Map
0148:             */
0149:            public static Component open(DatabaseConnection dbconn,
0150:                    String statement, VisualSQLEditorMetaData metadata,
0151:                    VisualSQLEditor vse) {
0152:                Log.getLogger().entering("QueryBuilder", "open"); // NOI18N
0153:                QueryEditorUILogger.logEditorOpened();
0154:
0155:                showBusyCursor(true);
0156:
0157:                QueryBuilder qb;
0158:                try {
0159:                    qb = new QueryBuilder(dbconn, statement, metadata, vse);
0160:                } catch (SQLException sqle) {
0161:                    qb = null;
0162:                    // JDTODO: restore this dialog
0163:                    //            // TODO:  popup an error dialog.
0164:                    //            ConnectionStatusPanel csp = new ConnectionStatusPanel() ;
0165:                    //            csp.configureDisplay(sqlStatement.getConnectionInfo(), false,sqle.getLocalizedMessage(),  "", 0, false ) ;
0166:                    //            // csp.setGeneralInfo("") ;
0167:                    //            csp.displayDialog( sqlStatement.getConnectionInfo() ) ;
0168:                }
0169:                final QueryBuilder queryBuilder = qb;
0170:                SwingUtilities.invokeLater(new Runnable() {
0171:                    public void run() {
0172:                        if (queryBuilder != null) {
0173:                            queryBuilder.open();
0174:                            queryBuilder.requestActive();
0175:                        }
0176:                        showBusyCursor(false);
0177:                    }
0178:                });
0179:
0180:                queryBuilder.getTextAreaFocusInvokeLater();
0181:                return queryBuilder;
0182:            }
0183:
0184:            /**
0185:             * Private constructor, invoked only from the open() factory method
0186:             */
0187:            private QueryBuilder(DatabaseConnection dbconn, String statement,
0188:                    VisualSQLEditorMetaData metadata, VisualSQLEditor vse)
0189:                    throws SQLException {
0190:                Log.getLogger().entering("QueryBuilder", "constructor");
0191:                this .dbconn = dbconn;
0192:                this .statement = statement;
0193:                this .vse = vse;
0194:
0195:                // Either pass in metadata, or have it created from db
0196:                this .qbMetaData = (metadata == null) ? new QueryBuilderMetaData(
0197:                        dbconn, this )
0198:                        : new QueryBuilderMetaData(metadata, this );
0199:
0200:                // Create a quoter to be used for delimiting identifiers
0201:                this .quoter = SQLIdentifiers.createQuoter(getConnection()
0202:                        .getMetaData());
0203:
0204:                // It would be nice to have a short title, but there isn't a convenient one
0205:                String title = dbconn.getName();
0206:
0207:                // Set the name to display
0208:                setName(title);
0209:                setDisplayName(title);
0210:
0211:                setLayout(new java.awt.BorderLayout());
0212:
0213:                ImageIcon imgIcon = new ImageIcon(
0214:                        getClass()
0215:                                .getResource(
0216:                                        "/org/netbeans/modules/db/sql/visualeditor/resources/query-editor-tab.png")); // NOI18N
0217:                if (imgIcon != null)
0218:                    setIcon(imgIcon.getImage());
0219:
0220:                _queryBuilderPane = new QueryBuilderPane(this );
0221:
0222:                // Add the pane to the end of the QueryBuilder container
0223:                add(_queryBuilderPane);
0224:
0225:                addKeyListener(this );
0226:            }
0227:
0228:            // used for syntax highlighting
0229:            public boolean isSchemaName(String schemaName) {
0230:                return qbMetaData.isSchemaName(schemaName);
0231:            }
0232:
0233:            public boolean isTableName(String tableName) {
0234:                return qbMetaData.isTableName(tableName);
0235:            }
0236:
0237:            public boolean isColumnName(String columnName) {
0238:                return qbMetaData.isColumnName(columnName);
0239:            }
0240:
0241:            /////////////////////////////////////////////////////////////////////////
0242:            // Delete support
0243:            /////////////////////////////////////////////////////////////////////////
0244:
0245:            /** delete action performer */
0246:            private final transient DeleteActionPerformer deleteActionPerformer = new DeleteActionPerformer();
0247:
0248:            /** copy action performer */
0249:            protected final transient CopyCutActionPerformer copyActionPerformer = new CopyCutActionPerformer(
0250:                    true);
0251:
0252:            /** cut action performer */
0253:            protected final transient CopyCutActionPerformer cutActionPerformer = new CopyCutActionPerformer(
0254:                    false);
0255:
0256:            // Implements ClipboardOwner
0257:            public void lostOwnership(Clipboard clipboard, Transferable contents) {
0258:            }
0259:
0260:            boolean isSelectionEmpty() {
0261:                Node[] nodes = getActivatedNodes();
0262:                if ((nodes != null) && (nodes.length != 0))
0263:                    return false;
0264:                else
0265:                    return true;
0266:            }
0267:
0268:            private boolean isActivated() {
0269:                return this  == TopComponent.getRegistry().getActivated();
0270:            }
0271:
0272:            /*** do not save across IDE session ***/
0273:            public int getPersistenceType() {
0274:                return TopComponent.PERSISTENCE_NEVER;
0275:            }
0276:
0277:            public String preferredID() {
0278:                return "QueryEditor"; //NOI18N
0279:            }
0280:
0281:            /** Called when this window is activated: make delete
0282:             * sensitive based on whether or not anything is selected and whether
0283:             * the clipboard contains something we can absorb. */
0284:            public void activateActions() {
0285:                if (isSelectionEmpty()) {
0286:                    disableDelete();
0287:                } else {
0288:                    enableDelete();
0289:                }
0290:                // for now cut / copy is always disabled.
0291:                disableCutCopy();
0292:            }
0293:
0294:            /** Called when the when the component is deactivated. We no longer
0295:             * allow our paste types to be invoked so clear it - get rid of
0296:             * the action performers as well. */
0297:            public void deactivateActions() {
0298:                if (deleteActionPerformer != null) {
0299:                    //            delete.setActionPerformer(null);
0300:                }
0301:            }
0302:
0303:            /** Called when the selection is non zero and the component is active:
0304:             * enable cut, copy and delete */
0305:            void enableDelete() {
0306:                if (!isActivated()) {
0307:                    return;
0308:                }
0309:                deleteActionPerformer.setEnabled(true);
0310:            }
0311:
0312:            /** Called when the selection is removed: disable delete */
0313:            void disableDelete() {
0314:                if (!isActivated()) {
0315:                    return;
0316:                }
0317:                deleteActionPerformer.setEnabled(false);
0318:                DeleteAction da = SystemAction.get(DeleteAction.class);
0319:                da.setEnabled(false);
0320:            }
0321:
0322:            /** Called when the selection is removed: disable cut/copy */
0323:            void disableCutCopy() {
0324:                if (DEBUG)
0325:                    System.out.println(" disableCutCopy called. " + "\n"); // NOI18N
0326:                // Fix 6265915 Copy/Cut menu items are always enabled
0327:                cutActionPerformer.setEnabled(false);
0328:                copyActionPerformer.setEnabled(false);
0329:            }
0330:
0331:            /** Class which performs delete action */
0332:            class DeleteActionPerformer extends AbstractAction implements 
0333:                    ActionPerformer {
0334:
0335:                public void actionPerformed(ActionEvent e) {
0336:                    performAction(null);
0337:                }
0338:
0339:                // Perform delete action.
0340:                public void performAction(SystemAction action) {
0341:                    // We run into deadlocks without this; !#$!@#!@ ModuleActions thread
0342:                    SwingUtilities.invokeLater(new Runnable() {
0343:                        public void run() {
0344:                            deleteSelection();
0345:                        }
0346:                    });
0347:                }
0348:            }
0349:
0350:            /** Class which performs copy and cut actions */
0351:            class CopyCutActionPerformer extends AbstractAction implements 
0352:                    ActionPerformer {
0353:                /** determine if adapter is used for copy or cut action. */
0354:                boolean isCopy;
0355:
0356:                /** Create new adapter */
0357:                public CopyCutActionPerformer(boolean b) {
0358:                    isCopy = b;
0359:                }
0360:
0361:                public void actionPerformed(ActionEvent e) {
0362:                    performAction(null);
0363:                }
0364:
0365:                /** Perform copy or cut action. */
0366:                public void performAction(SystemAction action) {
0367:                    // for now do nothing
0368:                }
0369:            }
0370:
0371:            /** Remove the currently selected components */
0372:            private void deleteSelection() {
0373:                if (DEBUG)
0374:                    System.out.println(" deleteSelection called. " + "\n"); // NOI18N
0375:                java.awt.KeyboardFocusManager kbfm = java.awt.KeyboardFocusManager
0376:                        .getCurrentKeyboardFocusManager();
0377:                java.awt.Component c = kbfm.getFocusOwner();
0378:                if (c != null) {
0379:                    java.awt.Container p = c.getParent();
0380:                    while (p != null) {
0381:                        if (p instanceof  QueryBuilderGraphFrame) {
0382:
0383:                            Node[] nodes = getActivatedNodes();
0384:                            if (nodes == null || nodes.length == 0) {
0385:                                return;
0386:                            }
0387:                            for (int i = 0; i < nodes.length; i++) {
0388:                                if ((nodes[i] instanceof  CondNode)) {
0389:                                    _queryBuilderPane
0390:                                            .getQueryBuilderGraphFrame()
0391:                                            .removeNode((CondNode) nodes[i]);
0392:                                } else if ((nodes[i] instanceof  JoinNode)) {
0393:                                    _queryBuilderPane
0394:                                            .getQueryBuilderGraphFrame()
0395:                                            .removeNode((JoinNode) nodes[i]);
0396:                                } else if ((nodes[i] instanceof  TableNode)) {
0397:                                    _queryBuilderPane
0398:                                            .getQueryBuilderGraphFrame()
0399:                                            .removeNode((TableNode) nodes[i]);
0400:                                }
0401:                            }
0402:                        }
0403:                        p = p.getParent();
0404:                    }
0405:                }
0406:            }
0407:
0408:            private void installActions(ActionMap map, InputMap keys) {
0409:                /*
0410:                 map.put(DefaultEditorKit.copyAction, copyActionPerformer);
0411:                 map.put(DefaultEditorKit.cutAction, cutActionPerformer);
0412:                 // Paste still done the old way...
0413:                 //map.put(DefaultEditorKit.pasteAction, pasteActionPerformer);
0414:                 */
0415:                map.put("delete", deleteActionPerformer); // or false
0416:                map.put(DefaultEditorKit.copyAction, copyActionPerformer);
0417:                map.put(DefaultEditorKit.cutAction, cutActionPerformer);
0418:
0419:                /*
0420:                // Popup menu from the keyboard
0421:                map.put ("org.openide.actions.PopupAction",
0422:                        new AbstractAction() {
0423:                    public void actionPerformed(ActionEvent evt) {
0424:                        SwingUtilities.invokeLater(new Runnable() {
0425:                            public void run() {
0426:                                showKeyboardPopup();
0427:                            }
0428:                        });
0429:                    }
0430:                });
0431:
0432:                keys.put(KeyStroke.getKeyStroke("control C"), DefaultEditorKit.copyAction);
0433:                keys.put(KeyStroke.getKeyStroke("control X"), DefaultEditorKit.cutAction);
0434:                keys.put(KeyStroke.getKeyStroke("control V"), DefaultEditorKit.pasteAction);
0435:                 */
0436:                keys.put(KeyStroke.getKeyStroke("DELETE"), "delete");
0437:            }
0438:
0439:            void getGraphFrameCanvasFocus() {
0440:                _queryBuilderPane.getQueryBuilderGraphFrame().getCanvasFocus();
0441:            }
0442:
0443:            void getTextAreaFocusInvokeLater() {
0444:                javax.swing.SwingUtilities.invokeLater(new Runnable() {
0445:                    public void run() {
0446:                        _queryBuilderPane.getQueryBuilderSqlTextArea()
0447:                                .requestFocus(true);
0448:                        _queryBuilderPane.getQueryBuilderSqlTextArea()
0449:                                .requestFocusInWindow();
0450:                    }
0451:                });
0452:            }
0453:
0454:            /** ignore */
0455:            public void keyTyped(KeyEvent e) {
0456:            }
0457:
0458:            /** ignore */
0459:            public void keyReleased(KeyEvent e) {
0460:            }
0461:
0462:            /** Handle the key pressed event and change the focus if a particular
0463:             * key combination is pressed. */
0464:            public void keyPressed(KeyEvent e) {
0465:                handleKeyPress(e);
0466:            }
0467:
0468:            public void handleKeyPress(KeyEvent e) {
0469:                if (e.isAltDown()) {
0470:                    int code = e.getKeyCode();
0471:                    switch (code) {
0472:                    // diagram pane
0473:                    case KeyEvent.VK_1:
0474:                        if (DEBUG)
0475:                            System.out.println(" Alt + 1 pressed. "); // NOI18N
0476:                        // ToDo: Decide whether this needs to be duplicated in the GraphLib version
0477:                        // _queryBuilderPane.getQueryBuilderGraphFrame().getFocus ();
0478:                        getGraphFrameCanvasFocus();
0479:                        break;
0480:                    // grid pane
0481:                    case KeyEvent.VK_2:
0482:                        if (DEBUG)
0483:                            System.out.println(" Alt + 2 pressed. "); // NOI18N
0484:                        if (_queryBuilderPane.getQueryBuilderInputTable()
0485:                                .getRowCount() > 0) {
0486:                            _queryBuilderPane.getQueryBuilderInputTable()
0487:                                    .setRowSelectionInterval(0, 0);
0488:                            _queryBuilderPane.getQueryBuilderInputTable()
0489:                                    .requestFocus(true);
0490:                        }
0491:                        break;
0492:                    // SQL text pane
0493:                    case KeyEvent.VK_3:
0494:                        if (DEBUG)
0495:                            System.out.println(" Alt + 3 pressed. "); // NOI18N
0496:                        _queryBuilderPane.getQueryBuilderSqlTextArea()
0497:                                .requestFocus(true);
0498:                        break;
0499:                    // Result Pane
0500:                    case KeyEvent.VK_4:
0501:                        if (DEBUG)
0502:                            System.out.println(" Alt + 4 pressed. "); // NOI18N
0503:                        _queryBuilderPane.getQueryBuilderResultTable()
0504:                                .requestFocus(true);
0505:                        break;
0506:                    }
0507:                }
0508:            }
0509:
0510:            String checkTableName(String tableName) throws SQLException {
0511:                return qbMetaData.checkTableName(tableName);
0512:            }
0513:
0514:            String checkFullTableName(String fullTableName) throws SQLException {
0515:                return qbMetaData.checkFullTableName(fullTableName);
0516:            }
0517:
0518:            String checkColumnName(String tableName, String columnName)
0519:                    throws SQLException {
0520:                return qbMetaData.checkColumnName(tableName, columnName);
0521:            }
0522:
0523:            boolean checkColumnNameForTable(Column col, String tableName) {
0524:                return qbMetaData.checkColumnNameForTable(col, tableName);
0525:            }
0526:
0527:            boolean checkTableColumnName(Column col) throws SQLException {
0528:                return qbMetaData.checkTableColumnName(col);
0529:            }
0530:
0531:            /****
0532:             * Check the database connection.
0533:             * If no connection, ask to retry.
0534:             * if user doesn't want to retry,
0535:             * then disable the query editor
0536:             */
0537:            //     public boolean checkDatabaseAndDisable(String query) {
0538:            //         if ( query == null )
0539:            // 	    query = _queryBuilderPane.getQueryBuilderSqlTextArea().getText() ;
0540:            //         if ( checkDatabaseConnection() == false ) {
0541:            // 	    Log.getLogger().finest("checkDatabaseConnection returns false ... \n " ); // NOI18N
0542:            //             // If we don't have a valid connection, disable all visual editing.
0543:            //             disableVisualEditing(query);
0544:            //             return false;
0545:            //         }
0546:            //         return true ;
0547:            //     }
0548:            /**
0549:             * Parse the query and regenerate all the panes
0550:             * If parsing fails, raise an notification and do nothing else
0551:             * If parsing succeeds, return true, false otherwise.
0552:             * @param text query to parse
0553:             * @param forceParse force a parse even if query hasn't changed
0554:             */
0555:            boolean populate(String query, boolean forceParse) {
0556:
0557:                Log.getLogger().entering("QueryBuilder", "populate", query); // NOI18N
0558:
0559:                if (!forceParse) {
0560:                    if (query.trim().equals(
0561:                            _queryBuilderPane.getQueryBuilderSqlTextArea()
0562:                                    .getText().trim())) {
0563:                        // no change, just return.
0564:                        Log.getLogger().finest(
0565:                                "  skipping populate(), no change"); //NOI18N
0566:                        return true;
0567:                    }
0568:                }
0569:
0570:                // Fix CR 6275870 Error when parsing invalid SQL
0571:                if (query.trim().equals(lastQuery)) {
0572:                    // no change, just return.
0573:                    Log.getLogger().finest("  skipping populate(), no change"); //NOI18N
0574:                    return true;
0575:                } else {
0576:                    lastQuery = new String(query.trim());
0577:                }
0578:
0579:                // if ( ! checkDatabaseAndDisable( query )) return false ;
0580:
0581:                // First parse the query, and report any exception
0582:                try {
0583:                    parseQuery(query);
0584:
0585:                    // if the parsing is successful and if the user modified query
0586:                    // by hand, then check for all the table names and column names.
0587:                    // if there is an error, give a message to the user and return false
0588:                    // else if there is only error in case and/or ommission of
0589:                    // tablename etc fix the query model with the correct values.
0590:
0591:                    if (!checkQuery())
0592:                        return false;
0593:
0594:                    _queryBuilderPane.getQueryBuilderGraphFrame()
0595:                            .setQBGFEnabled(true);
0596:                    _queryBuilderPane.setQueryBuilderInputTableEnabled(true);
0597:                    _queryBuilderPane.getQueryBuilderGraphFrame()
0598:                            .setTableColumnValidity(false);
0599:                    _queryBuilderPane.getQueryBuilderGraphFrame().setGroupBy(
0600:                            _queryModel.hasGroupBy());
0601:                    _graphicsEnabled = true;
0602:                    // Will be done later by generate()
0603:                    // setSqlText(query);
0604:                } catch (ParseException pe) {
0605:                    Log.getLogger().severe(
0606:                            "Parse error: " + pe.getLocalizedMessage()); // NOI18N
0607:                    promptForContinuation(pe.getMessage(), query);
0608:                    return false;
0609:                } catch (TokenMgrError tme) {
0610:                    Log.getLogger().severe(
0611:                            "Parse error: " + tme.getLocalizedMessage()); // NOI18N
0612:                    promptForContinuation(tme.getMessage(), query);
0613:                    return false;
0614:
0615:                } catch (SQLException sqe) {
0616:                    lastException = sqe;
0617:                    Log.getLogger().severe(
0618:                            "Parse error: " + sqe.getLocalizedMessage()); // NOI18N
0619:                    promptForContinuation(sqe.getMessage(), query);
0620:                    return false;
0621:                }
0622:
0623:                _parseErrorMessage = null;
0624:
0625:                // If parsing was successful...
0626:
0627:                // ...generate the editor panes
0628:                this .generate();
0629:
0630:                // ...save the sql command.
0631:                saveSqlCommand();
0632:
0633:                _queryBuilderPane.getQueryBuilderSqlTextArea().requestFocus();
0634:
0635:                return true;
0636:            }
0637:
0638:            /**
0639:             * Ask the user whether to Retry&Continue or Cancel&Continue
0640:             */
0641:            private boolean promptForContinuation(String msg, String query) {
0642:
0643:                // There could be an error or the typed SQL may not be SQL-92
0644:                // compliant. Give the user an option to keep the query and test by
0645:                // running it. If the user is satisfied then this could reflect in the
0646:                // backing file. In that case the tables may not be displayed in the
0647:                // graph properly. If the user thinks that there is a genuine error,
0648:                // then the previous good query will be restored.
0649:
0650:                Object[] options = {
0651:                        NbBundle.getMessage(QueryBuilder.class, "CONTINUE"), // "Continue"
0652:                        NbBundle.getMessage(QueryBuilder.class, "CANCEL") // "Cancel"
0653:                };
0654:                if (_queryBuilderPane.getQueryBuilderSqlTextArea()
0655:                        .queryChanged()) {
0656:                    int val = JOptionPane.showOptionDialog(this , (msg
0657:                            + "\n\n"
0658:                            + NbBundle.getMessage(QueryBuilder.class,
0659:                                    "PARSE_ERROR_MESSAGE") + NbBundle
0660:                            .getMessage(QueryBuilder.class,
0661:                                    "PARSE_ERROR_MESSAGE_PROMPT")), NbBundle
0662:                            .getMessage(QueryBuilder.class, "PARSE_ERROR"),
0663:                            JOptionPane.YES_NO_OPTION,
0664:                            JOptionPane.QUESTION_MESSAGE, null, options,
0665:                            options[0]);
0666:                    if (val == JOptionPane.NO_OPTION) { // Cancel - Revert to previous
0667:                        Log.getLogger().info("Query execution canceled"); // NOI18N
0668:                        _queryBuilderPane.getQueryBuilderSqlTextArea()
0669:                                .restoreLastGoodQuery();
0670:                        _queryBuilderPane.getQueryBuilderGraphFrame()
0671:                                .setQBGFEnabled(true);
0672:                        _queryBuilderPane
0673:                                .setQueryBuilderInputTableEnabled(true);
0674:                        _graphicsEnabled = true;
0675:                        _parseErrorMessage = null;
0676:                    } else { // Continue - Disable visual editing
0677:                        _parseErrorMessage = NbBundle.getMessage(
0678:                                QueryBuilder.class, "PARSE_ERROR_MESSAGE"); // NOI18N
0679:                        disableVisualEditing(query);
0680:                    }
0681:                } else {
0682:                    // display the message in the graph area
0683:                    _parseErrorMessage = NbBundle.getMessage(
0684:                            QueryBuilder.class, "PARSE_ERROR_MESSAGE"); // NOI18N
0685:                    disableVisualEditing(query);
0686:                }
0687:                return false;
0688:            }
0689:
0690:            // Disable the graph and grid panes, leaving only the text pane.
0691:            // Used when either a parse fails, or the database is down
0692:            private void disableVisualEditing(String query) {
0693:                _graphicsEnabled = false;
0694:                _queryBuilderPane.clear();
0695:                _queryBuilderPane.getQueryBuilderGraphFrame().setQBGFEnabled(
0696:                        false);
0697:                _queryBuilderPane.setQueryBuilderInputTableEnabled(false);
0698:
0699:                String command = getSqlCommand();
0700:                if (query != null && query.trim().length() != 0) {
0701:                    setSqlText(query);
0702:                    setSqlCommand(query);
0703:                } else {
0704:                    setSqlText(command);
0705:                }
0706:            }
0707:
0708:            /***************************************************************************
0709:             * Code for checking validity of queries
0710:             **************************************************************************/
0711:
0712:            /**
0713:             * Check the various parts of the query for valid table/column names
0714:             */
0715:            private boolean checkQuery() throws SQLException {
0716:
0717:                if ((getSqlText() != null)
0718:                        || (_queryBuilderPane.getQueryBuilderGraphFrame()
0719:                                .checkTableColumnValidity())) {
0720:
0721:                    // from
0722:                    if (!checkFrom())
0723:                        return false;
0724:
0725:                    // We  were calling a function to replace the "*" with the column 
0726:                    // names of the tables immediately after parsing the query. With the
0727:                    // introduction of routines to check the table and column names and 
0728:                    // to resolve them properly, if the from clause contains the table 
0729:                    // names not as they appear in database, we change them to match 
0730:                    // with those in the database. e.g. trip becomes "TRAVEL.TRIP". This
0731:                    // is done in function checkFrom which gets called after parsing is 
0732:                    // done. In the case of replaceStar being called immediately after 
0733:                    // parsing, the column names and table names were resolved without 
0734:                    // checking for their validity in the database. I have changed this 
0735:                    // sequence as follows:
0736:                    // 1. First parse the query.
0737:                    // 2. Check for table names in the from clause. If the names
0738:                    //    only differ in case or if they are missing schema name
0739:                    //    then they are corrected in the datamodel.
0740:                    // 3. These corrected table names are used to resolve the column 
0741:                    // names in SQLs like "select * from trip" when we call replaceStar()
0742:                    // function.  This should fix the problem where "select * from TRIP" 
0743:                    // was parsed properly but "select * from trip" used to give errors.
0744:                    // Bug Id : 4962093
0745:
0746:                    // we need to replace star after we validate all the table names
0747:                    // in the from list.
0748:                    _queryModel.replaceStar(this );
0749:
0750:                    // select
0751:                    if (!checkSelect())
0752:                        return false;
0753:
0754:                    // where
0755:                    if (!checkWhere())
0756:                        return false;
0757:
0758:                    // groupby
0759:                    if (!checkGroupBy())
0760:                        return false;
0761:
0762:                    // having
0763:                    if (!checkHaving())
0764:                        return false;
0765:
0766:                    // orderby
0767:                    if (!checkOrderBy())
0768:                        return false;
0769:
0770:                } else {
0771:                    // we are not validating the fromList as the query has not been
0772:                    // changed by the user.
0773:                    _queryModel.replaceStar(this );
0774:                }
0775:                return true;
0776:            }
0777:
0778:            /**
0779:             * Check the tables specified in the FROM clause (plus any columns
0780:             * specified in join conditions), against the DB Schema
0781:             */
0782:            private boolean checkFrom() throws SQLException {
0783:
0784:                if (DEBUG)
0785:                    System.out.println("checkFrom called... \n "); // NOI18N
0786:
0787:                // we could reuse this to find the tablename if the user
0788:                // only specifies "select 'column_name' from 'table_name'"
0789:                List fromTables;
0790:                // from
0791:                if (_queryModel.getFrom() != null) {
0792:
0793:                    fromTables = _queryModel.getFrom().getTableList();
0794:                    for (int i = 0; i < fromTables.size(); i++) {
0795:
0796:                        String fromTableName = ((JoinTable) fromTables.get(i))
0797:                                .getFullTableName();
0798:                        String fromTableSpec = ((JoinTable) fromTables.get(i))
0799:                                .getTableSpec();
0800:                        String checkedFullTableName = checkFullTableName(fromTableName);
0801:
0802:                        if (DEBUG)
0803:                            System.out
0804:                                    .println("checkFullTableName called, fromTableName: "
0805:                                            + fromTableName
0806:                                            + " returns: "
0807:                                            + checkedFullTableName + " \n "); // NOI18N
0808:                        if (checkedFullTableName == null) {
0809:                            // table not found, give an error
0810:                            showTableColumnNameError(fromTableName);
0811:                            return false;
0812:                        } else if (!checkedFullTableName.equals(fromTableName)) {
0813:                            // table found but maybe in a wrong case, replace
0814:                            // it in the querymodel's from
0815:                            if (DEBUG)
0816:                                System.out.println(" fromTableName = "
0817:                                        + fromTableName + // NOI18N
0818:                                        " fromTableSpec = " + fromTableSpec + // NOI18N
0819:                                        " \n"); // NOI18N
0820:                            _queryModel.getFrom().setTableSpec(fromTableSpec,
0821:                                    checkedFullTableName);
0822:                        }
0823:
0824:                        // now check the columns in the condition if any.
0825:                        List fromColumns = new ArrayList();
0826:                        ((JoinTable) fromTables.get(i))
0827:                                .getReferencedColumns(fromColumns);
0828:                        for (int j = 0; j < fromColumns.size(); j++) {
0829:                            Column fromColumn = (Column) fromColumns.get(j);
0830:                            if (!checkTableColumnName(fromColumn)) {
0831:                                showTableColumnNameError(fromColumn
0832:                                        .getColumnName());
0833:                                return false;
0834:                            }
0835:                        }
0836:                    }
0837:                }
0838:                return true;
0839:            }
0840:
0841:            /**
0842:             * Check the tables specified in the SELECT clause, against the DB Schema
0843:             */
0844:            private boolean checkSelect() throws SQLException {
0845:                if (DEBUG)
0846:                    System.out
0847:                            .println("checkSelect called. _queryModel.getSelect() = "
0848:                                    + _queryModel.getSelect()); // NOI18N
0849:                if (_queryModel.getSelect() != null) {
0850:                    ArrayList selectColumns = new ArrayList();
0851:                    _queryModel.getSelect().getReferencedColumns(selectColumns);
0852:                    if (!checkColumns(selectColumns))
0853:                        return false;
0854:                }
0855:                return true;
0856:            }
0857:
0858:            /**
0859:             * Check the tables specified in the WHERE clause against the DB schema
0860:             */
0861:            private boolean checkWhere() throws SQLException {
0862:                if (DEBUG)
0863:                    System.out.println("checkWhere called... "); // NOI18N
0864:                if (_queryModel.getWhere() != null) {
0865:                    ArrayList whereColumns = new ArrayList();
0866:                    _queryModel.getWhere().getReferencedColumns(whereColumns);
0867:                    if (!checkColumns(whereColumns))
0868:                        return false;
0869:                }
0870:                return true;
0871:            }
0872:
0873:            /**
0874:             * Check the tables specified in the GROUP BY clause against the DB schema
0875:             */
0876:            private boolean checkGroupBy() throws SQLException {
0877:                if (DEBUG)
0878:                    System.out.println("checkGroupBy called... "); // NOI18N
0879:                if (_queryModel.getGroupBy() != null) {
0880:                    ArrayList groupByColumns = new ArrayList();
0881:                    _queryModel.getGroupBy().getReferencedColumns(
0882:                            groupByColumns);
0883:                    if (!checkColumns(groupByColumns))
0884:                        return false;
0885:                }
0886:                return true;
0887:            }
0888:
0889:            /**
0890:             * Check the tables specified in the HAVING clause against the DB schema
0891:             */
0892:            private boolean checkHaving() throws SQLException {
0893:                if (DEBUG)
0894:                    System.out.println("checkHaving called... "); // NOI18N
0895:                if (_queryModel.getHaving() != null) {
0896:                    ArrayList havingColumns = new ArrayList();
0897:                    _queryModel.getHaving().getReferencedColumns(havingColumns);
0898:                    if (!checkColumns(havingColumns))
0899:                        return false;
0900:                }
0901:                return true;
0902:            }
0903:
0904:            /**
0905:             * Check the tables specified in the ORDER BY clause against the DB schema
0906:             */
0907:            private boolean checkOrderBy() throws SQLException {
0908:                if (DEBUG)
0909:                    System.out.println("checkOrderBy called... "); // NOI18N
0910:                OrderBy orderBy = _queryModel.getOrderBy();
0911:                if (orderBy != null) {
0912:                    ArrayList orderByColumns = new ArrayList();
0913:                    for (int i = 0; i < orderBy.getSortSpecificationCount(); i++) {
0914:                        Column sortColumn = orderBy.getSortSpecification(i)
0915:                                .getColumn();
0916:                        orderByColumns.add(sortColumn);
0917:                    }
0918:                    if (!checkColumns(orderByColumns))
0919:                        return false;
0920:                }
0921:                return true;
0922:            }
0923:
0924:            // Check and correct any columns that may have wrong or missing table
0925:            // specifications. If the column is not found in the database it displays
0926:            // an error message and returns false. If there is just case mismatch
0927:            // this function corrects the column name.
0928:            // The column name could be :
0929:            //    case 1 : <schema_name>.<table_name>.<column_name>
0930:            //    case 2 : <table_name>.<column_name>
0931:            //    case 3 : <alias_table_name>.<column_name>
0932:            //    case 4 : <column_name>
0933:            //
0934:            private boolean checkColumns(ArrayList columns) throws SQLException {
0935:                Log.getLogger().entering("QueryBuilder", "checkColumns"); // NOI18N
0936:                for (int i = 0; i < columns.size(); i++) {
0937:                    Column column = (Column) columns.get(i);
0938:                    String columnTableSpec = column.getTableSpec();
0939:                    String columnFullTableName = column.getFullTableName();
0940:
0941:                    // If the user has specified a column without tablename resolve it
0942:                    // from the from_table_list.
0943:                    // Reversed the first test, switched || to &&.
0944:                    if ((columnFullTableName == null)
0945:                            && (_queryModel.getFrom() != null)) {
0946:                        // Check every table in the From list, to see if any have
0947:                        // this column
0948:                        List fromTables = _queryModel.getFrom().getTableList();
0949:                        boolean found = false;
0950:                        for (int j = 0; j < fromTables.size(); j++) {
0951:                            String fromTableName = ((JoinTable) fromTables
0952:                                    .get(j)).getFullTableName();
0953:                            // this could be an alias
0954:                            String fromTableSpec = ((JoinTable) fromTables
0955:                                    .get(j)).getTableSpec();
0956:
0957:                            if (DEBUG)
0958:                                System.out.println(" checkColumns called " + // NOI18N
0959:                                        " fromTableName = " + fromTableName + // NOI18N
0960:                                        " fromTableSpec = " + fromTableSpec); // NOI18N
0961:                            // use the following function to check if fromTableSpec
0962:                            // is in the database. If it is found update the column.
0963:                            if (checkColumnNameForTable(column, fromTableSpec)) {
0964:                                found = true;
0965:                                break;
0966:                            }
0967:                        }
0968:                        // Give an error only if all the columns have been checked in all tables
0969:                        if (!found) {
0970:                            // table not found, give an error
0971:                            showTableColumnNameError(column.getColumnName());
0972:                            return false;
0973:                        }
0974:                    }
0975:
0976:                    if (!checkTableColumnName(column)
0977:                    // Not clear what this test was for; it meant that we only reported an error if
0978:                    // the column that failed was the last one
0979:                    // && ( i == ( columns.size() - 1 ) )
0980:                    ) {
0981:                        showTableColumnNameError(column.getColumnName());
0982:                        return false;
0983:                    }
0984:                    // the table has an alias, do not check the table name, just
0985:                    // check column name
0986:                }
0987:                return true;
0988:            }
0989:
0990:            /**
0991:             * Report an unrecognized table/column name
0992:             */
0993:            private void showTableColumnNameError(String error) {
0994:                String msg = NbBundle.getMessage(QueryBuilder.class,
0995:                        "TABLE_COLUMN_NAME_ERROR");
0996:                NotifyDescriptor d = new NotifyDescriptor.Message(error + " : "
0997:                        + msg + "\n\n", NotifyDescriptor.ERROR_MESSAGE);
0998:                DialogDisplayer.getDefault().notify(d);
0999:                _parseErrorMessage = error + " : " + msg + "\n\n";
1000:                String query = getSqlText();
1001:                disableVisualEditing(query);
1002:            }
1003:
1004:            /**
1005:             * Parse the current query (obtained from the RowSet).
1006:             * @param the current query
1007:             */
1008:            private void parseQuery(String query) throws ParseException {
1009:
1010:                Log.getLogger().entering("QueryBuilder", "parseQuery", query); // NOI18N
1011:
1012:                // Initialize the QueryModel object if necessary
1013:                if (_queryModel == null)
1014:                    _queryModel = new QueryModel(quoter);
1015:
1016:                _queryModel.parse(query);
1017:            }
1018:
1019:            /**
1020:             * Update the command property of the calling VSE, using the current
1021:             * contents of the Sql Text.
1022:             * Also, record this as the last valid query, for rollback purposes.
1023:             */
1024:            private void saveSqlCommand() {
1025:
1026:                // Done in setText now?
1027:                // _queryBuilderPane.getQueryBuilderSqlTextArea().saveLastGoodQuery();
1028:
1029:                // Comapare the current SQL text to the existing Command value; don't do the
1030:                // setValue operation if there has been no change
1031:                String query = getSqlText();
1032:                if (!query.equals(getSqlCommand())) {
1033:                    Log.getLogger().finest(
1034:                            "QB:  setting sql command to: " + query); //NOI18N
1035:                    setSqlCommand(query);
1036:                }
1037:            }
1038:
1039:            // Wrappers for SqlStatement methods, which are now handled by a combination of 
1040:            // VisualSqlEditor and DatabaseConnection
1041:
1042:            void setSqlCommand(String query) {
1043:                //        sqlStatement.setCommand(query) ;
1044:                vse.setStatement(query);
1045:            }
1046:
1047:            String getSqlCommand() {
1048:                //	return sqlStatement.getCommand();
1049:                return vse.getStatement();
1050:            }
1051:
1052:            // JDTODO - use dbconn
1053:            String getConnectionInfo() {
1054:                //	return sqlStatement.getConnectionInfo();
1055:                String conn = "";
1056:                try {
1057:                    conn = getConnection().getMetaData().getURL();
1058:                } catch (SQLException ex) {
1059:                    Exceptions.printStackTrace(ex);
1060:                }
1061:                return conn;
1062:            }
1063:
1064:            /**
1065:             * Return the java.sql.Connection associated with this dbconn, after opening 
1066:             * it if necessary.
1067:             */
1068:            Connection getConnection() {
1069:
1070:                Connection conn = dbconn.getJDBCConnection();
1071:                if (conn == null) {
1072:                    // Try to (re-) open the connection
1073:                    ConnectionManager.getDefault().showConnectionDialog(dbconn);
1074:                    conn = dbconn.getJDBCConnection();
1075:                    if (conn == null) {
1076:                        // Connection failed for some reason.  User may have cancelled.
1077:                        // If there's an exception, ConnectionDialog already reported it.
1078:                        String msg = NbBundle.getMessage(QueryBuilder.class,
1079:                                "CANNOT_ESTABLISH_CONNECTION"); // NOI18N
1080:                        NotifyDescriptor d = new NotifyDescriptor.Message(msg
1081:                                + "\n\n", NotifyDescriptor.ERROR_MESSAGE); // NOI18N
1082:                        DialogDisplayer.getDefault().notify(d);
1083:                    }
1084:                }
1085:                return conn;
1086:            }
1087:
1088:            // JDTODO - use dbconn, which requires ConnectionManager.disconnect
1089:            void closeQB() {
1090:                //	sqlStatement.close();
1091:            }
1092:
1093:            // Wrappers for schema methods that are used by other classes in the query builder
1094:
1095:            List getColumnNames(String fullTableName) throws SQLException {
1096:                return qbMetaData.getColumnNames(fullTableName);
1097:            }
1098:
1099:            public void getColumnNames(String fullTableName, List columnNames) {
1100:                qbMetaData.getColumnNames(fullTableName, columnNames);
1101:            }
1102:
1103:            List getImportedKeyColumns(String fullTableName)
1104:                    throws SQLException {
1105:                return qbMetaData.getImportedKeyColumns(fullTableName);
1106:            }
1107:
1108:            List<String> getAllTables() throws SQLException {
1109:                return qbMetaData.getAllTables();
1110:            }
1111:
1112:            List getPrimaryKeys(String fullTableName) throws SQLException {
1113:                return qbMetaData.getPrimaryKeys(fullTableName);
1114:            }
1115:
1116:            List getForeignKeys(String fullTableName) throws SQLException {
1117:                return qbMetaData.getForeignKeys(fullTableName);
1118:            }
1119:
1120:            String[] findForeignKey(String oldFullTableName,
1121:                    String newFullTableName, List foreignKeys) {
1122:                return qbMetaData.findForeignKey(oldFullTableName,
1123:                        newFullTableName, foreignKeys);
1124:            }
1125:
1126:            String[] findForeignKey(String fullTableName1, String colName1,
1127:                    String fullTableName2, String colName2) throws SQLException {
1128:                return qbMetaData.findForeignKey(fullTableName1, colName1,
1129:                        fullTableName2, colName2);
1130:            }
1131:
1132:            /**
1133:             * Execute the specified query against the database
1134:             * @param query the query to execute
1135:             */
1136:            void executeQuery(String query) {
1137:
1138:                Log.getLogger().entering("QueryBuilder", "executeQuery", query); // NOI18N
1139:
1140:                String sqlCommand = getSqlText(); // why not "query"?
1141:                ResultSet result = null; // value to be returned.
1142:
1143:                Connection connection = null;
1144:                PreparedStatement myStatement = null;
1145:
1146:                showBusyCursor(true);
1147:
1148:                boolean canExecute = true;
1149:
1150:                ParameterMetaData pmd = null;
1151:                int paramCount = 0;
1152:                try {
1153:                    connection = getConnection();
1154:                    if (connection == null) {
1155:                        canExecute = false;
1156:
1157:                    } else {
1158:
1159:                        myStatement = connection.prepareStatement(sqlCommand);
1160:                        pmd = myStatement.getParameterMetaData();
1161:                        paramCount = pmd.getParameterCount();
1162:                        if (DEBUG) {
1163:                            System.out.println(" Parameter Count  = "
1164:                                    + paramCount);
1165:                            for (int i = 1; i <= paramCount; i++) {
1166:                                System.out.println(" Parameter Type  = "
1167:                                        + pmd.getParameterType(i));
1168:                                System.out.println(" Parameter Type Name = "
1169:                                        + pmd.getParameterTypeName(i));
1170:                            }
1171:                        }
1172:                    }
1173:                } catch (SQLException e) {
1174:                    reportDatabaseError(e); // NOI18N
1175:                    canExecute = false;
1176:                } catch (AbstractMethodError e) {
1177:                    // Certain drivers (e.g., Sybase 5.5) can throw Errors because of incompatibility.  Catch and report.
1178:                    Log.getLogger().severe(
1179:                            "Error occurred when trying to retrieve table information: "
1180:                                    + e); // NOI18N
1181:                    String title = NbBundle.getMessage(QueryBuilder.class,
1182:                            "PROCESSING_ERROR");
1183:                    JOptionPane.showMessageDialog(this , e.toString() + "\n\n",
1184:                            title, JOptionPane.ERROR_MESSAGE);
1185:                    canExecute = false;
1186:                }
1187:
1188:                // Deal with any query parameters if we know about them.
1189:                if (canExecute && (_queryModel != null)) {
1190:                    if (getParseErrorMessage() == null
1191:                            && _queryModel.isParameterized()) {
1192:
1193:                        ArrayList list = new ArrayList();
1194:                        _queryModel.getParameterizedPredicates(list);
1195:                        String[] parameters = new String[list.size()];
1196:                        String[] values = new String[list.size()];
1197:
1198:                        for (int i = 0; i < parameters.length; i++) {
1199:                            parameters[i] = new String((String) list.get(i));
1200:                        }
1201:                        ParameterizedQueryDialog pqDlg = new ParameterizedQueryDialog(
1202:                                parameters, true);
1203:                        if (pqDlg.getReturnStatus() == ParameterizedQueryDialog.RETURNED_OK) {
1204:
1205:                            values = pqDlg.getParameterValues();
1206:                            try {
1207:                                for (int i = 0; i < values.length; i++) {
1208:                                    if (DEBUG) {
1209:                                        System.out.println(" command  = "
1210:                                                + sqlCommand);
1211:                                        System.out
1212:                                                .println("PreparedStatement i = "
1213:                                                        + i
1214:                                                        + " values = "
1215:                                                        + values[i]);
1216:                                    }
1217:                                    myStatement.setObject(i + 1, values[i], pmd
1218:                                            .getParameterType(i + 1));
1219:                                }
1220:
1221:                            } catch (SQLException e) {
1222:                                if (isUnsupportedFeature(e)) {
1223:                                    Log.getLogger().log(Level.FINE, null, e);
1224:                                    String msg = NbBundle.getMessage(
1225:                                            QueryBuilder.class,
1226:                                            "PARAMETERS_NOT_SUPPORTED");
1227:                                    reportProcessingError(msg);
1228:                                } else {
1229:                                    reportDatabaseError(e); // NOI18N
1230:                                }
1231:                                canExecute = false;
1232:
1233:                            }
1234:                        } else {
1235:                            // cancelled the dialog.
1236:                            canExecute = false;
1237:                        }
1238:                    } else if (paramCount != 0) {
1239:                        // we have a query which can not be parsed.
1240:                        ArrayList list = new ArrayList(paramCount);
1241:                        if (DEBUG) {
1242:                            System.out.println(" param count = " + paramCount);
1243:                            System.out.println(" list size  = " + list.size());
1244:                        }
1245:                        String[] parameters = new String[paramCount];
1246:                        String[] values = new String[paramCount];
1247:                        if (DEBUG) {
1248:                            System.out.println(" parameters size  = "
1249:                                    + parameters.length);
1250:                            System.out.println(" values size  = "
1251:                                    + values.length);
1252:                        }
1253:
1254:                        for (int i = 0; i < paramCount; i++) {
1255:                            parameters[i] = new String("Parameter "
1256:                                    + new Integer(i).toString());
1257:                        }
1258:                        if (DEBUG) {
1259:                            for (int i = 0; i < parameters.length; i++) {
1260:                                System.out.println(" parameter  = "
1261:                                        + parameters[i]);
1262:                            }
1263:                        }
1264:                        ParameterizedQueryDialog pqDlg = new ParameterizedQueryDialog(
1265:                                parameters, true);
1266:                        // System.out.println(pqDlg.getReturnStatus());
1267:                        if (pqDlg.getReturnStatus() == ParameterizedQueryDialog.RETURNED_OK) {
1268:                            values = pqDlg.getParameterValues();
1269:
1270:                            try {
1271:                                for (int i = 0; i < values.length; i++) {
1272:                                    if (DEBUG) {
1273:                                        System.out.println(" command  = "
1274:                                                + sqlCommand);
1275:                                        System.out
1276:                                                .println("PreparedStatement i = "
1277:                                                        + i
1278:                                                        + " values = "
1279:                                                        + values[i]);
1280:                                    }
1281:                                    myStatement.setObject(i + 1, values[i], pmd
1282:                                            .getParameterType(i + 1));
1283:                                }
1284:
1285:                            } catch (SQLException e) {
1286:                                reportDatabaseError(e); // NOI18N
1287:                                canExecute = false;
1288:                            }
1289:                        } else {
1290:                            // cancelled the dialog.
1291:                            canExecute = false;
1292:                        }
1293:                    }
1294:                }
1295:
1296:                // Now execute the query
1297:                if (canExecute) {
1298:
1299:                    try {
1300:                        boolean hasResults = myStatement.execute();
1301:                        if (hasResults) {
1302:                            result = myStatement.getResultSet();
1303:                            _queryBuilderPane.getQueryBuilderResultTable()
1304:                                    .displayResultSet(result);
1305:                            result.close();
1306:                        }
1307:
1308:                    } catch (SQLException e) {
1309:                        reportDatabaseError(e); // NOI18N
1310:                    }
1311:                }
1312:
1313:                // clean up stuff.
1314:                try {
1315:                    if (myStatement != null) {
1316:                        myStatement.close();
1317:                    }
1318:                } catch (SQLException se) {
1319:                    Log.getLogger().finest(
1320:                            "Error Closing statement: "
1321:                                    + se.getLocalizedMessage()); // NOI18N
1322:                }
1323:
1324:                showBusyCursor(false);
1325:                Log.getLogger().finest(
1326:                        "Returning from QueryBuilder.executeQuery"); // NOI18N
1327:
1328:            }
1329:
1330:            /**
1331:             * Initialize all the panes based on a new query passed in from the RowSet
1332:             */
1333:            void generate() {
1334:
1335:                Log.getLogger().entering("QueryBuilder", "generate"); // NOI18N
1336:
1337:                // Suppress updating of the text pane until we're ready
1338:                _updateText = false;
1339:                try {
1340:
1341:                    // Clear the current state.  It might be easier to recreate each of
1342:                    // the panes, as we did at startup.
1343:                    _queryBuilderPane.clear();
1344:                    // Generate the Diagram Pane and Grid Pane
1345:                    this .generateGraph();
1346:                } finally {
1347:                    _updateText = true;
1348:                }
1349:
1350:                // Generate the Text Pane
1351:                // It's not clear whether we should use the passed-in command,
1352:                // or generate it from the model
1353:                // _queryBuilderSqlTextArea.setText(command);
1354:                this .generateText();
1355:            }
1356:
1357:            /**
1358:             * Generate the query graph and tables that correspond to the current query model
1359:             */
1360:            private void generateGraph() {
1361:                // If this is false, graphics and model are disabled.  Don't build graph/table.
1362:                if (_graphicsEnabled)
1363:                    _queryBuilderPane.getQueryBuilderGraphFrame()
1364:                            .generateGraph(_queryModel);
1365:            }
1366:
1367:            /**
1368:             * Build the SQL query from the current model, and update the text pane
1369:             */
1370:            void generateText() {
1371:                // If this is false, graphics and model are disabled.  Don't generate text.
1372:                if (_graphicsEnabled) {
1373:                    setSqlText(_queryModel.genText());
1374:
1375:                    // Update command property except on first time through
1376:                    if (!firstTimeGenerateText) {
1377:                        saveSqlCommand();
1378:                    } else {
1379:                        firstTimeGenerateText = false;
1380:                    }
1381:                }
1382:            }
1383:
1384:            //     /**
1385:            //      * Disable everything except the SQL Text Pane
1386:            //      */
1387:            //     void disable() {
1388:            //     }
1389:
1390:            //     /**
1391:            //      * Re-enable the panes that were disabled
1392:            //      */
1393:            //     void enable() {
1394:            //     }
1395:
1396:            /***************************************************************************
1397:             * Accessors/Mutators
1398:             **************************************************************************/
1399:
1400:            /**
1401:             * Return the current query model
1402:             */
1403:            QueryModel getQueryModel() {
1404:                return _queryModel;
1405:            }
1406:
1407:            /**
1408:             *  Restore the last good query.
1409:             */
1410:
1411:            QueryBuilderPane getQueryBuilderPane() {
1412:                return (_queryBuilderPane);
1413:            }
1414:
1415:            public VisualSQLEditor getVisualSQLEditor() {
1416:                return vse;
1417:            }
1418:
1419:            /**
1420:             * Get the current SQL Text from the SqlTextArea
1421:             */
1422:            private String getSqlText() {
1423:                return _queryBuilderPane.getQueryBuilderSqlTextArea().getText();
1424:            }
1425:
1426:            /**
1427:             * Set text in the SqlTextArea
1428:             * @param text the new text
1429:             */
1430:            private void setSqlText(String text) {
1431:                _queryBuilderPane.getQueryBuilderSqlTextArea().setText(text);
1432:            }
1433:
1434:            /**
1435:             * Returns true if the current query is parameterized
1436:             */
1437:            private boolean isParameterized() {
1438:                return _queryModel.isParameterized();
1439:            }
1440:
1441:            // Provide access to metadata object (currently used during text generation)
1442:            public QueryBuilderMetaData getMetaData() {
1443:                return qbMetaData;
1444:            }
1445:
1446:            // Methods inherited from org.openide.windows.TopComponent
1447:
1448:            /**
1449:             * About to show.  Could have been previously hidden ( e.g.,
1450:             * when the user tabs back to the QueryEditor) or on first showing.
1451:             *
1452:             * We need to flush all the current information (model, graph, metadata),
1453:             * and read the command, as if we were starting for the first time.
1454:             */
1455:            protected void componentShowing() {
1456:
1457:                Log.getLogger().entering("QueryBuilder", "componentShowing"); // NOI18N
1458:
1459:                String command = getSqlCommand();
1460:
1461:                if (_queryModel == null)
1462:                    _queryModel = new QueryModel(quoter);
1463:
1464:                Log.getLogger().finest("  * command=" + command);
1465:
1466:                // Parse the current query, in case it has changed
1467:
1468:                // Special case for handling null queries -- prompt for an initial table
1469:                // We should probably allow this, since the user can delete the last table in the
1470:                // editor anyway, so we need to be able to deal with empty queries as a special case.
1471:                if ((command == null) || (command.trim().length() == 0)) {
1472:                    Log.getLogger().finest("QBShowing command is null");
1473:                    setVisible(true);
1474:                    this .repaint();
1475:                    String msg = NbBundle.getMessage(QueryBuilder.class,
1476:                            "EMPTY_QUERY_ADD_TABLE");
1477:                    NotifyDescriptor d = new NotifyDescriptor.Message(msg
1478:                            + "\n\n", NotifyDescriptor.ERROR_MESSAGE); // NOI18N
1479:                    DialogDisplayer.getDefault().notify(d);
1480:
1481:                    _queryBuilderPane.getQueryBuilderGraphFrame().addTable();
1482:
1483:                } else {
1484:
1485:                    String queryText = getSqlText();
1486:                    // parse and populate only if the query has changed.
1487:                    if (queryText == null
1488:                            || (!command.trim().equalsIgnoreCase(
1489:                                    queryText.trim()))) {
1490:                        this .populate(command, false);
1491:                        setVisible(true);
1492:                        this .repaint();
1493:                    }
1494:                }
1495:                activateActions();
1496:
1497:                _queryBuilderPane.getQueryBuilderSqlTextArea().requestFocus();
1498:
1499:                if (DEBUG)
1500:                    System.out
1501:                            .println(" _queryBuilderPane.getQueryBuilderSqlTextArea().requestFocus () called. "); // NOI18N
1502:
1503:            }
1504:
1505:            /**
1506:             * Component is about to be shown.
1507:             * Called when the user moves to another tab.
1508:             * If we have an associated rowset, update it with current text query.
1509:             */
1510:            @Override
1511:            protected void componentHidden() {
1512:                Log.getLogger().entering("QueryBuilder", "componentHidden");
1513:                String command = getSqlCommand();
1514:                if ((command != null) && (command.trim().length() != 0)) {
1515:                    String queryText = getSqlText();
1516:
1517:                    // parse and populate only if the query has changed.
1518:                    if (queryText == null
1519:                            || (!command.trim().equalsIgnoreCase(
1520:                                    queryText.trim()))) {
1521:                        if (_graphicsEnabled) {
1522:                            boolean good = this .populate(queryText, true);
1523:                            if (!good) {
1524:                                setSqlCommand(queryText); //HACK, temporary (jfb)
1525:                            }
1526:                        } else {
1527:                            setSqlCommand(queryText);
1528:                        }
1529:                    }
1530:                }
1531:                deactivateActions();
1532:            }
1533:
1534:            /** Opened for the first time */
1535:            @Override
1536:            protected void componentOpened() {
1537:
1538:                Log.getLogger().entering("QueryBuilder", "componentOpened");
1539:
1540:                activateActions();
1541:                ActionMap map = getActionMap();
1542:                InputMap keys = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
1543:                installActions(map, keys);
1544:
1545:                // QueryBuilder does not need to listen to VSE, because it will notify us
1546:                // directly if something changes. The SqlCommandCustomizer needs to listen 
1547:                // to VSE, because that's the only way it is notified of changes to the command 
1548:                // sqlStatement.addPropertyChangeListener(sqlStatementListener) ;
1549:                // vse.addPropertyChangeListener(sqlStatementListener) ;
1550:
1551:                // do NOT force a parse here.  It's done in componentShowing().
1552:                // populate( sqlStatement.getCommand()) ;
1553:            }
1554:
1555:            /* closed - not visible anywhere)
1556:             */
1557:            @Override
1558:            protected void componentClosed() {
1559:                Log.getLogger().entering("QueryBuilder", "componentClosed");
1560:
1561:                deactivateActions();
1562:
1563:                // JDTODO - use dbconn?
1564:                this .closeQB();
1565:                lastQuery = null;
1566:            }
1567:
1568:            /*****
1569:             * listener for changes in the sqlStatement - either the
1570:             * command changed or the connection changed (e.g., datasource changed).
1571:             */
1572:            // No longer needed, since the customizer will just call vse.setStatement,
1573:            // which can in turn update the QueryEditor
1574:            //    private PropertyChangeListener sqlStatementListener = new PropertyChangeListener() {
1575:            //        public void propertyChange(PropertyChangeEvent evt) {
1576:            //            // what property?
1577:            //            String propName = evt.getPropertyName() ;
1578:            //            Log.getLogger().finest("QB sqlStatement property change: " + propName ) ;
1579:            //            if ( propName.equals(VisualSQLEditor.PROP_STATEMENT)) {
1580:            //                Log.getLogger().finest(" newValue=" + getSqlCommand()) ;
1581:            //                populate( getSqlCommand() ) ;
1582:            //                _queryBuilderPane.getQueryBuilderSqlTextArea().requestFocus();
1583:            //
1584:            //             } else if ( propName.equals(SqlStatement.TITLE) ) { 
1585:            //                 Log.getLogger().finest(" title to " + sqlStatement.getTitle()) ; // NOI18N
1586:            //                 SwingUtilities.invokeLater(new Runnable() {
1587:            //                     public void run() {
1588:            //                         setDisplayName(sqlStatement.getTitle()) ;
1589:            //                     }
1590:            //                 }) ;
1591:            //             } else if ( propName.equals(SqlStatement.CLOSING)) {
1592:            //                 Log.getLogger().finest(" closing...") ; // NOI18N
1593:            //                 SwingUtilities.invokeLater(new Runnable() {
1594:            //                     public void run() {
1595:            //                         close() ;
1596:            //                     }
1597:            //                 }) ;
1598:            //             }
1599:            //        }
1600:            //    } ;
1601:            /***
1602:            private final JButton retryButton = new JButton(NbBundle.getMessage(QueryBuilder.class, "RETRY_AND_CONTINUE")) ;
1603:            private final JButton cancelButton = new JButton(NbBundle.getMessage(QueryBuilder.class, "CANCEL_AND_CONTINUE")) ;
1604:             **/
1605:            /******
1606:             * show a dialog with the a message saying the database connection is hosed.
1607:             * It has a Retry and Cancel button.
1608:             * returns true if the Retry is the closing action.
1609:             */
1610:            //    int ii = 0 ;
1611:            //    private boolean showRetryDialog() {
1612:            //	Log.getLogger().entering("QueryBuilder", "showRetryDialog", ii++);
1613:            //        ConnectionStatusPanel csp = new ConnectionStatusPanel() ;
1614:            //        csp.configureDisplay(getConnectionInfo(), false, lastException.getLocalizedMessage(),  "", 0, false ) ;
1615:            //        csp.setGeneralInfo(NbBundle.getMessage(QueryBuilder.class, "DATABASE_CONNECTION_ERROR") ) ;    // NOI18N
1616:            //        csp.setFooterInfo(NbBundle.getMessage(QueryBuilder.class, "NO_DATABASE_CONNECTION") ) ;      // NOI18N
1617:            //
1618:            //        final JButton retryButton = new JButton(NbBundle.getMessage(QueryBuilder.class, "RETRY_AND_CONTINUE")) ;
1619:            //        final JButton cancelButton = new JButton(NbBundle.getMessage(QueryBuilder.class, "CANCEL_AND_CONTINUE")) ;
1620:            //
1621:            //        // this listener is for the dialog.
1622:            //        final Object[] retVal = new Object[1] ;
1623:            //        ActionListener listener = new ActionListener() {
1624:            //            public void actionPerformed(java.awt.event.ActionEvent evt) {
1625:            //                Log.getLogger().finest("  retry dialog event: " + evt) ;
1626:            //                retVal[0] = evt.getSource() ;
1627:            //            }
1628:            //
1629:            //        };
1630:            //
1631:            //        DialogDescriptor dlg = new DialogDescriptor(csp,
1632:            //                NbBundle.getMessage(ConnectionStatusPanel.class, "ConStat_title", getConnectionInfo()), // NOI18N
1633:            //                true/*modal*/,
1634:            //                new Object[] {retryButton, cancelButton}, cancelButton,
1635:            //                        DialogDescriptor.DEFAULT_ALIGN, null, listener);
1636:            //
1637:            //        dlg.setClosingOptions( null );
1638:            //
1639:            //        Dialog dialog = DialogDisplayer.getDefault().createDialog(dlg);
1640:            //        dialog.setResizable(true);
1641:            //        dialog.pack() ;
1642:            //
1643:            //        // present dialog, waits for it to be disposed.
1644:            //        dialog.show();
1645:            //
1646:            //        boolean val = ( retVal[0] == retryButton ) ;
1647:            //        Log.getLogger().finest("  * dlg says:  Retry=" + val ) ;
1648:            //        return val ;
1649:            //    }
1650:
1651:            private boolean isUnsupportedFeature(SQLException e) {
1652:                return e.getErrorCode() == 17023 || // Oracle "Unsupported feature" error
1653:                        "S1C00".equals(e.getSQLState()); // MySQL "Optional feature not supported" error
1654:            }
1655:
1656:            private void reportProcessingError(String msg) {
1657:                // NbBundle.getMessage(QueryBuilder.class, key);
1658:                String title = NbBundle.getMessage(QueryBuilder.class,
1659:                        "PROCESSING_ERROR");
1660:
1661:                JOptionPane.showMessageDialog(this , msg + "\n\n", title,
1662:                        JOptionPane.ERROR_MESSAGE);
1663:            }
1664:
1665:            private void reportDatabaseError(SQLException e) {
1666:
1667:                Log.getLogger().log(Level.FINE, null, e);
1668:
1669:                String msg = isUnsupportedFeature(e) ? NbBundle.getMessage(
1670:                        QueryBuilder.class, "UNSUPPORTED_FEATURE") : e
1671:                        .getLocalizedMessage();
1672:
1673:                reportProcessingError(msg);
1674:
1675:                /*
1676:                ConnectionStatusPanel csp = new ConnectionStatusPanel() ;
1677:                csp.configureDisplay(sqlStatement.getConnectionInfo(), false, e.getLocalizedMessage(),  "", 0, false ) ;
1678:                csp.setGeneralInfo(msg) ;
1679:                csp.displayDialog( sqlStatement.getConnectionInfo() ) ;
1680:                 */
1681:
1682:            }
1683:
1684:            String getParseErrorMessage() {
1685:                return _parseErrorMessage;
1686:            }
1687:
1688:            /**
1689:             * Showing/hiding busy cursor, before this funcionality was in Rave winsys,
1690:             * the code is copied from that module.
1691:             * It needs to be called from event-dispatching thread to work synch,
1692:             * otherwise it is scheduled into that thread. */
1693:            static void showBusyCursor(final boolean busy) {
1694:                if (SwingUtilities.isEventDispatchThread()) {
1695:                    doShowBusyCursor(busy);
1696:                } else {
1697:                    SwingUtilities.invokeLater(new Runnable() {
1698:                        public void run() {
1699:                            doShowBusyCursor(busy);
1700:                        }
1701:                    });
1702:                }
1703:            }
1704:
1705:            private static void doShowBusyCursor(boolean busy) {
1706:                JFrame mainWindow = (JFrame) WindowManager.getDefault()
1707:                        .getMainWindow();
1708:                if (busy) {
1709:                    RepaintManager.currentManager(mainWindow)
1710:                            .paintDirtyRegions();
1711:                    mainWindow.getGlassPane().setCursor(
1712:                            Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1713:                    mainWindow.getGlassPane().setVisible(true);
1714:                    mainWindow.repaint();
1715:                } else {
1716:                    mainWindow.getGlassPane().setVisible(false);
1717:                    mainWindow.getGlassPane().setCursor(null);
1718:                    mainWindow.repaint();
1719:                }
1720:            }
1721:
1722:            public HelpCtx getHelpCtx() {
1723:                return new HelpCtx(
1724:                        "projrave_ui_elements_editors_about_query_editor"); // NOI18N
1725:            }
1726:
1727:        }
w__w___w___.___j__a__va_2_s__.co__m_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.