You can subscribe to this list here.
| 2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(8) |
Oct
(34) |
Nov
(7) |
Dec
(2) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
(29) |
Feb
(10) |
Mar
(14) |
Apr
(4) |
May
(2) |
Jun
|
Jul
(14) |
Aug
(25) |
Sep
(6) |
Oct
(18) |
Nov
(4) |
Dec
(14) |
| 2009 |
Jan
(28) |
Feb
(15) |
Mar
(15) |
Apr
(8) |
May
|
Jun
|
Jul
(1) |
Aug
(4) |
Sep
(12) |
Oct
(1) |
Nov
|
Dec
(22) |
| 2010 |
Jan
(14) |
Feb
|
Mar
(2) |
Apr
|
May
(7) |
Jun
|
Jul
(3) |
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
|
From: SVN by r. <sv...@ca...> - 2008-07-31 08:00:03
|
Author: roy Date: 2008-07-31 09:59:52 +0200 (Thu, 31 Jul 2008) New Revision: 276 Modified: ChangeLog Log: mention changes Modified: ChangeLog =================================================================== --- ChangeLog 2008-07-31 07:59:08 UTC (rev 275) +++ ChangeLog 2008-07-31 07:59:52 UTC (rev 276) @@ -6,6 +6,7 @@ * Fix for index out of bounds for strings without spaces * Fix for quit on some systems (hardy heron for example) * Added dump/read command to dump (a part of) a table + * Tab completion case sensitive fix (For example jo<tab> -> Job) 0.5 (2008-03-14) * Allow for commands to start in the background, this will allow to continue |
|
From: SVN by r. <sv...@ca...> - 2008-07-31 07:59:19
|
Author: roy
Date: 2008-07-31 09:59:08 +0200 (Thu, 31 Jul 2008)
New Revision: 275
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java
Log:
some threading fixes
fix 'case sensitive table names' when using tabcompletion
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-28 20:59:50 UTC (rev 274)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-31 07:59:08 UTC (rev 275)
@@ -403,6 +403,7 @@
@Override
void execute() {
output(getCommand().execute(cmd.sql));
+ repaint();
}
};
commandThread.start();
@@ -421,10 +422,12 @@
public abstract int getScreenWidth();
public abstract int getScreenHeight();
- protected synchronized void repaint() {
+ protected void repaint() {
if (paint) {
try {
- paint(screen);
+ synchronized(this) {
+ paint(screen);
+ }
} catch(Throwable t) {
error(t);
}
@@ -645,25 +648,29 @@
* Output data to the screen.
* @param data the data to print to the screen.
*/
- protected synchronized void output(List<? extends CharSequence> data) {
- for(CharSequence c : data) {
- output(c);
+ protected void output(List<? extends CharSequence> data) {
+ synchronized(this) {
+ for(CharSequence c : data) {
+ output(c);
+ }
}
}
/**
* Output data to the screen.
* @param data the data to print to the screen.
*/
- protected synchronized void output(CharSequence data) {
- List<CharSequence> screenBuffer = screen.getScreenBuffer();
- screenBuffer.addAll(getLines(data));
- if (spoolWriter != null) {
- try {
- spoolWriter.write(data.toString());
- spoolWriter.write("\n");
- } catch(IOException e) {
- screenBuffer.add("WARNING: Could not write to spool file");
- error(e);
+ protected void output(CharSequence data) {
+ synchronized(this) {
+ List<CharSequence> screenBuffer = screen.getScreenBuffer();
+ screenBuffer.addAll(getLines(data));
+ if (spoolWriter != null) {
+ try {
+ spoolWriter.write(data.toString());
+ spoolWriter.write("\n");
+ } catch(IOException e) {
+ screenBuffer.add("WARNING: Could not write to spool file");
+ error(e);
+ }
}
}
}
@@ -759,13 +766,15 @@
output("\n"+toColumns(matches));
}
if (match != null) {
- if (sub.length() > 0) {
- /*if (Character.isUpperCase(sub.charAt(0))) {
- match = match.toUpperCase();
- } else {
- match = match.toLowerCase();
- }*/
- match = DBConnector.getInstance().translateDbVar(match);
+ match = DBConnector.getInstance().translateDbVar(match);
+ if (sub.length() > 0 && !match.startsWith(sub)) { // case insensitive change
+ Point cursorPosition = screen.getCursorPosition();
+ List<StringBuilder> lines = getEditableCommand().getEditableLines();
+ if (lines.get(cursorPosition.y).length() >=sub.length()) {
+ cursorPosition.x-=sub.length();
+ lines.get(cursorPosition.y).delete(cursorPosition.x, cursorPosition.x + sub.length());
+ return match;
+ }
}
return match.substring(sub.length());
}
Modified: src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java 2008-07-28 20:59:50 UTC (rev 274)
+++ src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java 2008-07-31 07:59:08 UTC (rev 275)
@@ -39,8 +39,7 @@
private Window window;
public SQLShellWindow() {
- //super(getScreenWidth(),getScreenHeight(), true, "SQLShell");
- commands.register("WINDOW[\\s]+[A-Z]+", new WindowCommand());
+ //commands.register("WINDOW[\\s]+[A-Z]+", new WindowCommand());
}
@@ -54,9 +53,12 @@
return Toolkit.getScreenHeight();
}
+ @Override
public void debug(String debug) {
- CharColor color = new CharColor(CharColor.BLUE, CharColor.YELLOW);
- Toolkit.printString(debug, 1, getScreenHeight()-1, color);
+ synchronized(this) {
+ CharColor color = new CharColor(CharColor.BLUE, CharColor.YELLOW);
+ Toolkit.printString(debug, 1, getScreenHeight()-1, color);
+ }
}
@@ -72,60 +74,6 @@
*/
@Override
protected synchronized void paint() {
- /*
- CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD);
-
- List<CharSequence> tmpList = new ArrayList<CharSequence>();
- tmpList.addAll(screenBuffer);
-
- //add prompt
- List<? extends CharSequence> currentLines = commandLines.getLines();
- for (int i = 0; i < currentLines.size(); i++) {
- if (i == 0 && showPrompt) {
- tmpList.add(PROMPT+"> "+currentLines.get(i));
- } else {
- String nrI = Integer.toString(i+1);
- tmpList.add(emptyLine.substring(0,PROMPT.length() - nrI.length()) + nrI+"> "+currentLines.get(i));
- }
- }
- int startLine;
- if (tmpList.size() > getScreenHeight()-1) {
- startLine = tmpList.size() - (getScreenHeight()-1);
- if (pageUpCount > 0) {
- startLine -= (pageUpCount * getScreenHeight()/2);
- if (startLine < 0) {
- startLine = 0;
- }
- }
- } else {
- startLine = 0;
- }
- int lineNr;
- for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < getScreenHeight()-1; lineNr++) {
- CharSequence linePart = tmpList.get(lineNr);
- String line = linePart.length() >= emptyLine.length() ? linePart.toString() : linePart + emptyLine.substring(linePart.length());
- Toolkit.printString(line
- , 0, lineNr-startLine, color);
- }
- for (int lNr = lineNr; lNr < getScreenHeight(); lNr++) {
- Toolkit.printString(emptyLine, 0, lNr, color);
- }
-
- // paint cursor
- color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.REVERSE, CharColor.REVERSE);
- String cursorChar = " ";
- if (commandLines.getLines().size() > 0) {
- String tmp = commandLines.getLines().get(cursorPosition.y).toString();
- if (cursorPosition.x < 0) {
- //debug("Cursor position was: "+ cursorPosition +" fixing");
- cursorPosition.x = 0;
- }
- if (cursorPosition.x < tmp.length()) {
- cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1);
- }
- }
- Toolkit.printString(cursorChar, PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color);
- * */
SQLShellWindow.this.repaint();
}
@@ -234,60 +182,62 @@
@Override
public void paint(Screen screen) {
- CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD);
+ synchronized(this) {
+ CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD);
- List<CharSequence> tmpList = new ArrayList<CharSequence>();
- List<CharSequence> screenBuffer = screen.getScreenBuffer();
- tmpList.addAll(screenBuffer);
+ List<CharSequence> tmpList = new ArrayList<CharSequence>();
+ List<CharSequence> screenBuffer = screen.getScreenBuffer();
+ tmpList.addAll(screenBuffer);
- //add prompt
- List<? extends CharSequence> currentLines = commandLines.getLines();
- for (int i = 0; i < currentLines.size(); i++) {
- if (i == 0 && screen.getShowPrompt()) {
- tmpList.add(Screen.PROMPT+"> "+currentLines.get(i));
- } else {
- String nrI = Integer.toString(i+1);
- tmpList.add(screen.getEmptyLine().substring(0,Screen.PROMPT.length() - nrI.length()) + nrI+"> "+currentLines.get(i));
+ //add prompt
+ List<? extends CharSequence> currentLines = commandLines.getLines();
+ for (int i = 0; i < currentLines.size(); i++) {
+ if (i == 0 && screen.getShowPrompt()) {
+ tmpList.add(Screen.PROMPT+"> "+currentLines.get(i));
+ } else {
+ String nrI = Integer.toString(i+1);
+ tmpList.add(screen.getEmptyLine().substring(0,Screen.PROMPT.length() - nrI.length()) + nrI+"> "+currentLines.get(i));
+ }
}
- }
- int startLine;
- if (tmpList.size() > Toolkit.getScreenHeight()-1) {
- startLine = tmpList.size() - (Toolkit.getScreenHeight()-1);
- if (screen.getPageUpCount() > 0) {
- startLine -= (screen.getPageUpCount() * Toolkit.getScreenHeight()/2);
- if (startLine < 0) {
- startLine = 0;
+ int startLine;
+ if (tmpList.size() > Toolkit.getScreenHeight()-1) {
+ startLine = tmpList.size() - (Toolkit.getScreenHeight()-1);
+ if (screen.getPageUpCount() > 0) {
+ startLine -= (screen.getPageUpCount() * Toolkit.getScreenHeight()/2);
+ if (startLine < 0) {
+ startLine = 0;
+ }
}
+ } else {
+ startLine = 0;
}
- } else {
- startLine = 0;
- }
- int lineNr;
- for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < Toolkit.getScreenHeight()-1; lineNr++) {
- CharSequence linePart = tmpList.get(lineNr);
- String line = linePart.length() >= screen.getEmptyLine().length() ? linePart.toString() : linePart + screen.getEmptyLine().substring(linePart.length());
- Toolkit.printString(line
- , 0, lineNr-startLine, color);
- }
- for (int lNr = lineNr; lNr < Toolkit.getScreenHeight(); lNr++) {
- Toolkit.printString(screen.getEmptyLine(), 0, lNr, color);
- }
-
- // paint cursor
- color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.REVERSE, CharColor.REVERSE);
- String cursorChar = " ";
- Point cursorPosition = screen.getCursorPosition();
- if (commandLines.getLines().size() > 0) {
- String tmp = commandLines.getLines().get(cursorPosition.y).toString();
- if (cursorPosition.x < 0) {
- debug("Cursor position was: "+ cursorPosition +" fixing");
- cursorPosition.x = 0;
+ int lineNr;
+ for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < Toolkit.getScreenHeight()-1; lineNr++) {
+ CharSequence linePart = tmpList.get(lineNr);
+ String line = linePart.length() >= screen.getEmptyLine().length() ? linePart.toString() : linePart + screen.getEmptyLine().substring(linePart.length());
+ Toolkit.printString(line
+ , 0, lineNr-startLine, color);
}
- if (cursorPosition.x < tmp.length()) {
- cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1);
+ for (int lNr = lineNr; lNr < Toolkit.getScreenHeight(); lNr++) {
+ Toolkit.printString(screen.getEmptyLine(), 0, lNr, color);
}
+
+ // paint cursor
+ color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.REVERSE, CharColor.REVERSE);
+ String cursorChar = " ";
+ Point cursorPosition = screen.getCursorPosition();
+ if (commandLines.getLines().size() > 0) {
+ String tmp = commandLines.getLines().get(cursorPosition.y).toString();
+ if (cursorPosition.x < 0) {
+ debug("Cursor position was: "+ cursorPosition +" fixing");
+ cursorPosition.x = 0;
+ }
+ if (cursorPosition.x < tmp.length()) {
+ cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1);
+ }
+ }
+ Toolkit.printString(cursorChar, Screen.PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color);
}
- Toolkit.printString(cursorChar, Screen.PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color);
}
public static void main(String[] args) {
|
|
From: SVN by r. <sv...@ca...> - 2008-07-28 20:59:59
|
Author: roy
Date: 2008-07-28 22:59:50 +0200 (Mon, 28 Jul 2008)
New Revision: 274
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
Log:
made repaint synchronized
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-28 20:54:09 UTC (rev 273)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-28 20:59:50 UTC (rev 274)
@@ -421,7 +421,7 @@
public abstract int getScreenWidth();
public abstract int getScreenHeight();
- protected void repaint() {
+ protected synchronized void repaint() {
if (paint) {
try {
paint(screen);
|
|
From: SVN by r. <sv...@ca...> - 2008-07-28 20:54:22
|
Author: roy
Date: 2008-07-28 22:54:09 +0200 (Mon, 28 Jul 2008)
New Revision: 273
Added:
src/main/java/nl/improved/sqlclient/Screen.java
src/main/java/nl/improved/sqlclient/util/LimitedArrayList.java
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java
Log:
restructure of source code
made it (hopefully) a little more readable and extendable
still lots todo though ;(
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-28 20:20:24 UTC (rev 272)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-28 20:54:09 UTC (rev 273)
@@ -47,6 +47,7 @@
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import nl.improved.sqlclient.commands.*;
+import nl.improved.sqlclient.util.LimitedArrayList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -63,27 +64,6 @@
*/
private CommandThread commandThread;
/**
- * True when the prompt should be visible.
- * Normally it is not visible during the execution of a command
- */
- protected boolean showPrompt = true;
-
- /**
- * The (default) maximum matches to show in a selection dialog.
- */
- protected static final int MAX_MATCH_SIZE = 15;
- protected int MAX_LINE_LENGTH; // not static and final.. since it can change on window resize
-
- /**
- * Page up count 0 means were at the bottom of our screen.
- * Increasement of the pageup count moves the visible part of the screen up.
- */
- protected int pageUpCount = 0;
- /**
- * All lines in a screen.
- */
- protected List<CharSequence> screenBuffer = new LimitedArrayList<CharSequence>(1000);
- /**
* The current command lines.
*/
protected SQLCommand commandLines;
@@ -94,22 +74,8 @@
/**
* Index for browsing commands.
*/
- protected int commandIndex = 0;
+ private int commandIndex = 0;
/**
- * An empty line for easy line completion (fill with spaces).
- */
- protected String emptyLine;
- /**
- * The cursor position in the command lines list.
- * 0,0 means it is at the first line at the first character
- * 10,5 means it is at the 11th character at the 6th line
- */
- protected Point cursorPosition = new Point(0,0);
- /**
- * The prompt to show when entering sql commands.
- */
- protected static final String PROMPT = "SQL";
- /**
* Some debug info holding the last trace of an exception.
*/
private String lastExceptionDetails;
@@ -125,6 +91,8 @@
private ArrayBlockingQueue<CommandInfo> commandQueue = new ArrayBlockingQueue<CommandInfo>(10, true); // true means fair
+ private Screen screen;
+
/**
* A map of string key representation to a action that should be executed when a specific key is pressed.
*/
@@ -137,9 +105,10 @@
* Constructor.
*/
public AbstractSQLShellWindow() {
+ screen = new Screen();
char[] emptyLineChar = new char[getScreenWidth()];
Arrays.fill(emptyLineChar, ' ');
- emptyLine = new String(emptyLineChar);
+ screen.setEmptyLine(new String(emptyLineChar));
// initialize the command shell
commandLines = new SQLCommand();
@@ -167,6 +136,7 @@
specialActionKeys.put(InputKey.SpecialKey.LEFT, new KeyAction() {
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
if (cursorPosition.x > 0) {
cursorPosition.x--;
} else if (cursorPosition.y > 0) {
@@ -182,6 +152,7 @@
specialActionKeys.put(InputKey.SpecialKey.RIGHT, new KeyAction() {
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
CharSequence tmp = commandLines.getLines().get(cursorPosition.y);
if (cursorPosition.x < tmp.length()) {
cursorPosition.x++;
@@ -200,6 +171,7 @@
public void execute() {
if (commandIndex > 0) {
commandLines = commandHistory.get(--commandIndex);
+ Point cursorPosition = screen.getCursorPosition();
cursorPosition.y = commandLines.getLines().size()-1;
CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y);
cursorPosition.x = lineBuffer.length();
@@ -215,6 +187,7 @@
public void execute() {
if (commandIndex < commandHistory.size()-1) {
commandLines = commandHistory.get(++commandIndex);
+ Point cursorPosition = screen.getCursorPosition();
cursorPosition.y = commandLines.getLines().size()-1;
CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y);
cursorPosition.x = lineBuffer.length();
@@ -228,6 +201,7 @@
specialActionKeys.put(InputKey.SpecialKey.END,new KeyAction() {
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
int curLineEnd = commandLines.getLines().get(cursorPosition.y).length();
if (cursorPosition.x == curLineEnd) {
cursorPosition.y = commandLines.getLines().size()-1;
@@ -245,6 +219,7 @@
specialActionKeys.put(InputKey.SpecialKey.HOME, new KeyAction() {
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
if (cursorPosition.x == 0) {
cursorPosition.y = 0;
}
@@ -258,6 +233,7 @@
specialActionKeys.put(InputKey.SpecialKey.BACKSPACE, new KeyAction() {
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
if (cursorPosition.x == 0) {
if (cursorPosition.y > 0) {
joinLine();
@@ -278,6 +254,7 @@
specialActionKeys.put(InputKey.SpecialKey.DELETE, new KeyAction() {
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
if (cursorPosition.x < lineBuffer.length()) {
StringBuilder tmp = getEditableCommand().getEditableLines().get(cursorPosition.y);
@@ -292,9 +269,10 @@
specialActionKeys.put(InputKey.SpecialKey.PAGE_UP, new KeyAction() {
@Override
public void execute() {
+ List<CharSequence> screenBuffer = screen.getScreenBuffer();
if ((screenBuffer.size() + commandLines.getLines().size()
- - (getScreenHeight()/2) * pageUpCount) > 0) {
- pageUpCount++;
+ - (getScreenHeight()/2) * screen.getPageUpCount()) > 0) {
+ screen.setPageUpCount(screen.getPageUpCount() + 1);
}
}
@@ -306,8 +284,8 @@
specialActionKeys.put(InputKey.SpecialKey.PAGE_DOWN, new KeyAction() {
@Override
public void execute() {
- if (pageUpCount > 0) {
- pageUpCount--;
+ if (screen.getPageUpCount() > 0) {
+ screen.setPageUpCount(screen.getPageUpCount() - 1);
}
}
@Override
@@ -318,6 +296,7 @@
actionKeys.put("", new KeyAction() {
@Override
public void execute() { // ctrl+w
+ Point cursorPosition = screen.getCursorPosition();
if (cursorPosition.x == 0) {
if (cursorPosition.y > 0) {
joinLine();
@@ -340,6 +319,7 @@
actionKeys.put("", new KeyAction() { // ctrl+u
@Override
public void execute() {
+ Point cursorPosition = screen.getCursorPosition();
if (cursorPosition.x > 0) {
StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
lineBuffer.delete(0, cursorPosition.x);
@@ -385,7 +365,7 @@
}
});
- MAX_LINE_LENGTH = getScreenWidth()-(PROMPT.length()+2+1); // prompt + "> "
+ screen.MAX_LINE_LENGTH = getScreenWidth()-(Screen.PROMPT.length()+2+1); // prompt + "> "
output("Welcome to the SQLShell client.");
output("Type 'help' to get a list of available commands other then the default sql input.");
@@ -437,21 +417,23 @@
}
+ // TODO move to Screen???
public abstract int getScreenWidth();
public abstract int getScreenHeight();
- private void repaint() {
+
+ protected void repaint() {
if (paint) {
try {
- paint();
+ paint(screen);
} catch(Throwable t) {
error(t);
}
}
}
- public abstract void paint();
+ public abstract void paint(Screen screen);
public abstract void beep();
public abstract void debug(String debug);
- public abstract String select(List<String> items);
+ public abstract String select(List<String> items, Point p);
/**
* Returns the connection to the database
* @return the connection to the database
@@ -484,6 +466,7 @@
* Add a new line to the command lines buffer.
*/
private StringBuilder newLine() {
+ Point cursorPosition = screen.getCursorPosition();
cursorPosition.x = 0;
StringBuilder newLine = new StringBuilder();
getEditableCommand().getEditableLines().add(newLine);
@@ -498,7 +481,7 @@
protected void handleInput(InputKey inp) {
try {
if (!inp.isSpecialKey() || (inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_UP && inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_DOWN)) {
- pageUpCount = 0; // some character entered, so reset pageup count
+ screen.setPageUpCount(0); // some character entered, so reset pageup count
}
if (inp.isSpecialKey()) {
KeyAction ke = specialActionKeys.get(inp.getSpecialKeyValue());// || inp.toString().equals("") || inp.toString().equals("")) {
@@ -529,6 +512,7 @@
commandHistory.remove(commandIndex);
commandIndex = commandHistory.indexOf(newSqlCommand);
commandLines = newSqlCommand;
+ Point cursorPosition = screen.getCursorPosition();
cursorPosition.y = 0;
cursorPosition.x = 0;
repaint(); // force repaint
@@ -555,6 +539,7 @@
newLine();
}
commandIndex = commandHistory.size()-1;
+ Point cursorPosition = screen.getCursorPosition();
cursorPosition.y = commandLines.getLines().size()-1;
cursorPosition.x = commandLines.getLines().get(cursorPosition.y).length();
repaint(); // force repaint
@@ -564,6 +549,7 @@
CharSequence newText;
if (inp.getCharacter() == '\t') {
try {
+ Point cursorPosition = screen.getCursorPosition();
newText = getTabCompletion(commandLines, cursorPosition);
} catch(IllegalStateException e) {
output(getCommand().getCommandString()); // add command as well...
@@ -576,12 +562,13 @@
if (newText.equals("\n")) {
newLine(); // TODO Fix return in middle of an other line
} else {
+ Point cursorPosition = screen.getCursorPosition();
List<StringBuilder> editableLines = getEditableCommand().getEditableLines();
StringBuilder currentLine = editableLines.get(cursorPosition.y);
currentLine.insert(cursorPosition.x, newText);
cursorPosition.x += newText.length();
// check if the new line is becoming too long
- if (currentLine.length() > MAX_LINE_LENGTH) {
+ if (currentLine.length() > screen.MAX_LINE_LENGTH) {
// TODO search for lastspace that is not between '' ??
int lastSpace = SQLUtil.getLastBreakIndex(currentLine.toString());//currentLine.lastIndexOf(" ");
int lastChar = currentLine.charAt(lastSpace);
@@ -597,7 +584,7 @@
// check if the nextline has enough room for the new word
// if not.. add a new line
if (editableLines.get(cursorPosition.y+1).length()
- + (currentLine.length()-lastSpace+1) > MAX_LINE_LENGTH) {
+ + (currentLine.length()-lastSpace+1) > screen.MAX_LINE_LENGTH) {
StringBuilder newLine = new StringBuilder();
editableLines.add(cursorPosition.y+1, newLine);
}
@@ -668,6 +655,7 @@
* @param data the data to print to the screen.
*/
protected synchronized void output(CharSequence data) {
+ List<CharSequence> screenBuffer = screen.getScreenBuffer();
screenBuffer.addAll(getLines(data));
if (spoolWriter != null) {
try {
@@ -758,8 +746,15 @@
String match = null;
if (matches.size() == 1) {
match = matches.get(0);
- } else if (matches.size() > 1 && matches.size() < MAX_MATCH_SIZE) {
- match = select(matches);
+ } else if (matches.size() > 1 && matches.size() < Screen.MAX_MATCH_SIZE) {
+ int y;
+ Point cursorPosition = screen.getCursorPosition();
+ if (screen.getScreenBuffer().size() + cursorPosition.y > getScreenHeight()-3) {
+ y = getScreenHeight()-4;
+ } else {
+ y = screen.getScreenBuffer().size() + cursorPosition.y;
+ }
+ match = select(matches, new Point(cursorPosition.x, y));
} else if (matches.size() > 1) {
output("\n"+toColumns(matches));
}
@@ -919,7 +914,7 @@
StringBuilder returnValue = new StringBuilder();
for (int row = 0; row < values.size(); row+=nrOfColumns) {
for (int col = 0; col < nrOfColumns && row + col < values.size(); col++) {
- returnValue.append(values.get(row+col) + emptyLine.substring(0, maxWidth - values.get(row+col).length()));
+ returnValue.append(values.get(row+col) + screen.getEmptyLine().substring(0, maxWidth - values.get(row+col).length()));
}
returnValue.append('\n');
}
@@ -927,36 +922,6 @@
}
/**
- * A list which contains a limited number of lines.
- */
- private class LimitedArrayList<E> extends ArrayList<E> {
- private int maxSize;
- /**
- * Constructor.
- * @param maxSize the maximum number of lines the list may contain
- */
- public LimitedArrayList(int maxSize) {
- super(maxSize); // some sane default
- this.maxSize = maxSize;
- }
-
- @Override
- public boolean add(E object) {
- if (size() == maxSize) {
- remove(0);
- }
- return super.add(object);
- }
- @Override
- public void add(int index, E object) {
- if (size() == maxSize) {
- remove(0);
- }
- super.add(index, object);
- }
- }
-
- /**
* Connect command for setting up a connection to a database.
*/
private static class ConnectCommand implements Command {
@@ -1213,7 +1178,7 @@
if (cmd.getCommandString().equals(cmdString)) {
return cmd.getCommandString()+": "
+ cmd.getHelp().toString().replaceAll("\n"
- , "\n"+emptyLine.substring(0, cmd.getCommandString().length()+3));
+ , "\n"+screen.getEmptyLine().substring(0, cmd.getCommandString().length()+3));
}
}
}
@@ -1600,7 +1565,12 @@
output(commandString);
output(currentCommand.execute(new InputCommand(commandString)));
cmd=new StringBuilder();
- new Thread() { public void run() { repaint();}}.start();
+ new Thread() {
+ @Override
+ public void run() {
+ repaint();
+ }
+ }.start();
}
}
} catch(IOException e) {
@@ -1709,12 +1679,14 @@
this.cmd = cmd;
}
+ @Override
public final void run() {
- showPrompt = false;
+ screen.setShowPrompt(false);
+ repaint();
try {
execute();
} finally {
- showPrompt = true;
+ screen.setShowPrompt(true);
repaint();
}
}
@@ -1783,6 +1755,7 @@
}
private void joinLine() {
+ Point cursorPosition = screen.getCursorPosition();
StringBuilder line = getEditableCommand().getEditableLines().remove(cursorPosition.y);
cursorPosition.y--;
StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
Added: src/main/java/nl/improved/sqlclient/Screen.java
===================================================================
--- src/main/java/nl/improved/sqlclient/Screen.java 2008-07-28 20:20:24 UTC (rev 272)
+++ src/main/java/nl/improved/sqlclient/Screen.java 2008-07-28 20:54:09 UTC (rev 273)
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2008 Roy van der Kuil (ro...@va...)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package nl.improved.sqlclient;
+
+import java.util.List;
+import nl.improved.sqlclient.util.LimitedArrayList;
+
+/**
+ *
+ * @author roy
+ */
+public class Screen {
+
+ /**
+ * The (default) maximum matches to show in a selection dialog.
+ */
+ public static final int MAX_MATCH_SIZE = 15;
+ public int MAX_LINE_LENGTH; // not static and final.. since it can change on window resize
+ /**
+ * The prompt to show when entering sql commands.
+ */
+ public static final String PROMPT = "SQL";
+
+ /**
+ * True when the prompt should be visible.
+ * Normally it is not visible during the execution of a command
+ */
+ private boolean showPrompt = true;
+
+ /**
+ * Page up count 0 means were at the bottom of our screen.
+ * Increasement of the pageup count moves the visible part of the screen up.
+ */
+ private int pageUpCount = 0;
+ /**
+ * All lines in a screen.
+ */
+ private List<CharSequence> screenBuffer = new LimitedArrayList<CharSequence>(1000);
+ /**
+ * An empty line for easy line completion (fill with spaces).
+ */
+ private String emptyLine;
+ /**
+ * The cursor position in the command lines list.
+ * 0,0 means it is at the first line at the first character
+ * 10,5 means it is at the 11th character at the 6th line
+ */
+ private Point cursorPosition = new Point(0,0);
+
+ public Point getCursorPosition() {
+ return cursorPosition;
+ }
+
+ public List<CharSequence> getScreenBuffer() {
+ return screenBuffer;
+ }
+
+ public int getPageUpCount() {
+ return pageUpCount;
+ }
+
+ public void setPageUpCount(int pageUpCount) {
+ this.pageUpCount = pageUpCount;
+ }
+
+ public boolean getShowPrompt() {
+ return showPrompt;
+ }
+
+ public void setShowPrompt(boolean showPrompt) {
+ this.showPrompt = showPrompt;
+ }
+
+ public String getEmptyLine() {
+ return emptyLine;
+ }
+
+ public void setEmptyLine(String emptyLine) {
+ this.emptyLine = emptyLine;
+ }
+}
Modified: src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java 2008-07-28 20:20:24 UTC (rev 272)
+++ src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java 2008-07-28 20:54:09 UTC (rev 273)
@@ -1,8 +1,18 @@
/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright 2008 Roy van der Kuil (ro...@va...)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package nl.improved.sqlclient.jcurses;
import java.util.ArrayList;
@@ -17,6 +27,7 @@
import nl.improved.sqlclient.InputKey;
import nl.improved.sqlclient.Point;
import nl.improved.sqlclient.SQLCommand;
+import nl.improved.sqlclient.Screen;
import nl.improved.sqlclient.TabCompletionInfo;
import nl.improved.sqlclient.commands.Command;
@@ -61,6 +72,7 @@
*/
@Override
protected synchronized void paint() {
+ /*
CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD);
List<CharSequence> tmpList = new ArrayList<CharSequence>();
@@ -113,6 +125,8 @@
}
}
Toolkit.printString(cursorChar, PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color);
+ * */
+ SQLShellWindow.this.repaint();
}
private InputKey toInputKey(InputChar inputChar) {
@@ -208,14 +222,8 @@
}
@Override
- public String select(List<String> items) {
- int y;
- if (screenBuffer.size() + cursorPosition.y > getScreenHeight()-3) {
- y = getScreenHeight()-4;
- } else {
- y = screenBuffer.size() + cursorPosition.y;
- }
- PopUpMenu menu = new PopUpMenu(cursorPosition.x,Math.max(2, y-items.size()), "Find match");
+ public String select(List<String> items, Point p) {
+ PopUpMenu menu = new PopUpMenu(p.x,Math.max(2, p.y-items.size()), "Find match");
Iterator<String> iMatches = items.iterator();
while (iMatches.hasNext()) {
menu.add(iMatches.next());
@@ -225,27 +233,28 @@
}
@Override
- public void paint() {
+ public void paint(Screen screen) {
CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD);
List<CharSequence> tmpList = new ArrayList<CharSequence>();
+ List<CharSequence> screenBuffer = screen.getScreenBuffer();
tmpList.addAll(screenBuffer);
//add prompt
List<? extends CharSequence> currentLines = commandLines.getLines();
for (int i = 0; i < currentLines.size(); i++) {
- if (i == 0 && showPrompt) {
- tmpList.add(PROMPT+"> "+currentLines.get(i));
+ if (i == 0 && screen.getShowPrompt()) {
+ tmpList.add(Screen.PROMPT+"> "+currentLines.get(i));
} else {
String nrI = Integer.toString(i+1);
- tmpList.add(emptyLine.substring(0,PROMPT.length() - nrI.length()) + nrI+"> "+currentLines.get(i));
+ tmpList.add(screen.getEmptyLine().substring(0,Screen.PROMPT.length() - nrI.length()) + nrI+"> "+currentLines.get(i));
}
}
int startLine;
if (tmpList.size() > Toolkit.getScreenHeight()-1) {
startLine = tmpList.size() - (Toolkit.getScreenHeight()-1);
- if (pageUpCount > 0) {
- startLine -= (pageUpCount * Toolkit.getScreenHeight()/2);
+ if (screen.getPageUpCount() > 0) {
+ startLine -= (screen.getPageUpCount() * Toolkit.getScreenHeight()/2);
if (startLine < 0) {
startLine = 0;
}
@@ -256,17 +265,18 @@
int lineNr;
for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < Toolkit.getScreenHeight()-1; lineNr++) {
CharSequence linePart = tmpList.get(lineNr);
- String line = linePart.length() >= emptyLine.length() ? linePart.toString() : linePart + emptyLine.substring(linePart.length());
+ String line = linePart.length() >= screen.getEmptyLine().length() ? linePart.toString() : linePart + screen.getEmptyLine().substring(linePart.length());
Toolkit.printString(line
, 0, lineNr-startLine, color);
}
for (int lNr = lineNr; lNr < Toolkit.getScreenHeight(); lNr++) {
- Toolkit.printString(emptyLine, 0, lNr, color);
+ Toolkit.printString(screen.getEmptyLine(), 0, lNr, color);
}
// paint cursor
color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.REVERSE, CharColor.REVERSE);
String cursorChar = " ";
+ Point cursorPosition = screen.getCursorPosition();
if (commandLines.getLines().size() > 0) {
String tmp = commandLines.getLines().get(cursorPosition.y).toString();
if (cursorPosition.x < 0) {
@@ -277,7 +287,7 @@
cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1);
}
}
- Toolkit.printString(cursorChar, PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color);
+ Toolkit.printString(cursorChar, Screen.PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color);
}
public static void main(String[] args) {
Added: src/main/java/nl/improved/sqlclient/util/LimitedArrayList.java
===================================================================
--- src/main/java/nl/improved/sqlclient/util/LimitedArrayList.java 2008-07-28 20:20:24 UTC (rev 272)
+++ src/main/java/nl/improved/sqlclient/util/LimitedArrayList.java 2008-07-28 20:54:09 UTC (rev 273)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 Roy van der Kuil (ro...@va...)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package nl.improved.sqlclient.util;
+
+import java.util.ArrayList;
+
+/**
+ * A list which contains a limited number of lines.
+ */
+public class LimitedArrayList<E> extends ArrayList<E> {
+ private int maxSize;
+ /**
+ * Constructor.
+ * @param maxSize the maximum number of lines the list may contain
+ */
+ public LimitedArrayList(int maxSize) {
+ super(maxSize); // some sane default
+ this.maxSize = maxSize;
+ }
+
+ @Override
+ public boolean add(E object) {
+ if (size() == maxSize) {
+ remove(0);
+ }
+ return super.add(object);
+ }
+ @Override
+ public void add(int index, E object) {
+ if (size() == maxSize) {
+ remove(0);
+ }
+ super.add(index, object);
+ }
+}
|
|
From: SVN by r. <sv...@ca...> - 2008-07-28 20:20:35
|
Author: roy Date: 2008-07-28 22:20:24 +0200 (Mon, 28 Jul 2008) New Revision: 272 Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java Log: initial rewrite for non blocking pasting of commands Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java =================================================================== --- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-27 11:40:00 UTC (rev 271) +++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-28 20:20:24 UTC (rev 272) @@ -15,7 +15,15 @@ */ package nl.improved.sqlclient; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; @@ -32,6 +40,8 @@ import java.util.List; import java.util.Map; import java.util.LinkedHashMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; @@ -113,12 +123,15 @@ */ protected CommandManager commands = new CommandManager(); + private ArrayBlockingQueue<CommandInfo> commandQueue = new ArrayBlockingQueue<CommandInfo>(10, true); // true means fair + /** * A map of string key representation to a action that should be executed when a specific key is pressed. */ private Map<String, KeyAction> actionKeys = new LinkedHashMap<String, KeyAction>(); private Map<InputKey.SpecialKey, KeyAction> specialActionKeys = new LinkedHashMap<InputKey.SpecialKey, KeyAction>(); private boolean paint = true; + private boolean run = true; // set to false on quit /** * Constructor. @@ -152,6 +165,7 @@ // keys specialActionKeys.put(InputKey.SpecialKey.LEFT, new KeyAction() { + @Override public void execute() { if (cursorPosition.x > 0) { cursorPosition.x--; @@ -160,11 +174,13 @@ cursorPosition.x = commandLines.getLines().get(cursorPosition.y).length(); } } + @Override public CharSequence getHelp() { return "Arrow Left:\tMove cursor to the left"; } }); specialActionKeys.put(InputKey.SpecialKey.RIGHT, new KeyAction() { + @Override public void execute() { CharSequence tmp = commandLines.getLines().get(cursorPosition.y); if (cursorPosition.x < tmp.length()) { @@ -174,11 +190,13 @@ cursorPosition.y++; } } + @Override public CharSequence getHelp() { return "Arrow Right:\tMove cursor to the right"; } }); specialActionKeys.put(InputKey.SpecialKey.UP, new KeyAction() { + @Override public void execute() { if (commandIndex > 0) { commandLines = commandHistory.get(--commandIndex); @@ -187,11 +205,13 @@ cursorPosition.x = lineBuffer.length(); } } + @Override public CharSequence getHelp() { return "Arrow Up:\tBrowse to previous command in the history"; } }); specialActionKeys.put(InputKey.SpecialKey.DOWN, new KeyAction() { + @Override public void execute() { if (commandIndex < commandHistory.size()-1) { commandLines = commandHistory.get(++commandIndex); @@ -200,11 +220,13 @@ cursorPosition.x = lineBuffer.length(); } } + @Override public CharSequence getHelp() { return "Arrow Down:\tBrowse to next command in the history"; } }); specialActionKeys.put(InputKey.SpecialKey.END,new KeyAction() { + @Override public void execute() { int curLineEnd = commandLines.getLines().get(cursorPosition.y).length(); if (cursorPosition.x == curLineEnd) { @@ -215,22 +237,26 @@ cursorPosition.x = curLineEnd; } } + @Override public CharSequence getHelp() { return "End:\tMove the cursor to the end of the line, of if already there to the end of the command"; } }); specialActionKeys.put(InputKey.SpecialKey.HOME, new KeyAction() { + @Override public void execute() { if (cursorPosition.x == 0) { cursorPosition.y = 0; } cursorPosition.x = 0; } + @Override public CharSequence getHelp() { return "Home:\tMove the cursor to the start of the line, of if already there to the start of the command"; } }); specialActionKeys.put(InputKey.SpecialKey.BACKSPACE, new KeyAction() { + @Override public void execute() { if (cursorPosition.x == 0) { if (cursorPosition.y > 0) { @@ -244,11 +270,13 @@ } } } + @Override public CharSequence getHelp() { return "Backspace:\tRemove the character before the cursor position"; } }); specialActionKeys.put(InputKey.SpecialKey.DELETE, new KeyAction() { + @Override public void execute() { StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); if (cursorPosition.x < lineBuffer.length()) { @@ -256,6 +284,7 @@ tmp.deleteCharAt(cursorPosition.x); } } + @Override public CharSequence getHelp() { return "Del:\tDelete the charactor at the current cursor position"; } @@ -269,6 +298,7 @@ } } + @Override public CharSequence getHelp() { return "PageUp:\tMove back in screen history"; } @@ -280,11 +310,13 @@ pageUpCount--; } } + @Override public CharSequence getHelp() { return "PageDown:\tMove forward in screen history"; } }); actionKeys.put("", new KeyAction() { + @Override public void execute() { // ctrl+w if (cursorPosition.x == 0) { if (cursorPosition.y > 0) { @@ -300,11 +332,13 @@ lineBuffer.delete(previousBreak, cursorPosition.x); cursorPosition.x = previousBreak; } + @Override public CharSequence getHelp() { return "Control-W:\tRemove word before cursor position"; } }); actionKeys.put("", new KeyAction() { // ctrl+u + @Override public void execute() { if (cursorPosition.x > 0) { StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); @@ -320,6 +354,7 @@ lineBuffer.delete(0, lineBuffer.length()); } } + @Override public CharSequence getHelp() { return "Control-U:\tRemove all characters before the cursor position"; } @@ -354,6 +389,51 @@ output("Welcome to the SQLShell client."); output("Type 'help' to get a list of available commands other then the default sql input."); + + Runnable r = new Runnable() { + @Override + public void run() { + while ( run ) { + final CommandInfo cmd; + try { + cmd = commandQueue.poll(5, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + continue; + } + if (cmd == null) { + // TODO update waiting dot or something + continue; + } + // make sure only one command is run at once + if (commandThread != null && commandThread.isAlive()) { + try { + commandThread.join(); + } catch (InterruptedException ex) { + Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + } + } + output(cmd.sql.getLines()); + repaint(); + if (/*direct ||*/ !cmd.cmd.backgroundProcessSupported()) { + output(cmd.cmd.execute(cmd.sql)); + repaint(); + } else { + commandThread = new CommandThread(cmd.cmd) { + @Override + void execute() { + output(getCommand().execute(cmd.sql)); + } + }; + commandThread.start(); + } + + } + } + }; + Thread t = new Thread(r); + t.setDaemon(true); + t.start(); } @@ -758,7 +838,7 @@ * @param command the command to try and execute * @return true if it succeeded. */ - protected boolean executeCommand(SQLCommand sqlCommand) { + private boolean executeCommand(SQLCommand sqlCommand) { return executeCommand(sqlCommand, false); } @@ -779,26 +859,7 @@ if (command == null) { return false; } - // make sure only one command is run at once - if (commandThread != null && commandThread.isAlive()) { - try { - commandThread.join(); - } catch (InterruptedException ex) { - Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); - } - } - output(sqlCommand.getLines()); - if (direct || !command.backgroundProcessSupported()) { - output(command.execute(sqlCommand)); - } else { - commandThread = new CommandThread(command) { - @Override - void execute() { - output(getCommand().execute(sqlCommand)); - } - }; - commandThread.start(); - } + commandQueue.add(new CommandInfo(sqlCommand, command)); return true; } private Command createCommand(String commandString) { @@ -1077,6 +1138,7 @@ @Override public CharSequence execute(SQLCommand command) { paint = false; + run = false; close(); return "Application terminated."; } @@ -1731,4 +1793,14 @@ void execute(); CharSequence getHelp(); } + + private class CommandInfo { + private SQLCommand sql; + private Command cmd; + + public CommandInfo(SQLCommand sql, Command cmd) { + this.sql = sql; + this.cmd = cmd; + } + } } |
|
From: SVN by r. <sv...@ca...> - 2008-07-27 11:40:08
|
Author: roy
Date: 2008-07-27 13:40:00 +0200 (Sun, 27 Jul 2008)
New Revision: 271
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
Log:
fix regression bug for pageup count reset
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-27 11:36:47 UTC (rev 270)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-27 11:40:00 UTC (rev 271)
@@ -417,7 +417,7 @@
*/
protected void handleInput(InputKey inp) {
try {
- if (inp.isSpecialKey() && inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_UP && inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_DOWN) {
+ if (!inp.isSpecialKey() || (inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_UP && inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_DOWN)) {
pageUpCount = 0; // some character entered, so reset pageup count
}
if (inp.isSpecialKey()) {
|
|
From: SVN by r. <sv...@ca...> - 2008-07-27 11:36:55
|
Author: roy
Date: 2008-07-27 13:36:47 +0200 (Sun, 27 Jul 2008)
New Revision: 270
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
Log:
catch exceptions in paint()
print sql command as entered
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-27 11:27:29 UTC (rev 269)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-27 11:36:47 UTC (rev 270)
@@ -361,7 +361,11 @@
public abstract int getScreenHeight();
private void repaint() {
if (paint) {
- paint();
+ try {
+ paint();
+ } catch(Throwable t) {
+ error(t);
+ }
}
}
public abstract void paint();
@@ -453,9 +457,6 @@
}
beep(); // TODO clear search??
return;
- /*} else if (sqlCommand.getCommandString().equalsIgnoreCase("exit")) {
- close();
- return;*/
} else if (executeCommand(sqlCommand)) {
// clear command history
if (commandIndex != commandHistory.size()-1) {
@@ -577,6 +578,15 @@
* Output data to the screen.
* @param data the data to print to the screen.
*/
+ protected synchronized void output(List<? extends CharSequence> data) {
+ for(CharSequence c : data) {
+ output(c);
+ }
+ }
+ /**
+ * Output data to the screen.
+ * @param data the data to print to the screen.
+ */
protected synchronized void output(CharSequence data) {
screenBuffer.addAll(getLines(data));
if (spoolWriter != null) {
@@ -777,7 +787,7 @@
Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex);
}
}
- output(commandString);
+ output(sqlCommand.getLines());
if (direct || !command.backgroundProcessSupported()) {
output(command.execute(sqlCommand));
} else {
|
|
From: SVN by r. <sv...@ca...> - 2008-07-27 11:27:41
|
Author: roy
Date: 2008-07-27 13:27:29 +0200 (Sun, 27 Jul 2008)
New Revision: 269
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
src/main/java/nl/improved/sqlclient/SQLUtil.java
Log:
fixes in 'autobreak' to nextline code
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-23 20:57:12 UTC (rev 268)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-27 11:27:29 UTC (rev 269)
@@ -503,6 +503,7 @@
if (currentLine.length() > MAX_LINE_LENGTH) {
// TODO search for lastspace that is not between '' ??
int lastSpace = SQLUtil.getLastBreakIndex(currentLine.toString());//currentLine.lastIndexOf(" ");
+ int lastChar = currentLine.charAt(lastSpace);
if (lastSpace == -1) {
lastSpace = currentLine.length();
}
@@ -522,16 +523,20 @@
// fetch the next line
StringBuilder nextLine = editableLines.get(cursorPosition.y+1);
// if the nextline already has some text.. add a space in front of it
- if (nextLine.length() > 0) {
+ // if there is not already a 'breaking character' there
+ if (nextLine.length() > 0 && ! SQLUtil.isBreakCharacter(nextLine.charAt(0))) {
nextLine.insert(0, ' ');
}
// insert the new text at the beginning
- nextLine.insert(0, currentLine.subSequence(lastSpace+1, currentLine.length()));
+ nextLine.insert(0, currentLine.subSequence(lastSpace, currentLine.length()));
currentLine.delete(lastSpace, currentLine.length());
+ if (lastChar == ' ') {
+ nextLine.deleteCharAt(0);
+ }
// check if the cursor postition > the new line length
// calculate new x and go to nextline
if (cursorPosition.x >= lastSpace) {
- cursorPosition.x = cursorPosition.x - (lastSpace+1);
+ cursorPosition.x = cursorPosition.x - (lastSpace);
cursorPosition.y++;
}
}
Modified: src/main/java/nl/improved/sqlclient/SQLUtil.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-07-23 20:57:12 UTC (rev 268)
+++ src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-07-27 11:27:29 UTC (rev 269)
@@ -26,6 +26,7 @@
*/
public class SQLUtil {
+ final static char[] breakCharacters = new char[]{' ', '\t', '.', ','};
/**
* A regular expression statement for name chars.
*/
@@ -293,13 +294,21 @@
}
+ public static boolean isBreakCharacter(char c) {
+ for (char breakChar : breakCharacters) {
+ if (c == breakChar) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Returns the index of last spacing in the string.
* this method is used for clearing or breaking lines.
*/
public static int getLastBreakIndex(String s) {
int spaceIndex = 0;
- char[] breakCharacters = new char[]{' ', '\t', '.', ','};
for (int i = 0; i < breakCharacters.length; i++) {
int tmpIndex = s.lastIndexOf(breakCharacters[i]);
if (tmpIndex > 0 && tmpIndex > spaceIndex) {
|
|
From: SVN by r. <sv...@ca...> - 2008-07-23 20:57:23
|
Author: roy
Date: 2008-07-23 22:57:12 +0200 (Wed, 23 Jul 2008)
New Revision: 268
Modified:
src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
Log:
fix error in read.. not reading first row everytime
Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java
===================================================================
--- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-23 10:25:10 UTC (rev 267)
+++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-23 20:57:12 UTC (rev 268)
@@ -1434,7 +1434,7 @@
PreparedStatement pstmt = c.prepareStatement(query);
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
for (int nodeNr = 0; nodeNr < nodeList.getLength(); nodeNr++) {
- Element row = (Element) nodeList.item(0); // row
+ Element row = (Element) nodeList.item(nodeNr); // row
NodeList columns = row.getElementsByTagName("col");
for (int colNr = 0; colNr < columns.getLength(); colNr++) {
Element column = (Element) columns.item(colNr);
@@ -1447,6 +1447,7 @@
pstmt.setDate(colNr+1, new Date(formatter.parse(nodeValue).getTime()));
}
} else {
+ //debug(nodeNr +" ? "+column.getTextContent());
pstmt.setString(colNr+1, column.getTextContent());
}
}
|
|
From: SVN by r. <sv...@ca...> - 2008-07-23 10:25:20
|
Author: roy Date: 2008-07-23 12:25:10 +0200 (Wed, 23 Jul 2008) New Revision: 267 Modified: ChangeLog Log: mention changes Modified: ChangeLog =================================================================== --- ChangeLog 2008-07-23 09:50:14 UTC (rev 266) +++ ChangeLog 2008-07-23 10:25:10 UTC (rev 267) @@ -4,6 +4,8 @@ * Added tab completion for connect @ * Fix tabcompletion when using LIKE comparisons * Fix for index out of bounds for strings without spaces + * Fix for quit on some systems (hardy heron for example) + * Added dump/read command to dump (a part of) a table 0.5 (2008-03-14) * Allow for commands to start in the background, this will allow to continue |
|
From: SVN by r. <sv...@ca...> - 2008-07-23 09:50:24
|
Author: roy Date: 2008-07-23 11:50:14 +0200 (Wed, 23 Jul 2008) New Revision: 266 Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java Log: added dump/read command implementation.. not final yet though! Modified: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java =================================================================== --- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-23 07:24:09 UTC (rev 265) +++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-23 09:50:14 UTC (rev 266) @@ -17,8 +17,14 @@ import java.io.*; import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.ArrayList; import java.util.Iterator; @@ -28,7 +34,13 @@ import java.util.LinkedHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import nl.improved.sqlclient.commands.*; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * The SQLShell main class. @@ -130,6 +142,8 @@ commands.register("HELP[\\s]*.*", new HelpCommand()); commands.register("HISTORY[\\s]*.*", new HistoryCommand()); commands.register("SPOOL[\\s]*.*", new SpoolCommand()); + commands.register("DUMP[\\s]*.*[A-Z]+.*", new DumpCommand()); + commands.register("READ[\\s]*.*[A-Z]+.*", new ReadCommand()); commands.register("QUIT[\\s]*", new QuitCommand("quit")); commands.register("EXIT[\\s]*", new QuitCommand("exit")); //commands.register("\\\\Q[\\s]*", new QuitCommand("\\q")); @@ -1273,7 +1287,210 @@ return false; } } + /** + * Writes the result of a query into a dump file so that it can be read back. + */ + private class DumpCommand implements Command { + private String fileName; + private FileWriter dumpWriter; + @Override + public CharSequence execute(SQLCommand cmd) { + String command = cmd.getCommandString(); + String nextPart = command.substring("dump".length()).trim(); + String dumpFileName; + if (nextPart.indexOf(' ') > 0) { + dumpFileName = nextPart.substring(0, nextPart.indexOf(' ')); + } else { + dumpFileName = nextPart; + } + try { + File f = new File(toFileName(dumpFileName +".dmp")); + fileName = f.getAbsolutePath(); + if ((f.exists() && !f.canWrite()) || (!f.exists() && !f.createNewFile())) { + throw new IllegalStateException("Failed to create spool to file: '"+fileName+"'"); + } + dumpWriter = new FileWriter(fileName); + dumpWriter.write("<dump tablename=\"" + dumpFileName+"\">\n"); + String query = "select * from " + nextPart; + Connection c = DBConnector.getInstance().getConnection(); + Statement stmt = c.createStatement(); + ResultSet rs = stmt.executeQuery(query); + SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); + while (rs.next()) { + dumpWriter.write(" <row>\n"); + ResultSetMetaData metaData = rs.getMetaData(); + for (int col = 1; col <= metaData.getColumnCount(); col++) { + dumpWriter.write(" <col name=\""+metaData.getColumnName(col)+"\""); + if (metaData.getColumnType(col) == Types.DATE) { + dumpWriter.write(" type=\"date\">"); + Date date = rs.getDate(col); + if (date != null) { + dumpWriter.write(formatter.format(date)); + } + } else { + dumpWriter.write(">"); + if (rs.getString(col) != null) { + dumpWriter.write(rs.getString(col)); // TODO fix xml + } + } + dumpWriter.write("</col>\n"); + } + dumpWriter.write(" </row>\n"); + } + dumpWriter.write("</dump>"); + } catch (SQLException e) { + throw new IllegalStateException("Failed to execute query for dump("+fileName+"): " + e.toString(), e); + } catch (IOException e) { + throw new IllegalStateException("Failed to create dump ("+fileName+"): " + e.toString(), e); + } finally { + try { + dumpWriter.close(); + } catch (IOException ex) { + Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + } + } + return "Dump to "+fileName+" done."; + } + + @Override + public CharSequence getCommandString() { + return "dump"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; + } + @Override + public CharSequence getHelp() { + return "tablename [where clause]"; + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + /** + * Read the result of a dump file. + */ + private class ReadCommand implements Command { + private String fileName; + + @Override + public CharSequence execute(SQLCommand cmd) { + String command = cmd.getCommandString(); + String nextPart = command.substring("read".length()).trim(); + String dumpFileName; + if (nextPart.indexOf(' ') > 0) { + dumpFileName = nextPart.substring(0, nextPart.indexOf(' ')); + } else { + dumpFileName = nextPart; + } + try { + File f = new File(toFileName(dumpFileName +".dmp")); + fileName = f.getAbsolutePath(); + if (!f.exists() && !f.canRead()) { + throw new IllegalStateException("Failed to read dump file: '"+fileName+"'"); + } + // Step 1: create a DocumentBuilderFactory + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + // Step 2: create a DocumentBuilder + DocumentBuilder db = dbf.newDocumentBuilder(); + + // Step 3: parse the input file to get a Document object + Document doc = db.parse(new File(fileName)); + + Element documentElement = doc.getDocumentElement(); + String tableName = documentElement.getAttribute("tablename"); + NodeList nodeList = documentElement.getElementsByTagName("row"); + + String query = "insert into " + tableName +" ("; + String values = ") values ("; + Element n = (Element) nodeList.item(0); // row + NodeList cols = n.getElementsByTagName("col"); + output("LENGTH : "+ n.getNodeName() +"/ "+ cols.getLength()); + for (int colNr = 0; colNr < cols.getLength(); colNr++) { + query += cols.item(colNr).getAttributes().getNamedItem("name").getNodeValue(); + values += "?"; + if (colNr +1 < cols.getLength()) { + query +=", "; + values +=", "; + } + } + query = query + values +")"; + Connection c = DBConnector.getInstance().getConnection(); + PreparedStatement pstmt = c.prepareStatement(query); + SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); + for (int nodeNr = 0; nodeNr < nodeList.getLength(); nodeNr++) { + Element row = (Element) nodeList.item(0); // row + NodeList columns = row.getElementsByTagName("col"); + for (int colNr = 0; colNr < columns.getLength(); colNr++) { + Element column = (Element) columns.item(colNr); + Node type = column.getAttributes().getNamedItem("type"); + if (type != null && type.getNodeValue().equals("date")) { + String nodeValue = column.getTextContent(); + if (nodeValue == null || nodeValue.equals("")) { + pstmt.setDate(colNr+1, null); + } else { + pstmt.setDate(colNr+1, new Date(formatter.parse(nodeValue).getTime())); + } + } else { + pstmt.setString(colNr+1, column.getTextContent()); + } + } + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new IllegalStateException("Failed to execute update query for dump("+fileName+"): " + e.toString(), e); + } catch (IOException e) { + throw new IllegalStateException("Failed to read dump ("+fileName+"): " + e.toString(), e); + } catch (Exception e) { + throw new IllegalStateException("Failed to read dump ("+fileName+"): " + e.toString(), e); + } + return "Read from "+fileName+" done."; + } + + @Override + public CharSequence getCommandString() { + return "read"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; // TODO + } + @Override + public CharSequence getHelp() { + return "filename: read dump file from filename\n"; + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + private class ExecuteBatchCommand implements Command { private boolean cancelled; private Command currentCommand; |
|
From: SVN by r. <sv...@ca...> - 2008-07-23 07:24:21
|
Author: roy Date: 2008-07-23 09:24:09 +0200 (Wed, 23 Jul 2008) New Revision: 265 Added: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java src/main/java/nl/improved/sqlclient/InputKey.java src/main/java/nl/improved/sqlclient/jcurses/ src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java Log: abstraction layer in sqlshell window structure fixed 'quit' on hardy Added: src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java =================================================================== --- src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-16 21:03:05 UTC (rev 264) +++ src/main/java/nl/improved/sqlclient/AbstractSQLShellWindow.java 2008-07-23 07:24:09 UTC (rev 265) @@ -0,0 +1,1501 @@ +/* + * Copyright 2007 Roy van der Kuil (ro...@va...) and Stefan Rotman (st...@ro...) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package nl.improved.sqlclient; + +import java.io.*; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import nl.improved.sqlclient.commands.*; + +/** + * The SQLShell main class. + * This class provides a (textbased) window for entering sql commands. + */ +public abstract class AbstractSQLShellWindow { + + /** + * The current command thread executing a SQLShell command. + */ + private CommandThread commandThread; + /** + * True when the prompt should be visible. + * Normally it is not visible during the execution of a command + */ + protected boolean showPrompt = true; + + /** + * The (default) maximum matches to show in a selection dialog. + */ + protected static final int MAX_MATCH_SIZE = 15; + protected int MAX_LINE_LENGTH; // not static and final.. since it can change on window resize + + /** + * Page up count 0 means were at the bottom of our screen. + * Increasement of the pageup count moves the visible part of the screen up. + */ + protected int pageUpCount = 0; + /** + * All lines in a screen. + */ + protected List<CharSequence> screenBuffer = new LimitedArrayList<CharSequence>(1000); + /** + * The current command lines. + */ + protected SQLCommand commandLines; + /** + * All commands in history. + */ + private List<SQLCommand> commandHistory = new LimitedArrayList<SQLCommand>(50); + /** + * Index for browsing commands. + */ + protected int commandIndex = 0; + /** + * An empty line for easy line completion (fill with spaces). + */ + protected String emptyLine; + /** + * The cursor position in the command lines list. + * 0,0 means it is at the first line at the first character + * 10,5 means it is at the 11th character at the 6th line + */ + protected Point cursorPosition = new Point(0,0); + /** + * The prompt to show when entering sql commands. + */ + protected static final String PROMPT = "SQL"; + /** + * Some debug info holding the last trace of an exception. + */ + private String lastExceptionDetails; + + /** + * The output file when spool is on. + */ + private Writer spoolWriter; + /** + * A manager for available commands. + */ + protected CommandManager commands = new CommandManager(); + + /** + * A map of string key representation to a action that should be executed when a specific key is pressed. + */ + private Map<String, KeyAction> actionKeys = new LinkedHashMap<String, KeyAction>(); + private Map<InputKey.SpecialKey, KeyAction> specialActionKeys = new LinkedHashMap<InputKey.SpecialKey, KeyAction>(); + private boolean paint = true; + + /** + * Constructor. + */ + public AbstractSQLShellWindow() { + char[] emptyLineChar = new char[getScreenWidth()]; + Arrays.fill(emptyLineChar, ' '); + emptyLine = new String(emptyLineChar); + + // initialize the command shell + commandLines = new SQLCommand(); + commandHistory.add(commandLines); + newLine(); + + // Register all known commands + commands.register("CONNECT[\\s]*.*", new ConnectCommand()); + commands.register("DISCONNECT[\\s]*", new DisConnectCommand()); + commands.register("SHOW[\\s]+[A-Z]+(|[A-Z]|_|\\.)*(|[\\s]+HAVING[\\s][A-Z]*.*)", new ShowCommand()); + commands.register("DESC[\\s]+[A-Z]+(|[0-9]|[A-Z]|_|-|\\.)*", new DescCommand()); + commands.register("INFO[\\s]*", new InfoCommand()); + commands.register("HELP[\\s]*.*", new HelpCommand()); + commands.register("HISTORY[\\s]*.*", new HistoryCommand()); + commands.register("SPOOL[\\s]*.*", new SpoolCommand()); + commands.register("QUIT[\\s]*", new QuitCommand("quit")); + commands.register("EXIT[\\s]*", new QuitCommand("exit")); + //commands.register("\\\\Q[\\s]*", new QuitCommand("\\q")); + commands.register("@.*", new ExecuteBatchCommand()); + commands.register("(SELECT|UPDATE|ALTER|INSERT|DELETE).*;[\\s]*", new QueryCommand()); + + // keys + specialActionKeys.put(InputKey.SpecialKey.LEFT, new KeyAction() { + public void execute() { + if (cursorPosition.x > 0) { + cursorPosition.x--; + } else if (cursorPosition.y > 0) { + cursorPosition.y--; + cursorPosition.x = commandLines.getLines().get(cursorPosition.y).length(); + } + } + public CharSequence getHelp() { + return "Arrow Left:\tMove cursor to the left"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.RIGHT, new KeyAction() { + public void execute() { + CharSequence tmp = commandLines.getLines().get(cursorPosition.y); + if (cursorPosition.x < tmp.length()) { + cursorPosition.x++; + } else if (cursorPosition.y < commandLines.getLines().size()-1) { + cursorPosition.x = 0; + cursorPosition.y++; + } + } + public CharSequence getHelp() { + return "Arrow Right:\tMove cursor to the right"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.UP, new KeyAction() { + public void execute() { + if (commandIndex > 0) { + commandLines = commandHistory.get(--commandIndex); + cursorPosition.y = commandLines.getLines().size()-1; + CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y); + cursorPosition.x = lineBuffer.length(); + } + } + public CharSequence getHelp() { + return "Arrow Up:\tBrowse to previous command in the history"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.DOWN, new KeyAction() { + public void execute() { + if (commandIndex < commandHistory.size()-1) { + commandLines = commandHistory.get(++commandIndex); + cursorPosition.y = commandLines.getLines().size()-1; + CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y); + cursorPosition.x = lineBuffer.length(); + } + } + public CharSequence getHelp() { + return "Arrow Down:\tBrowse to next command in the history"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.END,new KeyAction() { + public void execute() { + int curLineEnd = commandLines.getLines().get(cursorPosition.y).length(); + if (cursorPosition.x == curLineEnd) { + cursorPosition.y = commandLines.getLines().size()-1; + CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y); + cursorPosition.x = lineBuffer.length(); + } else { + cursorPosition.x = curLineEnd; + } + } + public CharSequence getHelp() { + return "End:\tMove the cursor to the end of the line, of if already there to the end of the command"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.HOME, new KeyAction() { + public void execute() { + if (cursorPosition.x == 0) { + cursorPosition.y = 0; + } + cursorPosition.x = 0; + } + public CharSequence getHelp() { + return "Home:\tMove the cursor to the start of the line, of if already there to the start of the command"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.BACKSPACE, new KeyAction() { + public void execute() { + if (cursorPosition.x == 0) { + if (cursorPosition.y > 0) { + joinLine(); + } + } else { + StringBuilder tmp = getEditableCommand().getEditableLines().get(cursorPosition.y); + if (cursorPosition.x > 0) { + tmp.deleteCharAt(cursorPosition.x-1); + cursorPosition.x--; + } + } + } + public CharSequence getHelp() { + return "Backspace:\tRemove the character before the cursor position"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.DELETE, new KeyAction() { + public void execute() { + StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); + if (cursorPosition.x < lineBuffer.length()) { + StringBuilder tmp = getEditableCommand().getEditableLines().get(cursorPosition.y); + tmp.deleteCharAt(cursorPosition.x); + } + } + public CharSequence getHelp() { + return "Del:\tDelete the charactor at the current cursor position"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.PAGE_UP, new KeyAction() { + @Override + public void execute() { + if ((screenBuffer.size() + commandLines.getLines().size() + - (getScreenHeight()/2) * pageUpCount) > 0) { + pageUpCount++; + + } + } + public CharSequence getHelp() { + return "PageUp:\tMove back in screen history"; + } + }); + specialActionKeys.put(InputKey.SpecialKey.PAGE_DOWN, new KeyAction() { + @Override + public void execute() { + if (pageUpCount > 0) { + pageUpCount--; + } + } + public CharSequence getHelp() { + return "PageDown:\tMove forward in screen history"; + } + }); + actionKeys.put("", new KeyAction() { + public void execute() { // ctrl+w + if (cursorPosition.x == 0) { + if (cursorPosition.y > 0) { + joinLine(); + } + return; + } + StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); + int previousBreak = SQLUtil.getLastBreakIndex(lineBuffer.substring(0, cursorPosition.x-1)); + if (lineBuffer.charAt(previousBreak) == ' ' || lineBuffer.charAt(previousBreak) == '\t') { + previousBreak++; + } + lineBuffer.delete(previousBreak, cursorPosition.x); + cursorPosition.x = previousBreak; + } + public CharSequence getHelp() { + return "Control-W:\tRemove word before cursor position"; + } + }); + actionKeys.put("", new KeyAction() { // ctrl+u + public void execute() { + if (cursorPosition.x > 0) { + StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); + lineBuffer.delete(0, cursorPosition.x); + cursorPosition.x = 0; + } else if (cursorPosition.y > 0) { + StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); + if (lineBuffer.length() == 0) { + commandLines.getEditableLines().remove(cursorPosition.y); + } + cursorPosition.y--; + lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); + lineBuffer.delete(0, lineBuffer.length()); + } + } + public CharSequence getHelp() { + return "Control-U:\tRemove all characters before the cursor position"; + } + }); + actionKeys.put("", new KeyAction() { // ctrl+a + @Override + public void execute() { + output("Abort requested"); + if (commandThread.isAlive() && commandThread.getCommand().abort()) { + output("Abort done.."); + } + } + @Override + public CharSequence getHelp() { + return "Control-A:\tAbort current command (if it is supported by that command)"; + } + }); + actionKeys.put("", new KeyAction() { //Ctrl+D + @Override + public void execute() { + if (commandLines.getCommandString().length() == 0) { //Quit on empty commandline, ignore otherwise + executeCommand(new InputCommand("quit")); + } + } + @Override + public CharSequence getHelp() { + return "Control-D:\tExit sqlshell"; + } + }); + + MAX_LINE_LENGTH = getScreenWidth()-(PROMPT.length()+2+1); // prompt + "> " + + output("Welcome to the SQLShell client."); + output("Type 'help' to get a list of available commands other then the default sql input."); + } + + + public abstract int getScreenWidth(); + public abstract int getScreenHeight(); + private void repaint() { + if (paint) { + paint(); + } + } + public abstract void paint(); + public abstract void beep(); + public abstract void debug(String debug); + public abstract String select(List<String> items); + /** + * Returns the connection to the database + * @return the connection to the database + */ + public Connection getConnection() { + return DBConnector.getInstance().getConnection(); + } + + public void close() { + debug("CLOSE HERE"); + System.out.println("CLOSE HERE"); + if (spoolWriter != null) { + try { + spoolWriter.close(); + spoolWriter = null; + } catch(Exception e) {/*ignore*/} + } + } + + + /** + * Returns a string representation of the current command. + * @return a string representation of the current command. + */ + protected SQLCommand getCommand() { + return commandLines; + } + + /** + * Add a new line to the command lines buffer. + */ + private StringBuilder newLine() { + cursorPosition.x = 0; + StringBuilder newLine = new StringBuilder(); + getEditableCommand().getEditableLines().add(newLine); + cursorPosition.y = commandLines.getLines().size()-1; + return newLine; + } + + /** + * Handle key input. + * @param inp the character that is being pressed by the user. + */ + protected void handleInput(InputKey inp) { + try { + if (inp.isSpecialKey() && inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_UP && inp.getSpecialKeyValue() != InputKey.SpecialKey.PAGE_DOWN) { + pageUpCount = 0; // some character entered, so reset pageup count + } + if (inp.isSpecialKey()) { + KeyAction ke = specialActionKeys.get(inp.getSpecialKeyValue());// || inp.toString().equals("") || inp.toString().equals("")) { + if (ke != null) { + ke.execute(); + } else { + debug("Unknown character: "+ inp.getCharacter()); + } + } else { + KeyAction ke = actionKeys.get(Character.toString(inp.getCharacter())); + if (ke != null) { + ke.execute(); + } else { + if (inp.getCharacter() == '\n') { // newline... see if the command can be executed + // execute the command + SQLCommand sqlCommand = getCommand(); + String command = sqlCommand.getCommandString(); + // search command... + if (command.length() > 0 && command.charAt(0) == '/') { // search in history + String matchPattern=".*"+command.substring(1,command.length())+".*"; + for (int cIndex = commandHistory.size()-1; cIndex >=0; cIndex--) { + if (cIndex == commandIndex) { + continue; // skip current command + } + SQLCommand newSqlCommand = commandHistory.get(cIndex); + String commandString = newSqlCommand.getCommandString(); + if (commandString.matches(matchPattern)) { + commandHistory.remove(commandIndex); + commandIndex = commandHistory.indexOf(newSqlCommand); + commandLines = newSqlCommand; + cursorPosition.y = 0; + cursorPosition.x = 0; + repaint(); // force repaint + return; + } + } + beep(); // TODO clear search?? + return; + /*} else if (sqlCommand.getCommandString().equalsIgnoreCase("exit")) { + close(); + return;*/ + } else if (executeCommand(sqlCommand)) { + // clear command history + if (commandIndex != commandHistory.size()-1) { + SQLCommand tmpLines = commandLines; + commandLines = commandHistory.get(commandHistory.size()-1); + if (commandLines.getCommandString().equals("")) { + commandHistory.add(commandHistory.size()-1, tmpLines); + } else { + commandHistory.add(tmpLines); + commandLines = tmpLines; + } + } + if (!commandLines.getCommandString().equals("")) { + commandLines = new SQLCommand(); + commandHistory.add(commandLines); + newLine(); + } + commandIndex = commandHistory.size()-1; + cursorPosition.y = commandLines.getLines().size()-1; + cursorPosition.x = commandLines.getLines().get(cursorPosition.y).length(); + repaint(); // force repaint + return; + } + } + CharSequence newText; + if (inp.getCharacter() == '\t') { + try { + newText = getTabCompletion(commandLines, cursorPosition); + } catch(IllegalStateException e) { + output(getCommand().getCommandString()); // add command as well... + error(e); + return; + } + } else { + newText = Character.toString(inp.getCharacter()); + } + if (newText.equals("\n")) { + newLine(); // TODO Fix return in middle of an other line + } else { + List<StringBuilder> editableLines = getEditableCommand().getEditableLines(); + StringBuilder currentLine = editableLines.get(cursorPosition.y); + currentLine.insert(cursorPosition.x, newText); + cursorPosition.x += newText.length(); + // check if the new line is becoming too long + if (currentLine.length() > MAX_LINE_LENGTH) { + // TODO search for lastspace that is not between '' ?? + int lastSpace = SQLUtil.getLastBreakIndex(currentLine.toString());//currentLine.lastIndexOf(" "); + if (lastSpace == -1) { + lastSpace = currentLine.length(); + } + // check if there are enough 'next' lines + // if not.. add one + if (editableLines.size()-1 == cursorPosition.y) { + StringBuilder newLine = new StringBuilder(); + editableLines.add(newLine); + } + // check if the nextline has enough room for the new word + // if not.. add a new line + if (editableLines.get(cursorPosition.y+1).length() + + (currentLine.length()-lastSpace+1) > MAX_LINE_LENGTH) { + StringBuilder newLine = new StringBuilder(); + editableLines.add(cursorPosition.y+1, newLine); + } + // fetch the next line + StringBuilder nextLine = editableLines.get(cursorPosition.y+1); + // if the nextline already has some text.. add a space in front of it + if (nextLine.length() > 0) { + nextLine.insert(0, ' '); + } + // insert the new text at the beginning + nextLine.insert(0, currentLine.subSequence(lastSpace+1, currentLine.length())); + currentLine.delete(lastSpace, currentLine.length()); + // check if the cursor postition > the new line length + // calculate new x and go to nextline + if (cursorPosition.x >= lastSpace) { + cursorPosition.x = cursorPosition.x - (lastSpace+1); + cursorPosition.y++; + } + } + } + } + } + } catch(Throwable t) { + error(t); + } + repaint(); + } + + /** + * Return the editable version of the commandlines. + * If editing a previous command clone it and return the clone + * @return the editable version of the commandlines. + */ + protected SQLCommand getEditableCommand() { + if (commandHistory.indexOf(commandLines) != commandHistory.size()-1) { + List<? extends CharSequence> tmp = commandLines.getLines(); + if (commandHistory.get(commandHistory.size()-1).getLines().size() == 1 + && commandHistory.get(commandHistory.size()-1).getLines().get(0).length() == 0) { + commandLines = commandHistory.get(commandHistory.size()-1); + commandLines.getEditableLines().remove(0); + } else { + commandLines = new SQLCommand(); + commandHistory.add(commandLines); + } + for (int i = 0; i < tmp.size(); i++) { + commandLines.getEditableLines().add(new StringBuilder(tmp.get(i))); + } + commandIndex = commandHistory.size()-1; + } + return commandLines; + } + + /** + * Output data to the screen. + * @param data the data to print to the screen. + */ + protected synchronized void output(CharSequence data) { + screenBuffer.addAll(getLines(data)); + if (spoolWriter != null) { + try { + spoolWriter.write(data.toString()); + spoolWriter.write("\n"); + } catch(IOException e) { + screenBuffer.add("WARNING: Could not write to spool file"); + error(e); + } + } + } + + /** + * Output error exception to the screen. + * @param e the error to print to the screen + */ + protected synchronized void error(Throwable e) { + output(e.getMessage() == null ? e.toString() : e.getMessage()); + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + sw.flush(); + lastExceptionDetails = sw.toString(); + //output(sw.toString()); + } + + /** + * Return a list of table names available for the current connection. + * @return a list of table names available for the current connection. + */ + protected List<String> getTableNames() { + List<String> returnValue = new ArrayList<String>(); + try { + ResultSet rs = getConnection().getMetaData().getTables(getConnection().getCatalog(), DBConnector.getInstance().getSchema(), null, new String[]{"TABLE"}); + while (rs.next()) { + if (!returnValue.contains(rs.getString("TABLE_NAME"))) { + returnValue.add(rs.getString("TABLE_NAME")); + } + } + return returnValue; + } catch (SQLException ex) { + ex.printStackTrace(); + Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } + + /** + * Return a list of column names for the specified list of table names. + * @param tableNames a list of tableNames + * @return a list of column names for the specified list of table names. + */ + protected List<String> getColumnNames(List<String> tableNames) { + List<String> returnValues = new ArrayList<String>(); + Iterator<String> iTableNames = tableNames.iterator(); + while (iTableNames.hasNext()) { + String tableName = DBConnector.getInstance().translateDbVar(iTableNames.next().trim()); + try { + ResultSet rs = getConnection().getMetaData().getColumns(getConnection().getCatalog(), DBConnector.getInstance().getSchema(), tableName, "%"); + while (rs.next()) { + if (!returnValues.contains(rs.getString("COLUMN_NAME"))) { + returnValues.add(rs.getString("COLUMN_NAME")); + } + } + } catch (SQLException ex) { + throw new IllegalStateException("Failed to find columnnames for table: "+ tableName, ex); + } + } + return returnValues; + } + + /** + * Try to find a match in the provided list starging with sub. + * If more matches apply show the user a dialog to choose a match or simply display all matches in the window + * @param values all possible values to choose from (not limited with the sub parameter) + * @param sub the start of the match + * @return the match starting with sub minus the sub itself in the correct casing + */ + protected CharSequence findMatch(List<String> values, String sub) { + List<String> matches = new ArrayList<String>(); + Iterator<String> iValues = values.iterator(); + while (iValues.hasNext()) { + String value = iValues.next(); + if (value.toUpperCase().startsWith(sub.toUpperCase())) { + matches.add(value); + } + } + debug("Matches found: "+ matches.size() +" --> "+ sub +" / "+ values); + String match = null; + if (matches.size() == 1) { + match = matches.get(0); + } else if (matches.size() > 1 && matches.size() < MAX_MATCH_SIZE) { + match = select(matches); + } else if (matches.size() > 1) { + output("\n"+toColumns(matches)); + } + if (match != null) { + if (sub.length() > 0) { + /*if (Character.isUpperCase(sub.charAt(0))) { + match = match.toUpperCase(); + } else { + match = match.toLowerCase(); + }*/ + match = DBConnector.getInstance().translateDbVar(match); + } + return match.substring(sub.length()); + } + return null; + } + + /** + * Simple method to change a null value to an empty charsequence. + * @param s the charsequence to convert to empty if it is null + * @return empty when s was null or return s when s is not null + */ + protected CharSequence nullToEmpty(CharSequence s) { + if (s == null) { + return ""; + } + return s; + } + /** + * return the tab completion value. + * @param commandLines the current command + * @param cursorPosition the position where the tab completion was invocated + * @return the tab completion value. + */ + protected CharSequence getTabCompletion(SQLCommand commandLines, Point cursorPosition) { + TabCompletionInfo info = null; + String cmd = commandLines.getCommandString(); + if (cmd.length() > 0) { + if (cmd.indexOf(' ') > 0) { + cmd = cmd.substring(0, cmd.indexOf(' ')).trim(); + } + Command tmpCommand = commands.findCommand(cmd); + if (tmpCommand == null) { + for (Command c : commands.getCommands()) { + if (cmd.equalsIgnoreCase(c.getCommandString().toString())) { + tmpCommand = c; + break; + } + } + } + if (tmpCommand != null) { + info = tmpCommand.getTabCompletionInfo(commandLines, cursorPosition); + } + } + if (info == null) { + info = SQLUtil.getTabCompletionInfo(commandLines, cursorPosition); + } + if (info.getMatchType() == TabCompletionInfo.MatchType.SQL_KEYWORD) { + return nullToEmpty(findMatch(info.getPossibleMatches(), info.getStart())); + } + if (info.getMatchType() == TabCompletionInfo.MatchType.TABLE_NAMES) { + debug("table completion for \""+info.getStart()+"\""); + return nullToEmpty(findMatch(getTableNames(), info.getStart())); + } + if (info.getMatchType() == TabCompletionInfo.MatchType.COLUMN_NAMES) { + return nullToEmpty(findMatch(getColumnNames(info.getPossibleMatches()), info.getStart())); + } + if (info.getMatchType() == TabCompletionInfo.MatchType.OTHER) { + return nullToEmpty(findMatch(info.getPossibleMatches(), info.getStart())); + } + return ""; + } + + /** + * (Try) to execute a command) and return true if it succeeded. + * @param command the command to try and execute + * @return true if it succeeded. + */ + protected boolean executeCommand(SQLCommand sqlCommand) { + return executeCommand(sqlCommand, false); + } + + private boolean executeCommand(final SQLCommand sqlCommand, boolean direct) { + final String commandString = sqlCommand.getCommandString(); + if (commandString.equalsIgnoreCase("printStackTrace")) { + if (lastExceptionDetails == null) { + output("No known last exception to print"); + } else { + output(lastExceptionDetails); + } + return true; + } + Command command = createCommand(commandString); // first try to find a match without ; + if (command == null) { + command = createCommand(sqlCommand.getUntrimmedCommandString()); // then with ; for sql statements... + } + if (command == null) { + return false; + } + // make sure only one command is run at once + if (commandThread != null && commandThread.isAlive()) { + try { + commandThread.join(); + } catch (InterruptedException ex) { + Logger.getLogger(AbstractSQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + } + } + output(commandString); + if (direct || !command.backgroundProcessSupported()) { + output(command.execute(sqlCommand)); + } else { + commandThread = new CommandThread(command) { + @Override + void execute() { + output(getCommand().execute(sqlCommand)); + } + }; + commandThread.start(); + } + return true; + } + private Command createCommand(String commandString) { + Command command = commands.findCommand(commandString); + if (command != null) { + return command; + } + if (commandString.matches(".*;[\\s]*")) { + return new QueryCommand(); // TODO is this ever reached??? + } + return null; + } + + + + /** + * Method to convert a long string to a displayable list of strings with a max with of the screen width. + * @param text a (long) string + * @return the text devided into multiple lines to match the screen width + */ + private List<CharSequence> getLines(CharSequence text) { + int maxWidth = getScreenWidth(); + List<CharSequence> list = new ArrayList<CharSequence>(); + StringBuilder buffer = new StringBuilder(); + for (int i=0; i<text.length(); i++) { + char c = text.charAt(i); + if (c=='\n' || buffer.length() == maxWidth) { + String line = buffer.toString(); + list.add(line); + buffer = new StringBuilder(); + if (c != '\n') { + buffer.append(c); + } + } else if (c == '\r') { + //ignore + } else { + buffer.append(c); + } + } + if (buffer.length() > 0) { + list.add(buffer.toString()); + } + return list; + } + + /** + * Convert a list to a presentable text devided into multiple columns. + */ + private StringBuilder toColumns(List<? extends CharSequence> values) { + int maxWidth = 0; + Iterator<? extends CharSequence> iValues = values.iterator(); + while (iValues.hasNext()) { + maxWidth = Math.max(maxWidth, iValues.next().length()); + } + maxWidth+=2;// add extra space + int nrOfColumns = (getScreenWidth()) / maxWidth; + StringBuilder returnValue = new StringBuilder(); + for (int row = 0; row < values.size(); row+=nrOfColumns) { + for (int col = 0; col < nrOfColumns && row + col < values.size(); col++) { + returnValue.append(values.get(row+col) + emptyLine.substring(0, maxWidth - values.get(row+col).length())); + } + returnValue.append('\n'); + } + return returnValue; + } + + /** + * A list which contains a limited number of lines. + */ + private class LimitedArrayList<E> extends ArrayList<E> { + private int maxSize; + /** + * Constructor. + * @param maxSize the maximum number of lines the list may contain + */ + public LimitedArrayList(int maxSize) { + super(maxSize); // some sane default + this.maxSize = maxSize; + } + + @Override + public boolean add(E object) { + if (size() == maxSize) { + remove(0); + } + return super.add(object); + } + @Override + public void add(int index, E object) { + if (size() == maxSize) { + remove(0); + } + super.add(index, object); + } + } + + /** + * Connect command for setting up a connection to a database. + */ + private static class ConnectCommand implements Command { + /** + * Execute the connection command and return a readable result. + * @param command the command string for setting up a connection + * @return a readable result of the execution of this command. + */ + @Override + public CharSequence execute(SQLCommand cmd) { + String command = cmd.getCommandString(); + try { + String cmdString = command.substring("connect".length()).trim(); + if (cmdString.length() > 0 && cmdString.charAt(cmdString.length()-1) == ';') { + cmdString = cmdString.substring(0, cmdString.length()-1); + } + DBConnector.getInstance().connect(cmdString); + return "Connected.\n\n"; + } catch(SQLException e) { + throw new IllegalStateException("Failed to connect: " + e.getMessage(), e); + } + } + @Override + public CharSequence getCommandString() { + return "connect"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + List commandInfo = command.getLines(); + + String startOfCommand = SQLUtil.getStartOfCommand(commandInfo, commandPoint); + if (startOfCommand.indexOf('@') >= 0) { + String end = startOfCommand.substring(startOfCommand.lastIndexOf('@')+1); + List<String> identifiers = new ArrayList<String>(DBConnector.getInstance().getPredefinedConnectionIdentifiers()); + Collections.sort(identifiers); + return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER, identifiers, end); + } + return null; + } + + @Override + public CharSequence getHelp() { + StringBuffer buf = new StringBuffer(); + Iterator<String> idents = DBConnector.getInstance().getPredefinedConnectionIdentifiers().iterator(); + while (idents.hasNext()) { + buf.append(' '); + String ident = idents.next(); + buf.append(ident); + if (ident.equals(DBConnector.getInstance().getDefaultIdentifier())) { + buf.append(" *"); + } + if (idents.hasNext()) { + buf.append('\n'); + } + } + return "Create a conection to the database\n" + + " user/pass@ident -> connect the user with password pass to the ident\n" + + " user/@ident -> connect the user with an empty password pass to the ident\n"+ + " user@ident -> connect the user to the ident and prompt for password\n"+ + " @ident -> connect to the ident connection.\n"+ + " If default user and/or password are specified these will be used, \n"+ + " otherwise you will be prompted for a username and/or password.\n" + + "Currently configured connection identifiers:\n"+ + buf.toString(); + } + + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + /** + * Command that enables the user to close a connection. + */ + private static class DisConnectCommand implements Command { + @Override + public CharSequence execute(SQLCommand cmd) { + try { + DBConnector.getInstance().disconnect(); + return "Disconnected.\n\n"; + } catch(SQLException e) { + throw new IllegalStateException("Failed to disconnect: " + e.getMessage(), e); + } + } + @Override + public CharSequence getCommandString() { + return "disconnect"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; + } + @Override + public CharSequence getHelp() { + return "Close the current conection to the database"; + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + + /** + * Provide a list of commands executed. + */ + private class HistoryCommand implements Command { + @Override + public CharSequence execute(SQLCommand command) { + StringBuilder returnValue = new StringBuilder(); + Iterator<SQLCommand> iCommands = commandHistory.iterator(); + while (iCommands.hasNext()) { + SQLCommand cmd = iCommands.next(); + returnValue.append(cmd.getCommandString()); + returnValue.append('\n'); + } + return returnValue; + } + @Override + public CharSequence getCommandString() { + return "history"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; + } + @Override + public CharSequence getHelp() { + return "Show history of executed statements\n" + + "By using '/<search>' you can search the command history" ; + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + + /** + * Exit the client. + */ + private class QuitCommand implements Command { + private String cmd; + + public QuitCommand(String cmd) { + this.cmd = cmd; + } + @Override + public CharSequence execute(SQLCommand command) { + paint = false; + close(); + return "Application terminated."; + } + @Override + public CharSequence getHelp() { + return "Quit(exit) the application."; + } + @Override + public CharSequence getCommandString() { + return cmd; + } + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + /** + * Provide help to the user. + */ + private class HelpCommand implements Command { + @Override + public CharSequence execute(SQLCommand sqlCommand) { + // the execution of help consists of: + // 1. is general help.. + // 2. is detailed help about a specific command + // 3. help -k something --> search help for a specific keyword + String command = sqlCommand.getCommandString().trim(); + String cmdString = command.substring("help".length()).trim(); + if (cmdString.endsWith(";")) { + cmdString = cmdString.substring(0, cmdString.length()-1); + } + List<CharSequence> availableCommands = new ArrayList<CharSequence>(); + if (cmdString.length() > 0) { + if (cmdString.startsWith("-k")) { + String keyword = cmdString.subSequence(cmdString.indexOf(" "), cmdString.length()).toString().trim(); + StringBuilder returnValue = new StringBuilder(); + Iterator<Command> iCommands = commands.getCommands().iterator(); + while (iCommands.hasNext()) { + Command cmd= iCommands.next(); + if (cmd.getHelp().toString().indexOf(keyword) >=0 + || cmd.getCommandString().toString().indexOf(keyword) >=0) { + if (returnValue.length() == 0) { + returnValue.append("See the following commands for more details:\n"); + } + returnValue.append(" "); + returnValue.append(cmd.getCommandString()); + returnValue.append("\n"); + } + } + if (returnValue.length() == 0) { + return "Don't know what you mean by '"+ keyword+"'"; + } + return returnValue; + } else { + Iterator<Command> iCommands = commands.getCommands().iterator(); + while (iCommands.hasNext()) { + Command cmd= iCommands.next(); + if (cmd.getCommandString().equals(cmdString)) { + return cmd.getCommandString()+": " + + cmd.getHelp().toString().replaceAll("\n" + , "\n"+emptyLine.substring(0, cmd.getCommandString().length()+3)); + } + } + } + return "Unkown command '"+ cmdString+"'"; + } + // default print all commands + // TODO iterate + StringBuilder returnValue = new StringBuilder(); + returnValue.append("Available key mappings:\n"); + int max = 0; + Iterator<KeyAction> iKeyActions = actionKeys.values().iterator(); + while (iKeyActions.hasNext()) { + max = Math.max(max, iKeyActions.next().getHelp().toString().indexOf('\t')); + } + iKeyActions = actionKeys.values().iterator(); + while (iKeyActions.hasNext()) { + returnValue.append(" "); + //returnValue.append(iKeyActions.next().getHelp()); + String help = iKeyActions.next().getHelp().toString(); + int index = help.indexOf('\t'); + returnValue.append(help.substring(0, index)); + for (int i = index; i < max; i++) { + returnValue.append(' '); + } + returnValue.append(help.substring(index)); + returnValue.append('\n'); + } + returnValue.append("\n\nAvailable commands:\n"); + Iterator<Command> iCommands = commands.getCommands().iterator(); + while (iCommands.hasNext()) { + Command cmd = iCommands.next(); + availableCommands.add(cmd.getCommandString()); + } + returnValue.append(toColumns(availableCommands)); + String helpHeader = "\nHelp for SQLShell client "+SQLProperties.getProperty(SQLProperties.PropertyName.VERSION, "SVN Snapshot")+"\n"+ + "Here you find a list of available commands. "+ + "To get more information about a specific command enter:\n"+ + " help command (for example 'help help')\n\n"+ + "If the list is not sufficient enough you could try searching help using:\n"+ + " help -k searchstring (for example help -k column)\n"+ + "This results in a list of commands matching the searchstring\n\n"; + returnValue.insert(0, helpHeader); + return returnValue; + } + @Override + public CharSequence getCommandString() { + return "help"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; + } + @Override + public CharSequence getHelp() { + return "this command. Please use 'help' to get a list of available commands you can use."; + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + + /** + * Convert '~/' to the username dir. + * @param fileName the filename to convert + * @return the converted filename + */ + private static String toFileName(String fileName) { + if (fileName.startsWith("~/")) { + return System.getProperty("user.home")+fileName.substring(1); + } + return fileName; + } + + /** + * Writes in/output to a file. + */ + private class SpoolCommand implements Command { + private String fileName; + + @Override + public CharSequence execute(SQLCommand cmd) { + String command = cmd.getCommandString(); + String nextPart = command.substring("spool".length()).trim(); + if (nextPart.equalsIgnoreCase("off")) { + if (spoolWriter != null) { + try { + spoolWriter.close(); + } catch(Exception e) {/*ignore*/} + spoolWriter = null; + return "Spool closed."; + } else { + return "No spool to close."; + } + } else { + try { + File f = new File(toFileName(nextPart.trim())); + fileName = f.getAbsolutePath(); + if ((f.exists() && !f.canWrite()) || (!f.exists() && !f.createNewFile())) { + throw new IllegalStateException("Failed to create spool to file: '"+fileName+"'"); + } + spoolWriter = new FileWriter(fileName); + } catch (IOException e) { + throw new IllegalStateException("Failed to create spool ("+fileName+"): " + e.toString(), e); + } + return "Spool to "+fileName+" created."; + } + } + + @Override + public CharSequence getCommandString() { + return "spool"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + return null; + } + @Override + public CharSequence getHelp() { + return "filename: Spool all output and queries to the specified file\n"+ + "off : Stop spooling data to the file.\n" + + "Current status:"+(spoolWriter != null ? "on, writing to '"+fileName+"'" : "off"); + } + @Override + public boolean abort() { + return false;// not implemented + } + @Override + public boolean backgroundProcessSupported() { + return false; + } + } + + private class ExecuteBatchCommand implements Command { + private boolean cancelled; + private Command currentCommand; + @Override + public CharSequence execute(SQLCommand sqlCommand) { + cancelled = false; + currentCommand = null; + String command = sqlCommand.getCommandString(); + // read file from file system and execute + FileInputStream fin = null; + try { + fin = new FileInputStream(toFileName(command.substring(1))); + output("Reading file: "+ toFileName(command.substring(1))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fin)); + StringBuilder cmd = new StringBuilder(); + String line; + while ( ((line = reader.readLine()) != null)) { + if (cancelled) { + return "Aborted"; + } + if (line.startsWith("--")) { + continue; + } + cmd.append(line); + if (line.endsWith(";")) { + // Exec cmd + String commandString = cmd.toString(); + currentCommand = createCommand(commandString); + output(commandString); + output(currentCommand.execute(new InputCommand(commandString))); + cmd=new StringBuilder(); + new Thread() { public void run() { repaint();}}.start(); + } + } + } catch(IOException e) { + error(e); + } finally { + if (fin != null) try { fin.close();}catch(Exception e) {/*ignore*/} + if (cancelled) { + return "Execution of file '" + toFileName(command.substring(1)) +"' aborted...."; + } + return "File '" + toFileName(command.substring(1)) +"' executed successfully."; + } + } + + @Override + public CharSequence getCommandString() { + return "@"; + } + + /** + * Returns some tab completion info for the specified command. + * @param commandInfo the command lines + * @param commandPoint the cursor position + * @return some tab completion info for the specified command. + */ + @Override + public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { + String fileName = command.getCommandString().substring(1).trim(); // cutoff '@' + String dirName; + if (fileName.equals("")) { + fileName = "."; + dirName = "."; + } else { + fileName = toFileName(fileName); + if (fileName.indexOf('/') >= 0) { + File file = new File(fileName); + if (file.isDirectory()) { + fileName = ""; + dirName = file.getAbsolutePath()+"/"; + } else { + fileName = file.getName(); + dirName = file.getParent(); + } + } else { + dirName = "."; + } + } + return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER,Arrays.asList(new File(dirName).list()) , fileName); + } + + @Override + public CharSequence getHelp() { + return "Specify filename to execute a 'batch' command.\n"+ + "For example '@mystatements.sql' executes all statements part of the mystatements.sql file in the current directory."+ + "Note that all statements must be terminated with ';' (sql statements as well as connect statements or spool)"; + } + @Override + public boolean abort() { + cancelled = true; + if (currentCommand != null) { + currentCommand.abort(); + } + return true; + } + + @Override + public boolean backgroundProcessSupported() { + return true; + } + } + + /** + * Command class to execute a 'custom command'. + * this makes it possible to have 'automated' commands executed. + * E.g.: + * executeCommand(new InputCommand("connect")); + * will eventually execute the Connect command. + */ + private static class InputCommand extends SQLCommand { + private StringBuilder command; + + public InputCommand(String command) { + this.command = new StringBuilder(command); + } + + public InputCommand(StringBuilder command) { + this.command = command; + } + + @Override + public String getUntrimmedCommandString() { + return command.toString(); + } + @Override + public List<StringBuilder> getEditableLines() { + return Arrays.asList(new StringBuilder[]{command}); + } + @Override + public List<? extends CharSequence> getLines() { + return Arrays.asList(new StringBuilder[]{command}); + } + } + + private abstract class CommandThread extends Thread { + private Command cmd; + public CommandThread(Command cmd) { + this.cmd = cmd; + } + + public final void run() { + showPrompt = false; + try { + execute(); + } finally { + showPrompt = true; + repaint(); + } + } + + abstract void execute(); + + Command getCommand() { + retu... [truncated message content] |
|
From: SVN by r. <sv...@ca...> - 2008-07-16 21:03:15
|
Author: roy
Date: 2008-07-16 23:03:05 +0200 (Wed, 16 Jul 2008)
New Revision: 264
Modified:
src/main/java/nl/improved/sqlclient/SQLShell.java
Log:
rollback quit
improvements to ctrl+w
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-07-16 20:47:38 UTC (rev 263)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-07-16 21:03:05 UTC (rev 264)
@@ -225,11 +225,7 @@
public void execute() {
if (cursorPosition.x == 0) {
if (cursorPosition.y > 0) {
- StringBuilder line = getEditableCommand().getEditableLines().remove(cursorPosition.y);
- cursorPosition.y--;
- StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
- cursorPosition.x = lineBuffer.length();
- lineBuffer.append(line);
+ joinLine();
}
} else {
StringBuilder tmp = getEditableCommand().getEditableLines().get(cursorPosition.y);
@@ -256,7 +252,13 @@
}
});
actionKeys.put("", new KeyAction() {
- public void execute() {
+ public void execute() { // ctrl+w
+ if (cursorPosition.x == 0) {
+ if (cursorPosition.y > 0) {
+ joinLine();
+ }
+ return;
+ }
StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
int previousBreak = SQLUtil.getLastBreakIndex(lineBuffer.substring(0, cursorPosition.x-1));
if (lineBuffer.charAt(previousBreak) == ' ' || lineBuffer.charAt(previousBreak) == '\t') {
@@ -580,7 +582,7 @@
e.printStackTrace(new PrintWriter(sw));
sw.flush();
lastExceptionDetails = sw.toString();
- output(sw.toString());
+ //output(sw.toString());
}
/**
@@ -1166,9 +1168,7 @@
}
@Override
public CharSequence execute(SQLCommand command) {
- //close();
hide();
- Window.closeAllWindows();
return "Application terminated.";
}
@Override
@@ -1607,6 +1607,13 @@
}
+ private void joinLine() {
+ StringBuilder line = getEditableCommand().getEditableLines().remove(cursorPosition.y);
+ cursorPosition.y--;
+ StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
+ cursorPosition.x = lineBuffer.length();
+ lineBuffer.append(line);
+ }
private interface KeyAction {
void execute();
CharSequence getHelp();
@@ -1614,9 +1621,7 @@
public static void main(String[] args) {
SQLShell shell = new SQLShell();
- shell.setVisible(false);
- shell.setVisible(true);
- //shell.show();
+ shell.show();
//Interpret first argument as a connect argument
if (args.length > 0) {
|
|
From: SVN by r. <sv...@ca...> - 2008-07-16 20:47:50
|
Author: roy
Date: 2008-07-16 22:47:38 +0200 (Wed, 16 Jul 2008)
New Revision: 263
Modified:
ChangeLog
src/main/java/nl/improved/sqlclient/SQLShell.java
src/main/java/nl/improved/sqlclient/SQLUtil.java
Log:
fix array indexout of bounds..
a try for better quit..
Modified: ChangeLog
===================================================================
--- ChangeLog 2008-05-19 20:55:11 UTC (rev 262)
+++ ChangeLog 2008-07-16 20:47:38 UTC (rev 263)
@@ -3,6 +3,7 @@
* Fix desc table for columns containing numbers
* Added tab completion for connect @
* Fix tabcompletion when using LIKE comparisons
+ * Fix for index out of bounds for strings without spaces
0.5 (2008-03-14)
* Allow for commands to start in the background, this will allow to continue
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-05-19 20:55:11 UTC (rev 262)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-07-16 20:47:38 UTC (rev 263)
@@ -258,7 +258,10 @@
actionKeys.put("", new KeyAction() {
public void execute() {
StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y);
- int previousBreak = SQLUtil.getLastBreakIndex(lineBuffer.substring(0, cursorPosition.x));
+ int previousBreak = SQLUtil.getLastBreakIndex(lineBuffer.substring(0, cursorPosition.x-1));
+ if (lineBuffer.charAt(previousBreak) == ' ' || lineBuffer.charAt(previousBreak) == '\t') {
+ previousBreak++;
+ }
lineBuffer.delete(previousBreak, cursorPosition.x);
cursorPosition.x = previousBreak;
}
@@ -484,7 +487,10 @@
// check if the new line is becoming too long
if (currentLine.length() > MAX_LINE_LENGTH) {
// TODO search for lastspace that is not between '' ??
- int lastSpace = currentLine.lastIndexOf(" ");
+ int lastSpace = SQLUtil.getLastBreakIndex(currentLine.toString());//currentLine.lastIndexOf(" ");
+ if (lastSpace == -1) {
+ lastSpace = currentLine.length();
+ }
// check if there are enough 'next' lines
// if not.. add one
if (editableLines.size()-1 == cursorPosition.y) {
@@ -574,6 +580,7 @@
e.printStackTrace(new PrintWriter(sw));
sw.flush();
lastExceptionDetails = sw.toString();
+ output(sw.toString());
}
/**
@@ -1159,7 +1166,9 @@
}
@Override
public CharSequence execute(SQLCommand command) {
- hide(); // quit
+ //close();
+ hide();
+ Window.closeAllWindows();
return "Application terminated.";
}
@Override
@@ -1605,7 +1614,9 @@
public static void main(String[] args) {
SQLShell shell = new SQLShell();
- shell.show();
+ shell.setVisible(false);
+ shell.setVisible(true);
+ //shell.show();
//Interpret first argument as a connect argument
if (args.length > 0) {
Modified: src/main/java/nl/improved/sqlclient/SQLUtil.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-05-19 20:55:11 UTC (rev 262)
+++ src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-07-16 20:47:38 UTC (rev 263)
@@ -293,6 +293,10 @@
}
+ /**
+ * Returns the index of last spacing in the string.
+ * this method is used for clearing or breaking lines.
+ */
public static int getLastBreakIndex(String s) {
int spaceIndex = 0;
char[] breakCharacters = new char[]{' ', '\t', '.', ','};
|
|
From: SVN by r. <sv...@ca...> - 2008-05-19 20:55:22
|
Author: roy Date: 2008-05-19 22:55:11 +0200 (Mon, 19 May 2008) New Revision: 262 Modified: ChangeLog Log: some changes for mysql Modified: ChangeLog =================================================================== --- ChangeLog 2008-05-19 20:28:44 UTC (rev 261) +++ ChangeLog 2008-05-19 20:55:11 UTC (rev 262) @@ -1,4 +1,5 @@ 0.6 + * Mysql case sensitivity fixes * Fix desc table for columns containing numbers * Added tab completion for connect @ * Fix tabcompletion when using LIKE comparisons |
|
From: SVN by r. <sv...@ca...> - 2008-05-19 20:28:59
|
Author: roy
Date: 2008-05-19 22:28:44 +0200 (Mon, 19 May 2008)
New Revision: 261
Modified:
src/main/java/nl/improved/sqlclient/DBConnector.java
src/main/java/nl/improved/sqlclient/SQLShell.java
Log:
mysql fixes (table names are case sensitive)
Modified: src/main/java/nl/improved/sqlclient/DBConnector.java
===================================================================
--- src/main/java/nl/improved/sqlclient/DBConnector.java 2008-04-04 18:43:39 UTC (rev 260)
+++ src/main/java/nl/improved/sqlclient/DBConnector.java 2008-05-19 20:28:44 UTC (rev 261)
@@ -22,8 +22,7 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.Set;
import java.util.Map;
@@ -50,8 +49,8 @@
private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";
private static DBConnector instance = null;
- private boolean tableNamesUppercase = false;
+ private Map<String, String> tableNames;
private Map<String, ConnectionSettings> predefinedConnections;
private String defaultConnector;
@@ -100,10 +99,8 @@
if (name == null) {
return null;
}
- if (tableNamesUppercase) {
- return name.toUpperCase();
- }
- return name.toLowerCase();
+ String returnValue = tableNames == null ? null : tableNames.get(name.toLowerCase());
+ return returnValue == null ? name : returnValue;
}
public boolean treatDateAsTimestamp() {
@@ -287,18 +284,14 @@
activeConnection = DriverManager.getConnection(settings.getConnectionURL(), username, password);
activeConnection.setAutoCommit(autoCommit);
// INITIALIZE database settings
+ tableNames = new HashMap<String, String>();
try {
DatabaseMetaData metaData = activeConnection.getMetaData();
ResultSet rs = metaData.getTables(activeConnection.getCatalog(), getSchema()
, null, new String[]{"TABLE"});
while (rs.next()) {
String tableName = rs.getString("TABLE_NAME");
- for (int i = 0; i < tableName.length(); i++) {
- if (Character.isLetter(tableName.charAt(i))) {
- this.tableNamesUppercase = Character.isUpperCase(tableName.charAt(i));
- break;
- }
- }
+ tableNames.put(tableName.toLowerCase(), tableName);
}
rs = metaData.getTypeInfo();
dateIsTimeStamp = true;
@@ -331,6 +324,7 @@
activeConnection = null;
}
queryExecutor = null;
+ tableNames = null;
}
public Connection getConnection() {
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-04-04 18:43:39 UTC (rev 260)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-05-19 20:28:44 UTC (rev 261)
@@ -660,11 +660,12 @@
}
if (match != null) {
if (sub.length() > 0) {
- if (Character.isUpperCase(sub.charAt(0))) {
+ /*if (Character.isUpperCase(sub.charAt(0))) {
match = match.toUpperCase();
} else {
match = match.toLowerCase();
- }
+ }*/
+ match = DBConnector.getInstance().translateDbVar(match);
}
return match.substring(sub.length());
}
|
|
From: SVN by r. <sv...@ca...> - 2008-04-04 18:43:48
|
Author: roy Date: 2008-04-04 20:43:39 +0200 (Fri, 04 Apr 2008) New Revision: 260 Modified: ChangeLog Log: mention changes Modified: ChangeLog =================================================================== --- ChangeLog 2008-04-04 18:33:05 UTC (rev 259) +++ ChangeLog 2008-04-04 18:43:39 UTC (rev 260) @@ -1,6 +1,7 @@ 0.6 * Fix desc table for columns containing numbers * Added tab completion for connect @ + * Fix tabcompletion when using LIKE comparisons 0.5 (2008-03-14) * Allow for commands to start in the background, this will allow to continue |
|
From: SVN by r. <sv...@ca...> - 2008-04-04 18:33:16
|
Author: roy
Date: 2008-04-04 20:33:05 +0200 (Fri, 04 Apr 2008)
New Revision: 259
Modified:
src/main/java/nl/improved/sqlclient/
src/main/java/nl/improved/sqlclient/commands/DescCommand.java
Log:
added @Override
Property changes on: src/main/java/nl/improved/sqlclient
___________________________________________________________________
Name: svn:ignore
- .SQLPlusPlus.java.swp
.SQLPlus.java.swp
.DBConnector.java.swp
.SQLUtil.java.swp
.Point.java.swp
.SQLLineWrapper.java.swp
.SQLOutput.java.swp
.QueryExecutor.java.swp
+ .SQLPlusPlus.java.swp
.SQLPlus.java.swp
.DBConnector.java.swp
.SQLUtil.java.swp
.Point.java.swp
.SQLLineWrapper.java.swp
.SQLOutput.java.swp
.QueryExecutor.java.swp
.SQLShell.java.swp
Modified: src/main/java/nl/improved/sqlclient/commands/DescCommand.java
===================================================================
--- src/main/java/nl/improved/sqlclient/commands/DescCommand.java 2008-04-04 11:07:07 UTC (rev 258)
+++ src/main/java/nl/improved/sqlclient/commands/DescCommand.java 2008-04-04 18:33:05 UTC (rev 259)
@@ -34,6 +34,7 @@
/**
* Execute the describe command.
*/
+ @Override
public CharSequence execute(SQLCommand command) {
java.sql.Connection conn = DBConnector.getInstance().getConnection();
String cmd = command.getCommandString();
|
|
From: SVN by r. <sv...@ca...> - 2008-04-04 11:07:17
|
Author: roy
Date: 2008-04-04 13:07:07 +0200 (Fri, 04 Apr 2008)
New Revision: 258
Modified:
src/main/java/nl/improved/sqlclient/SQLUtil.java
src/test/java/nl/improved/sqlclient/SQLUtilTest.java
Log:
added test for like with tabcompletion
Modified: src/main/java/nl/improved/sqlclient/SQLUtil.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-04-03 13:20:14 UTC (rev 257)
+++ src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-04-04 11:07:07 UTC (rev 258)
@@ -45,7 +45,7 @@
/**
* SQL Comparators.
*/
- private static final String COMPARATOR = "(=|<>|<|>)";
+ private static final String COMPARATOR = "(=|<>|<|>|LIKE)";
/**
* A sql variable description.
*/
@@ -242,7 +242,6 @@
String VALUE = "('.*'|[0-9]+|"+VAR+")";
// VALUE COMPERATOR VALUE
// VALUE IN (.*)
-
String regExp = "(|"+VALUE+"(|[\\s]*"+COMPARATOR+"[\\s]*(|"+VALUE+"(|([\\s]+(AND|OR)[\\s]+(|"+VALUE+"(|[\\s]*"+COMPARATOR+"[\\s]*(|"+VALUE+"))))*))|[\\s]*IN[\\s]*(.*)[\\s]*))";
if (upperCommandString.matches(regExp)) {
int lastIndex = tmpCommand.lastIndexOf(' ');
Modified: src/test/java/nl/improved/sqlclient/SQLUtilTest.java
===================================================================
--- src/test/java/nl/improved/sqlclient/SQLUtilTest.java 2008-04-03 13:20:14 UTC (rev 257)
+++ src/test/java/nl/improved/sqlclient/SQLUtilTest.java 2008-04-04 11:07:07 UTC (rev 258)
@@ -364,7 +364,6 @@
assertTrue(matches.contains("AND"));
assertEquals("a", info.getStart());
-
sqlCommand = Arrays.asList(new String[]{"SELECT * FROM A,B WHERE c in('c','d','e') and A.x"});
cursorPos = new Point(sqlCommand.get(0).length(),0);
assertEquals("WHERE", SQLUtil.getLastKeyWord(sqlCommand.get(0)));
@@ -374,6 +373,16 @@
matches = info.getPossibleMatches();
assertTrue(matches.contains("A"));
assertEquals("x", info.getStart());
+
+ sqlCommand = Arrays.asList(new String[]{"SELECT * FROM A,B WHERE c like 'a%' and A.x"});
+ cursorPos = new Point(sqlCommand.get(0).length(),0);
+ assertEquals("WHERE", SQLUtil.getLastKeyWord(sqlCommand.get(0)));
+ info = SQLUtil.getTabCompletionInfo(sqlCommand, cursorPos);
+ assertNotNull(info);
+ assertEquals(TabCompletionInfo.MatchType.COLUMN_NAMES, info.getMatchType());
+ matches = info.getPossibleMatches();
+ assertTrue(matches.contains("A"));
+ assertEquals("x", info.getStart());
}
public void testGroupBy() {
|
|
From: SVN by r. <sv...@ca...> - 2008-04-03 13:20:30
|
Author: roy
Date: 2008-04-03 15:20:14 +0200 (Thu, 03 Apr 2008)
New Revision: 257
Modified:
src/main/java/nl/improved/sqlclient/SQLShell.java
Log:
added extra check for indexoutofbounds exception
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-18 21:19:11 UTC (rev 256)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-04-03 13:20:14 UTC (rev 257)
@@ -836,6 +836,10 @@
String cursorChar = " ";
if (commandLines.getLines().size() > 0) {
String tmp = commandLines.getLines().get(cursorPosition.y).toString();
+ if (cursorPosition.x < 0) {
+ debug("Cursor position was: "+ cursorPosition +" fixing");
+ cursorPosition.x = 0;
+ }
if (cursorPosition.x < tmp.length()) {
cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1);
}
|
|
From: SVN by r. <sv...@ca...> - 2008-03-18 21:19:21
|
Author: roy Date: 2008-03-18 22:19:11 +0100 (Tue, 18 Mar 2008) New Revision: 256 Modified: ChangeLog Log: mention changes Modified: ChangeLog =================================================================== --- ChangeLog 2008-03-18 21:18:43 UTC (rev 255) +++ ChangeLog 2008-03-18 21:19:11 UTC (rev 256) @@ -1,4 +1,8 @@ -0.5 +0.6 + * Fix desc table for columns containing numbers + * Added tab completion for connect @ + +0.5 (2008-03-14) * Allow for commands to start in the background, this will allow to continue reading keyboard input (currently used to abort commands) * Added help to keyboard mappings (pageup/down/end/home, etc) |
|
From: SVN by r. <sv...@ca...> - 2008-03-18 21:18:54
|
Author: roy
Date: 2008-03-18 22:18:43 +0100 (Tue, 18 Mar 2008)
New Revision: 255
Modified:
src/main/java/nl/improved/sqlclient/SQLShell.java
src/main/java/nl/improved/sqlclient/SQLUtil.java
src/main/java/nl/improved/sqlclient/TabCompletionInfo.java
src/main/java/nl/improved/sqlclient/commands/ShowCommand.java
Log:
small refector step to rename UNKNOWN to OTHER
added tab completion for connect @..
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-18 20:56:18 UTC (rev 254)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-18 21:18:43 UTC (rev 255)
@@ -22,6 +22,7 @@
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.LinkedHashMap;
@@ -720,7 +721,7 @@
if (info.getMatchType() == TabCompletionInfo.MatchType.COLUMN_NAMES) {
return nullToEmpty(findMatch(getColumnNames(info.getPossibleMatches()), info.getStart()));
}
- if (info.getMatchType() == TabCompletionInfo.MatchType.UNKNOWN) {
+ if (info.getMatchType() == TabCompletionInfo.MatchType.OTHER) {
return nullToEmpty(findMatch(info.getPossibleMatches(), info.getStart()));
}
Toolkit.beep();
@@ -964,6 +965,15 @@
*/
@Override
public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) {
+ List commandInfo = command.getLines();
+
+ String startOfCommand = SQLUtil.getStartOfCommand(commandInfo, commandPoint);
+ if (startOfCommand.indexOf('@') >= 0) {
+ String end = startOfCommand.substring(startOfCommand.lastIndexOf('@')+1);
+ List<String> identifiers = new ArrayList<String>(DBConnector.getInstance().getPredefinedConnectionIdentifiers());
+ Collections.sort(identifiers);
+ return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER, identifiers, end);
+ }
return null;
}
@@ -1448,7 +1458,7 @@
dirName = ".";
}
}
- return new TabCompletionInfo(TabCompletionInfo.MatchType.UNKNOWN,Arrays.asList(new File(dirName).list()) , fileName);
+ return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER,Arrays.asList(new File(dirName).list()) , fileName);
}
@Override
Modified: src/main/java/nl/improved/sqlclient/SQLUtil.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-03-18 20:56:18 UTC (rev 254)
+++ src/main/java/nl/improved/sqlclient/SQLUtil.java 2008-03-18 21:18:43 UTC (rev 255)
@@ -275,7 +275,7 @@
String columns = startOfCommand.substring(upperStart.indexOf("SELECT")+"SELECT".length(), upperStart.indexOf("FROM")).replaceAll(" ","");
return new TabCompletionInfo(TabCompletionInfo.MatchType.COLUMN_NAMES, Arrays.asList(columns.split(",")));
}
- return new TabCompletionInfo(TabCompletionInfo.MatchType.UNKNOWN, Arrays.asList(new String[0]));
+ return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER, Arrays.asList(new String[0]));
}
public static String getStartOfCommand(List<? extends CharSequence> commandInfo, Point commandPoint) {
Modified: src/main/java/nl/improved/sqlclient/TabCompletionInfo.java
===================================================================
--- src/main/java/nl/improved/sqlclient/TabCompletionInfo.java 2008-03-18 20:56:18 UTC (rev 254)
+++ src/main/java/nl/improved/sqlclient/TabCompletionInfo.java 2008-03-18 21:18:43 UTC (rev 255)
@@ -18,7 +18,7 @@
import java.util.List;
public class TabCompletionInfo {
- public enum MatchType {SQL_KEYWORD, TABLE_NAMES, COLUMN_NAMES, FILE_NAMES, UNKNOWN}
+ public enum MatchType {SQL_KEYWORD, TABLE_NAMES, COLUMN_NAMES, FILE_NAMES, OTHER}
private MatchType type;
private List<String> possibleMatches;
Modified: src/main/java/nl/improved/sqlclient/commands/ShowCommand.java
===================================================================
--- src/main/java/nl/improved/sqlclient/commands/ShowCommand.java 2008-03-18 20:56:18 UTC (rev 254)
+++ src/main/java/nl/improved/sqlclient/commands/ShowCommand.java 2008-03-18 21:18:43 UTC (rev 255)
@@ -122,9 +122,9 @@
String startOfCommand = SQLUtil.getStartOfCommand(command.getLines(), commandPoint);
String end = startOfCommand.substring(startOfCommand.lastIndexOf(' ')+1);
if (commandStringUpper.matches("SHOW[\\s]+(|T|TA|TAB|TABL|TABLE)")) {
- return new TabCompletionInfo(TabCompletionInfo.MatchType.UNKNOWN, Arrays.asList(new String[]{"TABLES"}), end);
+ return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER, Arrays.asList(new String[]{"TABLES"}), end);
}
- return new TabCompletionInfo(TabCompletionInfo.MatchType.UNKNOWN, Arrays.asList(new String[]{"HAVING"}), end);
+ return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER, Arrays.asList(new String[]{"HAVING"}), end);
}
/**
|
|
From: SVN by r. <sv...@ca...> - 2008-03-18 20:56:30
|
Author: roy
Date: 2008-03-18 21:56:18 +0100 (Tue, 18 Mar 2008)
New Revision: 254
Modified:
src/main/java/nl/improved/sqlclient/SQLShell.java
Log:
fix desc for columns containging numbers
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-14 15:14:40 UTC (rev 253)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-18 20:56:18 UTC (rev 254)
@@ -128,7 +128,7 @@
commands.register("CONNECT[\\s]*.*", new ConnectCommand());
commands.register("DISCONNECT[\\s]*", new DisConnectCommand());
commands.register("SHOW[\\s]+[A-Z]+(|[A-Z]|_|\\.)*(|[\\s]+HAVING[\\s][A-Z]*.*)", new ShowCommand());
- commands.register("DESC[\\s]+[A-Z]+(|[A-Z]|_|\\.)*", new DescCommand());
+ commands.register("DESC[\\s]+[A-Z]+(|[0-9]|[A-Z]|_|-|\\.)*", new DescCommand());
commands.register("WINDOW[\\s]+[A-Z]+", new WindowCommand());
commands.register("INFO[\\s]*", new InfoCommand());
commands.register("HELP[\\s]*.*", new HelpCommand());
|
|
From: SVN by r. <sv...@ca...> - 2008-03-14 15:14:50
|
Author: roy
Date: 2008-03-14 16:14:40 +0100 (Fri, 14 Mar 2008)
New Revision: 253
Modified:
src/main/java/nl/improved/sqlclient/SQLShell.java
Log:
hopefully an indexoutof bounds fixed
Modified: src/main/java/nl/improved/sqlclient/SQLShell.java
===================================================================
--- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-14 12:39:55 UTC (rev 252)
+++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-03-14 15:14:40 UTC (rev 253)
@@ -822,7 +822,7 @@
int lineNr;
for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < Toolkit.getScreenHeight()-1; lineNr++) {
CharSequence linePart = tmpList.get(lineNr);
- String line = linePart + emptyLine.substring(linePart.length());
+ String line = linePart.length() >= emptyLine.length() ? linePart.toString() : linePart + emptyLine.substring(linePart.length());
Toolkit.printString(line
, 0, lineNr-startLine, color);
}
|
|
From: SVN by r. <sv...@ca...> - 2008-03-14 12:40:07
|
Author: roy Date: 2008-03-14 13:39:55 +0100 (Fri, 14 Mar 2008) New Revision: 252 Modified: pom.xml Log: work on 0.6 started Modified: pom.xml =================================================================== --- pom.xml 2008-03-05 07:29:22 UTC (rev 251) +++ pom.xml 2008-03-14 12:39:55 UTC (rev 252) @@ -19,7 +19,7 @@ <groupId>nl.improved</groupId> <artifactId>sqlshell</artifactId> <packaging>jar</packaging> - <version>0.5</version> + <version>0.6-SNAPSHOT</version> <name>SQLShell ~ the improved sqlclient</name> <url>http://sqlshell.sourceforge.org</url> <build> |