提交 99b6c901 authored 作者: Thomas Mueller's avatar Thomas Mueller

Improve code coverage.

上级 048f3ba8
...@@ -240,7 +240,6 @@ public class Bnf { ...@@ -240,7 +240,6 @@ public class Bnf {
syntax = StringUtils.replaceAll(syntax, "||", "@concat@"); syntax = StringUtils.replaceAll(syntax, "||", "@concat@");
syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@"); syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@");
syntax = StringUtils.replaceAll(syntax, "A-Z|_", "@az_@"); syntax = StringUtils.replaceAll(syntax, "A-Z|_", "@az_@");
syntax = StringUtils.replaceAll(syntax, "a-f", "@af@");
syntax = StringUtils.replaceAll(syntax, "A-F", "@af@"); syntax = StringUtils.replaceAll(syntax, "A-F", "@af@");
syntax = StringUtils.replaceAll(syntax, "0-9", "@digit@"); syntax = StringUtils.replaceAll(syntax, "0-9", "@digit@");
syntax = StringUtils.replaceAll(syntax, "'['", "@openBracket@"); syntax = StringUtils.replaceAll(syntax, "'['", "@openBracket@");
...@@ -275,14 +274,18 @@ public class Bnf { ...@@ -275,14 +274,18 @@ public class Bnf {
public HashMap<String, String> getNextTokenList(String query) { public HashMap<String, String> getNextTokenList(String query) {
Sentence sentence = new Sentence(); Sentence sentence = new Sentence();
sentence.setQuery(query); sentence.setQuery(query);
for (RuleHead head : statements) { try {
if (!head.getSection().startsWith("Commands")) { for (RuleHead head : statements) {
continue; if (!head.getSection().startsWith("Commands")) {
} continue;
sentence.start(); }
if (head.getRule().autoComplete(sentence)) { sentence.start();
break; if (head.getRule().autoComplete(sentence)) {
break;
}
} }
} catch (IllegalStateException e) {
// ignore
} }
return sentence.getNext(); return sentence.getNext();
} }
......
...@@ -53,9 +53,7 @@ public class RuleElement implements Rule { ...@@ -53,9 +53,7 @@ public class RuleElement implements Rule {
} }
public boolean autoComplete(Sentence sentence) { public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) { sentence.stopIfRequired();
return false;
}
if (keyword) { if (keyword) {
String query = sentence.getQuery(); String query = sentence.getQuery();
String q = query.trim(); String q = query.trim();
......
...@@ -38,14 +38,12 @@ public class RuleFixed implements Rule { ...@@ -38,14 +38,12 @@ public class RuleFixed implements Rule {
} }
public boolean autoComplete(Sentence sentence) { public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) { sentence.stopIfRequired();
return false;
}
String query = sentence.getQuery(); String query = sentence.getQuery();
String s = query; String s = query;
switch(type) { switch(type) {
case YMD: case YMD:
while (s.length() > 0 && "0123456789- ".indexOf(s.charAt(0)) >= 0) { while (s.length() > 0 && "0123456789-".indexOf(s.charAt(0)) >= 0) {
s = s.substring(1); s = s.substring(1);
} }
if (s.length() == 0) { if (s.length() == 0) {
...@@ -53,7 +51,7 @@ public class RuleFixed implements Rule { ...@@ -53,7 +51,7 @@ public class RuleFixed implements Rule {
} }
break; break;
case HMS: case HMS:
while (s.length() > 0 && "0123456789:. ".indexOf(s.charAt(0)) >= 0) { while (s.length() > 0 && "0123456789:".indexOf(s.charAt(0)) >= 0) {
s = s.substring(1); s = s.substring(1);
} }
if (s.length() == 0) { if (s.length() == 0) {
...@@ -85,11 +83,8 @@ public class RuleFixed implements Rule { ...@@ -85,11 +83,8 @@ public class RuleFixed implements Rule {
} }
break; break;
case ANY_EXCEPT_2_DOLLAR: case ANY_EXCEPT_2_DOLLAR:
while (true) { while (s.length() > 0 && !s.startsWith("$$")) {
while (s.length() > 0 && !s.startsWith("$$")) { s = s.substring(1);
s = s.substring(1);
}
break;
} }
if (s.length() == 0) { if (s.length() == 0) {
sentence.add("anything", "Hello World", Sentence.KEYWORD); sentence.add("anything", "Hello World", Sentence.KEYWORD);
...@@ -113,20 +108,20 @@ public class RuleFixed implements Rule { ...@@ -113,20 +108,20 @@ public class RuleFixed implements Rule {
} }
break; break;
case ANY_WORD: case ANY_WORD:
while (s.length() > 0 && Character.isWhitespace(s.charAt(0))) { while (s.length() > 0 && !Character.isWhitespace(s.charAt(0))) {
s = s.substring(1); s = s.substring(1);
} }
if (s.length() == 0) {
sentence.add("anything", "anything", Sentence.KEYWORD);
}
break; break;
case HEX_START: case HEX_START:
if (s.startsWith("0X") || s.startsWith("0x")) { if (s.startsWith("0X") || s.startsWith("0x")) {
s = s.substring(2); s = s.substring(2);
} else if (s.startsWith("0")) {
s = s.substring(1);
}
if (s.length() == 0) {
sentence.add("0x", "0x", Sentence.KEYWORD);
} else if ("0".equals(s)) { } else if ("0".equals(s)) {
sentence.add("0x", "x", Sentence.KEYWORD); sentence.add("0x", "x", Sentence.KEYWORD);
} else if (s.length() == 0) {
sentence.add("0x", "0x", Sentence.KEYWORD);
} }
break; break;
case CONCAT: case CONCAT:
...@@ -138,11 +133,6 @@ public class RuleFixed implements Rule { ...@@ -138,11 +133,6 @@ public class RuleFixed implements Rule {
sentence.add("||", "||", Sentence.KEYWORD); sentence.add("||", "||", Sentence.KEYWORD);
} }
break; break;
case ANY_UNTIL_EOL:
while (s.length() > 0 && s.charAt(0) != '\n') {
s = s.substring(1);
}
break;
case AZ_UNDERSCORE: case AZ_UNDERSCORE:
if (s.length() > 0 && (Character.isLetter(s.charAt(0)) || s.charAt(0) == '_')) { if (s.length() > 0 && (Character.isLetter(s.charAt(0)) || s.charAt(0) == '_')) {
s = s.substring(1); s = s.substring(1);
...@@ -184,6 +174,10 @@ public class RuleFixed implements Rule { ...@@ -184,6 +174,10 @@ public class RuleFixed implements Rule {
sentence.add("]", "]", Sentence.KEYWORD); sentence.add("]", "]", Sentence.KEYWORD);
} }
break; break;
// no autocomplete support for comments
// (comments are not reachable in the bnf tree)
case ANY_UNTIL_EOL:
case ANY_UNTIL_END:
default: default:
throw new AssertionError("type="+type); throw new AssertionError("type="+type);
} }
......
...@@ -48,9 +48,7 @@ public class RuleList implements Rule { ...@@ -48,9 +48,7 @@ public class RuleList implements Rule {
} }
public boolean autoComplete(Sentence sentence) { public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) { sentence.stopIfRequired();
return false;
}
String old = sentence.getQuery(); String old = sentence.getQuery();
if (or) { if (or) {
for (Rule r : list) { for (Rule r : list) {
......
...@@ -30,9 +30,7 @@ public class RuleOptional implements Rule { ...@@ -30,9 +30,7 @@ public class RuleOptional implements Rule {
} }
} }
public boolean autoComplete(Sentence sentence) { public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) { sentence.stopIfRequired();
return false;
}
rule.autoComplete(sentence); rule.autoComplete(sentence);
return true; return true;
} }
......
...@@ -26,13 +26,11 @@ public class RuleRepeat implements Rule { ...@@ -26,13 +26,11 @@ public class RuleRepeat implements Rule {
} }
public void setLinks(HashMap<String, RuleHead> ruleMap) { public void setLinks(HashMap<String, RuleHead> ruleMap) {
// rule.setLinks(ruleMap); // not required, because it's already linked
} }
public boolean autoComplete(Sentence sentence) { public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) { sentence.stopIfRequired();
return false;
}
while (rule.autoComplete(sentence)) { while (rule.autoComplete(sentence)) {
// nothing to do // nothing to do
} }
......
...@@ -70,11 +70,12 @@ public class Sentence { ...@@ -70,11 +70,12 @@ public class Sentence {
/** /**
* Check if it's time to stop processing. * Check if it's time to stop processing.
* Processing auto-complete shouldn't take more than a few milliseconds. * Processing auto-complete shouldn't take more than a few milliseconds.
* * If processing is stopped, this methods throws an IllegalStateException
* @return true if it's time to stop processing
*/ */
boolean shouldStop() { void stopIfRequired() {
return System.currentTimeMillis() > stopAt; if (System.currentTimeMillis() > stopAt) {
throw new IllegalStateException();
}
} }
/** /**
......
...@@ -71,7 +71,7 @@ public abstract class Command implements CommandInterface { ...@@ -71,7 +71,7 @@ public abstract class Command implements CommandInterface {
* *
* @return the list of parameters * @return the list of parameters
*/ */
public abstract ArrayList< ? extends ParameterInterface> getParameters(); public abstract ArrayList<? extends ParameterInterface> getParameters();
/** /**
* Check if this command is read only. * Check if this command is read only.
......
...@@ -26,7 +26,7 @@ public class CommandContainer extends Command { ...@@ -26,7 +26,7 @@ public class CommandContainer extends Command {
this.prepared = prepared; this.prepared = prepared;
} }
public ArrayList< ? extends ParameterInterface> getParameters() { public ArrayList<? extends ParameterInterface> getParameters() {
return prepared.getParameters(); return prepared.getParameters();
} }
......
...@@ -466,7 +466,7 @@ public interface CommandInterface { ...@@ -466,7 +466,7 @@ public interface CommandInterface {
* *
* @return the parameters * @return the parameters
*/ */
ArrayList< ? extends ParameterInterface> getParameters(); ArrayList<? extends ParameterInterface> getParameters();
/** /**
* Execute the query. * Execute the query.
......
...@@ -24,7 +24,7 @@ public class CommandList extends Command { ...@@ -24,7 +24,7 @@ public class CommandList extends Command {
this.remaining = remaining; this.remaining = remaining;
} }
public ArrayList< ? extends ParameterInterface> getParameters() { public ArrayList<? extends ParameterInterface> getParameters() {
return command.getParameters(); return command.getParameters();
} }
......
...@@ -88,8 +88,8 @@ public class MetaRecord implements Comparable<MetaRecord> { ...@@ -88,8 +88,8 @@ public class MetaRecord implements Comparable<MetaRecord> {
* @return -1, 0, or 1 * @return -1, 0, or 1
*/ */
public int compareTo(MetaRecord other) { public int compareTo(MetaRecord other) {
int c1 = getCreateOrder(getObjectType()); int c1 = getCreateOrder();
int c2 = getCreateOrder(other.getObjectType()); int c2 = other.getCreateOrder();
if (c1 != c2) { if (c1 != c2) {
return c1 - c2; return c1 - c2;
} }
...@@ -100,11 +100,10 @@ public class MetaRecord implements Comparable<MetaRecord> { ...@@ -100,11 +100,10 @@ public class MetaRecord implements Comparable<MetaRecord> {
* Get the sort order id for this object type. Objects are created in this * Get the sort order id for this object type. Objects are created in this
* order when opening a database. * order when opening a database.
* *
* @param type the database object type
* @return the sort index * @return the sort index
*/ */
private int getCreateOrder(int type) { private int getCreateOrder() {
switch(type) { switch(objectType) {
case DbObject.SETTING: case DbObject.SETTING:
return 0; return 0;
case DbObject.USER: case DbObject.USER:
...@@ -136,7 +135,7 @@ public class MetaRecord implements Comparable<MetaRecord> { ...@@ -136,7 +135,7 @@ public class MetaRecord implements Comparable<MetaRecord> {
case DbObject.COMMENT: case DbObject.COMMENT:
return 14; return 14;
default: default:
throw DbException.throwInternalError("type="+type); throw DbException.throwInternalError("type="+objectType);
} }
} }
......
...@@ -29,7 +29,7 @@ implements ParameterMetaData ...@@ -29,7 +29,7 @@ implements ParameterMetaData
private JdbcPreparedStatement prep; private JdbcPreparedStatement prep;
private int paramCount; private int paramCount;
private ArrayList< ? extends ParameterInterface> parameters; private ArrayList<? extends ParameterInterface> parameters;
JdbcParameterMetaData(Trace trace, JdbcPreparedStatement prep, CommandInterface command, int id) { JdbcParameterMetaData(Trace trace, JdbcPreparedStatement prep, CommandInterface command, int id) {
setTrace(trace, TraceObject.PARAMETER_META_DATA, id); setTrace(trace, TraceObject.PARAMETER_META_DATA, id);
......
...@@ -202,7 +202,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat ...@@ -202,7 +202,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
try { try {
debugCodeCall("clearParameters"); debugCodeCall("clearParameters");
checkClosed(); checkClosed();
ArrayList< ? extends ParameterInterface> parameters = command.getParameters(); ArrayList<? extends ParameterInterface> parameters = command.getParameters();
for (int i = 0, size = parameters.size(); i < size; i++) { for (int i = 0, size = parameters.size(); i < size; i++) {
ParameterInterface param = parameters.get(i); ParameterInterface param = parameters.get(i);
// can only delete old temp files if they are not in the batch // can only delete old temp files if they are not in the batch
...@@ -1077,7 +1077,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat ...@@ -1077,7 +1077,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
try { try {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Value[] set = batchParameters.get(i); Value[] set = batchParameters.get(i);
ArrayList< ? extends ParameterInterface> parameters = command.getParameters(); ArrayList<? extends ParameterInterface> parameters = command.getParameters();
for (int j = 0; j < set.length; j++) { for (int j = 0; j < set.length; j++) {
Value value = set[j]; Value value = set[j];
ParameterInterface param = parameters.get(j); ParameterInterface param = parameters.get(j);
...@@ -1123,7 +1123,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat ...@@ -1123,7 +1123,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
debugCodeCall("addBatch"); debugCodeCall("addBatch");
checkClosedForWrite(); checkClosedForWrite();
try { try {
ArrayList< ? extends ParameterInterface> parameters = command.getParameters(); ArrayList<? extends ParameterInterface> parameters = command.getParameters();
int size = parameters.size(); int size = parameters.size();
Value[] set = new Value[size]; Value[] set = new Value[size];
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
...@@ -1254,7 +1254,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat ...@@ -1254,7 +1254,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
private void setParameter(int parameterIndex, Value value) throws SQLException { private void setParameter(int parameterIndex, Value value) throws SQLException {
checkClosed(); checkClosed();
parameterIndex--; parameterIndex--;
ArrayList< ? extends ParameterInterface> parameters = command.getParameters(); ArrayList<? extends ParameterInterface> parameters = command.getParameters();
if (parameterIndex < 0 || parameterIndex >= parameters.size()) { if (parameterIndex < 0 || parameterIndex >= parameters.size()) {
throw DbException.getInvalidValueException("parameterIndex", parameterIndex + 1); throw DbException.getInvalidValueException("parameterIndex", parameterIndex + 1);
} }
...@@ -1496,9 +1496,9 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat ...@@ -1496,9 +1496,9 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
protected boolean checkClosed(boolean write) throws SQLException { protected boolean checkClosed(boolean write) throws SQLException {
if (super.checkClosed(write)) { if (super.checkClosed(write)) {
// if the session was re-connected, re-prepare the statement // if the session was re-connected, re-prepare the statement
ArrayList< ? extends ParameterInterface> oldParams = command.getParameters(); ArrayList<? extends ParameterInterface> oldParams = command.getParameters();
command = conn.prepareCommand(sqlStatement, fetchSize); command = conn.prepareCommand(sqlStatement, fetchSize);
ArrayList< ? extends ParameterInterface> newParams = command.getParameters(); ArrayList<? extends ParameterInterface> newParams = command.getParameters();
for (int i = 0, size = oldParams.size(); i < size; i++) { for (int i = 0, size = oldParams.size(); i < size; i++) {
ParameterInterface old = oldParams.get(i); ParameterInterface old = oldParams.get(i);
Value value = old.getParamValue(); Value value = old.getParamValue();
......
...@@ -57,7 +57,7 @@ implements ObjectFactory ...@@ -57,7 +57,7 @@ implements ObjectFactory
* not JdbcDataSource. * not JdbcDataSource.
*/ */
//## Java 1.4 begin ## //## Java 1.4 begin ##
public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable< ? , ? > environment) { public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("getObjectInstance obj={0} name={1} nameCtx={2} environment={3}", obj, name, nameCtx, environment); trace.debug("getObjectInstance obj={0} name={1} nameCtx={2} environment={3}", obj, name, nameCtx, environment);
} }
......
...@@ -429,7 +429,7 @@ public class TraceObject { ...@@ -429,7 +429,7 @@ public class TraceObject {
/** /**
* INTERNAL * INTERNAL
*/ */
public static String toString(String sql, ArrayList< ? extends ParameterInterface> params) { public static String toString(String sql, ArrayList<? extends ParameterInterface> params) {
StatementBuilder buff = new StatementBuilder(sql); StatementBuilder buff = new StatementBuilder(sql);
if (params != null && params.size() > 0) { if (params != null && params.size() > 0) {
buff.append(" {"); buff.append(" {");
......
...@@ -208,7 +208,7 @@ public class TcpServerThread implements Runnable { ...@@ -208,7 +208,7 @@ public class TcpServerThread implements Runnable {
private void setParameters(Command command) throws IOException { private void setParameters(Command command) throws IOException {
int len = transfer.readInt(); int len = transfer.readInt();
ArrayList< ? extends ParameterInterface> params = command.getParameters(); ArrayList<? extends ParameterInterface> params = command.getParameters();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Parameter p = (Parameter) params.get(i); Parameter p = (Parameter) params.get(i);
p.setValue(transfer.readValue()); p.setValue(transfer.readValue());
...@@ -227,7 +227,7 @@ public class TcpServerThread implements Runnable { ...@@ -227,7 +227,7 @@ public class TcpServerThread implements Runnable {
boolean readonly = command.isReadOnly(); boolean readonly = command.isReadOnly();
cache.addObject(id, command); cache.addObject(id, command);
boolean isQuery = command.isQuery(); boolean isQuery = command.isQuery();
ArrayList< ? extends ParameterInterface> params = command.getParameters(); ArrayList<? extends ParameterInterface> params = command.getParameters();
transfer.writeInt(getState(old)).writeBoolean(isQuery).writeBoolean(readonly) transfer.writeInt(getState(old)).writeBoolean(isQuery).writeBoolean(readonly)
.writeInt(params.size()); .writeInt(params.size());
if (operation == SessionRemote.SESSION_PREPARE_READ_PARAMS) { if (operation == SessionRemote.SESSION_PREPARE_READ_PARAMS) {
......
...@@ -116,7 +116,7 @@ public class FileSystemZip extends FileSystem { ...@@ -116,7 +116,7 @@ public class FileSystemZip extends FileSystem {
return true; return true;
} }
ZipFile file = openZipFile(fileName); ZipFile file = openZipFile(fileName);
Enumeration< ? extends ZipEntry> en = file.entries(); Enumeration<? extends ZipEntry> en = file.entries();
while (en.hasMoreElements()) { while (en.hasMoreElements()) {
ZipEntry entry = en.nextElement(); ZipEntry entry = en.nextElement();
String n = entry.getName(); String n = entry.getName();
...@@ -165,7 +165,7 @@ public class FileSystemZip extends FileSystem { ...@@ -165,7 +165,7 @@ public class FileSystemZip extends FileSystem {
ZipFile file = openZipFile(path); ZipFile file = openZipFile(path);
String dirName = getEntryName(path); String dirName = getEntryName(path);
String prefix = path.substring(0, path.length() - dirName.length()); String prefix = path.substring(0, path.length() - dirName.length());
Enumeration< ? extends ZipEntry> en = file.entries(); Enumeration<? extends ZipEntry> en = file.entries();
ArrayList<String> list = New.arrayList(); ArrayList<String> list = New.arrayList();
while (en.hasMoreElements()) { while (en.hasMoreElements()) {
ZipEntry entry = en.nextElement(); ZipEntry entry = en.nextElement();
......
...@@ -634,7 +634,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -634,7 +634,7 @@ public abstract class Table extends SchemaObjectBase {
} }
} }
private void remove(ArrayList< ? extends DbObject> list, DbObject obj) { private void remove(ArrayList<? extends DbObject> list, DbObject obj) {
if (list != null) { if (list != null) {
int i = list.indexOf(obj); int i = list.indexOf(obj);
if (i >= 0) { if (i >= 0) {
......
...@@ -90,7 +90,7 @@ public class CompressTool { ...@@ -90,7 +90,7 @@ public class CompressTool {
public int compress(byte[] in, int len, Compressor compress, byte[] out) { public int compress(byte[] in, int len, Compressor compress, byte[] out) {
int newLen = 0; int newLen = 0;
out[0] = (byte) compress.getAlgorithm(); out[0] = (byte) compress.getAlgorithm();
int start = 1 + writeInt(out, 1, len); int start = 1 + writeVariableInt(out, 1, len);
newLen = compress.compress(in, len, out, start); newLen = compress.compress(in, len, out, start);
if (newLen > len + start || newLen <= 0) { if (newLen > len + start || newLen <= 0) {
out[0] = Compressor.NO; out[0] = Compressor.NO;
...@@ -111,8 +111,8 @@ public class CompressTool { ...@@ -111,8 +111,8 @@ public class CompressTool {
int algorithm = in[0]; int algorithm = in[0];
Compressor compress = getCompressor(algorithm); Compressor compress = getCompressor(algorithm);
try { try {
int len = readInt(in, 1); int len = readVariableInt(in, 1);
int start = 1 + getLength(len); int start = 1 + getVariableIntLength(len);
byte[] buff = Utils.newBytes(len); byte[] buff = Utils.newBytes(len);
compress.expand(in, start, in.length - start, buff, 0, len); compress.expand(in, start, in.length - start, buff, 0, len);
return buff; return buff;
...@@ -128,15 +128,22 @@ public class CompressTool { ...@@ -128,15 +128,22 @@ public class CompressTool {
int algorithm = in[0]; int algorithm = in[0];
Compressor compress = getCompressor(algorithm); Compressor compress = getCompressor(algorithm);
try { try {
int len = readInt(in, 1); int len = readVariableInt(in, 1);
int start = 1 + getLength(len); int start = 1 + getVariableIntLength(len);
compress.expand(in, start, in.length - start, out, outPos, len); compress.expand(in, start, in.length - start, out, outPos, len);
} catch (Exception e) { } catch (Exception e) {
throw DbException.get(ErrorCode.COMPRESSION_ERROR, e); throw DbException.get(ErrorCode.COMPRESSION_ERROR, e);
} }
} }
private int readInt(byte[] buff, int pos) { /**
* Read a variable size integer using Rice coding.
*
* @param buff the buffer
* @param pos the position
* @return the integer
*/
public static int readVariableInt(byte[] buff, int pos) {
int x = buff[pos++] & 0xff; int x = buff[pos++] & 0xff;
if (x < 0x80) { if (x < 0x80) {
return x; return x;
...@@ -155,7 +162,16 @@ public class CompressTool { ...@@ -155,7 +162,16 @@ public class CompressTool {
+ (buff[pos] & 0xff); + (buff[pos] & 0xff);
} }
private int writeInt(byte[] buff, int pos, int x) { /**
* Write a variable size integer using Rice coding.
* Negative values need 5 bytes.
*
* @param buff the buffer
* @param pos the position
* @param x the value
* @return the number of bytes written (0-5)
*/
public static int writeVariableInt(byte[] buff, int pos, int x) {
if (x < 0) { if (x < 0) {
buff[pos++] = (byte) 0xf0; buff[pos++] = (byte) 0xf0;
buff[pos++] = (byte) (x >> 24); buff[pos++] = (byte) (x >> 24);
...@@ -191,7 +207,14 @@ public class CompressTool { ...@@ -191,7 +207,14 @@ public class CompressTool {
} }
} }
private int getLength(int x) { /**
* Get a variable size integer length using Rice coding.
* Negative values need 5 bytes.
*
* @param x the value
* @return the number of bytes needed (0-5)
*/
public static int getVariableIntLength(int x) {
if (x < 0) { if (x < 0) {
return 5; return 5;
} else if (x < 0x80) { } else if (x < 0x80) {
......
...@@ -476,7 +476,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -476,7 +476,7 @@ public class Recover extends Tool implements DataHandler {
boolean last = (type & Page.FLAG_LAST) != 0; boolean last = (type & Page.FLAG_LAST) != 0;
type &= ~Page.FLAG_LAST; type &= ~Page.FLAG_LAST;
if (!PageStore.checksumTest(s.getBytes(), (int) page, pageSize)) { if (!PageStore.checksumTest(s.getBytes(), (int) page, pageSize)) {
writer.println("-- ERROR: page " + page + " checksum mismatch type: " + type); writeDataError(writer, "checksum mismatch type: " + type, s.getBytes());
} }
s.readShortInt(); s.readShortInt();
switch (type) { switch (type) {
......
...@@ -256,9 +256,6 @@ public class Shell extends Tool implements Runnable { ...@@ -256,9 +256,6 @@ public class Shell extends Tool implements Runnable {
} }
rs = prep.executeQuery(); rs = prep.executeQuery();
printResult(rs, false); printResult(rs, false);
} catch (SQLException e) {
println("Exception: " + e.toString());
e.printStackTrace(err);
} finally { } finally {
JdbcUtils.closeSilently(rs); JdbcUtils.closeSilently(rs);
JdbcUtils.closeSilently(prep); JdbcUtils.closeSilently(prep);
...@@ -271,9 +268,6 @@ public class Shell extends Tool implements Runnable { ...@@ -271,9 +268,6 @@ public class Shell extends Tool implements Runnable {
"SELECT CAST(TABLE_SCHEMA AS VARCHAR(32)) AS \"Schema\", TABLE_NAME AS \"Table Name\" " + "SELECT CAST(TABLE_SCHEMA AS VARCHAR(32)) AS \"Schema\", TABLE_NAME AS \"Table Name\" " +
"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) {
println("Exception: " + e.toString());
e.printStackTrace(err);
} finally { } finally {
JdbcUtils.closeSilently(rs); JdbcUtils.closeSilently(rs);
} }
...@@ -365,7 +359,12 @@ public class Shell extends Tool implements Runnable { ...@@ -365,7 +359,12 @@ public class Shell extends Tool implements Runnable {
String user = "sa"; String user = "sa";
String driver = null; String driver = null;
try { try {
Properties prop = SortedProperties.loadProperties(serverPropertiesDir + "/" + Constants.SERVER_PROPERTIES_NAME); Properties prop;
if ("null".equals(serverPropertiesDir)) {
prop = new Properties();
} else {
prop = SortedProperties.loadProperties(serverPropertiesDir + "/" + Constants.SERVER_PROPERTIES_NAME);
}
String data = null; String data = null;
boolean found = false; boolean found = false;
for (int i = 0;; i++) { for (int i = 0;; i++) {
...@@ -481,9 +480,22 @@ public class Shell extends Tool implements Runnable { ...@@ -481,9 +480,22 @@ public class Shell extends Tool implements Runnable {
private void execute(String sql) { private void execute(String sql) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
boolean result;
try { try {
result = stat.execute(sql); ResultSet rs = null;
try {
if (stat.execute(sql)) {
rs = stat.getResultSet();
int rowCount = printResult(rs, listMode);
time = System.currentTimeMillis() - time;
println("(" + rowCount + (rowCount == 1 ? " row, " : " rows, ") + time + " ms)");
} else {
int updateCount = stat.getUpdateCount();
time = System.currentTimeMillis() - time;
println("(Update count: " + updateCount + ", " + time + " ms)");
}
} finally {
JdbcUtils.closeSilently(rs);
}
} catch (SQLException e) { } catch (SQLException e) {
println("Error: " + e.toString()); println("Error: " + e.toString());
if (listMode) { if (listMode) {
...@@ -491,24 +503,6 @@ public class Shell extends Tool implements Runnable { ...@@ -491,24 +503,6 @@ public class Shell extends Tool implements Runnable {
} }
return; return;
} }
ResultSet rs = null;
try {
if (result) {
rs = stat.getResultSet();
int rowCount = printResult(rs, listMode);
time = System.currentTimeMillis() - time;
println("(" + rowCount + (rowCount == 1 ? " row, " : " rows, ") + time + " ms)");
} else {
int updateCount = stat.getUpdateCount();
time = System.currentTimeMillis() - time;
println("(Update count: " + updateCount + ", " + time + " ms)");
}
} catch (SQLException e) {
println("Error: " + e.toString());
e.printStackTrace(err);
} finally {
JdbcUtils.closeSilently(rs);
}
} }
private int printResult(ResultSet rs, boolean asList) throws SQLException { private int printResult(ResultSet rs, boolean asList) throws SQLException {
......
...@@ -33,7 +33,7 @@ public class SoftHashMap<K, V> extends AbstractMap<K, V> { ...@@ -33,7 +33,7 @@ public class SoftHashMap<K, V> extends AbstractMap<K, V> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void processQueue() { private void processQueue() {
while (true) { while (true) {
Reference< ? extends V> o = queue.poll(); Reference<? extends V> o = queue.poll();
if (o == null) { if (o == null) {
return; return;
} }
......
...@@ -89,7 +89,7 @@ public class TempFileDeleter { ...@@ -89,7 +89,7 @@ public class TempFileDeleter {
*/ */
public void deleteUnused() { public void deleteUnused() {
while (queue != null) { while (queue != null) {
Reference< ? extends Object> ref = queue.poll(); Reference<? extends Object> ref = queue.poll();
if (ref == null) { if (ref == null) {
break; break;
} }
......
...@@ -13,6 +13,7 @@ import java.sql.Connection; ...@@ -13,6 +13,7 @@ import java.sql.Connection;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.Server; import org.h2.tools.Server;
import org.h2.util.StringUtils;
import org.h2.util.Task; import org.h2.util.Task;
/** /**
...@@ -92,20 +93,47 @@ public class TestWeb extends TestBase { ...@@ -92,20 +93,47 @@ public class TestWeb extends TestBase {
result = client.get(url, "query.do?sql=@HISTORY"); result = client.get(url, "query.do?sql=@HISTORY");
result = client.get(url, "getHistory.do?id=4"); result = client.get(url, "getHistory.do?id=4");
assertContains(result, "select * from test"); assertContains(result, "select * from test");
result = client.get(url, "autoCompleteList.do?query=select 'abc"); result = client.get(url, "autoCompleteList.do?query=select 'abc");
// expected: ' assertContains(StringUtils.urlDecode(result), "'");
assertContains(result, "%27"); result = client.get(url, "autoCompleteList.do?query=select 'abc''");
assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=select 'abc' ");
assertContains(StringUtils.urlDecode(result), "||");
result = client.get(url, "autoCompleteList.do?query=select 'abc' |");
assertContains(StringUtils.urlDecode(result), "|");
result = client.get(url, "autoCompleteList.do?query=select 'abc' || ");
assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=call timestamp '2");
assertContains(result, "20");
result = client.get(url, "autoCompleteList.do?query=call time '1");
assertContains(StringUtils.urlDecode(result), "12:00:00");
result = client.get(url, "autoCompleteList.do?query=call timestamp '2001-01-01 12:00:00.");
assertContains(result, "nanoseconds");
result = client.get(url, "autoCompleteList.do?query=call timestamp '2001-01-01 12:00:00.00");
assertContains(result, "nanoseconds");
result = client.get(url, "autoCompleteList.do?query=call $$ hello world");
assertContains(StringUtils.urlDecode(result), "$$");
result = client.get(url, "autoCompleteList.do?query=alter index ");
assertContains(StringUtils.urlDecode(result), "character");
result = client.get(url, "autoCompleteList.do?query=alter index idx");
assertContains(StringUtils.urlDecode(result), "character");
result = client.get(url, "autoCompleteList.do?query=alter index \"IDX_");
assertContains(StringUtils.urlDecode(result), "\"");
result = client.get(url, "autoCompleteList.do?query=alter index \"IDX_\"\"");
assertContains(StringUtils.urlDecode(result), "\"");
result = client.get(url, "autoCompleteList.do?query=help ");
assertContains(result, "anything");
result = client.get(url, "autoCompleteList.do?query=help select");
assertContains(result, "anything");
result = client.get(url, "autoCompleteList.do?query=call ");
assertContains(result, "0x");
result = client.get(url, "autoCompleteList.do?query=call 0");
assertContains(result, "0x");
result = client.get(url, "autoCompleteList.do?query=call 0x");
assertContains(result, "hex character");
result = client.get(url, "autoCompleteList.do?query=call 0x123");
assertContains(result, "hex character");
result = client.get(url, "autoCompleteList.do?query=se"); result = client.get(url, "autoCompleteList.do?query=se");
// long time = System.currentTimeMillis();
// for (int i=0; i<1000; i++) {
// if(System.currentTimeMillis()-time > 15000) {
// break;
// }
// result = client.get(url, "autoCompleteList.do?query=select * from ");
assertContains(result, "select"); assertContains(result, "select");
assertContains(result, "set"); assertContains(result, "set");
result = client.get(url, "tables.do"); result = client.get(url, "tables.do");
...@@ -117,7 +145,9 @@ public class TestWeb extends TestBase { ...@@ -117,7 +145,9 @@ public class TestWeb extends TestBase {
result = client.get(url, "autoCompleteList.do?query=select id x from test te where t"); result = client.get(url, "autoCompleteList.do?query=select id x from test te where t");
assertContains(result, "te"); assertContains(result, "te");
result = client.get(url, "autoCompleteList.do?query=select * from test where name = '"); result = client.get(url, "autoCompleteList.do?query=select * from test where name = '");
assertContains(result, "%27"); assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=select * from information_schema.columns where columns.");
assertContains(result, "column_name");
result = client.get(url, "query.do?sql=delete from test"); result = client.get(url, "query.do?sql=delete from test");
result = client.get(url, "query.do?sql=@LOOP 10 @STATEMENT insert into test values(?, 'Hello')"); result = client.get(url, "query.do?sql=@LOOP 10 @STATEMENT insert into test values(?, 'Hello')");
......
...@@ -6,11 +6,16 @@ ...@@ -6,11 +6,16 @@
*/ */
package org.h2.test.unit; package org.h2.test.unit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random; import java.util.Random;
import org.h2.compress.CompressLZF; import org.h2.compress.CompressLZF;
import org.h2.compress.Compressor; import org.h2.compress.Compressor;
...@@ -18,6 +23,7 @@ import org.h2.engine.Constants; ...@@ -18,6 +23,7 @@ import org.h2.engine.Constants;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.util.IOUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.Task; import org.h2.util.Task;
...@@ -27,6 +33,7 @@ import org.h2.util.Task; ...@@ -27,6 +33,7 @@ import org.h2.util.Task;
public class TestCompress extends TestBase { public class TestCompress extends TestBase {
private boolean testPerformance; private boolean testPerformance;
private byte[] buff = new byte[10];
/** /**
* Run just this test. * Run just this test.
...@@ -43,6 +50,7 @@ public class TestCompress extends TestBase { ...@@ -43,6 +50,7 @@ public class TestCompress extends TestBase {
System.exit(0); System.exit(0);
return; return;
} }
testVariableSizeInt();
testMultiThreaded(); testMultiThreaded();
if (config.big) { if (config.big) {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
...@@ -62,6 +70,30 @@ public class TestCompress extends TestBase { ...@@ -62,6 +70,30 @@ public class TestCompress extends TestBase {
testVariableEnd(); testVariableEnd();
} }
private void testVariableSizeInt() {
assertEquals(1, CompressTool.getVariableIntLength(0));
assertEquals(2, CompressTool.getVariableIntLength(0x80));
assertEquals(3, CompressTool.getVariableIntLength(0x4000));
assertEquals(4, CompressTool.getVariableIntLength(0x200000));
assertEquals(5, CompressTool.getVariableIntLength(0x10000000));
assertEquals(5, CompressTool.getVariableIntLength(-1));
for (int x = 0; x < 0x20000; x++) {
testVar(x);
testVar(Integer.MIN_VALUE + x);
testVar(Integer.MAX_VALUE - x);
testVar(0x200000 + x - 100);
testVar(0x10000000 + x - 100);
}
}
private void testVar(int x) {
int len = CompressTool.getVariableIntLength(x);
int l2 = CompressTool.writeVariableInt(buff, 0, x);
assertEquals(len, l2);
int x2 = CompressTool.readVariableInt(buff, 0);
assertEquals(x2, x);
}
private void testMultiThreaded() throws Exception { private void testMultiThreaded() throws Exception {
Task[] tasks = new Task[3]; Task[] tasks = new Task[3];
for (int i = 0; i < tasks.length; i++) { for (int i = 0; i < tasks.length; i++) {
...@@ -166,7 +198,7 @@ public class TestCompress extends TestBase { ...@@ -166,7 +198,7 @@ public class TestCompress extends TestBase {
} }
} }
private void test(int len) { private void test(int len) throws IOException {
Random r = new Random(len); Random r = new Random(len);
for (int pattern = 0; pattern < 4; pattern++) { for (int pattern = 0; pattern < 4; pattern++) {
byte[] buff = new byte[len]; byte[] buff = new byte[len];
...@@ -200,7 +232,8 @@ public class TestCompress extends TestBase { ...@@ -200,7 +232,8 @@ public class TestCompress extends TestBase {
} }
} }
CompressTool utils = CompressTool.getInstance(); CompressTool utils = CompressTool.getInstance();
for (String a : new String[] { "LZF", "No", "Deflate" }) { // level 9 is highest, strategy 2 is huffman only
for (String a : new String[] { "LZF", "No", "Deflate", "Deflate level 9 strategy 2" }) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
byte[] out = utils.compress(buff, a); byte[] out = utils.compress(buff, a);
byte[] test = utils.expand(out); byte[] test = utils.expand(out);
...@@ -209,6 +242,20 @@ public class TestCompress extends TestBase { ...@@ -209,6 +242,20 @@ public class TestCompress extends TestBase {
} }
assertEquals(buff.length, test.length); assertEquals(buff.length, test.length);
assertEquals(buff, test); assertEquals(buff, test);
Arrays.fill(test, (byte) 0);
utils.expand(out, test, 0);
assertEquals(buff, test);
}
for (String a : new String[] { null, "LZF", "DEFLATE", "ZIP", "GZIP" }) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream out2 = CompressTool.wrapOutputStream(out, a, "test");
IOUtils.copy(new ByteArrayInputStream(buff), out2);
out2.close();
InputStream in = new ByteArrayInputStream(out.toByteArray());
in = CompressTool.wrapInputStream(in, a, "test");
out.reset();
IOUtils.copy(in, out);
assertEquals(buff, out.toByteArray());
} }
} }
} }
......
...@@ -44,11 +44,6 @@ public class TestFileSystem extends TestBase { ...@@ -44,11 +44,6 @@ public class TestFileSystem extends TestBase {
testDatabaseInJar(); testDatabaseInJar();
// set default part size to 1 << 10 // set default part size to 1 << 10
FileSystem.getInstance("split:10:" + getBaseDir() + "/fs"); FileSystem.getInstance("split:10:" + getBaseDir() + "/fs");
if (!config.splitFileSystem) {
testFileSystem("nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:" + getBaseDir() + "/fs");
}
testFileSystem(getBaseDir() + "/fs"); testFileSystem(getBaseDir() + "/fs");
testFileSystem(FileSystemMemory.PREFIX); testFileSystem(FileSystemMemory.PREFIX);
FileSystemDatabase fs = FileSystemDatabase.register("jdbc:h2:mem:fs"); FileSystemDatabase fs = FileSystemDatabase.register("jdbc:h2:mem:fs");
...@@ -57,7 +52,15 @@ public class TestFileSystem extends TestBase { ...@@ -57,7 +52,15 @@ public class TestFileSystem extends TestBase {
testFileSystem(FileSystemMemory.PREFIX_LZF); testFileSystem(FileSystemMemory.PREFIX_LZF);
testUserHome(); testUserHome();
fs.unregister(); fs.unregister();
IOUtils.delete(getBaseDir() + "/fs"); try {
if (!config.splitFileSystem) {
testFileSystem("split:" + getBaseDir() + "/fs");
testFileSystem("nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:nioMapped:" + getBaseDir() + "/fs");
}
} finally {
IOUtils.delete(getBaseDir() + "/fs");
}
} }
private void testDatabaseInMemFileSys() throws SQLException { private void testDatabaseInMemFileSys() throws SQLException {
......
...@@ -7,10 +7,14 @@ ...@@ -7,10 +7,14 @@
package org.h2.test.unit; package org.h2.test.unit;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.engine.Constants;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
...@@ -31,11 +35,80 @@ public class TestRecovery extends TestBase { ...@@ -31,11 +35,80 @@ public class TestRecovery extends TestBase {
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
public void test() throws SQLException { public void test() throws Exception {
testCorrupt();
testWithTransactionLog();
testCompressedAndUncompressed(); testCompressedAndUncompressed();
testRunScript(); testRunScript();
} }
private void testCorrupt() throws Exception {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table test(id int, name varchar) as select 1, 'Hello World1'");
conn.close();
FileObject f = FileSystem.getInstance(getBaseDir()).openFileObject(getBaseDir() + "/recovery.h2.db", "rw");
byte[] buff = new byte[Constants.DEFAULT_PAGE_SIZE];
while (f.getFilePointer() < f.length()) {
f.readFully(buff, 0, buff.length);
if (new String(buff).indexOf("Hello World1") >= 0) {
buff[buff.length - 1]++;
f.seek(f.getFilePointer() - buff.length);
f.write(buff, 0, buff.length);
}
}
f.close();
Recover.main("-dir", getBaseDir(), "-db", "recovery");
String script = IOUtils.readStringAndClose(new InputStreamReader(IOUtils.openFileInputStream(getBaseDir() + "/recovery.h2.sql")), -1);
assertContains(script, "checksum mismatch");
assertContains(script, "dump:");
assertContains(script, "Hello World2");
}
private void testWithTransactionLog() throws SQLException {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table truncate(id int primary key) as select x from system_range(1, 1000)");
stat.execute("create table test(id int primary key, data int, text varchar)");
stat.execute("create index on test(data, id)");
stat.execute("insert into test direct select x, 0, null from system_range(1, 1000)");
stat.execute("insert into test values(-1, -1, space(10000))");
stat.execute("checkpoint");
stat.execute("delete from test where id = -1");
stat.execute("truncate table truncate");
conn.setAutoCommit(false);
long base = 0;
while (true) {
ResultSet rs = stat.executeQuery("select value from information_schema.settings where name = 'info.FILE_WRITE'");
rs.next();
long count = rs.getLong(1);
if (base == 0) {
base = count;
} else if (count > base + 10) {
break;
}
stat.execute("update test set data=0");
stat.execute("update test set text=space(10000) where id = 0");
stat.execute("update test set data=1, text = null");
conn.commit();
}
stat.execute("shutdown immediately");
try {
conn.close();
} catch (Exception e) {
// expected
}
Recover.main("-dir", getBaseDir(), "-db", "recovery");
conn = getConnection("recovery");
conn.close();
Recover.main("-dir", getBaseDir(), "-db", "recovery", "-removePassword");
conn = getConnection("recovery", getUser(), "");
conn.close();
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
}
private void testCompressedAndUncompressed() throws SQLException { private void testCompressedAndUncompressed() throws SQLException {
DeleteDbFiles.execute(getBaseDir(), "recovery", true); DeleteDbFiles.execute(getBaseDir(), "recovery", true);
DeleteDbFiles.execute(getBaseDir(), "recovery2", true); DeleteDbFiles.execute(getBaseDir(), "recovery2", true);
...@@ -74,10 +147,12 @@ public class TestRecovery extends TestBase { ...@@ -74,10 +147,12 @@ public class TestRecovery extends TestBase {
org.h2.Driver.load(); org.h2.Driver.load();
Connection conn = getConnection("recovery"); Connection conn = getConnection("recovery");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("create table \"Joe\"\"s Table\" as select 1");
stat.execute("create table test as select * from system_range(1, 100)"); stat.execute("create table test as select * from system_range(1, 100)");
stat.execute("create view \"TEST VIEW OF TABLE TEST\" as select * from test");
stat.execute("create table a(id int primary key) as select * from system_range(1, 100)"); stat.execute("create table a(id int primary key) as select * from system_range(1, 100)");
stat.execute("create table b(id int references a(id)) as select * from system_range(1, 100)"); stat.execute("create table b(id int references a(id)) as select * from system_range(1, 100)");
stat.execute("create table c(d clob) as select space(10000) || 'end'"); stat.execute("create table lob(c clob, b blob) as select space(10000) || 'end', SECURE_RAND(10000)");
stat.execute("create table d(d varchar) as select space(10000) || 'end'"); stat.execute("create table d(d varchar) as select space(10000) || 'end'");
stat.execute("alter table a add foreign key(id) references b(id)"); stat.execute("alter table a add foreign key(id) references b(id)");
// all rows have the same value - so that SCRIPT can't re-order the rows // all rows have the same value - so that SCRIPT can't re-order the rows
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
package org.h2.test.unit; package org.h2.test.unit;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
...@@ -13,10 +14,9 @@ import java.io.LineNumberReader; ...@@ -13,10 +14,9 @@ import java.io.LineNumberReader;
import java.io.PipedInputStream; import java.io.PipedInputStream;
import java.io.PipedOutputStream; import java.io.PipedOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.sql.SQLException;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.Shell; import org.h2.tools.Shell;
import org.h2.util.Task;
/** /**
* Test the shell tool. * Test the shell tool.
...@@ -46,42 +46,62 @@ public class TestShell extends TestBase { ...@@ -46,42 +46,62 @@ public class TestShell extends TestBase {
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
public void test() throws IOException { public void test() throws Exception {
Shell shell = new Shell();
ByteArrayOutputStream buff = new ByteArrayOutputStream();
shell.setOut(new PrintStream(buff));
shell.runTool("-url", "jdbc:h2:mem:", "-driver", "org.h2.Driver",
"-user", "sa", "-password", "sa", "-properties", "null", "-sql", "select 'Hello ' || 'World' as hi");
String s = new String(buff.toByteArray());
assertContains(s, "HI");
assertContains(s, "Hello World");
assertContains(s, "(1 row, ");
test(true);
test(false);
}
private void test(final boolean commandLineArgs) throws IOException {
testIn = new PipedInputStream(); testIn = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(testIn); PipedOutputStream out = new PipedOutputStream(testIn);
toolOut = new PrintStream(out, true); toolOut = new PrintStream(out, true);
out = new PipedOutputStream(); out = new PipedOutputStream();
testOut = new PrintStream(out, true); testOut = new PrintStream(out, true);
toolIn = new PipedInputStream(out); toolIn = new PipedInputStream(out);
new Thread(new Runnable() { Task task = new Task() {
public void run() { public void call() throws Exception {
try { try {
Shell shell = new Shell(); Shell shell = new Shell();
shell.setIn(toolIn); shell.setIn(toolIn);
shell.setOut(toolOut); shell.setOut(toolOut);
shell.setErr(toolOut); shell.setErr(toolOut);
shell.runTool(); if (commandLineArgs) {
} catch (SQLException e) { shell.runTool("-url", "jdbc:h2:mem:",
e.printStackTrace(); "-user", "sa", "-password", "sa");
} else {
shell.runTool();
}
} finally { } finally {
toolOut.close(); toolOut.close();
} }
} }
}).start(); };
task.execute();
InputStreamReader reader = new InputStreamReader(testIn); InputStreamReader reader = new InputStreamReader(testIn);
lineReader = new LineNumberReader(reader); lineReader = new LineNumberReader(reader);
read(""); read("");
read("Welcome to H2 Shell"); read("Welcome to H2 Shell");
read("Exit with"); read("Exit with");
read("[Enter]"); if (!commandLineArgs) {
testOut.println("jdbc:h2:mem:"); read("[Enter]");
read("URL"); testOut.println("jdbc:h2:mem:");
testOut.println("org.h2.Driver"); read("URL");
read("Driver"); testOut.println("");
testOut.println("sa"); read("Driver");
read("User"); testOut.println("sa");
testOut.println("sa"); read("User");
read("Password"); testOut.println("sa");
read("Password");
}
read("Commands are case insensitive"); read("Commands are case insensitive");
read("help or ?"); read("help or ?");
read("list"); read("list");
...@@ -92,6 +112,31 @@ public class TestShell extends TestBase { ...@@ -92,6 +112,31 @@ public class TestShell extends TestBase {
read("history"); read("history");
read("quit or exit"); read("quit or exit");
read(""); read("");
testOut.println("history");
read("sql> No history");
testOut.println("1");
read("sql> Not found");
testOut.println("select 1 a;");
read("sql> A");
read("1");
read("(1 row,");
testOut.println("history");
read("sql> #1: select 1 a");
read("To re-run a statement, type the number and press and enter");
testOut.println("1");
read("sql> select 1 a");
read("A");
read("1");
read("(1 row,");
testOut.println("select 'x' || space(1000) large, 'y' small;");
read("sql> LARGE");
read("x");
read("(data is partially truncated)");
read("(1 row,");
testOut.println("select error;");
read("sql> Error:");
read("select error");
testOut.println("create table test(id int primary key, name varchar)\n;"); testOut.println("create table test(id int primary key, name varchar)\n;");
read("sql> ...>"); read("sql> ...>");
testOut.println("show public"); testOut.println("show public");
...@@ -105,12 +150,52 @@ public class TestShell extends TestBase { ...@@ -105,12 +150,52 @@ public class TestShell extends TestBase {
read("sql> ID"); read("sql> ID");
read("1 "); read("1 ");
read("(1 row,"); read("(1 row,");
testOut.println("maxwidth");
read("sql> Usage: maxwidth <integer value>");
read("Maximum column width is now 100");
testOut.println("maxwidth 80");
read("sql> Maximum column width is now 80");
testOut.println("autocommit");
read("sql> Usage: autocommit [true|false]");
read("Autocommit is now true");
testOut.println("autocommit false");
read("sql> Autocommit is now false");
testOut.println("autocommit true");
read("sql> Autocommit is now true");
testOut.println("describe");
read("sql> Usage: describe [<schema name>.]<table name>");
testOut.println("describe test"); testOut.println("describe test");
read("sql> Column Name"); read("sql> Column Name");
read("ID"); read("ID");
read("NAME"); read("NAME");
testOut.println("describe public.test");
read("sql> Column Name");
read("ID");
read("NAME");
testOut.println("\n;");
read("sql>");
testOut.println("list");
read("sql> Result list mode is now on");
testOut.println("select 1 a, 2 b;");
read("sql> A: 1");
read("B: 2");
read("(1 row, ");
testOut.println("list");
read("sql> Result list mode is now off");
testOut.println("help");
read("sql> Commands are case insensitive");
read("help or ?");
read("list");
read("maxwidth");
read("show");
read("describe");
read("autocommit");
read("history");
read("quit or exit");
read("");
testOut.println("exit"); testOut.println("exit");
read("sql>"); read("sql>");
task.get();
} }
private String read(String expectedStart) throws IOException { private String read(String expectedStart) throws IOException {
......
...@@ -218,7 +218,7 @@ public class WeakIdentityHashMap<K, V> implements Map<K, V> { ...@@ -218,7 +218,7 @@ public class WeakIdentityHashMap<K, V> implements Map<K, V> {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public void putAll(Map< ? extends K, ? extends V> m) { public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论