Unverified 提交 15476b8b authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1562 from katzyn/misc

Assorted minor changes
...@@ -21,6 +21,12 @@ Change Log ...@@ -21,6 +21,12 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Issue #1561: Incorrect documentation and strange fallback value of SysProperties.FILE_ENCODING
</li>
<li>PR #1557: increase lock timeout to TestConcurrentUpdate due to Travis failures
</li>
<li>Issue #1554: REGEXP_REPLACE - accept 'g' flag in PostgreSQL compatibility mode
</li>
<li>Issue #950: Comparison between databases in README.md and in features.html <li>Issue #950: Comparison between databases in README.md and in features.html
</li> </li>
<li>Issue #1549: [RFE] Implement locking modes (select for update) <li>Issue #1549: [RFE] Implement locking modes (select for update)
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
*/ */
package org.h2.engine; package org.h2.engine;
import java.io.File;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -42,26 +44,16 @@ public class SysProperties { ...@@ -42,26 +44,16 @@ public class SysProperties {
public static final String H2_BROWSER = "h2.browser"; public static final String H2_BROWSER = "h2.browser";
/** /**
* System property <code>file.encoding</code> (default: Cp1252).<br /> * System property <code>file.separator</code>.<br />
* It is usually set by the system and is the default encoding used for the * It is set by the system, and used to build absolute file names.
* RunScript and CSV tool.
*/
public static final String FILE_ENCODING =
Utils.getProperty("file.encoding", "Cp1252");
/**
* System property <code>file.separator</code> (default: /).<br />
* It is usually set by the system, and used to build absolute file names.
*/ */
public static final String FILE_SEPARATOR = public static final String FILE_SEPARATOR = File.separator;
Utils.getProperty("file.separator", "/");
/** /**
* System property <code>line.separator</code> (default: \n).<br /> * System property <code>line.separator</code>.<br />
* It is usually set by the system, and used by the script and trace tools. * It is set by the system, and used by the script and trace tools.
*/ */
public static final String LINE_SEPARATOR = public static final String LINE_SEPARATOR = System.lineSeparator();
Utils.getProperty("line.separator", "\n");
/** /**
* System property <code>user.home</code> (empty string if not set).<br /> * System property <code>user.home</code> (empty string if not set).<br />
......
...@@ -17,6 +17,7 @@ import java.sql.ResultSet; ...@@ -17,6 +17,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
...@@ -1350,50 +1351,11 @@ public class Function extends Expression implements FunctionCall { ...@@ -1350,50 +1351,11 @@ public class Function extends Expression implements FunctionCall {
break; break;
} }
case REGEXP_REPLACE: { case REGEXP_REPLACE: {
String input = v0.getString();
String regexp = v1.getString(); String regexp = v1.getString();
String replacement = v2.getString(); String replacement = v2.getString();
if (database.getMode().regexpReplaceBackslashReferences) { String regexpMode = v3 != null ? v3.getString() : null;
if ((replacement.indexOf('\\') >= 0) || (replacement.indexOf('$') >= 0)) { result = regexpReplace(input, regexp, replacement, regexpMode);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < replacement.length(); i++) {
char c = replacement.charAt(i);
if (c == '$') {
sb.append('\\');
} else if (c == '\\' && ++i < replacement.length()) {
c = replacement.charAt(i);
sb.append(c >= '0' && c <= '9' ? '$' : '\\');
}
sb.append(c);
}
replacement = sb.toString();
}
}
String regexpMode = v3 == null || v3.getString() == null ? "" :
v3.getString();
boolean isInPostgreSqlMode = Mode.ModeEnum.PostgreSQL.equals(database.getMode().getEnum());
int flags = makeRegexpFlags(regexpMode, isInPostgreSqlMode);
try {
if(isInPostgreSqlMode && !regexpMode.contains("g")) {
result = ValueString.get(
Pattern.compile(regexp, flags).matcher(v0.getString())
.replaceFirst(replacement),
database.getMode().treatEmptyStringsAsNull);
} else {
result = ValueString.get(
Pattern.compile(regexp, flags).matcher(v0.getString())
.replaceAll(replacement),
database.getMode().treatEmptyStringsAsNull);
}
} catch (StringIndexOutOfBoundsException e) {
throw DbException.get(
ErrorCode.LIKE_ESCAPE_ERROR_1, e, replacement);
} catch (PatternSyntaxException e) {
throw DbException.get(
ErrorCode.LIKE_ESCAPE_ERROR_1, e, regexp);
} catch (IllegalArgumentException e) {
throw DbException.get(
ErrorCode.LIKE_ESCAPE_ERROR_1, e, replacement);
}
break; break;
} }
case RPAD: case RPAD:
...@@ -1656,8 +1618,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1656,8 +1618,7 @@ public class Function extends Expression implements FunctionCall {
break; break;
case REGEXP_LIKE: { case REGEXP_LIKE: {
String regexp = v1.getString(); String regexp = v1.getString();
String regexpMode = v2 == null || v2.getString() == null ? "" : String regexpMode = v2 != null ? v2.getString() : null;
v2.getString();
int flags = makeRegexpFlags(regexpMode, false); int flags = makeRegexpFlags(regexpMode, false);
try { try {
result = ValueBoolean.get(Pattern.compile(regexp, flags) result = ValueBoolean.get(Pattern.compile(regexp, flags)
...@@ -2040,6 +2001,40 @@ public class Function extends Expression implements FunctionCall { ...@@ -2040,6 +2001,40 @@ public class Function extends Expression implements FunctionCall {
return md; return md;
} }
private Value regexpReplace(String input, String regexp, String replacement, String regexpMode) {
Mode mode = database.getMode();
if (mode.regexpReplaceBackslashReferences) {
if ((replacement.indexOf('\\') >= 0) || (replacement.indexOf('$') >= 0)) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < replacement.length(); i++) {
char c = replacement.charAt(i);
if (c == '$') {
sb.append('\\');
} else if (c == '\\' && ++i < replacement.length()) {
c = replacement.charAt(i);
sb.append(c >= '0' && c <= '9' ? '$' : '\\');
}
sb.append(c);
}
replacement = sb.toString();
}
}
boolean isInPostgreSqlMode = Mode.ModeEnum.PostgreSQL.equals(mode.getEnum());
int flags = makeRegexpFlags(regexpMode, isInPostgreSqlMode);
try {
Matcher matcher = Pattern.compile(regexp, flags).matcher(input);
return ValueString.get(isInPostgreSqlMode && (regexpMode == null || regexpMode.indexOf('g') < 0) ?
matcher.replaceFirst(replacement) : matcher.replaceAll(replacement),
mode.treatEmptyStringsAsNull);
} catch (StringIndexOutOfBoundsException e) {
throw DbException.get(ErrorCode.LIKE_ESCAPE_ERROR_1, e, replacement);
} catch (PatternSyntaxException e) {
throw DbException.get(ErrorCode.LIKE_ESCAPE_ERROR_1, e, regexp);
} catch (IllegalArgumentException e) {
throw DbException.get(ErrorCode.LIKE_ESCAPE_ERROR_1, e, replacement);
}
}
private static int makeRegexpFlags(String stringFlags, boolean ignoreGlobalFlag) { private static int makeRegexpFlags(String stringFlags, boolean ignoreGlobalFlag) {
int flags = Pattern.UNICODE_CASE; int flags = Pattern.UNICODE_CASE;
if (stringFlags != null) { if (stringFlags != null) {
......
...@@ -44,7 +44,7 @@ public class Csv implements SimpleRowSource { ...@@ -44,7 +44,7 @@ public class Csv implements SimpleRowSource {
private String[] columnNames; private String[] columnNames;
private String characterSet = SysProperties.FILE_ENCODING; private String characterSet;
private char escapeCharacter = '\"'; private char escapeCharacter = '\"';
private char fieldDelimiter = '\"'; private char fieldDelimiter = '\"';
private char fieldSeparatorRead = ','; private char fieldSeparatorRead = ',';
...@@ -136,7 +136,6 @@ public class Csv implements SimpleRowSource { ...@@ -136,7 +136,6 @@ public class Csv implements SimpleRowSource {
* @param rs the result set - the result set must be positioned before the * @param rs the result set - the result set must be positioned before the
* first row. * first row.
* @param charset the charset or null to use the system default charset * @param charset the charset or null to use the system default charset
* (see system property file.encoding)
* @return the number of rows written * @return the number of rows written
*/ */
public int write(String outputFileName, ResultSet rs, String charset) public int write(String outputFileName, ResultSet rs, String charset)
...@@ -184,7 +183,6 @@ public class Csv implements SimpleRowSource { ...@@ -184,7 +183,6 @@ public class Csv implements SimpleRowSource {
* @param colNames or null if the column names should be read from the CSV * @param colNames or null if the column names should be read from the CSV
* file * file
* @param charset the charset or null to use the system default charset * @param charset the charset or null to use the system default charset
* (see system property file.encoding)
* @return the result set * @return the result set
*/ */
public ResultSet read(String inputFileName, String[] colNames, public ResultSet read(String inputFileName, String[] colNames,
...@@ -246,9 +244,7 @@ public class Csv implements SimpleRowSource { ...@@ -246,9 +244,7 @@ public class Csv implements SimpleRowSource {
private void init(String newFileName, String charset) { private void init(String newFileName, String charset) {
this.fileName = newFileName; this.fileName = newFileName;
if (charset != null) { this.characterSet = charset;
this.characterSet = charset;
}
} }
private void initWrite() throws IOException { private void initWrite() throws IOException {
...@@ -256,7 +252,8 @@ public class Csv implements SimpleRowSource { ...@@ -256,7 +252,8 @@ public class Csv implements SimpleRowSource {
try { try {
OutputStream out = FileUtils.newOutputStream(fileName, false); OutputStream out = FileUtils.newOutputStream(fileName, false);
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE); out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE);
output = new BufferedWriter(new OutputStreamWriter(out, characterSet)); output = new BufferedWriter(characterSet != null ?
new OutputStreamWriter(out, characterSet) : new OutputStreamWriter(out));
} catch (Exception e) { } catch (Exception e) {
close(); close();
throw DbException.convertToIOException(e); throw DbException.convertToIOException(e);
...@@ -314,7 +311,7 @@ public class Csv implements SimpleRowSource { ...@@ -314,7 +311,7 @@ public class Csv implements SimpleRowSource {
try { try {
InputStream in = FileUtils.newInputStream(fileName); InputStream in = FileUtils.newInputStream(fileName);
in = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE); in = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE);
input = new InputStreamReader(in, characterSet); input = characterSet != null ? new InputStreamReader(in, characterSet) : new InputStreamReader(in);
} catch (IOException e) { } catch (IOException e) {
close(); close();
throw e; throw e;
......
...@@ -166,7 +166,7 @@ public class Profiler implements Runnable { ...@@ -166,7 +166,7 @@ public class Profiler implements Runnable {
} }
continue; continue;
} }
try (Reader reader = new InputStreamReader(new FileInputStream(arg), "CP1252")) { try (Reader reader = new InputStreamReader(new FileInputStream(arg))) {
LineNumberReader r = new LineNumberReader(reader); LineNumberReader r = new LineNumberReader(reader);
while (true) { while (true) {
String line = r.readLine(); String line = r.readLine();
...@@ -177,7 +177,7 @@ public class Profiler implements Runnable { ...@@ -177,7 +177,7 @@ public class Profiler implements Runnable {
} }
} }
} }
try (Reader reader = new InputStreamReader(new FileInputStream(arg), "CP1252")) { try (Reader reader = new InputStreamReader(new FileInputStream(arg))) {
LineNumberReader r = new LineNumberReader(reader); LineNumberReader r = new LineNumberReader(reader);
processList(readStackTrace(r)); processList(readStackTrace(r));
} }
......
...@@ -8,6 +8,7 @@ package org.h2.test.scripts; ...@@ -8,6 +8,7 @@ package org.h2.test.scripts;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.nio.charset.StandardCharsets;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
...@@ -46,8 +47,7 @@ public class TestScriptSimple extends TestDb { ...@@ -46,8 +47,7 @@ public class TestScriptSimple extends TestDb {
reconnect(); reconnect();
String inFile = "org/h2/test/scripts/testSimple.in.txt"; String inFile = "org/h2/test/scripts/testSimple.in.txt";
InputStream is = getClass().getClassLoader().getResourceAsStream(inFile); InputStream is = getClass().getClassLoader().getResourceAsStream(inFile);
LineNumberReader lineReader = new LineNumberReader( LineNumberReader lineReader = new LineNumberReader(new InputStreamReader(is, StandardCharsets.UTF_8));
new InputStreamReader(is, "Cp1252"));
try (ScriptReader reader = new ScriptReader(lineReader)) { try (ScriptReader reader = new ScriptReader(lineReader)) {
while (true) { while (true) {
String sql = reader.readStatement(); String sql = reader.readStatement();
......
...@@ -802,3 +802,4 @@ partitioned tri partitions ...@@ -802,3 +802,4 @@ partitioned tri partitions
discard enhancements nolock surefire logarithm discard enhancements nolock surefire logarithm
qualification opportunity jumping exploited unacceptable vrs duplicated qualification opportunity jumping exploited unacceptable vrs duplicated
queryparser tokenized freeze factorings recompilation unenclosed rfe dsync queryparser tokenized freeze factorings recompilation unenclosed rfe dsync
econd irst bcef
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论