提交 3f000aa1 authored 作者: Thomas Mueller's avatar Thomas Mueller

shell test

上级 713b55c8
...@@ -8,6 +8,7 @@ package org.h2.tools; ...@@ -8,6 +8,7 @@ package org.h2.tools;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
...@@ -33,12 +34,15 @@ import org.h2.util.JdbcUtils; ...@@ -33,12 +34,15 @@ import org.h2.util.JdbcUtils;
public class Shell { public class Shell {
PrintStream out = System.out; PrintStream out = System.out;
PrintStream err = System.err;
private InputStream in = System.in;
private Connection conn; private Connection conn;
private Statement stat; private Statement stat;
private boolean listMode; private boolean listMode;
private int maxColumnSize = 100; private int maxColumnSize = 100;
// Windows: '\u00b3'; // Windows: '\u00b3';
private char boxVertical = '|'; private char boxVertical = '|';
private BufferedReader reader;
/** /**
* The command line interface for this tool. The options must be split into * The command line interface for this tool. The options must be split into
...@@ -61,16 +65,35 @@ public class Shell { ...@@ -61,16 +65,35 @@ public class Shell {
} }
private void showUsage() { private void showUsage() {
out.println("An interactive command line database tool."); println("An interactive command line database tool.");
out.println("java "+getClass().getName() + "\n" + println("java "+getClass().getName() + "\n" +
" [-url <url>] The database URL\n" + " [-url <url>] The database URL\n" +
" [-user <user>] The user name\n" + " [-user <user>] The user name\n" +
" [-password <pwd>] The password\n" + " [-password <pwd>] The password\n" +
" [-driver <class>] The JDBC driver class to use (not required in most cases)"); " [-driver <class>] The JDBC driver class to use (not required in most cases)");
out.println("See also http://h2database.com/javadoc/" + getClass().getName().replace('.', '/') + ".html"); println("See also http://h2database.com/javadoc/" + getClass().getName().replace('.', '/') + ".html");
} }
private void run(String[] args) throws SQLException { /**
* Redirects the input and output. By default, System.in, out and err are
* used.
*
* @param in the input stream to use
* @param out the output stream to use
* @param err the output error stream to use
*/
public void setStreams(InputStream in, PrintStream out, PrintStream err) {
this.in = in;
this.out = out;
this.err = err;
}
/**
* Run the shell tool with the given command line settings.
*
* @param args the command line settings
*/
public void run(String[] args) throws SQLException {
String url = null; String url = null;
String user = ""; String user = "";
String password = ""; String password = "";
...@@ -85,7 +108,7 @@ public class Shell { ...@@ -85,7 +108,7 @@ public class Shell {
String driver = args[++i]; String driver = args[++i];
ClassUtils.loadUserClass(driver); ClassUtils.loadUserClass(driver);
} else { } else {
out.println("Unsupported option: " + args[i]); println("Unsupported option: " + args[i]);
showUsage(); showUsage();
return; return;
} }
...@@ -99,24 +122,25 @@ public class Shell { ...@@ -99,24 +122,25 @@ public class Shell {
} }
private void showHelp() { private void showHelp() {
out.println("Commands are case insensitive; SQL statements end with ';'"); println("Commands are case insensitive; SQL statements end with ';'");
out.println("help or ? Display this help"); println("help or ? Display this help");
out.println("list Toggle result list mode"); println("list Toggle result list mode");
out.println("maxwidth Set maximum column width (default is 100)"); println("maxwidth Set maximum column width (default is 100)");
out.println("show List all tables"); println("show List all tables");
out.println("describe Describe a table"); println("describe Describe a table");
out.println("quit or exit Close the connection and exit"); println("quit or exit Close the connection and exit");
out.println(); println("");
} }
private void promptLoop() { private void promptLoop() {
out.println(); println("");
out.println("Welcome to H2 Shell " + Constants.getFullVersion()); println("Welcome to H2 Shell " + Constants.getFullVersion());
out.println("Exit with Ctrl+C"); println("Exit with Ctrl+C");
if (conn != null) { if (conn != null) {
showHelp(); showHelp();
} }
String statement = null; String statement = null;
reader = new BufferedReader(new InputStreamReader(in));
while (true) { while (true) {
try { try {
if (conn == null) { if (conn == null) {
...@@ -124,9 +148,9 @@ public class Shell { ...@@ -124,9 +148,9 @@ public class Shell {
showHelp(); showHelp();
} }
if (statement == null) { if (statement == null) {
out.print("sql> "); print("sql> ");
} else { } else {
out.print("...> "); print("...> ");
} }
String line = readLine(); String line = readLine();
if (line == null) { if (line == null) {
...@@ -147,11 +171,11 @@ public class Shell { ...@@ -147,11 +171,11 @@ public class Shell {
showHelp(); showHelp();
} else if ("LIST".equals(upper)) { } else if ("LIST".equals(upper)) {
listMode = !listMode; listMode = !listMode;
out.println("Result list mode is now " + (listMode ? "on" : "off")); println("Result list mode is now " + (listMode ? "on" : "off"));
} else if (upper.startsWith("DESCRIBE")) { } else if (upper.startsWith("DESCRIBE")) {
String tableName = upper.substring("DESCRIBE".length()).trim(); String tableName = upper.substring("DESCRIBE".length()).trim();
if (tableName.length() == 0) { if (tableName.length() == 0) {
out.println("Usage: describe [<schema name>.]<table name>"); println("Usage: describe [<schema name>.]<table name>");
} else { } else {
String schemaName = null; String schemaName = null;
int dot = tableName.indexOf('.'); int dot = tableName.indexOf('.');
...@@ -181,8 +205,8 @@ public class Shell { ...@@ -181,8 +205,8 @@ public class Shell {
rs = prep.executeQuery(); rs = prep.executeQuery();
printResult(rs, false); printResult(rs, false);
} catch (SQLException e) { } catch (SQLException e) {
out.println("Exception: " + e.toString()); println("Exception: " + e.toString());
e.printStackTrace(); e.printStackTrace(err);
} finally { } finally {
JdbcUtils.closeSilently(rs); JdbcUtils.closeSilently(rs);
JdbcUtils.closeSilently(prep); JdbcUtils.closeSilently(prep);
...@@ -196,8 +220,8 @@ public class Shell { ...@@ -196,8 +220,8 @@ public class Shell {
"FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_SCHEMA, TABLE_NAME"); "FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_SCHEMA, TABLE_NAME");
printResult(rs, false); printResult(rs, false);
} catch (SQLException e) { } catch (SQLException e) {
out.println("Exception: " + e.toString()); println("Exception: " + e.toString());
e.printStackTrace(); e.printStackTrace(err);
} finally { } finally {
JdbcUtils.closeSilently(rs); JdbcUtils.closeSilently(rs);
} }
...@@ -206,9 +230,9 @@ public class Shell { ...@@ -206,9 +230,9 @@ public class Shell {
try { try {
maxColumnSize = Integer.parseInt(upper); maxColumnSize = Integer.parseInt(upper);
} catch (Exception e) { } catch (Exception e) {
out.println("Usage: maxwidth <integer value>"); println("Usage: maxwidth <integer value>");
} }
out.println("Maximum column width is now " + maxColumnSize); println("Maximum column width is now " + maxColumnSize);
} else { } else {
if (statement == null) { if (statement == null) {
statement = line; statement = line;
...@@ -221,24 +245,24 @@ public class Shell { ...@@ -221,24 +245,24 @@ public class Shell {
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
out.println("SQL Exception: " + e.getMessage()); println("SQL Exception: " + e.getMessage());
statement = null; statement = null;
} catch (IOException e) { } catch (IOException e) {
out.println(e.getMessage()); println(e.getMessage());
break; break;
} catch (Exception e) { } catch (Exception e) {
out.println("Exception: " + e.toString()); println("Exception: " + e.toString());
e.printStackTrace(); e.printStackTrace(err);
break; break;
} }
} }
if (conn != null) { if (conn != null) {
try { try {
conn.close(); conn.close();
out.println("Connection closed"); println("Connection closed");
} catch (SQLException e) { } catch (SQLException e) {
out.println("SQL Exception:"); println("SQL Exception: " + e.getMessage());
e.printStackTrace(); e.printStackTrace(err);
} }
} }
} }
...@@ -269,29 +293,39 @@ public class Shell { ...@@ -269,29 +293,39 @@ public class Shell {
} catch (IOException e) { } catch (IOException e) {
// ignore // ignore
} }
out.println("[Enter] " + url); println("[Enter] " + url);
out.print("URL "); print("URL ");
url = readLine(url); url = readLine(url);
if (driver == null) { if (driver == null) {
driver = JdbcDriverUtils.getDriver(url); driver = JdbcDriverUtils.getDriver(url);
} }
if (driver != null) { if (driver != null) {
out.println("[Enter] " + driver); println("[Enter] " + driver);
} }
out.print("Driver "); print("Driver ");
driver = readLine(driver); driver = readLine(driver);
out.println("[Enter] " + user); println("[Enter] " + user);
out.print("User "); print("User ");
user = readLine(user); user = readLine(user);
out.println("[Enter] Hide"); println("[Enter] Hide");
out.print("Password "); print("Password ");
String password = readLine(); String password = readLine();
if (password.length() == 0) { if (password.length() == 0) {
password = readPassword(); password = readPassword();
} }
conn = JdbcUtils.getConnection(driver, url, user, password); conn = JdbcUtils.getConnection(driver, url, user, password);
stat = conn.createStatement(); stat = conn.createStatement();
out.println("Connected"); println("Connected");
}
private void print(String s) {
out.print(s);
out.flush();
}
private void println(String s) {
out.println(s);
out.flush();
} }
private String readPassword() throws IOException { private String readPassword() throws IOException {
...@@ -299,7 +333,7 @@ public class Shell { ...@@ -299,7 +333,7 @@ public class Shell {
Method getConsole = System.class.getMethod("console", new Class[0]); Method getConsole = System.class.getMethod("console", new Class[0]);
Object console = getConsole.invoke(null, (Object[]) null); Object console = getConsole.invoke(null, (Object[]) null);
Method readPassword = console.getClass().getMethod("readPassword", new Class[0]); Method readPassword = console.getClass().getMethod("readPassword", new Class[0]);
System.out.print("Password "); print("Password ");
char[] password = (char[]) readPassword.invoke(console, (Object[]) null); char[] password = (char[]) readPassword.invoke(console, (Object[]) null);
return password == null ? null : new String(password); return password == null ? null : new String(password);
} catch (Throwable t) { } catch (Throwable t) {
...@@ -324,7 +358,7 @@ public class Shell { ...@@ -324,7 +358,7 @@ public class Shell {
} }
PasswordHider thread = new PasswordHider(); PasswordHider thread = new PasswordHider();
thread.start(); thread.start();
out.print("Password > "); print("Password > ");
String p = readLine(); String p = readLine();
thread.stop = true; thread.stop = true;
try { try {
...@@ -332,7 +366,7 @@ public class Shell { ...@@ -332,7 +366,7 @@ public class Shell {
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore // ignore
} }
out.print("\b\b"); print("\b\b");
return p; return p;
} }
...@@ -342,7 +376,7 @@ public class Shell { ...@@ -342,7 +376,7 @@ public class Shell {
} }
private String readLine() throws IOException { private String readLine() throws IOException {
String line = new BufferedReader(new InputStreamReader(System.in)).readLine(); String line = reader.readLine();
if (line == null) { if (line == null) {
throw new IOException("Aborted"); throw new IOException("Aborted");
} }
...@@ -355,7 +389,7 @@ public class Shell { ...@@ -355,7 +389,7 @@ public class Shell {
try { try {
result = stat.execute(sql); result = stat.execute(sql);
} catch (SQLException e) { } catch (SQLException e) {
out.println("Error: " + e.toString()); println("Error: " + e.toString());
return; return;
} }
ResultSet rs = null; ResultSet rs = null;
...@@ -364,15 +398,15 @@ public class Shell { ...@@ -364,15 +398,15 @@ public class Shell {
rs = stat.getResultSet(); rs = stat.getResultSet();
int rowCount = printResult(rs, listMode); int rowCount = printResult(rs, listMode);
time = System.currentTimeMillis() - time; time = System.currentTimeMillis() - time;
out.println("(" + rowCount + (rowCount == 1 ? " row, " : " rows, ") + time + " ms)"); println("(" + rowCount + (rowCount == 1 ? " row, " : " rows, ") + time + " ms)");
} else { } else {
int updateCount = stat.getUpdateCount(); int updateCount = stat.getUpdateCount();
time = System.currentTimeMillis() - time; time = System.currentTimeMillis() - time;
out.println("(Update count: " + updateCount + ", " + time + " ms)"); println("(Update count: " + updateCount + ", " + time + " ms)");
} }
} catch (SQLException e) { } catch (SQLException e) {
out.println("Error: " + e.toString()); println("Error: " + e.toString());
e.printStackTrace(); e.printStackTrace(err);
} finally { } finally {
JdbcUtils.closeSilently(rs); JdbcUtils.closeSilently(rs);
} }
...@@ -414,7 +448,7 @@ public class Shell { ...@@ -414,7 +448,7 @@ public class Shell {
} }
} }
} }
out.println(buff.toString()); println(buff.toString());
} }
int rowCount = 0; int rowCount = 0;
while (rs.next()) { while (rs.next()) {
...@@ -422,7 +456,7 @@ public class Shell { ...@@ -422,7 +456,7 @@ public class Shell {
buff.setLength(0); buff.setLength(0);
if (listMode) { if (listMode) {
if (rowCount > 1) { if (rowCount > 1) {
out.println(); println("");
} }
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (i > 0) { if (i > 0) {
...@@ -457,7 +491,7 @@ public class Shell { ...@@ -457,7 +491,7 @@ public class Shell {
} }
} }
} }
out.println(buff.toString()); println(buff.toString());
} }
if (rowCount == 0 && listMode) { if (rowCount == 0 && listMode) {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
...@@ -465,7 +499,7 @@ public class Shell { ...@@ -465,7 +499,7 @@ public class Shell {
buff.append(label); buff.append(label);
buff.append('\n'); buff.append('\n');
} }
out.println(buff.toString()); println(buff.toString());
} }
return rowCount; return rowCount;
} }
......
...@@ -105,6 +105,7 @@ import org.h2.test.unit.TestRecovery; ...@@ -105,6 +105,7 @@ import org.h2.test.unit.TestRecovery;
import org.h2.test.unit.TestSampleApps; import org.h2.test.unit.TestSampleApps;
import org.h2.test.unit.TestScriptReader; import org.h2.test.unit.TestScriptReader;
import org.h2.test.unit.TestSecurity; import org.h2.test.unit.TestSecurity;
import org.h2.test.unit.TestShell;
import org.h2.test.unit.TestStreams; import org.h2.test.unit.TestStreams;
import org.h2.test.unit.TestStringCache; import org.h2.test.unit.TestStringCache;
import org.h2.test.unit.TestStringUtils; import org.h2.test.unit.TestStringUtils;
...@@ -162,25 +163,20 @@ java org.h2.test.TestAll timer ...@@ -162,25 +163,20 @@ java org.h2.test.TestAll timer
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
TestAll test = new TestAll(); TestAll test = new TestAll();
test.printSystem(); test.printSystem();
System.setProperty("h2.maxMemoryRowsDistinct", "128");
/* /*
not tested: not tested:
ResultTempTable PreparedProcedure PREPARE <name>(column,...) AS ...
HashIndex Procedure
HashCursor DeallocateProcedure DEALLOCATE [PLAN] <name>
Shell ExecuteProcedure EXECUTE <name>[([p[,...])]
ExecuteProcedure
PreparedProcedure
Procedure
DeallocateProcedure
create an mbean for each database? server? (jconsole) create an mbean for each database? server? (jconsole)
jazoon jazoon
upload and test javadoc/index.html
in help.csv, use complete examples for functions; add a test case in help.csv, use complete examples for functions; add a test case
improve javadocs improve javadocs
...@@ -539,6 +535,7 @@ Roadmap: ...@@ -539,6 +535,7 @@ Roadmap:
new TestScriptReader().runTest(this); new TestScriptReader().runTest(this);
runTest("org.h2.test.unit.TestServlet"); runTest("org.h2.test.unit.TestServlet");
new TestSecurity().runTest(this); new TestSecurity().runTest(this);
new TestShell().runTest(this);
new TestStreams().runTest(this); new TestStreams().runTest(this);
new TestStringCache().runTest(this); new TestStringCache().runTest(this);
new TestStringUtils().runTest(this); new TestStringUtils().runTest(this);
......
...@@ -351,7 +351,13 @@ public abstract class TestBase { ...@@ -351,7 +351,13 @@ public abstract class TestBase {
error(result + " does not contain: " + contains); error(result + " does not contain: " + contains);
} }
} }
protected void checkStartsWith(String text, String expectedStart) throws Exception {
if (!text.startsWith(expectedStart)) {
error(text + " does not start with: " + expectedStart);
}
}
protected void check(double a, double b) throws Exception { protected void check(double a, double b) throws Exception {
if (a != b) { if (a != b) {
error("double a: " + a + " b: " + b); error("double a: " + a + " b: " + b);
......
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.sql.SQLException;
import org.h2.test.TestBase;
import org.h2.tools.Shell;
/**
* Test the shell tool.
*/
public class TestShell extends TestBase {
PrintStream toolOut;
InputStream toolIn;
PrintStream testOut;
PipedInputStream testIn;
LineNumberReader lineReader;
public void test() throws Exception {
testIn = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(testIn);
toolOut = new PrintStream(out, true);
out = new PipedOutputStream();
testOut = new PrintStream(out, true);
toolIn = new PipedInputStream(out);
new Thread(new Runnable() {
public void run() {
try {
Shell shell = new Shell();
shell.setStreams(toolIn, toolOut, toolOut);
shell.run(new String[0]);
} catch (SQLException e) {
e.printStackTrace();
} finally {
toolOut.close();
}
}
}).start();
InputStreamReader reader = new InputStreamReader(testIn);
lineReader = new LineNumberReader(reader);
read("");
read("Welcome to H2 Shell");
read("Exit with");
read("[Enter]");
testOut.println("jdbc:h2:mem:");
read("URL");
testOut.println("org.h2.Driver");
read("Driver");
testOut.println("sa");
read("User");
testOut.println("sa");
read("Password");
read("Commands are case insensitive");
read("help or ?");
read("list");
read("maxwidth");
read("show");
read("describe");
read("quit or exit");
read("");
testOut.println("create table test(id int primary key, name varchar)\n;");
read("sql> ...>");
testOut.println("show public");
read("sql>");
while (read("").startsWith("INFORMATION_SCHEMA")) {
// ignore
}
testOut.println("insert into test values(1, 'Hello');");
read("sql>");
testOut.println("select * from test;");
read("sql> ID");
read("1 ");
read("(1 row,");
testOut.println("describe test");
read("sql> Column Name");
read("ID");
read("NAME");
testOut.println("exit");
read("sql>");
}
private String read(String expectedStart) throws Exception {
String line = lineReader.readLine();
// System.out.println(": " + line);
checkStartsWith(line, expectedStart);
return line;
}
}
...@@ -19,7 +19,7 @@ public class Build extends BuildBase { ...@@ -19,7 +19,7 @@ public class Build extends BuildBase {
/** /**
* Run the build. * Run the build.
* *
* @params args the command line arguments * @param args the command line arguments
*/ */
public static void main(String[] args) { public static void main(String[] args) {
new Build().run(args); new Build().run(args);
......
...@@ -226,10 +226,10 @@ public class BuildBase { ...@@ -226,10 +226,10 @@ public class BuildBase {
} }
/** /**
* Read a final static field in a class using reflection. * Reads the value from a static method of a class using reflection.
* *
* @param className the name of the class * @param className the name of the class
* @param fieldName the field name * @param methodName the field name
* @return the value as a string * @return the value as a string
*/ */
protected String getStaticValue(String className, String methodName) { protected String getStaticValue(String className, String methodName) {
...@@ -371,9 +371,10 @@ public class BuildBase { ...@@ -371,9 +371,10 @@ public class BuildBase {
if (file.getName().startsWith(".svn")) { if (file.getName().startsWith(".svn")) {
// ignore // ignore
} else if (file.isDirectory()) { } else if (file.isDirectory()) {
File[] files = file.listFiles(); String[] fileNames = file.list();
for (int i = 0; i < files.length; i++) { String path = file.getPath();
addFiles(list, files[i]); for (int i = 0; i < fileNames.length; i++) {
addFiles(list, new File(path, fileNames[i]));
} }
} else { } else {
list.add(file); list.add(file);
...@@ -628,16 +629,17 @@ public class BuildBase { ...@@ -628,16 +629,17 @@ public class BuildBase {
delete(new File(dir)); delete(new File(dir));
} }
private void delete(File f) { private void delete(File file) {
if (f.exists()) { if (file.exists()) {
if (f.isDirectory()) { if (file.isDirectory()) {
File[] list = f.listFiles(); String[] fileNames = file.list();
for (int i = 0; i < list.length; i++) { String path = file.getPath();
delete(list[i]); for (int i = 0; i < fileNames.length; i++) {
delete(new File(path, fileNames[i]));
} }
} }
if (!f.delete()) { if (!file.delete()) {
throw new Error("Can not delete " + f.getPath()); throw new Error("Can not delete " + file.getPath());
} }
} }
} }
......
...@@ -514,5 +514,5 @@ derbynet ado happy derbyclient unspecified federated sysadmin lengths doing ...@@ -514,5 +514,5 @@ derbynet ado happy derbyclient unspecified federated sysadmin lengths doing
gives clunky cooperative paged conflicts ontology freely regards standards gives clunky cooperative paged conflicts ontology freely regards standards
placing refer informational unlocks memo unlimited unmounted keeping hints placing refer informational unlocks memo unlimited unmounted keeping hints
hides heterogeneous construction rutema prepending rowscn overrides jconsole hides heterogeneous construction rutema prepending rowscn overrides jconsole
mbean explicit directs leaves printing holds covariant redirector mbean explicit directs leaves printing holds covariant redirector piped
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论