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

--no commit message

--no commit message
上级 b504a2db
#Fri Feb 01 15:26:30 CET 2008
javac=javac
#Sun Feb 03 11:48:01 CET 2008
benchmark.drivers.dir=C\:/data/java
javac=javac
jdk=1.4
path.lucene.jar=C\:/data/classpath/lucene-core-2.2.0.jar
path.servlet.jar=C\:/data/classpath/servlet-api.jar
version.name.maven=1.0.66
path.lucene.jar=C\:/data/classpath/lucene-core-2.2.0.jar
jdk=1.4
......@@ -56,43 +56,38 @@
</target>
<target name="codeswitchAndroid" depends="codeswitchPrepare">
<propertyfile file="ant-build.properties">
<entry key="jdk" value="1.3" />
</propertyfile>
<java classname="org.h2.tools.code.CodeSwitch" classpath="bin">
<arg line="+JDK13 -JDK14 -JDK16 -AWT src/main/org/h2"/>
<arg line="+JDK13 -JDK14 -JDK16 -AWT src/main/org/h2 -set ant-build.properties jdk 1.3"/>
</java>
</target>
<target name="codeswitchJdk13" depends="codeswitchPrepare">
<java classname="org.h2.tools.code.CodeSwitch" classpath="bin">
<arg line="+JDK13 -JDK14 -JDK16 +AWT src/main/org/h2"/>
<arg line="+JDK13 -JDK14 -JDK16 +AWT src/main/org/h2 -set ant-build.properties jdk 1.3"/>
</java>
<propertyfile file="ant-build.properties">
<entry key="jdk" value="1.3" />
</propertyfile>
<property name="jdk" value="1.3"/>
</target>
<target name="codeswitchJdk14" depends="codeswitchPrepare" if="codeswitch.14">
<target name="codeswitchJdk14" depends="codeswitchPrepare">
<java classname="org.h2.tools.code.CodeSwitch" classpath="bin">
<arg line="-JDK13 +JDK14 -JDK16 +AWT src/main/org/h2"/>
<arg line="-JDK13 +JDK14 -JDK16 +AWT src/main/org/h2 -set ant-build.properties jdk 1.4"/>
</java>
<propertyfile file="ant-build.properties">
<entry key="jdk" value="1.4" />
</propertyfile>
</target>
<target name="codeswitchJdk16" depends="codeswitchPrepare" if="codeswitch.16">
<target name="codeswitchJdk16" depends="codeswitchPrepare">
<java classname="org.h2.tools.code.CodeSwitch" classpath="bin">
<arg line="-JDK13 +JDK14 +JDK16 +AWT src/main/org/h2"/>
<arg line="-JDK13 +JDK14 +JDK16 +AWT src/main/org/h2 -set ant-build.properties jdk 1.6"/>
</java>
<propertyfile file="ant-build.properties">
<entry key="jdk" value="1.6" />
</propertyfile>
</target>
<target name="compileResources" depends="clean, codeswitchJdk14, codeswitchJdk16">
<target name="codeswitchJdk14Auto" if="codeswitch.14">
<antcall target="codeswitchJdk14" />
</target>
<target name="codeswitchJdk16Auto" if="codeswitch.16">
<antcall target="codeswitchJdk16" />
</target>
<target name="compileResources" depends="clean, codeswitchJdk14Auto, codeswitchJdk16Auto">
<javac executable="${javac}" srcdir="src/main" destdir="bin" debug="true" includes="org/h2/util/Resources.java"/>
<java classname="org.h2.util.Resources" classpath="bin"/>
<delete>
......@@ -159,7 +154,7 @@
<javac executable="${javac}" srcdir="bin" destdir="bin" debug="true" includes="org/h2/**"/>
</target>
<target name="docs" depends="clean,javadoc,compile">
<target name="docs" depends="clean, javadoc, compile">
<copy todir="docs">
<fileset dir="src/docsrc" includes="index.html"/>
<fileset dir="src/docsrc" includes="html/**/*" excludes="**/*.jsp" />
......
......@@ -456,6 +456,11 @@ Also, there may be compatibility problems on the SQL level, with the catalog, or
Problems are fixed as they are found.
Currently, statements can not be cancelled when using the PG protocol.
</p>
<p>
PostgreSQL ODBC Driver Setup requires a database password, that means it
is not possible to connect to H2 databases without password. This is a limitation
of the ODBC driver.
</p>
<h3>Security Considerations</h3>
<p>
......
......@@ -108,7 +108,7 @@ via PayPal:
</li><li>Antonio Casqueiro, Portugal
</li><li>lumber-mill.co.jp, Japan
</li><li>Oliver Computing LLC, USA
</li><li>Harpal Grover, USA
</li><li>Harpal Grover Consulting Inc., USA
</li></ul>
</div></td></tr></table></body></html>
......@@ -295,9 +295,16 @@ public class Set extends Prepared {
session.setVariable(stringValue, expr.getValue(session));
break;
}
case SetTypes.QUERY_TIMEOUT: {
int value = getIntValue();
session.setQueryTimeout(value);
break;
}
default:
throw Message.getInternalError("type="+type);
}
// the meta data information has changed
database.getNextModificationDataId();
return 0;
}
......
......@@ -21,8 +21,7 @@ public class SetTypes {
public static final int COMPRESS_LOB = 23, ALLOW_LITERALS = 24, MULTI_THREADED = 25, SCHEMA = 26;
public static final int OPTIMIZE_REUSE_RESULTS = 27, SCHEMA_SEARCH_PATH = 28, UNDO_LOG = 29;
public static final int REFERENTIAL_INTEGRITY = 30, MVCC = 31, MAX_OPERATION_MEMORY = 32, EXCLUSIVE = 33;
public static final int CREATE_BUILD = 34;
public static final int VARIABLE = 35;
public static final int CREATE_BUILD = 34, VARIABLE = 35, QUERY_TIMEOUT = 36;
private static ObjectArray types = new ObjectArray();
......@@ -62,6 +61,7 @@ public class SetTypes {
setType(EXCLUSIVE, "EXCLUSIVE");
setType(CREATE_BUILD, "CREATE_BUILD");
setType(VARIABLE, "@");
setType(QUERY_TIMEOUT, "QUERY_TIMEOUT");
}
private static void setType(int type, String name) {
......
......@@ -21,6 +21,11 @@ import org.h2.message.TraceSystem;
*/
public class SysProperties {
/**
* INTERNAL
*/
public static final String H2_MAX_QUERY_TIMEOUT = "h2.maxQueryTimeout";
/**
* System property <code>file.encoding</code> (default: Cp1252).<br />
* It is usually set by the system and is the default encoding used for the RunScript and CSV tool.
......@@ -172,6 +177,12 @@ public class SysProperties {
*/
public static final int MAX_FILE_RETRY = Math.max(1, getIntSetting("h2.maxFileRetry", 16));
/**
* System property <code>h2.maxQueryTimeout</code> (default: 0).<br />
* The maximum timeout of a query. The default is 0, meaning no limit.
*/
public static final int MAX_QUERY_TIMEOUT = getIntSetting(H2_MAX_QUERY_TIMEOUT, 0);
/**
* System property <code>h2.minColumnNameMap</code> (default: 3).<br />
* The minimum number of columns where a hash table is created when result set
......@@ -335,7 +346,7 @@ public class SysProperties {
return s == null ? defaultValue : s;
}
private static int getIntSetting(String name, int defaultValue) {
public static int getIntSetting(String name, int defaultValue) {
String s = getProperty(name);
if (s != null) {
try {
......@@ -363,4 +374,11 @@ public class SysProperties {
return baseDir;
}
/**
* INTERNAL
*/
public static int getMaxQueryTimeout() {
return getIntSetting(H2_MAX_QUERY_TIMEOUT, 0);
}
}
......@@ -81,6 +81,7 @@ public class Session implements SessionInterface {
private long currentCommandStart;
private HashMap variables;
private HashSet temporaryResults;
private int queryTimeout = SysProperties.getMaxQueryTimeout();
public Session() {
}
......@@ -543,6 +544,9 @@ public class Session implements SessionInterface {
public void setCurrentCommand(Command command, long startTime) {
this.currentCommand = command;
this.currentCommandStart = startTime;
if (queryTimeout > 0) {
cancelAt = startTime + queryTimeout;
}
}
public void checkCancelled() throws SQLException {
......@@ -703,4 +707,17 @@ public class Session implements SessionInterface {
}
}
public void setQueryTimeout(int queryTimeout) {
int max = SysProperties.getMaxQueryTimeout();
if (max != 0 && (max < queryTimeout || queryTimeout == 0)) {
// the value must be at most max
queryTimeout = max;
}
this.queryTimeout = queryTimeout;
}
public int getQueryTimeout() {
return queryTimeout;
}
}
......@@ -39,6 +39,7 @@ import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLob;
import org.h2.value.ValueNull;
import org.h2.value.ValueString;
//#ifdef JDK16
/*
......@@ -67,6 +68,7 @@ public class JdbcConnection extends TraceObject implements Connection {
private CommandInterface setAutoCommitTrue, setAutoCommitFalse, getAutoCommit;
private CommandInterface getReadOnly, getGeneratedKeys;
private CommandInterface setLockMode, getLockMode;
private CommandInterface setQueryTimeout, getQueryTimeout;
private Exception openStackTrace;
//#ifdef JDK14
private int savepointId;
......@@ -249,6 +251,8 @@ public class JdbcConnection extends TraceObject implements Connection {
getGeneratedKeys = closeAndSetNull(getGeneratedKeys);
getLockMode = closeAndSetNull(getLockMode);
setLockMode = closeAndSetNull(setLockMode);
getQueryTimeout = closeAndSetNull(getQueryTimeout);
setQueryTimeout = closeAndSetNull(setQueryTimeout);
} finally {
session.close();
}
......@@ -519,7 +523,7 @@ public class JdbcConnection extends TraceObject implements Connection {
/**
* Changes the current transaction isolation level. Calling this method will
* commit any open transactions, even if the new level is the same as the
* commit an open transaction, even if the new level is the same as the
* old one, except if the level is not supported.
*
* @param level the new transaction isolation level,
......@@ -556,6 +560,43 @@ public class JdbcConnection extends TraceObject implements Connection {
}
}
/**
* INTERNAL
*/
public void setQueryTimeout(int seconds) throws SQLException {
try {
commit();
setQueryTimeout = prepareCommand("SET QUERY_TIMEOUT ?", setQueryTimeout);
((ParameterInterface) setQueryTimeout.getParameters().get(0)).setValue(ValueInt.get(seconds * 1000));
setQueryTimeout.executeUpdate();
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* INTERNAL
*/
public int getQueryTimeout() throws SQLException {
try {
getQueryTimeout = prepareCommand("SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?", getQueryTimeout);
((ParameterInterface) getQueryTimeout.getParameters().get(0)).setValue(ValueString.get("QUERY_TIMEOUT"));
ResultInterface result = getQueryTimeout.executeQuery(0, false);
result.next();
int queryTimeout = result.currentRow()[0].getInt();
result.close();
if (queryTimeout == 0) {
return 0;
} else {
// round to the next second, otherwise 999 millis would return 0 seconds
return (queryTimeout + 999) / 1000;
}
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Returns the current transaction isolation level.
*
......
......@@ -31,8 +31,6 @@ public class JdbcStatement extends TraceObject implements Statement {
protected JdbcResultSet resultSet;
protected int maxRows;
protected boolean escapeProcessing = true;
protected int queryTimeout;
protected boolean queryTimeoutSet;
protected int fetchSize = SysProperties.SERVER_RESULT_SET_FETCH_SIZE;
protected int updateCount;
private CommandInterface executingCommand;
......@@ -519,6 +517,8 @@ public class JdbcStatement extends TraceObject implements Statement {
/**
* Gets the current query timeout in seconds.
* This method will return 0 if no query timeout is set.
* The result is rounded to the next second.
*
* @return the timeout in seconds
* @throws SQLException if this object is closed
......@@ -527,7 +527,7 @@ public class JdbcStatement extends TraceObject implements Statement {
try {
debugCodeCall("getQueryTimeout");
checkClosed();
return queryTimeout;
return conn.getQueryTimeout();
} catch (Throwable e) {
throw logAndConvert(e);
}
......@@ -535,7 +535,8 @@ public class JdbcStatement extends TraceObject implements Statement {
/**
* Sets the current query timeout in seconds.
* This method will succeed, even if the functionality is not supported by the database.
* Calling this method will commit an open transaction, even if the value is the same as before.
* Changing the value will affect all statements of this connection.
*
* @param seconds the timeout in seconds -
* 0 means no timeout, values smaller 0 will throw an exception
......@@ -548,8 +549,7 @@ public class JdbcStatement extends TraceObject implements Statement {
if (seconds < 0) {
throw Message.getInvalidValueException("" + seconds, "seconds");
}
queryTimeout = seconds;
queryTimeoutSet = true;
conn.setQueryTimeout(seconds);
} catch (Throwable e) {
throw logAndConvert(e);
}
......
......@@ -1033,6 +1033,17 @@ This setting can be appended to the database URL: jdbc:h2:test;OPTIMIZE_REUSE_RE
SET OPTIMIZE_REUSE_RESULTS 0
"
"Commands (Other)","SET QUERY_TIMEOUT","
SET QUERY_TIMEOUT int
","
Set the query timeout of the current session to the given value.
The timeout is in milliseconds. All kinds of statements will
throw an exception if they take longer than the given value.
The default timeout is 0, meaning no timeout.
","
SET QUERY_TIMEOUT 10000
"
"Commands (Other)","SET PASSWORD","
SET PASSWORD string
","
......
......@@ -708,10 +708,11 @@ public class MetaTable extends Table {
add(rows, new String[] { "property." + s, SysProperties.getStringSetting(s, "") });
}
}
add(rows, new String[] { "MVCC", database.isMultiVersion() ? "TRUE" : "FALSE" });
add(rows, new String[] { "EXCLUSIVE", database.getExclusiveSession() == null ? "FALSE" : "TRUE" });
add(rows, new String[] { "MODE", database.getMode().getName() });
add(rows, new String[] { "MULTI_THREADED", database.getMultiThreaded() ? "1" : "0"});
add(rows, new String[] { "MVCC", database.isMultiVersion() ? "TRUE" : "FALSE" });
add(rows, new String[] { "QUERY_TIMEOUT", "" + session.getQueryTimeout() });
add(rows, new String[]{"h2.allowBigDecimalExtensions", "" + SysProperties.ALLOW_BIG_DECIMAL_EXTENSIONS});
add(rows, new String[]{"h2.baseDir", "" + SysProperties.getBaseDir()});
add(rows, new String[]{"h2.check", "" + SysProperties.CHECK});
......@@ -725,6 +726,7 @@ public class MetaTable extends Table {
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.maxFileRetry", "" + SysProperties.MAX_FILE_RETRY});
add(rows, new String[]{SysProperties.H2_MAX_QUERY_TIMEOUT, "" + SysProperties.getMaxQueryTimeout()});
add(rows, new String[]{"h2.lobCloseBetweenReads", "" + SysProperties.lobCloseBetweenReads});
add(rows, new String[]{"h2.objectCache", "" + SysProperties.OBJECT_CACHE});
add(rows, new String[]{"h2.objectCacheSize", "" + SysProperties.OBJECT_CACHE_SIZE});
......
......@@ -167,7 +167,6 @@ timer test
// repeatable test with a very big database (making backups of the database files)
Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes
ODBC must include a password; I cannot use the default 'sa' with no password for it.
Test with many columns (180), create index
add a 'kill process while altering tables' test case
......@@ -175,7 +174,7 @@ Roadmap:
History:
Statement.setQueryTimeout() is now supported. New session setting QUERY_TIMEOUT, and new system property h2.maxQueryTimeout.
*/
......
......@@ -10,6 +10,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.test.TestBase;
......@@ -41,6 +43,70 @@ public class TestCancel extends TestBase {
}
public void test() throws Exception {
testMaxQueryTimeout();
testQueryTimeout();
testJdbcQueryTimeout();
testCancelStatement();
}
private void testJdbcQueryTimeout() throws Exception {
deleteDb("cancel");
Connection conn = getConnection("cancel");
Statement stat = conn.createStatement();
check(0, stat.getQueryTimeout());
stat.setQueryTimeout(1);
check(1, stat.getQueryTimeout());
Statement s2 = conn.createStatement();
check(1, s2.getQueryTimeout());
ResultSet rs = s2.executeQuery("SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'QUERY_TIMEOUT'");
rs.next();
check(1000, rs.getInt(1));
try {
stat.executeQuery("SELECT MAX(RAND()) FROM SYSTEM_RANGE(1, 100000000)");
error("unexpected success");
} catch (SQLException e) {
check(ErrorCode.STATEMENT_WAS_CANCELLED, e.getErrorCode());
}
stat.setQueryTimeout(0);
stat.execute("SET QUERY_TIMEOUT 1100");
check(2, stat.getQueryTimeout());
conn.close();
}
private void testQueryTimeout() throws Exception {
deleteDb("cancel");
Connection conn = getConnection("cancel");
Statement stat = conn.createStatement();
stat.execute("SET QUERY_TIMEOUT 10");
try {
stat.executeQuery("SELECT MAX(RAND()) FROM SYSTEM_RANGE(1, 100000000)");
error("unexpected success");
} catch (SQLException e) {
check(ErrorCode.STATEMENT_WAS_CANCELLED, e.getErrorCode());
}
conn.close();
}
private void testMaxQueryTimeout() throws Exception {
deleteDb("cancel");
int oldMax = SysProperties.getMaxQueryTimeout();
try {
System.setProperty(SysProperties.H2_MAX_QUERY_TIMEOUT, "" + 10);
Connection conn = getConnection("cancel");
Statement stat = conn.createStatement();
try {
stat.executeQuery("SELECT MAX(RAND()) FROM SYSTEM_RANGE(1, 100000000)");
error("unexpected success");
} catch (SQLException e) {
check(ErrorCode.STATEMENT_WAS_CANCELLED, e.getErrorCode());
}
conn.close();
} finally {
System.setProperty("h2.maxQueryTimeout", "" + oldMax);
}
}
private void testCancelStatement() throws Exception {
deleteDb("cancel");
Connection conn = getConnection("cancel");
Statement stat = conn.createStatement();
......
......@@ -27,6 +27,7 @@ import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.h2.constant.SysProperties;
import org.h2.jdbc.JdbcConnection;
import org.h2.test.TestAll;
import org.h2.test.TestBase;
......@@ -392,9 +393,15 @@ public class TestCrashAPI extends TestBase {
}
public void testCase(int i) throws Exception {
int old = SysProperties.getMaxQueryTimeout();
try {
System.setProperty(SysProperties.H2_MAX_QUERY_TIMEOUT, "" + 10000);
baseDir = "dataCrash";
testOne(i);
} finally {
baseDir = "data";
System.setProperty(SysProperties.H2_MAX_QUERY_TIMEOUT, "" + old);
}
}
public void test() throws Exception {
......
......@@ -4,10 +4,21 @@
*/
package org.h2.tools.code;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
/**
* This application allows to switch source code to different 'modes', so that
......@@ -25,15 +36,16 @@ public class CodeSwitch {
private ArrayList lines;
private boolean changed;
public static void main(String[] argv) {
public static void main(String[] argv) throws Exception {
(new CodeSwitch()).run(argv);
}
private void run(String[] a) {
private void run(String[] a) throws Exception {
if (a.length == 0) {
showUsage();
return;
}
String propertiesFile = null, property = null, value = null;
boolean path = false;
recurse = true;
for (int i = 0; i < a.length; i++) {
......@@ -45,6 +57,10 @@ public class CodeSwitch {
recurse = true;
} else if (p.startsWith("-r-")) {
recurse = false;
} else if (p.startsWith("-set")) {
propertiesFile = a[++i];
property = a[++i];
value = a[++i];
} else if (p.startsWith("-")) {
switchOff.add(p.substring(1));
} else {
......@@ -60,15 +76,42 @@ public class CodeSwitch {
if (switchOff.size() == 0 && switchOn.size() == 0) {
printSwitches();
}
if (propertiesFile != null) {
setProperty(propertiesFile, property, value);
}
}
private static class SortedProperties extends Properties {
private static final long serialVersionUID = 3926204645298674434L;
public synchronized Enumeration keys() {
Vector v = new Vector(keySet());
Collections.sort(v);
return v.elements();
}
}
private void setProperty(String propertiesFile, String property, String value) throws IOException {
SortedProperties prop = new SortedProperties();
InputStream in = new BufferedInputStream(new FileInputStream(propertiesFile));
prop.load(in);
in.close();
prop.setProperty(property, value);
OutputStream out = new BufferedOutputStream(new FileOutputStream(propertiesFile));
prop.store(out, null);
out.close();
}
private void showUsage() {
String className = getClass().getName();
System.out.println("Usage: java " + className + " [-r+] [-r-] paths [+|-][labels]");
System.out.println("Usage: java " + className + " [-r+] [-r-] paths [+|-][labels] [-set file property value]");
System.out.println("If no labels are specified then all used");
System.out.println("labels in the source code are shown.");
System.out.println("-r+ recurse subdirectories (default)");
System.out.println("-r- do not recurse subdirectories");
System.out.println("-set will update a value in a properties file after switching");
System.out.println("Use +MODE to switch on code labeled MODE");
System.out.println("Use -MODE to switch off code labeled MODE");
System.out.println("Path: Any number of path or files may be specified.");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论