提交 886d1c5c authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 dd4dd186
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
<mkdir dir="docs/javadoc"/> <mkdir dir="docs/javadoc"/>
<javadoc <javadoc
sourcepath="src/main" sourcepath="src/main"
packagenames="org.h2.jdbc.*,org.h2.jdbcx.*,org.h2.tools.*,org.h2.api.*" packagenames="org.h2.jdbc.*,org.h2.jdbcx.*,org.h2.tools.*,org.h2.api.*,org.h2.constant.*"
doclet="org.h2.tools.doclet.Doclet" doclet="org.h2.tools.doclet.Doclet"
docletpath="bin" docletpath="bin"
/> />
......
...@@ -570,12 +570,16 @@ public class Select extends Query { ...@@ -570,12 +570,16 @@ public class Select extends Query {
} }
} }
} }
if (sort != null && !isQuickQuery && !isGroupQuery && (!distinct || isDistinctQuery)) { if (sort != null && !isQuickQuery && !isGroupQuery) {
Index index = getSortIndex(); Index index = getSortIndex();
Index current = topTableFilter.getIndex(); Index current = topTableFilter.getIndex();
if (index != null && (current.getIndexType().isScan() || current == index)) { if (index != null && (current.getIndexType().isScan() || current == index)) {
topTableFilter.setIndex(index); topTableFilter.setIndex(index);
sortUsingIndex = true; if (!distinct || isDistinctQuery) {
// sort using index wouldn't work correctly for distinct result sets
// because it would break too early when limit is used
sortUsingIndex = true;
}
} }
} }
} }
......
...@@ -27,10 +27,11 @@ public class JdbcBatchUpdateException extends BatchUpdateException { ...@@ -27,10 +27,11 @@ public class JdbcBatchUpdateException extends BatchUpdateException {
* INTERNAL * INTERNAL
*/ */
public void printStackTrace() { public void printStackTrace() {
super.printStackTrace(); // The default implementation already does that,
if (getNextException() != null) { // but we do it again to avoid problems.
getNextException().printStackTrace(); // If it is not implemented, somebody might implement it
} // later on which would be a problem if done in the wrong way.
printStackTrace(System.err);
} }
/** /**
......
...@@ -55,7 +55,7 @@ import java.sql.SQLClientInfoException; ...@@ -55,7 +55,7 @@ import java.sql.SQLClientInfoException;
*/ */
public class JdbcConnection extends TraceObject implements Connection { public class JdbcConnection extends TraceObject implements Connection {
// TODO test: check if enough synchronization on jdbc objects // TODO test: check if enough synchronization on jdbc objects
// TODO feature auto-reconnect on lost connection! // TODO feature: auto-reconnect on lost connection
private String url; private String url;
private String user; private String user;
......
...@@ -61,17 +61,11 @@ public class JdbcSQLException extends SQLException { ...@@ -61,17 +61,11 @@ public class JdbcSQLException extends SQLException {
* Prints the stack trace to the standard error stream. * Prints the stack trace to the standard error stream.
*/ */
public void printStackTrace() { public void printStackTrace() {
super.printStackTrace(); // The default implementation already does that,
//#ifdef JDK13 // but we do it again to avoid problems.
/* // If it is not implemented, somebody might implement it
if (cause != null) { // later on which would be a problem if done in the wrong way.
cause.printStackTrace(); printStackTrace(System.err);
}
*/
//#endif
if (getNextException() != null) {
getNextException().printStackTrace();
}
} }
/** /**
...@@ -89,8 +83,15 @@ public class JdbcSQLException extends SQLException { ...@@ -89,8 +83,15 @@ public class JdbcSQLException extends SQLException {
} }
*/ */
//#endif //#endif
if (getNextException() != null) { // getNextException().printStackTrace(s) would be very very slow
getNextException().printStackTrace(s); // if many exceptions are joined
SQLException next = getNextException();
for (int i = 0; i < 100 && next != null; i++) {
s.println(next.toString());
next = next.getNextException();
}
if (next != null) {
s.println("(truncated)");
} }
} }
} }
...@@ -110,8 +111,15 @@ public class JdbcSQLException extends SQLException { ...@@ -110,8 +111,15 @@ public class JdbcSQLException extends SQLException {
} }
*/ */
//#endif //#endif
if (getNextException() != null) { // getNextException().printStackTrace(s) would be very very slow
getNextException().printStackTrace(s); // if many exceptions are joined
SQLException next = getNextException();
for (int i = 0; i < 100 && next != null; i++) {
s.println(next.toString());
next = next.getNextException();
}
if (next != null) {
s.println("(truncated)");
} }
} }
} }
......
...@@ -31,9 +31,10 @@ import org.h2.message.Message; ...@@ -31,9 +31,10 @@ import org.h2.message.Message;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.NetUtils;
/** /**
* A factory to create encrypted sockets. To generate new keystore, use the * A factory to create encrypted sockets. To generate new keystore, use the
* SecureKeyStoreBuilder tool. * SecureKeyStoreBuilder tool.
*/ */
public class SecureSocketFactory { public class SecureSocketFactory {
...@@ -42,7 +43,7 @@ public class SecureSocketFactory { ...@@ -42,7 +43,7 @@ public class SecureSocketFactory {
private static final String KEYSTORE_KEY = "javax.net.ssl.keyStore"; private static final String KEYSTORE_KEY = "javax.net.ssl.keyStore";
private static final String KEYSTORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword"; private static final String KEYSTORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword";
public static final String KEYSTORE_PASSWORD = "h2pass"; public static final String KEYSTORE_PASSWORD = "h2pass";
// TODO security / SSL: need a way to disable anonymous ssl // TODO security / SSL: need a way to disable anonymous ssl
private static final boolean ENABLE_ANONYMOUS_SSL = true; private static final boolean ENABLE_ANONYMOUS_SSL = true;
private static SecureSocketFactory factory; private static SecureSocketFactory factory;
...@@ -58,7 +59,7 @@ public class SecureSocketFactory { ...@@ -58,7 +59,7 @@ public class SecureSocketFactory {
} }
return factory; return factory;
} }
public Socket createSocket(InetAddress address, int port) throws IOException { public Socket createSocket(InetAddress address, int port) throws IOException {
Socket socket = null; Socket socket = null;
//#ifdef JDK14 //#ifdef JDK14
...@@ -80,7 +81,13 @@ public class SecureSocketFactory { ...@@ -80,7 +81,13 @@ public class SecureSocketFactory {
//#ifdef JDK14 //#ifdef JDK14
setKeystore(); setKeystore();
ServerSocketFactory f = SSLServerSocketFactory.getDefault(); ServerSocketFactory f = SSLServerSocketFactory.getDefault();
SSLServerSocket secureSocket = (SSLServerSocket) f.createServerSocket(port); SSLServerSocket secureSocket;
InetAddress bindAddress = NetUtils.getBindAddress();
if (bindAddress == null) {
secureSocket = (SSLServerSocket) f.createServerSocket(port);
} else {
secureSocket = (SSLServerSocket) f.createServerSocket(port, 0, bindAddress);
}
if (ENABLE_ANONYMOUS_SSL) { if (ENABLE_ANONYMOUS_SSL) {
String[] list = secureSocket.getEnabledCipherSuites(); String[] list = secureSocket.getEnabledCipherSuites();
list = addAnonymous(list); list = addAnonymous(list);
...@@ -95,7 +102,7 @@ public class SecureSocketFactory { ...@@ -95,7 +102,7 @@ public class SecureSocketFactory {
private static byte[] getBytes(String hex) throws SQLException { private static byte[] getBytes(String hex) throws SQLException {
return ByteUtils.convertStringToBytes(hex); return ByteUtils.convertStringToBytes(hex);
} }
private static byte[] getKeyStoreBytes(KeyStore store, String password) throws IOException { private static byte[] getKeyStoreBytes(KeyStore store, String password) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream(); ByteArrayOutputStream bout = new ByteArrayOutputStream();
try { try {
...@@ -105,16 +112,16 @@ public class SecureSocketFactory { ...@@ -105,16 +112,16 @@ public class SecureSocketFactory {
} }
return bout.toByteArray(); return bout.toByteArray();
} }
public static KeyStore getKeyStore(String password) throws IOException { public static KeyStore getKeyStore(String password) throws IOException {
try { try {
// The following source code can be re-generated when you have a keystore file. // The following source code can be re-generated when you have a keystore file.
// This code is (hopefully) more Java version independent than using keystores directly. // This code is (hopefully) more Java version independent than using keystores directly.
// See also: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4887561 (1.4.2 cannot read keystore written with 1.4.1) // See also: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4887561 (1.4.2 cannot read keystore written with 1.4.1)
// --- generated code start --- // --- generated code start ---
KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType()); KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
store.load(null, password.toCharArray()); store.load(null, password.toCharArray());
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); KeyFactory keyFactory = KeyFactory.getInstance("RSA");
store.load(null, password.toCharArray()); store.load(null, password.toCharArray());
...@@ -133,8 +140,8 @@ public class SecureSocketFactory { ...@@ -133,8 +140,8 @@ public class SecureSocketFactory {
throw Message.convertToIOException(e); throw Message.convertToIOException(e);
} }
} }
private void setKeystore() throws IOException { private void setKeystore() throws IOException {
Properties p = System.getProperties(); Properties p = System.getProperties();
if (p.getProperty(KEYSTORE_KEY) == null) { if (p.getProperty(KEYSTORE_KEY) == null) {
String fileName = FileUtils.getFileInUserHome(KEYSTORE); String fileName = FileUtils.getFileInUserHome(KEYSTORE);
......
...@@ -81,8 +81,8 @@ public class FtpServer implements Service { ...@@ -81,8 +81,8 @@ public class FtpServer implements Service {
} }
} }
public ServerSocket createDataSocket() throws IOException { public ServerSocket createDataSocket() throws SQLException {
ServerSocket dataSocket = new ServerSocket(0); ServerSocket dataSocket = NetUtils.createServerSocket(0, false);
return dataSocket; return dataSocket;
} }
......
...@@ -24,6 +24,7 @@ import org.h2.message.TraceSystem; ...@@ -24,6 +24,7 @@ import org.h2.message.TraceSystem;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.NetUtils;
import org.h2.util.RandomUtils; import org.h2.util.RandomUtils;
import org.h2.util.SortedProperties; import org.h2.util.SortedProperties;
...@@ -52,7 +53,7 @@ public class FileLock { ...@@ -52,7 +53,7 @@ public class FileLock {
private volatile ServerSocket socket; private volatile ServerSocket socket;
private boolean locked; private boolean locked;
private Trace trace; private Trace trace;
// private java.nio.channels.FileLock fileLock; // private java.nio.channels.FileLock fileLock;
public FileLock(TraceSystem traceSystem, int sleep) { public FileLock(TraceSystem traceSystem, int sleep) {
...@@ -267,7 +268,7 @@ public class FileLock { ...@@ -267,7 +268,7 @@ public class FileLock {
} }
try { try {
// 0 to use any free port // 0 to use any free port
socket = new ServerSocket(0); socket = NetUtils.createServerSocket(0, false);
int port = socket.getLocalPort(); int port = socket.getLocalPort();
properties.setProperty("ipAddress", ipAddress); properties.setProperty("ipAddress", ipAddress);
properties.setProperty("port", String.valueOf(port)); properties.setProperty("port", String.valueOf(port));
...@@ -323,6 +324,6 @@ public class FileLock { ...@@ -323,6 +324,6 @@ public class FileLock {
} else { } else {
throw Message.getSQLException(ErrorCode.UNSUPPORTED_LOCK_METHOD_1, method); throw Message.getSQLException(ErrorCode.UNSUPPORTED_LOCK_METHOD_1, method);
} }
} }
} }
...@@ -712,43 +712,44 @@ public class MetaTable extends Table { ...@@ -712,43 +712,44 @@ public class MetaTable extends Table {
add(rows, new String[] { "EXCLUSIVE", database.getExclusiveSession() == null ? "FALSE" : "TRUE" }); add(rows, new String[] { "EXCLUSIVE", database.getExclusiveSession() == null ? "FALSE" : "TRUE" });
add(rows, new String[] { "MODE", database.getMode().getName() }); add(rows, new String[] { "MODE", database.getMode().getName() });
add(rows, new String[] { "MULTI_THREADED", database.getMultiThreaded() ? "1" : "0"}); add(rows, new String[] { "MULTI_THREADED", database.getMultiThreaded() ? "1" : "0"});
DiskFile dataFile = database.getDataFile(); add(rows, new String[]{"h2.allowBigDecimalExtensions", "" + SysProperties.ALLOW_BIG_DECIMAL_EXTENSIONS});
if (dataFile != null) { add(rows, new String[]{"h2.baseDir", "" + SysProperties.getBaseDir()});
add(rows, new String[] { "CACHE_TYPE", dataFile.getCache().getTypeName() });
if (session.getUser().getAdmin()) {
add(rows, new String[]{"info.FILE_DISK_WRITE", "" + dataFile.getWriteCount()});
add(rows, new String[]{"info.FILE_DISK_READ", "" + dataFile.getReadCount()});
add(rows, new String[]{"info.FILE_INDEX_WRITE", "" + database.getIndexFile().getWriteCount()});
add(rows, new String[]{"info.FILE_INDEX_READ", "" + database.getIndexFile().getReadCount()});
}
}
add(rows, new String[]{"h2.check", "" + SysProperties.CHECK}); add(rows, new String[]{"h2.check", "" + SysProperties.CHECK});
add(rows, new String[]{"h2.check2", "" + SysProperties.CHECK2}); add(rows, new String[]{"h2.check2", "" + SysProperties.CHECK2});
add(rows, new String[]{"h2.clientTraceDirectory", SysProperties.CLIENT_TRACE_DIRECTORY});
add(rows, new String[]{"h2.defaultMaxMemoryUndo", "" + SysProperties.DEFAULT_MAX_MEMORY_UNDO});
add(rows, new String[]{"h2.emergencySpaceInitial", "" + SysProperties.EMERGENCY_SPACE_INITIAL});
add(rows, new String[]{"h2.emergencySpaceMin", "" + SysProperties.EMERGENCY_SPACE_MIN});
add(rows, new String[]{"h2.lobFilesInDirectories", "" + SysProperties.LOB_FILES_IN_DIRECTORIES}); add(rows, new String[]{"h2.lobFilesInDirectories", "" + SysProperties.LOB_FILES_IN_DIRECTORIES});
add(rows, new String[]{"h2.lobFilesPerDirectory", "" + SysProperties.LOB_FILES_PER_DIRECTORY}); add(rows, new String[]{"h2.lobFilesPerDirectory", "" + SysProperties.LOB_FILES_PER_DIRECTORY});
add(rows, new String[]{"h2.runFinalize", "" + SysProperties.runFinalize});
add(rows, new String[]{"h2.optimizeMinMax", "" + SysProperties.OPTIMIZE_MIN_MAX});
add(rows, new String[]{"h2.optimizeIn", "" + SysProperties.OPTIMIZE_IN});
add(rows, new String[]{"h2.redoBufferSize", "" + SysProperties.REDO_BUFFER_SIZE});
add(rows, new String[]{"h2.recompileAlways", "" + SysProperties.RECOMPILE_ALWAYS});
add(rows, new String[]{"h2.optimizeSubqueryCache", "" + SysProperties.OPTIMIZE_SUBQUERY_CACHE});
add(rows, new String[]{"h2.overflowExceptions", "" + SysProperties.OVERFLOW_EXCEPTIONS});
add(rows, new String[]{"h2.logAllErrors", "" + SysProperties.LOG_ALL_ERRORS}); add(rows, new String[]{"h2.logAllErrors", "" + SysProperties.LOG_ALL_ERRORS});
add(rows, new String[]{"h2.logAllErrorsFile", "" + SysProperties.LOG_ALL_ERRORS_FILE}); add(rows, new String[]{"h2.logAllErrorsFile", "" + SysProperties.LOG_ALL_ERRORS_FILE});
add(rows, new String[]{"h2.serverCachedObjects", "" + SysProperties.SERVER_CACHED_OBJECTS}); add(rows, new String[]{"h2.maxFileRetry", "" + SysProperties.MAX_FILE_RETRY});
add(rows, new String[]{"h2.serverResultSetFetchSize", "" + SysProperties.SERVER_RESULT_SET_FETCH_SIZE}); add(rows, new String[]{"h2.lobCloseBetweenReads", "" + SysProperties.lobCloseBetweenReads});
add(rows, new String[]{"h2.emergencySpaceInitial", "" + SysProperties.EMERGENCY_SPACE_INITIAL});
add(rows, new String[]{"h2.emergencySpaceMin", "" + SysProperties.EMERGENCY_SPACE_MIN});
add(rows, new String[]{"h2.objectCache", "" + SysProperties.OBJECT_CACHE}); add(rows, new String[]{"h2.objectCache", "" + SysProperties.OBJECT_CACHE});
add(rows, new String[]{"h2.objectCacheSize", "" + SysProperties.OBJECT_CACHE_SIZE}); add(rows, new String[]{"h2.objectCacheSize", "" + SysProperties.OBJECT_CACHE_SIZE});
add(rows, new String[]{"h2.objectCacheMaxPerElementSize", "" + SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE}); add(rows, new String[]{"h2.objectCacheMaxPerElementSize", "" + SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE});
add(rows, new String[]{"h2.clientTraceDirectory", SysProperties.CLIENT_TRACE_DIRECTORY}); add(rows, new String[]{"h2.optimizeIn", "" + SysProperties.OPTIMIZE_IN});
add(rows, new String[]{"h2.optimizeInJoin", "" + SysProperties.OPTIMIZE_IN_JOIN});
add(rows, new String[]{"h2.optimizeMinMax", "" + SysProperties.OPTIMIZE_MIN_MAX});
add(rows, new String[]{"h2.optimizeSubqueryCache", "" + SysProperties.OPTIMIZE_SUBQUERY_CACHE});
add(rows, new String[]{"h2.overflowExceptions", "" + SysProperties.OVERFLOW_EXCEPTIONS});
add(rows, new String[]{"h2.recompileAlways", "" + SysProperties.RECOMPILE_ALWAYS});
add(rows, new String[]{"h2.redoBufferSize", "" + SysProperties.REDO_BUFFER_SIZE});
add(rows, new String[]{"h2.runFinalize", "" + SysProperties.runFinalize});
add(rows, new String[]{"h2.scriptDirectory", SysProperties.scriptDirectory}); add(rows, new String[]{"h2.scriptDirectory", SysProperties.scriptDirectory});
add(rows, new String[]{"h2.maxFileRetry", "" + SysProperties.MAX_FILE_RETRY}); add(rows, new String[]{"h2.serverCachedObjects", "" + SysProperties.SERVER_CACHED_OBJECTS});
add(rows, new String[]{"h2.lobCloseBetweenReads", "" + SysProperties.lobCloseBetweenReads}); add(rows, new String[]{"h2.serverResultSetFetchSize", "" + SysProperties.SERVER_RESULT_SET_FETCH_SIZE});
add(rows, new String[]{"h2.allowBigDecimalExtensions", "" + SysProperties.ALLOW_BIG_DECIMAL_EXTENSIONS}); DiskFile dataFile = database.getDataFile();
add(rows, new String[]{"h2.baseDir", "" + SysProperties.getBaseDir()}); if (dataFile != null) {
add(rows, new String[]{"h2.defaultMaxMemoryUndo", "" + SysProperties.DEFAULT_MAX_MEMORY_UNDO}); add(rows, new String[] { "CACHE_TYPE", dataFile.getCache().getTypeName() });
if (session.getUser().getAdmin()) {
add(rows, new String[]{"info.FILE_DISK_WRITE", "" + dataFile.getWriteCount()});
add(rows, new String[]{"info.FILE_DISK_READ", "" + dataFile.getReadCount()});
add(rows, new String[]{"info.FILE_INDEX_WRITE", "" + database.getIndexFile().getWriteCount()});
add(rows, new String[]{"info.FILE_INDEX_READ", "" + database.getIndexFile().getReadCount()});
}
}
break; break;
} }
case TYPE_INFO: { case TYPE_INFO: {
......
...@@ -9,9 +9,11 @@ import java.net.BindException; ...@@ -9,9 +9,11 @@ import java.net.BindException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.security.SecureSocketFactory; import org.h2.security.SecureSocketFactory;
...@@ -20,6 +22,8 @@ import org.h2.security.SecureSocketFactory; ...@@ -20,6 +22,8 @@ import org.h2.security.SecureSocketFactory;
*/ */
public class NetUtils { public class NetUtils {
private static InetAddress bindAddress;
public static Socket createLoopbackSocket(int port, boolean ssl) throws IOException { public static Socket createLoopbackSocket(int port, boolean ssl) throws IOException {
return createSocket("127.0.0.1", port, ssl); return createSocket("127.0.0.1", port, ssl);
} }
...@@ -58,15 +62,37 @@ public class NetUtils { ...@@ -58,15 +62,37 @@ public class NetUtils {
} }
} }
/**
* Get the bind address if the system property h2.bindAddress is set, or
* null if not.
*
* @return the bind address
*/
public static InetAddress getBindAddress() throws UnknownHostException {
String host = SysProperties.BIND_ADDRESS;
if (host == null || host.length() == 0) {
return null;
}
synchronized (NetUtils.class) {
if (bindAddress == null) {
bindAddress = InetAddress.getByName(host);
}
}
return bindAddress;
}
private static ServerSocket createServerSocketTry(int port, boolean ssl) throws SQLException { private static ServerSocket createServerSocketTry(int port, boolean ssl) throws SQLException {
// TODO server sockets: maybe automatically open the next port if this is in use?
// TODO server sockets: maybe a parameter to allow anonymous ssl?
try { try {
if (ssl) { if (ssl) {
SecureSocketFactory f = SecureSocketFactory.getInstance(); SecureSocketFactory f = SecureSocketFactory.getInstance();
return f.createServerSocket(port); return f.createServerSocket(port);
} else { } else {
return new ServerSocket(port); InetAddress bindAddress = getBindAddress();
if (bindAddress == null) {
return new ServerSocket(port);
} else {
return new ServerSocket(port, 0, bindAddress);
}
} }
} catch (BindException be) { } catch (BindException be) {
throw Message.getSQLException(ErrorCode.EXCEPTION_OPENING_PORT_2, throw Message.getSQLException(ErrorCode.EXCEPTION_OPENING_PORT_2,
......
...@@ -11,7 +11,6 @@ import org.h2.server.TcpServer; ...@@ -11,7 +11,6 @@ import org.h2.server.TcpServer;
import org.h2.store.fs.FileSystemDisk; import org.h2.store.fs.FileSystemDisk;
import org.h2.test.db.TestAutoRecompile; import org.h2.test.db.TestAutoRecompile;
import org.h2.test.db.TestBackup; import org.h2.test.db.TestBackup;
import org.h2.test.db.TestBatchUpdates;
import org.h2.test.db.TestBigDb; import org.h2.test.db.TestBigDb;
import org.h2.test.db.TestBigResult; import org.h2.test.db.TestBigResult;
import org.h2.test.db.TestCases; import org.h2.test.db.TestCases;
...@@ -49,6 +48,7 @@ import org.h2.test.db.TestTransaction; ...@@ -49,6 +48,7 @@ import org.h2.test.db.TestTransaction;
import org.h2.test.db.TestTriggersConstraints; import org.h2.test.db.TestTriggersConstraints;
import org.h2.test.db.TestTwoPhaseCommit; import org.h2.test.db.TestTwoPhaseCommit;
import org.h2.test.db.TestView; import org.h2.test.db.TestView;
import org.h2.test.jdbc.TestBatchUpdates;
import org.h2.test.jdbc.TestCallableStatement; import org.h2.test.jdbc.TestCallableStatement;
import org.h2.test.jdbc.TestCancel; import org.h2.test.jdbc.TestCancel;
import org.h2.test.jdbc.TestDataSource; import org.h2.test.jdbc.TestDataSource;
...@@ -149,16 +149,32 @@ java org.h2.test.TestAll timer ...@@ -149,16 +149,32 @@ java org.h2.test.TestAll timer
/* /*
staging.trace.db.gz staging.trace.db.gz
drop table logs;
CREATE TABLE Logs(id INT PRIMARY KEY, procid INT);
CREATE unique INDEX procIdx ON Logs(procid, id);
@LOOP 1000 INSERT INTO Logs VALUES(?, MOD(?, 100000));
ANALYZE SAMPLE_SIZE 0;
script nodata;
EXPLAIN SELECT id FROM Logs WHERE procid=2 AND id<100;
h2CallableStatementBatchTest.zip
h2-2007-12-27_test.zip
docs,
History:
The bind IP address can now be set when using multi-homed host (if multiple network adapters are available)
using the system property h2.bindAddress.
Batch update: Calling BatchUpdateException.printStackTrace() could result in out of memory. Fixed.
Create system property documentation from Javadocs.
allow queries as well in batch updates allow queries as well in batch updates
CALL syntax should probably work for regular executeUpdate as well. CALL syntax should probably work for regular executeUpdate as well.
http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/callablestatement.html#1000220 http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/callablestatement.html#1000220
-Djboss.bind.address=<ip_address> Automatically switch source code before compiling
-Dh2.bindAddress=...
[echo] Java version is 1.6 but source code is switched to 1.4. [echo] Java version is 1.6 but source code is switched to 1.4.
[echo] Run ant codeswitchJdk... first. [echo] Run ant codeswitchJdk... first.
...@@ -487,7 +503,6 @@ Features of H2 ...@@ -487,7 +503,6 @@ Features of H2
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 TestBatchUpdates().runTest(this);
new TestBigDb().runTest(this); new TestBigDb().runTest(this);
new TestBigResult().runTest(this); new TestBigResult().runTest(this);
new TestCache().runTest(this); new TestCache().runTest(this);
...@@ -531,6 +546,7 @@ Features of H2 ...@@ -531,6 +546,7 @@ Features of H2
new TestPgServer().runTest(this); new TestPgServer().runTest(this);
// jdbc // jdbc
new TestBatchUpdates().runTest(this);
new TestCallableStatement().runTest(this); new TestCallableStatement().runTest(this);
new TestCancel().runTest(this); new TestCancel().runTest(this);
new TestDatabaseEventListener().runTest(this); new TestDatabaseEventListener().runTest(this);
......
...@@ -66,20 +66,25 @@ public class TestOptimizations extends TestBase { ...@@ -66,20 +66,25 @@ public class TestOptimizations extends TestBase {
checkFalse(rs.next()); checkFalse(rs.next());
stat.execute("ANALYZE"); stat.execute("ANALYZE");
rs = stat.executeQuery("SELECT DISTINCT TYPE FROM TEST ORDER BY TYPE"); rs = stat.executeQuery("SELECT DISTINCT TYPE FROM TEST ORDER BY TYPE");
for (int i = 0; rs.next(); i++) { for (int i = 0; i < 10; i++) {
check(rs.next());
check(i, rs.getInt(1)); check(i, rs.getInt(1));
} }
checkFalse(rs.next()); checkFalse(rs.next());
rs = stat.executeQuery("SELECT DISTINCT TYPE FROM TEST ORDER BY TYPE LIMIT 5 OFFSET 2"); rs = stat.executeQuery("SELECT DISTINCT TYPE FROM TEST ORDER BY TYPE LIMIT 5 OFFSET 2");
for (int i = 2; i < 7; i++) { for (int i = 2; i < 7; i++) {
rs.next(); check(rs.next());
check(i, rs.getInt(1)); check(i, rs.getInt(1));
} }
checkFalse(rs.next()); checkFalse(rs.next());
rs = stat.executeQuery("SELECT DISTINCT TYPE FROM TEST ORDER BY TYPE LIMIT 0 OFFSET 0 SAMPLE_SIZE 3"); rs = stat.executeQuery("SELECT DISTINCT TYPE FROM TEST ORDER BY TYPE LIMIT 0 OFFSET 0 SAMPLE_SIZE 3");
// must have at least one row
check(rs.next());
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
rs.next(); rs.getInt(1);
check(i, rs.getInt(1)); if (i > 0 && !rs.next()) {
break;
}
} }
checkFalse(rs.next()); checkFalse(rs.next());
conn.close(); conn.close();
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html). * Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group * Initial Developer: H2 Group
*/ */
package org.h2.test.db; package org.h2.test.jdbc;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.sql.BatchUpdateException; import java.sql.BatchUpdateException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
...@@ -36,6 +38,37 @@ public class TestBatchUpdates extends TestBase { ...@@ -36,6 +38,37 @@ public class TestBatchUpdates extends TestBase {
PreparedStatement prep; PreparedStatement prep;
public void test() throws Exception { public void test() throws Exception {
testException();
testCoffee();
}
private void testException() throws Exception {
deleteDb("batchUpdates");
Connection conn = getConnection("batchUpdates");
Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key)");
PreparedStatement prep = conn.prepareStatement("insert into test values(?)");
for (int i = 0; i < 700; i++) {
prep.setString(1, "x");
prep.addBatch();
}
try {
prep.executeBatch();
} catch (BatchUpdateException e) {
PrintStream temp = System.err;
try {
ByteArrayOutputStream buff = new ByteArrayOutputStream();
PrintStream p = new PrintStream(buff);
System.setErr(p);
e.printStackTrace();
} finally {
System.setErr(temp);
}
}
conn.close();
}
private void testCoffee() throws Exception {
deleteDb("batchUpdates"); deleteDb("batchUpdates");
this.conn = getConnection("batchUpdates"); this.conn = getConnection("batchUpdates");
stat = conn.createStatement(); stat = conn.createStatement();
......
...@@ -36,4 +36,5 @@ To call getFD().sync() (which results in the OS call fsync()), ...@@ -36,4 +36,5 @@ To call getFD().sync() (which results in the OS call fsync()),
set the system property derby.storage.fileSyncTransactionLog to true true. set the system property derby.storage.fileSyncTransactionLog to true true.
See See
http://db.apache.org/derby/javadoc/engine/org/apache/derby/iapi/reference/Property.html#FILESYNC_TRANSACTION_LOG http://db.apache.org/derby/javadoc/engine/org/apache/derby/iapi/reference/Property.html#FILESYNC_TRANSACTION_LOG
Missing features:
LIMIT OFFSET is not supported.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论