提交 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,15 +570,19 @@ public class Select extends Query { ...@@ -570,15 +570,19 @@ 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);
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; sortUsingIndex = true;
} }
} }
} }
}
public double getCost() { public double getCost() {
return cost; return cost;
......
...@@ -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,6 +31,7 @@ import org.h2.message.Message; ...@@ -31,6 +31,7 @@ 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
...@@ -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);
......
...@@ -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;
...@@ -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));
......
...@@ -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 {
InetAddress bindAddress = getBindAddress();
if (bindAddress == null) {
return new ServerSocket(port); 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论