--- /dev/null
+package com.quantum.view;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ExtendedModifyEvent;
+import org.eclipse.swt.custom.ExtendedModifyListener;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IKeyBindingService;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.part.ViewPart;
+
+import com.quantum.Messages;
+import com.quantum.QuantumPlugin;
+import com.quantum.actions.ExecuteAction;
+import com.quantum.actions.ExportQueryAction;
+import com.quantum.actions.ImportQueryAction;
+import com.quantum.model.Bookmark;
+import com.quantum.model.NotConnectedException;
+import com.quantum.sql.MultiSQLServer;
+import com.quantum.sql.parser.SQLLexx;
+import com.quantum.sql.parser.Token;
+import com.quantum.view.bookmark.BookmarkNode;
+import com.quantum.view.bookmark.BookmarkView;
+
+public class SQLQueryView extends ViewPart {
+ private ExecuteAction executeAction;
+ private ImportQueryAction importQueryAction;
+ private ExportQueryAction exportQueryAction;
+ private Label statusImage;
+ private Label status;
+ private ProgressBar progress;
+ private StyledText widget;
+ private ToolItem autoCommitItem;
+ private ToolItem commitItem;
+ private ToolItem rollbackItem;
+ private Color STRING_LITERAL;
+ private Color KEYWORD;
+ private Color COMMENT;
+ private Color NUMERIC;
+ private Color DEFAULT;
+ private long parseTime = 0;
+ private long fullTime = 0;
+ public SQLQueryView() {
+ super();
+ }
+ public void setFocus() {
+
+ String title = "Quantum SQL Query Editor";
+ BookmarkNode bookmarkNode = null;
+ Bookmark bookmark = null;
+ Connection con = null;
+ if (BookmarkView.getInstance() != null ) {
+ bookmarkNode = BookmarkView.getInstance().getCurrentBookmark();
+ }
+ if (bookmarkNode != null)
+ bookmark = bookmarkNode.getBookmark();
+ if (bookmark != null) {
+ title = bookmark.getName() + " (" + title + ")";
+ setTitle( title );
+ try {
+ con = bookmark.getConnection();
+ } catch (NotConnectedException e) {
+ // Doesn't matter, "con" remains null
+ }
+ }
+
+ updateAutoCommitState(bookmark, con);
+
+ widget.setFocus();
+
+ }
+ public static SQLQueryView getInstance() {
+ return (SQLQueryView) QuantumPlugin.getDefault().getView("com.quantum.view.sqlqueryview");
+
+ }
+
+ public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
+ initActions();
+ KEYWORD = new Color(parent.getShell().getDisplay(), 126, 0, 75);
+ STRING_LITERAL = new Color(parent.getShell().getDisplay(), 0, 0, 255);
+ COMMENT = new Color(parent.getShell().getDisplay(), 88, 148, 64);
+ NUMERIC = new Color(parent.getShell().getDisplay(), 255, 0, 0);
+ DEFAULT = new Color(parent.getShell().getDisplay(), 0, 0, 0);
+ Composite main = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(1, false);
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ main.setLayout(layout);
+ ToolBar toolbar = new ToolBar(main, SWT.HORIZONTAL);
+ ToolItem item = new ToolItem(toolbar, SWT.PUSH);
+ item.setImage(QuantumPlugin.getImage("play.gif")); //$NON-NLS-1$
+ item.setToolTipText(Messages.getString("sqlqueryview.executeQuery")); //$NON-NLS-1$
+ item.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ executeAction.run();
+ }
+ });
+ item = new ToolItem(toolbar, SWT.SEPARATOR);
+ item = new ToolItem(toolbar, SWT.PUSH);
+ item.setImage(QuantumPlugin.getImage("import.gif")); //$NON-NLS-1$
+ item.setToolTipText(Messages.getString("sqlqueryview.importQuery")); //$NON-NLS-1$
+ item.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ importQueryAction.run();
+ }
+ });
+ item = new ToolItem(toolbar, SWT.PUSH);
+ item.setImage(QuantumPlugin.getImage("export.gif")); //$NON-NLS-1$
+ item.setToolTipText(Messages.getString("sqlqueryview.exportQuery")); //$NON-NLS-1$
+ item.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ exportQueryAction.run();
+ }
+ });
+ item = new ToolItem(toolbar, SWT.PUSH);
+ item.setImage(QuantumPlugin.getImage("clear.gif")); //$NON-NLS-1$
+ item.setToolTipText(Messages.getString("sqlqueryview.clear")); //$NON-NLS-1$
+ item.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ setQuery(""); //$NON-NLS-1$
+ }
+ });
+
+ item = new ToolItem(toolbar, SWT.SEPARATOR);
+
+ commitItem = new ToolItem(toolbar, SWT.PUSH);
+ commitItem.setImage(QuantumPlugin.getImage("commit.gif")); //$NON-NLS-1$
+ commitItem.setToolTipText(Messages.getString("SQLQueryView.Commit")); //$NON-NLS-1$
+ commitItem.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent event) {
+ try {
+ BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
+ if (node != null) MultiSQLServer.getInstance().commit(
+ node.getBookmark().getConnection());
+ } catch (NotConnectedException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ rollbackItem = new ToolItem(toolbar, SWT.PUSH);
+ rollbackItem.setImage(QuantumPlugin.getImage("rollback.gif")); //$NON-NLS-1$
+ rollbackItem.setToolTipText(Messages.getString("SQLQueryView.RollBack")); //$NON-NLS-1$
+ rollbackItem.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent event) {
+ }
+ public void widgetSelected(SelectionEvent event) {
+ try {
+ BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
+ if (node != null) MultiSQLServer.getInstance().rollback(
+ node.getBookmark().getConnection());
+ } catch (NotConnectedException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ autoCommitItem = new ToolItem(toolbar, SWT.CHECK);
+ autoCommitItem.setImage(QuantumPlugin.getImage("autocommit.gif")); //$NON-NLS-1$
+ autoCommitItem.setToolTipText(Messages.getString("SQLQueryView.AutoCommit")); //$NON-NLS-1$
+ autoCommitItem.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent event) {
+ BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
+ if (node == null) return;
+ Connection con = null;
+ try {
+ // Get the connection
+ con = node.getBookmark().getConnection();
+ // If connected (else will throw exception and jump out) switchs the state of the
+ // autoCommit option of the JDBC driver
+ MultiSQLServer.getInstance().setAutoCommit( con, autoCommitItem.getSelection());
+ } catch (NotConnectedException e) {
+ //Doesn't matter
+ }
+ // Update the bookmark and the buttons
+ updateAutoCommitState(node.getBookmark(), con);
+
+ }
+ });
+ BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
+ if (node == null) autoCommitItem.setSelection(true);
+ else autoCommitItem.setSelection(node.getBookmark().isAutoCommit());
+ if (autoCommitItem.getSelection()) {
+ commitItem.setEnabled(false);
+ rollbackItem.setEnabled(false);
+ } else {
+ commitItem.setEnabled(true);
+ rollbackItem.setEnabled(true);
+ }
+ widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL);
+
+ IActionBars bars = this.getViewSite().getActionBars();
+ bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
+ bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
+ bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
+ bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
+
+ widget.setEditable(true);
+ widget.addExtendedModifyListener(modifyListener);
+
+ GridData gridData = new GridData();
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.verticalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ gridData.grabExcessVerticalSpace = true;
+ widget.setLayoutData(gridData);
+
+ Composite bottomStatus = new Composite(main, SWT.NONE);
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ bottomStatus.setLayoutData(gridData);
+
+ GridLayout horizontal = new GridLayout(3, false);
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ bottomStatus.setLayout(horizontal);
+
+ statusImage = new Label(bottomStatus, SWT.NONE);
+ status = new Label(bottomStatus, SWT.NONE);
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ status.setLayoutData(gridData);
+
+ progress = new ProgressBar(bottomStatus, SWT.HORIZONTAL);
+
+ status.setText(Messages.getString("sqlqueryview.done")); //$NON-NLS-1$
+ statusImage.setImage(QuantumPlugin.getImage("success.gif")); //$NON-NLS-1$
+ progress.setMinimum(0);
+
+ IKeyBindingService keyBindingService = getSite().getKeyBindingService();
+ // TODO: check the version numbers for this method
+ keyBindingService.setScopes(new String[] {
+ "org.eclipse.ui.globalScope",
+ "com.quantum.view.sql"
+ });
+ keyBindingService.registerAction(this.executeAction);
+ }
+
+ /**
+ * Sets the state of the "Commit", "Rollback" and "autoCommit" buttons
+ * to reflect the situation in the connection
+ */
+ protected void updateAutoCommitState(Bookmark bookmark, Connection con) {
+ boolean autoCommit = true;
+ // Calculate the state of the autoCommit option
+ if (con != null)
+ {
+ // If we have a connection, the autoCommit state is that of the connection
+ try {
+ autoCommit = con.getAutoCommit();
+ } catch (SQLException e) {
+ // Doesn't matter, we take default
+ }
+ } else {
+ // if no connection, we try the autoCommit of the bookmark, or else the default
+ if (bookmark != null) autoCommit = bookmark.isAutoCommit();
+ }
+ // Set the autoCommit state of the bookmark to the calculated
+ if (bookmark != null) bookmark.setAutoCommit(autoCommit);
+ // Set the state of the buttons to the correct autoCommit state
+ autoCommitItem.setSelection(autoCommit);
+ if (autoCommitItem.getSelection()) {
+ commitItem.setEnabled(false);
+ rollbackItem.setEnabled(false);
+ } else {
+ commitItem.setEnabled(true);
+ rollbackItem.setEnabled(true);
+ }
+ }
+ public void setProgress(int increment, int max) {
+ progress.setMaximum(max);
+ progress.setSelection(increment);
+ }
+
+ private void initActions() {
+ executeAction = new ExecuteAction();
+ executeAction.init(this);
+ importQueryAction = new ImportQueryAction();
+ importQueryAction.init(this);
+ exportQueryAction = new ExportQueryAction();
+ exportQueryAction.init(this);
+ }
+
+ public void setStatus(String text) {
+ statusImage.setImage(null);
+ status.setText(text);
+ }
+
+ public void setStatus(Image img, String text) {
+ statusImage.setImage(img);
+ status.setText(text);
+ }
+
+ public String getQuery() {
+ return widget.getText();
+ }
+
+ public void setQuery(String text) {
+ widget.setText(text);
+ }
+
+ private String[] keywords = {
+ "ADD", "ALL", "ALTER", "AND", "ANY",
+ "AS", "ASC", "AUTOINCREMENT", "AVA", "BETWEEN",
+ "BINARY", "BIT", "BOOLEAN", "BY", "CREATE",
+ "BYTE", "CHAR", "CHARACTER", "COLUMN", "CONSTRAINT",
+ "COUNT", "COUNTER", "CURRENCY", "DATABASE", "DATE",
+ "DATETIME", "DELETE", "DESC", "DISALLOW", "DISTINCT",
+ "DISTINCTROW", "DOUBLE", "DROP", "EXISTS", "FROM",
+ "FLOAT", "FLOAT4", "FLOAT8", "FOREIGN", "GENERAL",
+ "GROUP", "GUID", "HAVING", "INNER", "INSERT",
+ "IGNORE", "IMP", "IN", "INDEX", "INT",
+ "INTEGER", "INTEGER1", "INTEGER2", "INTEGER4", "INTO",
+ "IS", "JOIN", "KEY", "LEFT", "LEVEL",
+ "LIKE", "LOGICAL", "LONG", "LONGBINARY", "LONGTEXT",
+ "MAX", "MEMO", "MIN", "MOD", "MONEY",
+ "NOT", "NULL", "NUMBER", "NUMERIC", "OLEOBJECT",
+ "ON", "PIVOT", "OPTION", "PRIMARY", "ORDER",
+ "OUTER", "OWNERACCESS", "PARAMETERS", "PERCENT", "REAL",
+ "REFERENCES", "RIGHT", "SELECT", "SET", "SHORT",
+ "SINGLE", "SMALLINT", "SOME", "STDEV", "STDEVP",
+ "STRING", "SUM", "TABLE", "TABLEID", "TEXT",
+ "TIME", "TIMESTAMP", "TOP", "TRANSFORM", "UNION",
+ "UNIQUE", "UPDATE", "VALUE", "VALUES", "VAR",
+ "VARBINARY", "VARCHAR", "VARP", "WHERE", "WITH",
+ "YESNO" };
+
+ SyntaxHighlighter textUpdater = new SyntaxHighlighter();
+
+ private class UpdateRequest {
+ public UpdateRequest(String text, int start, int length) {
+ this.text = text;
+ this.start = start;
+ this.length = length;
+ }
+ public String text;
+ public int start;
+ public int length;
+ }
+
+ private class SyntaxHighlighter extends Thread {
+ private boolean running = true;
+ private LinkedList requests = new LinkedList();
+ public SyntaxHighlighter() {
+ super();
+ setPriority(Thread.MIN_PRIORITY);
+ start();
+ }
+ public synchronized void updateText(String text, int start, int length) {
+ requests.add(new UpdateRequest(text, start, length));
+ notify();
+ }
+ public synchronized void shutdown() {
+ running = false;
+ interrupt();
+ }
+ public void run() {
+ while (running) {
+ try {
+ synchronized (this) {
+ if (requests.size() <= 0) {
+ wait();
+ } else {
+ Thread.sleep(10);
+ }
+ }
+ UpdateRequest request = (UpdateRequest) requests.removeFirst();
+ String text = request.text.toUpperCase();
+ //int dirtyStart = request.start;
+ //int dirtyEnd = request.start + request.length;
+ StyleRange styleRange;
+ long startTime = System.currentTimeMillis();
+ Vector tokens = SQLLexx.parse(text);
+ long subTime = System.currentTimeMillis();
+ Vector styles = new Vector();
+ int min = Integer.MAX_VALUE;
+ int max = 0;
+ for (int i = 0; i < tokens.size(); i++) {
+ Token t = (Token) tokens.elementAt(i);
+ String value = t.getValue();
+ int start = t.getStart();
+ int length = t.getEnd() - t.getStart();
+ styleRange = new StyleRange();
+ styleRange.start = start;
+ styleRange.length = value.length();
+ styleRange.fontStyle = SWT.NULL;
+ styleRange.foreground = DEFAULT;
+ //boolean upper = start <= dirtyEnd && start >= dirtyStart;
+ //boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
+ //boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
+ //if (upper || lower || both) {
+ if (true) { // Let's update the whole text, as some comment changes can alter everything
+ min = Math.min(start, min);
+ max = Math.max(max, start + length);
+ if (t.getType() == Token.IDENTIFIER) {
+ boolean keyword = false;
+ for (int index = 0; index < keywords.length; index++) {
+ if (value.equals(keywords[index])) {
+ keyword = true;
+ }
+ }
+ if (keyword) {
+ styleRange.fontStyle = SWT.BOLD;
+ styleRange.foreground = KEYWORD;
+ } else {
+ styleRange.foreground = DEFAULT;
+ }
+ styles.addElement(styleRange);
+ } else if (t.getType() == Token.COMMENT) {
+ styleRange.foreground = COMMENT;
+ styles.addElement(styleRange);
+ } else if (t.getType() == Token.LITERAL) {
+ styleRange.foreground = STRING_LITERAL;
+ styles.addElement(styleRange);
+ } else if (t.getType() == Token.NUMERIC) {
+ styleRange.foreground = NUMERIC;
+ styles.addElement(styleRange);
+ } else {
+ styles.addElement(styleRange);
+ }
+ }
+ }
+ StyleRange[] ranges = new StyleRange[styles.size()];
+ for (int k = 0; k < ranges.length; k++) {
+ ranges[k] = (StyleRange) styles.elementAt(k);
+ }
+ if (max >= 0 && ranges.length > 0) {
+ setStyles(ranges, min, max - min);
+ }
+ long endTime = System.currentTimeMillis();
+ parseTime = subTime - startTime;
+ fullTime = endTime - startTime;
+ } catch (NoSuchElementException e) {
+ // ignore a missing request
+ } catch (InterruptedException e) {
+ // ignore any interruptions
+ }
+ }
+ }
+ }
+ public void setStyles(final StyleRange[] styles, final int start, final int length) {
+ getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ try {
+ for (int i = 0; i < styles.length; i++) {
+ widget.setStyleRange(styles[i]);
+ }
+ } catch (Throwable t) {
+ System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$
+ // ignore any errors
+ }
+ }
+ });
+ }
+
+ ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
+ public void modifyText(ExtendedModifyEvent event) {
+ textUpdater.updateText(getQuery(), event.start, event.length);
+ }
+ };
+
+ private Action cutAction = new Action() {
+ public void run() {
+ widget.cut();
+ }
+ };
+ private Action copyAction = new Action() {
+ public void run() {
+ widget.copy();
+ }
+ };
+ private Action pasteAction = new Action() {
+ public void run() {
+ widget.paste();
+ }
+ };
+ private Action selectAllAction = new Action() {
+ public void run() {
+ widget.selectAll();
+ }
+ };
+}