提交 e31965cf authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 454: Use Charset for type-safety.

上级 efdeceb1
......@@ -18,7 +18,8 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>Queries with both LIMIT and OFFSET could throw an IllegalArgumentException.
<ul><li>Issue 454: Use Charset for type-safety.
</li><li>Queries with both LIMIT and OFFSET could throw an IllegalArgumentException.
</li><li>MVStore: larger stores (multiple GB) are now much faster.
</li><li>When using local temporary tables and not dropping them manually before closing the session,
and then killing the process could result in a database that couldn't be opened (except when using
......@@ -26,11 +27,11 @@ Change Log
</li><li>Support TRUNC(timestamp) for improved Oracle compatibility.
</li><li>Add support for CREATE TABLE TEST (ID BIGSERIAL) for PostgreSQL compatibility. Patch from Jesse Long.
</li><li>Add new collation command SET BINARY_COLLATION UNSIGNED, helps with people testing BINARY columns in MySQL mode.
</li><li>Fix issue #453, ABBA race conditions in TABLE LINK connection sharing.
</li><li>Fix Issue 449: Postgres Serial data type should not automatically be marked as primary key
</li><li>Fix Issue 406: support "SELECT h2version()"
</li><li>Fix Issue 389: When there is a multi-column primary key, H2 does not seem to always pick the right index
</li><li>Fix Issue 305: Implement SELECT ... FOR FETCH ONLY
</li><li>Issue 453: ABBA race conditions in TABLE LINK connection sharing.
</li><li>Issue 449: Postgres Serial data type should not automatically be marked as primary key
</li><li>Issue 406: support "SELECT h2version()"
</li><li>Issue 389: When there is a multi-column primary key, H2 does not seem to always pick the right index
</li><li>Issue 305: Implement SELECT ... FOR FETCH ONLY
</li><li>Issue 274: Sybase/MSSQLServer compatibility - Add GETDATE and CHARINDEX system functions
</li><li>Issue 274: Sybase/MSSQLServer compatibility - swap parameters of CONVERT function.
</li><li>Issue 274: Sybase/MSSQLServer compatibility - support index clause e.g. "select * from test (index table1_index)"
......
......@@ -8,6 +8,7 @@ package org.h2.command;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.text.Collator;
import java.util.ArrayList;
import java.util.HashSet;
......@@ -4733,7 +4734,7 @@ public class Parser {
}
}
if (readIf("CHARSET")) {
command.setCharset(readString());
command.setCharset(Charset.forName(readString()));
}
return command;
}
......@@ -4777,7 +4778,7 @@ public class Parser {
}
}
if (readIf("CHARSET")) {
command.setCharset(readString());
command.setCharset(Charset.forName(readString()));
}
}
if (readIf("SCHEMA")) {
......
......@@ -9,6 +9,7 @@ package org.h2.command.dml;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import org.h2.command.CommandInterface;
import org.h2.command.Prepared;
import org.h2.engine.Constants;
......@@ -30,7 +31,7 @@ public class RunScriptCommand extends ScriptBase {
*/
private static final char UTF8_BOM = '\uFEFF';
private String charset = Constants.UTF8;
private Charset charset = Constants.UTF8;
public RunScriptCommand(Session session) {
super(session);
......@@ -84,7 +85,7 @@ public class RunScriptCommand extends ScriptBase {
}
}
public void setCharset(String charset) {
public void setCharset(Charset charset) {
this.charset = charset;
}
......
......@@ -11,6 +11,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
......@@ -66,7 +67,7 @@ import org.h2.value.ValueString;
*/
public class ScriptCommand extends ScriptBase {
private String charset = Constants.UTF8;
private Charset charset = Constants.UTF8;
private Set<String> schemaNames;
private Collection<Table> tables;
private boolean passwords;
......@@ -625,12 +626,8 @@ public class ScriptCommand extends ScriptBase {
private void reset() {
result = null;
buffer = null;
try {
lineSeparatorString = SysProperties.LINE_SEPARATOR;
lineSeparator = lineSeparatorString.getBytes(charset);
} catch (IOException e) {
throw DbException.convertIOException(e, null);
}
lineSeparatorString = SysProperties.LINE_SEPARATOR;
lineSeparator = lineSeparatorString.getBytes(charset);
}
private boolean excludeSchema(Schema schema) {
......@@ -691,7 +688,7 @@ public class ScriptCommand extends ScriptBase {
this.simple = simple;
}
public void setCharset(String charset) {
public void setCharset(Charset charset) {
this.charset = charset;
}
......
......@@ -6,6 +6,7 @@
*/
package org.h2.engine;
import java.nio.charset.Charset;
import java.sql.ResultSet;
/**
......@@ -463,7 +464,7 @@ public class Constants {
/**
* Name of the character encoding format.
*/
public static final String UTF8 = "UTF8";
public static final Charset UTF8 = Charset.forName("UTF-8");
/**
* The maximum time in milliseconds to keep the cost of a view.
......
......@@ -657,10 +657,10 @@ public class Function extends Expression implements FunctionCall {
result = ValueString.get(StringUtils.javaDecode(v0.getString()));
break;
case STRINGTOUTF8:
result = ValueBytes.getNoCopy(StringUtils.utf8Encode(v0.getString()));
result = ValueBytes.getNoCopy(v0.getString().getBytes(Constants.UTF8));
break;
case UTF8TOSTRING:
result = ValueString.get(StringUtils.utf8Decode(v0.getBytesNoCopy()));
result = ValueString.get(new String(v0.getBytesNoCopy(), Constants.UTF8));
break;
case XMLCOMMENT:
result = ValueString.get(StringUtils.xmlComment(v0.getString()));
......
......@@ -650,55 +650,6 @@ public class DataUtils {
Constants.VERSION_MINOR + "." + Constants.BUILD_ID + "]";
}
/**
* Convert the text to UTF-8 format. For the Unicode characters
* 0xd800-0xdfff only one byte is returned.
*
* @param s the text
* @return the UTF-8 representation
*/
public static byte[] utf8Encode(String s) {
try {
return s.getBytes(Constants.UTF8);
} catch (Exception e) {
// UnsupportedEncodingException
throw newIllegalArgumentException("UTF-8 not supported", e);
}
}
/**
* Convert a UTF-8 representation of a text to the text.
*
* @param utf8 the UTF-8 representation
* @return the text
*/
public static String utf8Decode(byte[] utf8) {
try {
return new String(utf8, Constants.UTF8);
} catch (Exception e) {
// UnsupportedEncodingException
throw newIllegalArgumentException("UTF-8 not supported", e);
}
}
/**
* Convert a UTF-8 representation of a text to the text using the given
* offset and length.
*
* @param bytes the UTF-8 representation
* @param offset the offset in the bytes array
* @param length the number of bytes
* @return the text
*/
public static String utf8Decode(byte[] bytes, int offset, int length) {
try {
return new String(bytes, offset, length, Constants.UTF8);
} catch (Exception e) {
// UnsupportedEncodingException
throw newIllegalArgumentException("UTF-8 not supported", e);
}
}
/**
* Create an array of bytes with the given size. If this is not possible
* because not enough memory is available, an OutOfMemoryError with the
......
......@@ -21,6 +21,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.h2.compress.CompressLZF;
import org.h2.compress.Compressor;
import org.h2.engine.Constants;
import org.h2.mvstore.cache.CacheLongKeyLIRS;
import org.h2.mvstore.cache.FilePathCache;
import org.h2.mvstore.type.StringDataType;
......@@ -600,7 +601,7 @@ public class MVStore {
fileReadCount++;
DataUtils.readFully(file, 0, buff);
for (int i = 0; i < 3 * BLOCK_SIZE; i += BLOCK_SIZE) {
String s = DataUtils.utf8Decode(buff.array(), i, BLOCK_SIZE)
String s = new String(buff.array(), i, BLOCK_SIZE, Constants.UTF8)
.trim();
HashMap<String, String> m = DataUtils.parseMap(s);
String f = m.remove("fletcher");
......@@ -613,8 +614,8 @@ public class MVStore {
} catch (NumberFormatException e) {
check = -1;
}
s = s.substring(0, s.lastIndexOf("fletcher") - 1) + " ";
byte[] bytes = DataUtils.utf8Encode(s);
s = s.substring(0, s.lastIndexOf("fletcher") - 1);
byte[] bytes = s.getBytes(Constants.UTF8);
int checksum = DataUtils.getFletcher32(bytes, bytes.length / 2 * 2);
if (check != checksum) {
continue;
......@@ -640,10 +641,10 @@ public class MVStore {
fileHeader.put("rootChunk", "" + rootChunkStart);
fileHeader.put("version", "" + currentVersion);
DataUtils.appendMap(buff, fileHeader);
byte[] bytes = DataUtils.utf8Encode(buff.toString() + " ");
byte[] bytes = buff.toString().getBytes(Constants.UTF8);
int checksum = DataUtils.getFletcher32(bytes, bytes.length / 2 * 2);
DataUtils.appendMap(buff, "fletcher", Integer.toHexString(checksum));
bytes = DataUtils.utf8Encode(buff.toString());
bytes = buff.toString().getBytes(Constants.UTF8);
DataUtils.checkArgument(bytes.length <= BLOCK_SIZE,
"File header too large: {0}", buff);
return bytes;
......
......@@ -946,7 +946,7 @@ public class WebApp {
}
final Connection conn = session.getConnection();
if (SysProperties.CONSOLE_STREAM && server.getAllowChunked()) {
String page = StringUtils.utf8Decode(server.getFile("result.jsp"));
String page = new String(server.getFile("result.jsp"), Constants.UTF8);
int idx = page.indexOf("${result}");
// the first element of the list is the header, the last the footer
list.add(0, page.substring(0, idx));
......
......@@ -12,13 +12,15 @@ import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.h2.engine.Constants;
import org.h2.util.New;
import org.h2.util.StringUtils;
/**
* This servlet lets the H2 Console be used in a standard servlet container
......@@ -130,12 +132,12 @@ public class WebServlet extends HttpServlet {
byte[] bytes = server.getFile(file);
if (bytes == null) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
bytes = StringUtils.utf8Encode("File not found: " + file);
bytes = ("File not found: " + file).getBytes(Constants.UTF8);
} else {
if (session != null && file.endsWith(".jsp")) {
String page = StringUtils.utf8Decode(bytes);
String page = new String(bytes, Constants.UTF8);
page = PageParser.parse(page, session.map);
bytes = StringUtils.utf8Encode(page);
bytes = page.getBytes(Constants.UTF8);
}
resp.setContentType(mimeType);
if (!cache) {
......
......@@ -148,10 +148,10 @@ class WebThread extends WebApp implements Runnable {
bytes = server.getFile(file);
if (bytes == null) {
message = "HTTP/1.0 404 Not Found\r\n";
bytes = StringUtils.utf8Encode("File not found: " + file);
bytes = ("File not found: " + file).getBytes(Constants.UTF8);
} else {
if (session != null && file.endsWith(".jsp")) {
String page = StringUtils.utf8Decode(bytes);
String page = new String(bytes, Constants.UTF8);
if (SysProperties.CONSOLE_STREAM) {
Iterator<String> it = (Iterator<String>) session.map.remove("chunks");
if (it != null) {
......@@ -165,7 +165,7 @@ class WebThread extends WebApp implements Runnable {
while (it.hasNext()) {
String s = it.next();
s = PageParser.parse(s, session.map);
bytes = StringUtils.utf8Encode(s);
bytes = s.getBytes(Constants.UTF8);
if (bytes.length == 0) {
continue;
}
......@@ -181,7 +181,7 @@ class WebThread extends WebApp implements Runnable {
}
}
page = PageParser.parse(page, session.map);
bytes = StringUtils.utf8Encode(page);
bytes = page.getBytes(Constants.UTF8);
}
message = "HTTP/1.1 200 OK\r\n";
message += "Content-Type: " + mimeType + "\r\n";
......
......@@ -18,6 +18,7 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
......@@ -26,7 +27,6 @@ import org.h2.tools.CompressTool;
import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
import org.h2.util.New;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
import org.h2.value.Value;
import org.h2.value.ValueLob;
......@@ -199,7 +199,7 @@ public class LobStorage {
if (SysProperties.LOB_IN_DATABASE) {
int precision;
if (type == Value.CLOB) {
precision = StringUtils.utf8Decode(small).length();
precision = new String(small, Constants.UTF8).length();
} else {
precision = small.length;
}
......@@ -834,7 +834,7 @@ public class LobStorage {
if (len < 0) {
buffer = null;
} else {
buffer = StringUtils.utf8Encode(new String(charBuffer, 0, len));
buffer = new String(charBuffer, 0, len).getBytes(Constants.UTF8);
length += len;
remaining -= len;
}
......
......@@ -14,6 +14,8 @@ import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Arrays;
import org.h2.engine.Constants;
import org.h2.mvstore.DataUtils;
import org.h2.security.AES;
import org.h2.security.BlockCipher;
......@@ -37,7 +39,7 @@ public class FilePathCrypt extends FilePathWrapper {
public FileChannel open(String mode) throws IOException {
String[] parsed = parse(name);
FileChannel file = FileUtils.open(parsed[1], mode);
byte[] passwordBytes = DataUtils.utf8Encode(parsed[0]);
byte[] passwordBytes = parsed[0].getBytes(Constants.UTF8);
return new FileCrypt(name, passwordBytes, file);
}
......
......@@ -11,6 +11,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
......@@ -177,20 +178,20 @@ public class RunScript extends Tool {
}
private void process(Connection conn, String fileName,
boolean continueOnError, String charsetName) throws SQLException, IOException {
boolean continueOnError, Charset charset) throws SQLException, IOException {
InputStream in = FileUtils.newInputStream(fileName);
String path = FileUtils.getParent(fileName);
try {
in = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE);
Reader reader = new InputStreamReader(in, charsetName);
process(conn, continueOnError, path, reader, charsetName);
Reader reader = new InputStreamReader(in, charset);
process(conn, continueOnError, path, reader, charset);
} finally {
IOUtils.closeSilently(in);
}
}
private void process(Connection conn, boolean continueOnError,
String path, Reader reader, String charsetName) throws SQLException, IOException {
String path, Reader reader, Charset charset) throws SQLException, IOException {
Statement stat = conn.createStatement();
ScriptReader r = new ScriptReader(reader);
while (true) {
......@@ -208,7 +209,7 @@ public class RunScript extends Tool {
if (!FileUtils.isAbsolute(sql)) {
sql = path + SysProperties.FILE_SEPARATOR + sql;
}
process(conn, sql, continueOnError, charsetName);
process(conn, sql, continueOnError, charset);
} else {
try {
if (showResults && !trim.startsWith("-->")) {
......@@ -286,12 +287,12 @@ public class RunScript extends Tool {
* @param user the user name
* @param password the password
* @param fileName the script file
* @param charsetName the character set name or null for UTF-8
* @param charset the character set or null for UTF-8
* @param continueOnError if execution should be continued if an error occurs
*/
public static void execute(String url, String user, String password,
String fileName, String charsetName, boolean continueOnError) throws SQLException {
new RunScript().process(url, user, password, fileName, charsetName, continueOnError);
String fileName, Charset charset, boolean continueOnError) throws SQLException {
new RunScript().process(url, user, password, fileName, charset, continueOnError);
}
/**
......@@ -301,20 +302,20 @@ public class RunScript extends Tool {
* @param user the user name
* @param password the password
* @param fileName the script file
* @param charsetName the character set name or null for UTF-8
* @param charset the character set or null for UTF-8
* @param continueOnError if execution should be continued if an error occurs
*/
void process(String url, String user, String password,
String fileName, String charsetName,
String fileName, Charset charset,
boolean continueOnError) throws SQLException {
try {
org.h2.Driver.load();
Connection conn = DriverManager.getConnection(url, user, password);
if (charsetName == null) {
charsetName = Constants.UTF8;
if (charset == null) {
charset = Constants.UTF8;
}
try {
process(conn, fileName, continueOnError, charsetName);
process(conn, fileName, continueOnError, charset);
} finally {
conn.close();
}
......
......@@ -18,7 +18,6 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import org.h2.constant.SysProperties;
......@@ -379,13 +378,7 @@ public class IOUtils {
* @return the reader
*/
public static Reader getBufferedReader(InputStream in) {
try {
//
return in == null ? null : new BufferedReader(new InputStreamReader(in, Constants.UTF8));
} catch (Exception e) {
// UnsupportedEncodingException
throw DbException.convert(e);
}
return in == null ? null : new BufferedReader(new InputStreamReader(in, Constants.UTF8));
}
/**
......@@ -398,13 +391,8 @@ public class IOUtils {
* @return the reader
*/
public static Reader getReader(InputStream in) {
try {
// InputStreamReader may read some more bytes
return in == null ? null : new BufferedReader(new InputStreamReader(in, Constants.UTF8));
} catch (Exception e) {
// UnsupportedEncodingException
throw DbException.convert(e);
}
// InputStreamReader may read some more bytes
return in == null ? null : new BufferedReader(new InputStreamReader(in, Constants.UTF8));
}
/**
......@@ -415,23 +403,7 @@ public class IOUtils {
* @return the writer
*/
public static Writer getBufferedWriter(OutputStream out) {
try {
return out == null ? null : new BufferedWriter(new OutputStreamWriter(out, Constants.UTF8));
} catch (Exception e) {
// UnsupportedEncodingException
throw DbException.convert(e);
}
}
/**
* Create a reader to read from a string.
* If the string is null, this method returns null.
*
* @param s the string or null
* @return the reader
*/
public static Reader getReaderFromString(String s) {
return s == null ? null : new StringReader(s);
return out == null ? null : new BufferedWriter(new OutputStreamWriter(out, Constants.UTF8));
}
/**
......@@ -475,7 +447,7 @@ public class IOUtils {
if (s == null) {
return null;
}
return new ByteArrayInputStream(StringUtils.utf8Encode(s));
return new ByteArrayInputStream(s.getBytes(Constants.UTF8));
}
/**
......
......@@ -325,55 +325,6 @@ public class StringUtils {
return "\"" + javaEncode(s) + "\"";
}
/**
* Convert the text to UTF-8 format. For the Unicode characters
* 0xd800-0xdfff only one byte is returned.
*
* @param s the text
* @return the UTF-8 representation
*/
public static byte[] utf8Encode(String s) {
try {
return s.getBytes(Constants.UTF8);
} catch (Exception e) {
// UnsupportedEncodingException
throw DbException.convert(e);
}
}
/**
* Convert a UTF-8 representation of a text to the text.
*
* @param utf8 the UTF-8 representation
* @return the text
*/
public static String utf8Decode(byte[] utf8) {
try {
return new String(utf8, Constants.UTF8);
} catch (Exception e) {
// UnsupportedEncodingException
throw DbException.convert(e);
}
}
/**
* Convert a UTF-8 representation of a text to the text using the given
* offset and length.
*
* @param bytes the UTF-8 representation
* @param offset the offset in the bytes array
* @param length the number of bytes
* @return the text
*/
public static String utf8Decode(byte[] bytes, int offset, int length) {
try {
return new String(bytes, offset, length, Constants.UTF8);
} catch (Exception e) {
// UnsupportedEncodingException
throw DbException.convert(e);
}
}
/**
* Convert a string array to the Java source code that represents this
* array. Null will be converted to 'null'.
......@@ -479,7 +430,7 @@ public class StringUtils {
buff[j++] = (byte) ch;
}
}
String s = utf8Decode(buff, 0, j);
String s = new String(buff, 0, j, Constants.UTF8);
return s;
}
......
......@@ -22,8 +22,10 @@ import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.engine.SessionInterface;
import org.h2.jdbc.JdbcBlob;
import org.h2.jdbc.JdbcClob;
......@@ -32,7 +34,6 @@ import org.h2.message.DbException;
import org.h2.store.LobStorage;
import org.h2.tools.SimpleResultSet;
import org.h2.util.New;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
/**
......@@ -539,7 +540,7 @@ public class DataType {
}
case Value.CLOB: {
if (session == null) {
v = LobStorage.createSmallLob(Value.CLOB, StringUtils.utf8Encode(rs.getString(columnIndex)));
v = LobStorage.createSmallLob(Value.CLOB, rs.getString(columnIndex).getBytes(Constants.UTF8));
} else {
Reader in = rs.getCharacterStream(columnIndex);
if (in == null) {
......
......@@ -9,6 +9,7 @@ package org.h2.value;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.lang.ref.SoftReference;
import java.math.BigDecimal;
import java.sql.Date;
......@@ -18,14 +19,15 @@ import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.store.DataHandler;
import org.h2.store.LobStorage;
import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils;
import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
......@@ -426,7 +428,7 @@ public abstract class Value {
}
public Reader getReader() {
return IOUtils.getReaderFromString(getString());
return new StringReader(getString());
}
/**
......@@ -832,7 +834,7 @@ public abstract class Value {
case FLOAT:
return ValueFloat.get(Float.parseFloat(s.trim()));
case CLOB:
return LobStorage.createSmallLob(CLOB, StringUtils.utf8Encode(s));
return LobStorage.createSmallLob(CLOB, s.getBytes(Constants.UTF8));
case BLOB:
return LobStorage.createSmallLob(BLOB, StringUtils.convertHexToBytes(s.trim()));
case ARRAY:
......
......@@ -144,7 +144,7 @@ public class ValueLob extends Value {
try {
if (handler == null) {
String s = IOUtils.readStringAndClose(in, (int) length);
return createSmallLob(Value.CLOB, StringUtils.utf8Encode(s));
return createSmallLob(Value.CLOB, s.getBytes(Constants.UTF8));
}
boolean compress = handler.getLobCompressionAlgorithm(Value.CLOB) != null;
long remaining = Long.MAX_VALUE;
......@@ -163,7 +163,7 @@ public class ValueLob extends Value {
len = len < 0 ? 0 : len;
}
if (len <= handler.getMaxLengthInplaceLob()) {
byte[] small = StringUtils.utf8Encode(new String(buff, 0, len));
byte[] small = new String(buff, 0, len).getBytes(Constants.UTF8);
return ValueLob.createSmallLob(Value.CLOB, small);
}
ValueLob lob = new ValueLob(Value.CLOB, null);
......@@ -204,7 +204,7 @@ public class ValueLob extends Value {
try {
while (true) {
precision += len;
byte[] b = StringUtils.utf8Encode(new String(buff, 0, len));
byte[] b = new String(buff, 0, len).getBytes(Constants.UTF8);
out.write(b, 0, b.length);
remaining -= len;
if (remaining <= 0) {
......@@ -546,7 +546,7 @@ public class ValueLob extends Value {
try {
if (type == Value.CLOB) {
if (small != null) {
return StringUtils.utf8Decode(small);
return new String(small, Constants.UTF8);
}
return IOUtils.readStringAndClose(getReader(), len);
}
......
......@@ -196,7 +196,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
try {
if (type == Value.CLOB) {
if (small != null) {
return StringUtils.utf8Decode(small);
return new String(small, Constants.UTF8);
}
return IOUtils.readStringAndClose(getReader(), len);
}
......@@ -407,7 +407,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
len = len < 0 ? 0 : len;
}
if (len <= handler.getMaxLengthInplaceLob()) {
byte[] small = StringUtils.utf8Encode(new String(buff, 0, len));
byte[] small = new String(buff, 0, len).getBytes(Constants.UTF8);
return ValueLobDb.createSmallLob(Value.CLOB, small, len);
}
ValueLobDb lob = new ValueLobDb(Value.CLOB, null, 0);
......@@ -461,7 +461,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
try {
while (true) {
precision += len;
byte[] b = StringUtils.utf8Encode(new String(buff, 0, len));
byte[] b = new String(buff, 0, len).getBytes(Constants.UTF8);
out.write(b, 0, b.length);
remaining -= len;
if (remaining <= 0) {
......
......@@ -5,6 +5,9 @@
*/
package org.h2.test.store;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
......@@ -36,6 +39,7 @@ public class TestMVTableEngine extends TestBase {
public void test() throws Exception {
//testSpeed();
// testBlob();
testExclusiveLock();
testEncryption();
testReadOnly();
......@@ -63,7 +67,7 @@ int tes;
}
FileUtils.deleteRecursive(getBaseDir(), true);
}
private void testSpeed(String dbName) throws Exception {
FileUtils.deleteRecursive(getBaseDir(), true);
Connection conn;
......@@ -124,6 +128,35 @@ int tes;
//System.out.println(prof.getTop(10));
System.out.println((System.currentTimeMillis() - time) + " " + dbName + " after");
}
private void testBlob() throws SQLException, IOException {
FileUtils.deleteRecursive(getBaseDir(), true);
String dbName = "mvstore" +
";DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine";
Connection conn;
Statement stat;
conn = getConnection(dbName);
stat = conn.createStatement();
stat.execute("create table test(id int, name blob)");
PreparedStatement prep = conn.prepareStatement("insert into test values(1, ?)");
prep.setBinaryStream(1, new ByteArrayInputStream(new byte[1000]));
prep.execute();
conn.close();
conn = getConnection(dbName);
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from test");
while (rs.next()) {
InputStream in = rs.getBinaryStream(2);
int len = 0;
while (in.read() >= 0) {
len++;
}
assertEquals(10000, len);
}
conn.close();
FileUtils.deleteRecursive(getBaseDir(), true);
}
private void testEncryption() throws Exception {
FileUtils.deleteRecursive(getBaseDir(), true);
......
......@@ -17,6 +17,7 @@ import java.io.RandomAccessFile;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.h2.engine.Constants;
import org.h2.tools.RunScript;
/**
......@@ -89,7 +90,7 @@ public class Migrate {
"-password", password
});
file.renameTo(new File(file.getAbsoluteFile() + ".backup"));
RunScript.execute(url, user, password, TEMP_SCRIPT, "UTF-8", true);
RunScript.execute(url, user, password, TEMP_SCRIPT, Constants.UTF8, true);
new File(TEMP_SCRIPT).delete();
}
......
......@@ -12,10 +12,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import org.h2.engine.Constants;
import org.h2.message.DbException;
/**
* The reader input stream wraps a reader and convert the character to the UTF-8
......@@ -35,11 +34,7 @@ public class ReaderInputStream extends InputStream {
chars = new char[Constants.IO_BUFFER_SIZE];
this.reader = reader;
out = new ByteArrayOutputStream(Constants.IO_BUFFER_SIZE);
try {
writer = new BufferedWriter(new OutputStreamWriter(out, Constants.UTF8));
} catch (UnsupportedEncodingException e) {
throw DbException.convert(e);
}
writer = new BufferedWriter(new OutputStreamWriter(out, Constants.UTF8));
}
private void fillBuffer() throws IOException {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论