提交 41540b10 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 22752adb
...@@ -31,7 +31,7 @@ public class Bnf { ...@@ -31,7 +31,7 @@ public class Bnf {
static final boolean COMBINE_KEYWORDS = false; static final boolean COMBINE_KEYWORDS = false;
private static final String SEPARATORS = " [](){}|.,\r\n<>:-+*/=<\">!'"; private static final String SEPARATORS = " [](){}|.,\r\n<>:-+*/=<\">!'$";
private static final long MAX_PARSE_TIME = 100; private static final long MAX_PARSE_TIME = 100;
private final Random random = new Random(); private final Random random = new Random();
...@@ -127,6 +127,7 @@ public class Bnf { ...@@ -127,6 +127,7 @@ public class Bnf {
addFixedRule("anythingExceptDoubleQuote", RuleFixed.ANY_EXCEPT_DOUBLE_QUOTE); addFixedRule("anythingExceptDoubleQuote", RuleFixed.ANY_EXCEPT_DOUBLE_QUOTE);
addFixedRule("anythingUntilEndOfLine", RuleFixed.ANY_UNTIL_EOL); addFixedRule("anythingUntilEndOfLine", RuleFixed.ANY_UNTIL_EOL);
addFixedRule("anythingUntilEndComment", RuleFixed.ANY_UNTIL_END); addFixedRule("anythingUntilEndComment", RuleFixed.ANY_UNTIL_END);
addFixedRule("anythingExceptTwoDollarSigns", RuleFixed.ANY_EXCEPT_2_DOLLAR);
addFixedRule("anything", RuleFixed.ANY_WORD); addFixedRule("anything", RuleFixed.ANY_WORD);
addFixedRule("@hexStart@", RuleFixed.HEX_START); addFixedRule("@hexStart@", RuleFixed.HEX_START);
addFixedRule("@concat@", RuleFixed.CONCAT); addFixedRule("@concat@", RuleFixed.CONCAT);
......
...@@ -19,6 +19,7 @@ public class RuleFixed implements Rule { ...@@ -19,6 +19,7 @@ public class RuleFixed implements Rule {
static final int ANY_UNTIL_EOL = 5; static final int ANY_UNTIL_EOL = 5;
static final int ANY_UNTIL_END = 6; static final int ANY_UNTIL_END = 6;
static final int ANY_WORD = 7; static final int ANY_WORD = 7;
static final int ANY_EXCEPT_2_DOLLAR = 8;
static final int HEX_START = 10, CONCAT = 11, AZ_UNDERLINE = 12, AF = 13, DIGIT = 14; static final int HEX_START = 10, CONCAT = 11, AZ_UNDERLINE = 12, AF = 13, DIGIT = 14;
private final int type; private final int type;
...@@ -39,6 +40,7 @@ public class RuleFixed implements Rule { ...@@ -39,6 +40,7 @@ public class RuleFixed implements Rule {
case ANY_EXCEPT_SINGLE_QUOTE: case ANY_EXCEPT_SINGLE_QUOTE:
case ANY_EXCEPT_DOUBLE_QUOTE: case ANY_EXCEPT_DOUBLE_QUOTE:
case ANY_WORD: case ANY_WORD:
case ANY_EXCEPT_2_DOLLAR:
case ANY_UNTIL_END: { case ANY_UNTIL_END: {
return "XYZ"; return "XYZ";
} }
...@@ -70,6 +72,7 @@ public class RuleFixed implements Rule { ...@@ -70,6 +72,7 @@ public class RuleFixed implements Rule {
case ANY_EXCEPT_SINGLE_QUOTE: case ANY_EXCEPT_SINGLE_QUOTE:
case ANY_EXCEPT_DOUBLE_QUOTE: case ANY_EXCEPT_DOUBLE_QUOTE:
case ANY_WORD: case ANY_WORD:
case ANY_EXCEPT_2_DOLLAR:
case ANY_UNTIL_END: { case ANY_UNTIL_END: {
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
int len = r.nextBoolean() ? 1 : r.nextInt(5); int len = r.nextBoolean() ? 1 : r.nextInt(5);
...@@ -168,6 +171,14 @@ public class RuleFixed implements Rule { ...@@ -168,6 +171,14 @@ public class RuleFixed implements Rule {
} }
} }
break; break;
case ANY_EXCEPT_2_DOLLAR:
while (true) {
while (s.length() > 0 && !s.startsWith("$$")) {
s = s.substring(1);
}
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);
...@@ -237,6 +248,12 @@ public class RuleFixed implements Rule { ...@@ -237,6 +248,12 @@ public class RuleFixed implements Rule {
sentence.add("'", "'", Sentence.KEYWORD); sentence.add("'", "'", Sentence.KEYWORD);
} }
break; break;
case ANY_EXCEPT_2_DOLLAR:
if (query.length() == 0) {
sentence.add("anything", "Hello World", Sentence.KEYWORD);
sentence.add("'", "'", Sentence.KEYWORD);
}
break;
case ANY_EXCEPT_DOUBLE_QUOTE: case ANY_EXCEPT_DOUBLE_QUOTE:
if (query.length() == 0) { if (query.length() == 0) {
sentence.add("anything", "identifier", Sentence.KEYWORD); sentence.add("anything", "identifier", Sentence.KEYWORD);
......
...@@ -57,7 +57,7 @@ public class CommandRemote implements CommandInterface { ...@@ -57,7 +57,7 @@ public class CommandRemote implements CommandInterface {
for (int i = 0; i < transferList.size(); i++) { for (int i = 0; i < transferList.size(); i++) {
try { try {
Transfer transfer = (Transfer) transferList.get(i); Transfer transfer = (Transfer) transferList.get(i);
if (readParams) { if (readParams && createParams) {
session.traceOperation("SESSION_PREPARE_READ_PARAMS", id); session.traceOperation("SESSION_PREPARE_READ_PARAMS", id);
transfer.writeInt(SessionRemote.SESSION_PREPARE_READ_PARAMS).writeInt(id).writeString(sql); transfer.writeInt(SessionRemote.SESSION_PREPARE_READ_PARAMS).writeInt(id).writeString(sql);
} else { } else {
......
...@@ -150,7 +150,7 @@ public class Parser { ...@@ -150,7 +150,7 @@ public class Parser {
// used during the tokenizer phase // used during the tokenizer phase
private static final int CHAR_END = -1, CHAR_VALUE = 2, CHAR_QUOTED = 3; private static final int CHAR_END = -1, CHAR_VALUE = 2, CHAR_QUOTED = 3;
private static final int CHAR_NAME = 4, CHAR_SPECIAL_1 = 5, CHAR_SPECIAL_2 = 6; private static final int CHAR_NAME = 4, CHAR_SPECIAL_1 = 5, CHAR_SPECIAL_2 = 6;
private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8; private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8, CHAR_DOLLAR_QUOTED_STRING = 9;
// this are token types // this are token types
private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE = 5; private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE = 5;
...@@ -2561,7 +2561,21 @@ public class Parser { ...@@ -2561,7 +2561,21 @@ public class Parser {
i++; i++;
} }
currentToken = "'"; currentToken = "'";
checkLiterals(false); checkLiterals(true);
currentValue = ValueString.get(StringCache.getNew(result));
parseIndex = i;
currentTokenType = VALUE;
return;
}
case CHAR_DOLLAR_QUOTED_STRING: {
String result = null;
int begin = i - 1;
while (types[i] == CHAR_DOLLAR_QUOTED_STRING) {
i++;
}
result = sqlCommand.substring(begin, i);
currentToken = "'";
checkLiterals(true);
currentValue = ValueString.get(StringCache.getNew(result)); currentValue = ValueString.get(StringCache.getNew(result));
parseIndex = i; parseIndex = i;
currentTokenType = VALUE; currentTokenType = VALUE;
...@@ -2712,6 +2726,26 @@ public class Parser { ...@@ -2712,6 +2726,26 @@ public class Parser {
type = CHAR_SPECIAL_1; type = CHAR_SPECIAL_1;
} }
break; break;
case '$':
if (SysProperties.DOLLAR_QUOTING && command[i + 1] == '$' && (i == 0 || command[i - 1] <= ' ')) {
// dollar quoted string
changed = true;
command[i] = ' ';
command[i + 1] = ' ';
startLoop = i;
i += 2;
checkRunOver(i, len, startLoop);
while (command[i] != '$' || command[i + 1] != '$') {
types[i++] = CHAR_DOLLAR_QUOTED_STRING;
checkRunOver(i, len, startLoop);
}
command[i] = ' ';
command[i + 1] = ' ';
i++;
} else {
type = CHAR_SPECIAL_1;
}
break;
case '(': case '(':
case ')': case ')':
case '{': case '{':
...@@ -2723,7 +2757,6 @@ public class Parser { ...@@ -2723,7 +2757,6 @@ public class Parser {
case '%': case '%':
case '?': case '?':
case '@': case '@':
case '$':
case ']': case ']':
type = CHAR_SPECIAL_1; type = CHAR_SPECIAL_1;
break; break;
......
...@@ -183,6 +183,14 @@ public class SysProperties { ...@@ -183,6 +183,14 @@ public class SysProperties {
*/ */
public static final int DELAY_WRONG_PASSWORD_MAX = getIntSetting("h2.delayWrongPasswordMax", 4000); public static final int DELAY_WRONG_PASSWORD_MAX = getIntSetting("h2.delayWrongPasswordMax", 4000);
/**
* System property <code>h2.dollarQuoting</code> (default: true).<br />
* Dollar quoting is used to quote text without having to use escape
* characters. A dollar quoted string starts and ends with $$. Inside the
* text, $$ is not allowed.
*/
public static final boolean DOLLAR_QUOTING = getBooleanSetting("h2.dollarQuoting", true);
/** /**
* System property <code>h2.emergencySpaceInitial</code> (default: 262144).<br /> * System property <code>h2.emergencySpaceInitial</code> (default: 262144).<br />
* Size of 'reserve' file to detect disk full problems early. * Size of 'reserve' file to detect disk full problems early.
......
...@@ -35,7 +35,8 @@ package org.h2.engine; ...@@ -35,7 +35,8 @@ package org.h2.engine;
* - No " Message.get" (must be "throw Message.get") * - No " Message.get" (must be "throw Message.get")
* - No TODO in the docs, remove @~ in .utf8.txt files * - No TODO in the docs, remove @~ in .utf8.txt files
* - Run regression test with JDK 1.4 and 1.5 * - Run regression test with JDK 1.4 and 1.5
* - Use latest versions of other dbs (Derby 10.4.1.3; PostgreSQL 8.3.1; MySQL 5.0.51) * - Use latest versions of other dbs (Derby 10.4.1.3;
* PostgreSQL 8.3.1; MySQL 5.0.51)
* - Change version(s) in performance.html * - Change version(s) in performance.html
* - Run 'ant benchmark' (with JDK 1.4 currently) * - Run 'ant benchmark' (with JDK 1.4 currently)
* - Copy the benchmark results and update the performance page and diagram * - Copy the benchmark results and update the performance page and diagram
......
...@@ -580,6 +580,9 @@ public class Session implements SessionInterface { ...@@ -580,6 +580,9 @@ public class Session implements SessionInterface {
return firstUncommittedPos; return firstUncommittedPos;
} }
/**
* This method is called after the log file has committed this session.
*/
public void setAllCommitted() { public void setAllCommitted() {
firstUncommittedLog = LogSystem.LOG_WRITTEN; firstUncommittedLog = LogSystem.LOG_WRITTEN;
firstUncommittedPos = LogSystem.LOG_WRITTEN; firstUncommittedPos = LogSystem.LOG_WRITTEN;
......
...@@ -238,7 +238,8 @@ public class SessionRemote implements SessionInterface, DataHandler { ...@@ -238,7 +238,8 @@ public class SessionRemote implements SessionInterface, DataHandler {
private void upgradeClientVersionIfPossible() { private void upgradeClientVersionIfPossible() {
try { try {
// TODO check if a newer client version can be used - not required when sending TCP_DRIVER_VERSION_6 // TODO check if a newer client version can be used
// not required when sending TCP_DRIVER_VERSION_6
CommandInterface command = prepareCommand("SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?", 1); CommandInterface command = prepareCommand("SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?", 1);
ParameterInterface param = (ParameterInterface) command.getParameters().get(0); ParameterInterface param = (ParameterInterface) command.getParameters().get(0);
param.setValue(ValueString.get("info.BUILD_ID")); param.setValue(ValueString.get("info.BUILD_ID"));
......
...@@ -75,5 +75,4 @@ public class ParameterRemote implements ParameterInterface { ...@@ -75,5 +75,4 @@ public class ParameterRemote implements ParameterInterface {
transfer.writeInt(p.getNullable()); transfer.writeInt(p.getNullable());
} }
} }
...@@ -1027,6 +1027,16 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1027,6 +1027,16 @@ public class JdbcConnection extends TraceObject implements Connection {
private int translateGetEnd(String sql, int i, char c) throws SQLException { private int translateGetEnd(String sql, int i, char c) throws SQLException {
int len = sql.length(); int len = sql.length();
switch(c) { switch(c) {
case '$': {
if (i < len - 1 && sql.charAt(i + 1) == '$' && (i == 0 || sql.charAt(i - 1) <= ' ')) {
int j = sql.indexOf("$$", i + 2);
if (j < 0) {
throw Message.getSyntaxError(sql, i);
}
return j + 1;
}
return i;
}
case '\'': { case '\'': {
int j = sql.indexOf('\'', i + 1); int j = sql.indexOf('\'', i + 1);
if (j < 0) { if (j < 0) {
...@@ -1173,6 +1183,11 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -1173,6 +1183,11 @@ public class JdbcConnection extends TraceObject implements Connection {
} }
chars[i] = ' '; chars[i] = ' ';
break; break;
case '$':
if (SysProperties.DOLLAR_QUOTING) {
i = translateGetEnd(sql, i, c);
}
break;
default: default:
} }
} }
......
...@@ -77,6 +77,12 @@ public class Trace { ...@@ -77,6 +77,12 @@ public class Trace {
buff.append(lineSeparator); buff.append(lineSeparator);
buff.append("/*SQL "); buff.append("/*SQL ");
if (params.length() > 0) { if (params.length() > 0) {
// This looks like a bug, but it is intentional:
// If there are no parameters, the SQL statement is
// the rest of the line. If there are parameters, they
// are appended at the end of the line. Knowing the size
// of the statement simplifies separating the SQL statement
// from the parameters (no need to parse).
buff.append("l:"); buff.append("l:");
buff.append(sql.length()); buff.append(sql.length());
} }
......
...@@ -1333,7 +1333,7 @@ A value. Parameters can be indexed, for example ?1 meaning the first parameter. ...@@ -1333,7 +1333,7 @@ A value. Parameters can be indexed, for example ?1 meaning the first parameter.
'Hello' 'Hello'
" "
"Other Grammar","Value"," "Other Grammar","Value","
string | hexNumber | int | long | decimal | double | string | dollarQuotedString | hexNumber | int | long | decimal | double |
date | time | timestamp | boolean | bytes | array | null date | time | timestamp | boolean | bytes | array | null
"," ","
A value of any data type, or null A value of any data type, or null
...@@ -1398,6 +1398,7 @@ An alias is a name that is only valid in the context of the statement. ...@@ -1398,6 +1398,7 @@ An alias is a name that is only valid in the context of the statement.
"," ","
A A
" "
"Other Grammar","Quoted Name"," "Other Grammar","Quoted Name","
""anythingExceptDoubleQuote"" ""anythingExceptDoubleQuote""
"," ","
...@@ -1406,6 +1407,7 @@ Two double quotes can be used to create a single double quote inside an identifi ...@@ -1406,6 +1407,7 @@ Two double quotes can be used to create a single double quote inside an identifi
"," ","
""FirstName"" ""FirstName""
" "
"Other Grammar","String"," "Other Grammar","String","
'anythingExceptSingleQuote' 'anythingExceptSingleQuote'
"," ","
...@@ -1414,6 +1416,17 @@ Two single quotes can be used to create a single quote inside a string. ...@@ -1414,6 +1416,17 @@ Two single quotes can be used to create a single quote inside a string.
"," ","
'John''s car' 'John''s car'
" "
"Other Grammar","Dollar Quoted String","
$$anythingExceptTwoDollarSigns$$
","
A string starts and ends with two dollar signs.
Two dollar signs are not allowed within the text.
No escaping is required within the text.
","
$$John's car$$
"
"Other Grammar","Int"," "Other Grammar","Int","
[- | +] digit [...] [- | +] digit [...]
"," ","
...@@ -1421,6 +1434,7 @@ The maximum integer number is 2147483647, the minimum is -2147483648. ...@@ -1421,6 +1434,7 @@ The maximum integer number is 2147483647, the minimum is -2147483648.
"," ","
10 10
" "
"Other Grammar","Long"," "Other Grammar","Long","
[- | +] digit [...] [- | +] digit [...]
"," ","
......
...@@ -10,6 +10,7 @@ import java.io.IOException; ...@@ -10,6 +10,7 @@ import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.message.Message; import org.h2.message.Message;
/** /**
...@@ -49,6 +50,7 @@ public class ScriptReader { ...@@ -49,6 +50,7 @@ public class ScriptReader {
return null; return null;
} }
StringBuffer buff = new StringBuffer(200); StringBuffer buff = new StringBuffer(200);
int previous = 0;
int c = read(); int c = read();
while (true) { while (true) {
if (c < 0) { if (c < 0) {
...@@ -58,6 +60,34 @@ public class ScriptReader { ...@@ -58,6 +60,34 @@ public class ScriptReader {
break; break;
} }
switch (c) { switch (c) {
case '$': {
buff.append((char) c);
c = read();
if (c == '$' && SysProperties.DOLLAR_QUOTING && previous <= ' ') {
// dollar quoted string
buff.append((char) c);
while (true) {
c = read();
if (c < 0) {
break;
}
buff.append((char) c);
if (c == '$') {
c = read();
if (c < 0) {
break;
}
buff.append((char) c);
if (c == '$') {
break;
}
}
}
previous = c;
c = read();
}
break;
}
case '\'': case '\'':
buff.append((char) c); buff.append((char) c);
while (true) { while (true) {
...@@ -70,6 +100,7 @@ public class ScriptReader { ...@@ -70,6 +100,7 @@ public class ScriptReader {
break; break;
} }
} }
previous = c;
c = read(); c = read();
break; break;
case '"': case '"':
...@@ -84,10 +115,12 @@ public class ScriptReader { ...@@ -84,10 +115,12 @@ public class ScriptReader {
break; break;
} }
} }
previous = c;
c = read(); c = read();
break; break;
case '/': { case '/': {
int last = c; int last = c;
previous = c;
c = read(); c = read();
if (c == '*') { if (c == '*') {
// block comment // block comment
...@@ -119,6 +152,7 @@ public class ScriptReader { ...@@ -119,6 +152,7 @@ public class ScriptReader {
} }
} }
} }
previous = c;
c = read(); c = read();
} else if (c == '/') { } else if (c == '/') {
// single line comment // single line comment
...@@ -141,6 +175,7 @@ public class ScriptReader { ...@@ -141,6 +175,7 @@ public class ScriptReader {
break; break;
} }
} }
previous = c;
c = read(); c = read();
} else { } else {
buff.append((char) last); buff.append((char) last);
...@@ -148,6 +183,7 @@ public class ScriptReader { ...@@ -148,6 +183,7 @@ public class ScriptReader {
break; break;
} }
case '-': { case '-': {
previous = c;
int last = c; int last = c;
c = read(); c = read();
if (c == '-') { if (c == '-') {
...@@ -171,17 +207,20 @@ public class ScriptReader { ...@@ -171,17 +207,20 @@ public class ScriptReader {
break; break;
} }
} }
previous = c;
c = read(); c = read();
} else { } else {
buff.append((char) last); buff.append((char) last);
} }
break; break;
} }
default: default: {
buff.append((char) c); buff.append((char) c);
previous = c;
c = read(); c = read();
} }
} }
}
return buff.toString(); return buff.toString();
} }
......
...@@ -219,13 +219,14 @@ http://www.w3schools.com/sql/ ...@@ -219,13 +219,14 @@ http://www.w3schools.com/sql/
History: History:
Some databases could not be opened when appending Some databases could not be opened when appending
;RECOVER=1 to the database URL. ;RECOVER=1 to the database URL.
The Japanese translation of the error messages and the H2 Console has been completed The Japanese translation of the error messages and the H2 Console
by Masahiro Ikemoto (Arizona Design Inc.) has been completed by Masahiro Ikemoto (Arizona Design Inc.)
Updates made to updatable rows are now visible within the same result set. Updates made to updatable rows are now visible within the same result set.
DatabaseMetaData.ownUpdatesAreVisible now returns true. DatabaseMetaData.ownUpdatesAreVisible now returns true.
ParameterMetaData now returns the correct data ParameterMetaData now returns the correct data
for INSERT and UPDATE statements. for INSERT and UPDATE statements.
H2 Shell: DESCRIBE now supports an schema name. H2 Shell: DESCRIBE now supports an schema name.
A subset of the PostgreSQL 'dollar quoting' feature is now supported.
Roadmap: Roadmap:
...@@ -428,53 +429,54 @@ Roadmap: ...@@ -428,53 +429,54 @@ Roadmap:
* Run all tests with the current settings. * Run all tests with the current settings.
*/ */
private void test() throws Exception { private void test() throws Exception {
System.out.println(); System.out.println();
System.out.println("Test big:"+big+" net:"+networked+" cipher:"+cipher+" memory:"+memory+" log:"+logMode+" diskResult:"+diskResult + " mvcc:" + mvcc + " deleteIndex:" + deleteIndex); System.out.println("Test big:"+big+" net:"+networked+" cipher:"+cipher+" memory:"+memory+" log:"+logMode+" diskResult:"+diskResult + " mvcc:" + mvcc + " deleteIndex:" + deleteIndex);
beforeTest(); beforeTest();
// db // db
// new TestScriptSimple().runTest(this); new TestScriptSimple().runTest(this);
// new TestScript().runTest(this); new TestScript().runTest(this);
// new TestAutoRecompile().runTest(this); new TestAutoRecompile().runTest(this);
// new TestBackup().runTest(this); new TestBackup().runTest(this);
// new TestBigDb().runTest(this); new TestBigDb().runTest(this);
// new TestBigResult().runTest(this); new TestBigResult().runTest(this);
// new TestCases().runTest(this); new TestCases().runTest(this);
// new TestCheckpoint().runTest(this); new TestCheckpoint().runTest(this);
// new TestCluster().runTest(this); new TestCluster().runTest(this);
// new TestCompatibility().runTest(this); new TestCompatibility().runTest(this);
// new TestCsv().runTest(this); new TestCsv().runTest(this);
// new TestEncryptedDb().runTest(this); new TestEncryptedDb().runTest(this);
// new TestExclusive().runTest(this); new TestExclusive().runTest(this);
// new TestFullText().runTest(this); new TestFullText().runTest(this);
// new TestFunctions().runTest(this); new TestFunctions().runTest(this);
// new TestIndex().runTest(this); new TestIndex().runTest(this);
// new TestLinkedTable().runTest(this); new TestLinkedTable().runTest(this);
// new TestListener().runTest(this); new TestListener().runTest(this);
// new TestLob().runTest(this); new TestLob().runTest(this);
// new TestLogFile().runTest(this); new TestLogFile().runTest(this);
// new TestMemoryUsage().runTest(this); new TestMemoryUsage().runTest(this);
// new TestMultiConn().runTest(this); new TestMultiConn().runTest(this);
// new TestMultiDimension().runTest(this); new TestMultiDimension().runTest(this);
// new TestMultiThread().runTest(this); new TestMultiThread().runTest(this);
// new TestOpenClose().runTest(this); new TestOpenClose().runTest(this);
// new TestOptimizations().runTest(this); new TestOptimizations().runTest(this);
// new TestPowerOff().runTest(this); new TestPowerOff().runTest(this);
// new TestReadOnly().runTest(this); new TestReadOnly().runTest(this);
// new TestRights().runTest(this); new TestRights().runTest(this);
// new TestRunscript().runTest(this); new TestRunscript().runTest(this);
// new TestSQLInjection().runTest(this); new TestSQLInjection().runTest(this);
// new TestSessionsLocks().runTest(this); new TestSessionsLocks().runTest(this);
// new TestSequence().runTest(this); new TestSequence().runTest(this);
// new TestSpaceReuse().runTest(this); new TestSpaceReuse().runTest(this);
// new TestSpeed().runTest(this); new TestSpeed().runTest(this);
// new TestTempTables().runTest(this); new TestTempTables().runTest(this);
// new TestTransaction().runTest(this); new TestTransaction().runTest(this);
// new TestTriggersConstraints().runTest(this); new TestTriggersConstraints().runTest(this);
// new TestTwoPhaseCommit().runTest(this); new TestTwoPhaseCommit().runTest(this);
// new TestView().runTest(this); new TestView().runTest(this);
//
// // jdbc // jdbc
new TestBatchUpdates().runTest(this); new TestBatchUpdates().runTest(this);
new TestCallableStatement().runTest(this); new TestCallableStatement().runTest(this);
new TestCancel().runTest(this); new TestCancel().runTest(this);
...@@ -489,57 +491,57 @@ Roadmap: ...@@ -489,57 +491,57 @@ Roadmap:
new TestUpdatableResultSet().runTest(this); new TestUpdatableResultSet().runTest(this);
new TestZloty().runTest(this); new TestZloty().runTest(this);
// // jdbcx // jdbcx
// new TestConnectionPool().runTest(this); new TestConnectionPool().runTest(this);
// new TestDataSource().runTest(this); new TestDataSource().runTest(this);
// new TestXA().runTest(this); new TestXA().runTest(this);
// new TestXASimple().runTest(this); new TestXASimple().runTest(this);
//
// // server // server
// new TestNestedLoop().runTest(this); new TestNestedLoop().runTest(this);
// new TestWeb().runTest(this); new TestWeb().runTest(this);
// new TestPgServer().runTest(this); new TestPgServer().runTest(this);
//
// // mvcc // mvcc
// new TestMvcc1().runTest(this); new TestMvcc1().runTest(this);
// new TestMvcc2().runTest(this); new TestMvcc2().runTest(this);
// new TestMvcc3().runTest(this); new TestMvcc3().runTest(this);
//
// // synth // synth
// new TestCrashAPI().runTest(this); new TestCrashAPI().runTest(this);
// new TestRandomSQL().runTest(this); new TestRandomSQL().runTest(this);
// new TestKillRestart().runTest(this); new TestKillRestart().runTest(this);
// new TestKillRestartMulti().runTest(this); new TestKillRestartMulti().runTest(this);
//
// // unit // unit
// new TestBitField().runTest(this); new TestBitField().runTest(this);
// new TestCache().runTest(this); new TestCache().runTest(this);
// new TestCompress().runTest(this); new TestCompress().runTest(this);
// new TestDataPage().runTest(this); new TestDataPage().runTest(this);
// new TestDate().runTest(this); new TestDate().runTest(this);
// new TestExit().runTest(this); new TestExit().runTest(this);
// new TestFile().runTest(this); new TestFile().runTest(this);
// new TestFileLock().runTest(this); new TestFileLock().runTest(this);
// new TestFtp().runTest(this); new TestFtp().runTest(this);
// new TestFileSystem().runTest(this); new TestFileSystem().runTest(this);
// new TestIntArray().runTest(this); new TestIntArray().runTest(this);
// new TestIntIntHashMap().runTest(this); new TestIntIntHashMap().runTest(this);
// new TestMultiThreadedKernel().runTest(this); new TestMultiThreadedKernel().runTest(this);
// new TestOverflow().runTest(this); new TestOverflow().runTest(this);
// new TestPattern().runTest(this); new TestPattern().runTest(this);
// new TestReader().runTest(this); new TestReader().runTest(this);
// new TestRecovery().runTest(this); new TestRecovery().runTest(this);
// new TestSampleApps().runTest(this); new TestSampleApps().runTest(this);
// 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 TestStreams().runTest(this); new TestStreams().runTest(this);
// new TestStringCache().runTest(this); new TestStringCache().runTest(this);
// new TestStringUtils().runTest(this); new TestStringUtils().runTest(this);
// new TestTools().runTest(this); new TestTools().runTest(this);
// new TestValue().runTest(this); new TestValue().runTest(this);
// new TestValueHashMap().runTest(this); new TestValueHashMap().runTest(this);
// new TestValueMemory().runTest(this); new TestValueMemory().runTest(this);
afterTest(); afterTest();
} }
......
...@@ -570,8 +570,12 @@ public abstract class TestBase { ...@@ -570,8 +570,12 @@ public abstract class TestBase {
} }
protected void checkNotGeneralException(SQLException e) throws Exception { protected void checkNotGeneralException(SQLException e) throws Exception {
checkNotGeneralException("", e);
}
protected void checkNotGeneralException(String message, SQLException e) throws Exception {
if (e != null && e.getSQLState().startsWith("HY000")) { if (e != null && e.getSQLState().startsWith("HY000")) {
TestBase.logError("Unexpected General error", e); TestBase.logError("Unexpected General error " + message, e);
} }
} }
......
...@@ -36,6 +36,24 @@ public class TestSQLInjection extends TestBase { ...@@ -36,6 +36,24 @@ public class TestSQLInjection extends TestBase {
check(checkPasswordSecure("123456")); check(checkPasswordSecure("123456"));
checkFalse(checkPasswordSecure("abcdef")); checkFalse(checkPasswordSecure("abcdef"));
checkFalse(checkPasswordSecure("' OR ''='")); checkFalse(checkPasswordSecure("' OR ''='"));
stat.execute("CALL 123");
stat.execute("CALL 'Hello'");
stat.execute("CALL $$Hello World$$");
stat.execute("SET ALLOW_LITERALS NUMBERS");
stat.execute("CALL 123");
try {
stat.execute("CALL 'Hello'");
error();
} catch (SQLException e) {
checkNotGeneralException(e);
}
try {
stat.execute("CALL $$Hello World$$");
error();
} catch (SQLException e) {
checkNotGeneralException(e);
}
stat.execute("SET ALLOW_LITERALS NONE"); stat.execute("SET ALLOW_LITERALS NONE");
try { try {
......
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
package org.h2.test.jdbc; package org.h2.test.jdbc;
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 java.util.Random;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -17,13 +19,156 @@ import org.h2.test.TestBase; ...@@ -17,13 +19,156 @@ import org.h2.test.TestBase;
*/ */
public class TestNativeSQL extends TestBase { public class TestNativeSQL extends TestBase {
Connection conn;
public void test() throws Exception { public void test() throws Exception {
deleteDb("nativeSql"); deleteDb("nativeSql");
Connection conn = getConnection("nativeSql"); conn = getConnection("nativeSql");
testPairs();
testCases();
testRandom();
testQuotes();
conn.close();
check(conn.isClosed());
}
private void testQuotes() throws Exception {
Statement stat = conn.createStatement();
Random random = new Random(1);
String s = "'\"$/-* \n";
for (int i = 0; i < 200; i++) {
StringBuffer buffQuoted = new StringBuffer();
StringBuffer buffRaw = new StringBuffer();
if (random.nextBoolean()) {
buffQuoted.append("'");
for (int j = 0; j < 10; j++) {
char c = s.charAt(random.nextInt(s.length()));
if (c == '\'') {
buffQuoted.append('\'');
}
buffQuoted.append(c);
buffRaw.append(c);
}
buffQuoted.append("'");
} else {
buffQuoted.append("$$");
for (int j = 0; j < 10; j++) {
char c = s.charAt(random.nextInt(s.length()));
buffQuoted.append(c);
buffRaw.append(c);
if (c == '$') {
buffQuoted.append(' ');
buffRaw.append(' ');
}
}
buffQuoted.append("$$");
}
String sql = "CALL " + buffQuoted.toString();
ResultSet rs = stat.executeQuery(sql);
rs.next();
String raw = buffRaw.toString();
check(raw, rs.getString(1));
}
}
private void testRandom() throws Exception {
Random random = new Random(1);
for (int i = 0; i < 100; i++) {
StringBuffer buff = new StringBuffer("{oj }");
String s = "{}\'\"-/*$ $-";
for (int j = random.nextInt(30); j > 0; j--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
String sql = buff.toString();
try {
conn.nativeSQL(sql);
} catch (SQLException e) {
checkNotGeneralException(sql, e);
}
}
String smallest = null;
for (int i = 0; i < 1000; i++) {
StringBuffer buff = new StringBuffer("{oj }");
for (int j = random.nextInt(10); j > 0; j--) {
String s;
switch(random.nextInt(7)) {
case 0:
buff.append(" $$");
s = "{}\'\"-/* a\n";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
buff.append("$$");
break;
case 1:
buff.append("'");
s = "{}\"-/*$ a\n";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
buff.append("'");
break;
case 2:
buff.append("\"");
s = "{}'-/*$ a\n";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
buff.append("\"");
break;
case 3:
buff.append("/*");
s = "{}'\"-/$ a\n";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
buff.append("*/");
break;
case 4:
buff.append("--");
s = "{}'\"-/$ a";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
buff.append("\n");
break;
case 5:
buff.append("//");
s = "{}'\"-/$ a";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
buff.append("\n");
break;
case 6:
s = " a\n";
for (int k = random.nextInt(5); k > 0; k--) {
buff.append(s.charAt(random.nextInt(s.length())));
}
break;
}
}
String sql = buff.toString();
try {
conn.nativeSQL(sql);
} catch (Exception e) {
if (smallest == null || sql.length() < smallest.length()) {
smallest = sql;
}
}
}
if (smallest != null) {
conn.nativeSQL(smallest);
}
}
private void testPairs() throws Exception {
for (int i = 0; i < PAIRS.length; i += 2) { for (int i = 0; i < PAIRS.length; i += 2) {
test(conn, PAIRS[i], PAIRS[i + 1]); test(conn, PAIRS[i], PAIRS[i + 1]);
} }
}
private void testCases() throws Exception {
conn.nativeSQL("TEST"); conn.nativeSQL("TEST");
conn.nativeSQL("TEST--testing"); conn.nativeSQL("TEST--testing");
conn.nativeSQL("TEST--testing{oj }"); conn.nativeSQL("TEST--testing{oj }");
...@@ -49,15 +194,13 @@ public class TestNativeSQL extends TestBase { ...@@ -49,15 +194,13 @@ public class TestNativeSQL extends TestBase {
checkNotGeneralException(e); checkNotGeneralException(e);
} }
checkFalse(conn.isClosed()); checkFalse(conn.isClosed());
conn.close();
check(conn.isClosed());
} }
static final String[] PAIRS = new String[] { "CREATE TABLE TEST(ID INT PRIMARY KEY)", static final String[] PAIRS = new String[] {
"CREATE TABLE TEST(ID INT PRIMARY KEY)",
"CREATE TABLE TEST(ID INT PRIMARY KEY)", "CREATE TABLE TEST(ID INT PRIMARY KEY)",
"INSERT INTO TEST VALUES(1)", "INSERT INTO TEST VALUES(1)", "INSERT INTO TEST VALUES(1)", "INSERT INTO TEST VALUES(1)",
"SELECT '{nothing}' FROM TEST", "SELECT '{nothing}' FROM TEST", "SELECT '{nothing}' FROM TEST", "SELECT '{nothing}' FROM TEST",
"SELECT '{fn ABS(1)}' FROM TEST", "SELECT '{fn ABS(1)}' FROM TEST", "SELECT '{fn ABS(1)}' FROM TEST", "SELECT '{fn ABS(1)}' FROM TEST",
......
...@@ -58,7 +58,7 @@ public class TestScriptReader extends TestBase { ...@@ -58,7 +58,7 @@ public class TestScriptReader extends TestBase {
switch (random.nextInt(10)) { switch (random.nextInt(10)) {
case 0: { case 0: {
int l = random.nextInt(4); int l = random.nextInt(4);
String[] ch = new String[] { "\n", "\r", " ", "*", "a", "0" }; String[] ch = new String[] { "\n", "\r", " ", "*", "a", "0", "$ " };
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
} }
...@@ -67,7 +67,7 @@ public class TestScriptReader extends TestBase { ...@@ -67,7 +67,7 @@ public class TestScriptReader extends TestBase {
case 1: { case 1: {
buff.append('\''); buff.append('\'');
int l = random.nextInt(4); int l = random.nextInt(4);
String[] ch = new String[] { ";", "\n", "\r", "--", "//", "/", "-", "*", "/*", "*/", "\"" }; String[] ch = new String[] { ";", "\n", "\r", "--", "//", "/", "-", "*", "/*", "*/", "\"", "$ " };
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
} }
...@@ -77,7 +77,7 @@ public class TestScriptReader extends TestBase { ...@@ -77,7 +77,7 @@ public class TestScriptReader extends TestBase {
case 2: { case 2: {
buff.append('"'); buff.append('"');
int l = random.nextInt(4); int l = random.nextInt(4);
String[] ch = new String[] { ";", "\n", "\r", "--", "//", "/", "-", "*", "/*", "*/", "\'" }; String[] ch = new String[] { ";", "\n", "\r", "--", "//", "/", "-", "*", "/*", "*/", "\'", "$" };
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
} }
...@@ -87,14 +87,14 @@ public class TestScriptReader extends TestBase { ...@@ -87,14 +87,14 @@ public class TestScriptReader extends TestBase {
case 3: { case 3: {
buff.append('-'); buff.append('-');
if (random.nextBoolean()) { if (random.nextBoolean()) {
String[] ch = new String[] { "\n", "\r", "*", "a", " " }; String[] ch = new String[] { "\n", "\r", "*", "a", " ", "$ " };
int l = 1 + random.nextInt(4); int l = 1 + random.nextInt(4);
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
} }
} else { } else {
buff.append('-'); buff.append('-');
String[] ch = new String[] { ";", "-", "//", "/*", "*/", "a" }; String[] ch = new String[] { ";", "-", "//", "/*", "*/", "a", "$" };
int l = random.nextInt(4); int l = random.nextInt(4);
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
...@@ -106,14 +106,14 @@ public class TestScriptReader extends TestBase { ...@@ -106,14 +106,14 @@ public class TestScriptReader extends TestBase {
case 4: { case 4: {
buff.append('/'); buff.append('/');
if (random.nextBoolean()) { if (random.nextBoolean()) {
String[] ch = new String[] { "\n", "\r", "a", " ", "- " }; String[] ch = new String[] { "\n", "\r", "a", " ", "- ", "$ " };
int l = 1 + random.nextInt(4); int l = 1 + random.nextInt(4);
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
} }
} else { } else {
buff.append('*'); buff.append('*');
String[] ch = new String[] { ";", "-", "//", "/* ", "--", "\n", "\r", "a" }; String[] ch = new String[] { ";", "-", "//", "/* ", "--", "\n", "\r", "a", "$" };
int l = random.nextInt(4); int l = random.nextInt(4);
for (int j = 0; j < l; j++) { for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]); buff.append(ch[random.nextInt(ch.length)]);
...@@ -122,6 +122,27 @@ public class TestScriptReader extends TestBase { ...@@ -122,6 +122,27 @@ public class TestScriptReader extends TestBase {
} }
break; break;
} }
case 5: {
if (buff.length() > 0) {
buff.append(" ");
}
buff.append("$");
if (random.nextBoolean()) {
String[] ch = new String[] { "\n", "\r", "a", " ", "- ", "/ " };
int l = 1 + random.nextInt(4);
for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]);
}
} else {
buff.append("$");
String[] ch = new String[] { ";", "-", "//", "/* ", "--", "\n", "\r", "a", "$ " };
int l = random.nextInt(4);
for (int j = 0; j < l; j++) {
buff.append(ch[random.nextInt(ch.length)]);
}
buff.append("$$");
}
}
} }
} }
return buff.toString(); return buff.toString();
...@@ -139,6 +160,11 @@ public class TestScriptReader extends TestBase { ...@@ -139,6 +160,11 @@ public class TestScriptReader extends TestBase {
check(source.readStatement(), "//;\na"); check(source.readStatement(), "//;\na");
check(source.readStatement(), null); check(source.readStatement(), null);
source.close(); source.close();
s = "/\n$ \n\n $';$$a$$ $\n;'";
source = new ScriptReader(new StringReader(s));
check(source.readStatement(), "/\n$ \n\n $';$$a$$ $\n;'");
check(source.readStatement(), null);
source.close();
} }
} }
...@@ -507,4 +507,5 @@ originator brought contribution effectively assumes waives conjunction ...@@ -507,4 +507,5 @@ originator brought contribution effectively assumes waives conjunction
informs negotiations collectively omissions trial nor qualify steward neither informs negotiations collectively omissions trial nor qualify steward neither
worldwide everyone additions expense lawsuit checksums jazoon flashback worldwide everyone additions expense lawsuit checksums jazoon flashback
dieguez dfile mvn dversion dgroup dpackaging dartifact durl dpom pom dieguez dfile mvn dversion dgroup dpackaging dartifact durl dpom pom
subpackages slowed deactivate throttled noindex expired subpackages slowed deactivate throttled noindex expired arizona export
intentional knowing
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论