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

--no commit message

--no commit message
上级 0b2f337b
...@@ -3201,7 +3201,7 @@ public class Parser { ...@@ -3201,7 +3201,7 @@ public class Parser {
} else if (readIf("USER")) { } else if (readIf("USER")) {
return parseCreateUser(); return parseCreateUser();
} else if (readIf("TRIGGER")) { } else if (readIf("TRIGGER")) {
return parseCreateTrigger(); return parseCreateTrigger(force);
} else if (readIf("ROLE")) { } else if (readIf("ROLE")) {
return parseCreateRole(); return parseCreateRole();
} else if (readIf("SCHEMA")) { } else if (readIf("SCHEMA")) {
...@@ -3421,7 +3421,7 @@ public class Parser { ...@@ -3421,7 +3421,7 @@ public class Parser {
return command; return command;
} }
private CreateTrigger parseCreateTrigger() throws SQLException { private CreateTrigger parseCreateTrigger(boolean force) throws SQLException {
boolean ifNotExists = readIfNoExists(); boolean ifNotExists = readIfNoExists();
String triggerName = readIdentifierWithSchema(null); String triggerName = readIdentifierWithSchema(null);
Schema schema = getSchema(); Schema schema = getSchema();
...@@ -3448,6 +3448,7 @@ public class Parser { ...@@ -3448,6 +3448,7 @@ public class Parser {
String tableName = readIdentifierWithSchema(); String tableName = readIdentifierWithSchema();
checkSchema(schema); checkSchema(schema);
CreateTrigger command = new CreateTrigger(session, getSchema()); CreateTrigger command = new CreateTrigger(session, getSchema());
command.setForce(force);
command.setTriggerName(triggerName); command.setTriggerName(triggerName);
command.setIfNotExists(ifNotExists); command.setIfNotExists(ifNotExists);
command.setBefore(isBefore); command.setBefore(isBefore);
......
...@@ -30,6 +30,7 @@ public class CreateTrigger extends SchemaCommand { ...@@ -30,6 +30,7 @@ public class CreateTrigger extends SchemaCommand {
private boolean noWait; private boolean noWait;
private String tableName; private String tableName;
private String triggerClassName; private String triggerClassName;
private boolean force;
public CreateTrigger(Session session, Schema schema) { public CreateTrigger(Session session, Schema schema) {
super(session, schema); super(session, schema);
...@@ -90,10 +91,14 @@ public class CreateTrigger extends SchemaCommand { ...@@ -90,10 +91,14 @@ public class CreateTrigger extends SchemaCommand {
trigger.setQueueSize(queueSize); trigger.setQueueSize(queueSize);
trigger.setRowBased(rowBased); trigger.setRowBased(rowBased);
trigger.setTypeMask(typeMask); trigger.setTypeMask(typeMask);
trigger.setTriggerClassName(session, triggerClassName); trigger.setTriggerClassName(session, triggerClassName, force);
db.addSchemaObject(session, trigger); db.addSchemaObject(session, trigger);
table.addTrigger(trigger); table.addTrigger(trigger);
return 0; return 0;
} }
public void setForce(boolean force) {
this.force = force;
}
} }
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
*/ */
package org.h2.constant; package org.h2.constant;
import java.sql.SQLException;
import java.sql.Savepoint;
/** /**
* This class defines the error codes used for SQL exceptions. * This class defines the error codes used for SQL exceptions.
*/ */
...@@ -895,7 +898,19 @@ public class ErrorCode { ...@@ -895,7 +898,19 @@ public class ErrorCode {
*/ */
public static final int UNSUPPORTED_CIPHER = 90055; public static final int UNSUPPORTED_CIPHER = 90055;
private int todo; /**
* The error with code <code>90056</code> is thrown when
* updating or deleting from a table with a foreign key constraint
* that should set the default value, but there is no default value defined.
* Example:
* <pre>
* CREATE TABLE TEST(ID INT, PARENT INT);
* INSERT INTO TEST VALUES(1, 1), (2, 1);
* ALTER TABLE TEST ADD CONSTRAINT TEST_ID_PARENT
* FOREIGN KEY(PARENT) REFERENCES(ID) ON DELETE SET DEFAULT;
* DELETE FROM TEST WHERE ID=1;
* </pre>
*/
public static final int NO_DEFAULT_SET_1 = 90056; public static final int NO_DEFAULT_SET_1 = 90056;
/** /**
...@@ -908,7 +923,6 @@ public class ErrorCode { ...@@ -908,7 +923,6 @@ public class ErrorCode {
* </pre> * </pre>
*/ */
public static final int CONSTRAINT_NOT_FOUND_1 = 90057; public static final int CONSTRAINT_NOT_FOUND_1 = 90057;
public static final int DUPLICATE_TABLE_ALIAS = 90058;
/** /**
* The error with code <code>90059</code> is thrown when * The error with code <code>90059</code> is thrown when
...@@ -921,6 +935,16 @@ public class ErrorCode { ...@@ -921,6 +935,16 @@ public class ErrorCode {
* </pre> * </pre>
*/ */
public static final int AMBIGUOUS_COLUMN_NAME_1 = 90059; public static final int AMBIGUOUS_COLUMN_NAME_1 = 90059;
/**
* The error with code <code>90060</code> is thrown when
* trying to use a file locking mechanism that is not supported.
* Currently only FILE (the default) and SOCKET are supported
* Example:
* <pre>
* jdbc:h2:test;FILE_LOCK=LDAP
* </pre>
*/
public static final int UNSUPPORTED_LOCK_METHOD_1 = 90060; public static final int UNSUPPORTED_LOCK_METHOD_1 = 90060;
/** /**
...@@ -929,6 +953,14 @@ public class ErrorCode { ...@@ -929,6 +953,14 @@ public class ErrorCode {
* It could also be a firewall problem. * It could also be a firewall problem.
*/ */
public static final int EXCEPTION_OPENING_PORT_2 = 90061; public static final int EXCEPTION_OPENING_PORT_2 = 90061;
/**
* The error with code <code>90062</code> is thrown when
* a directory or file could not be created. This can occur when
* trying to create a directory if a file with the same name already
* exists, or vice versa.
*
*/
public static final int FILE_CREATION_FAILED_1 = 90062; public static final int FILE_CREATION_FAILED_1 = 90062;
/** /**
...@@ -940,9 +972,46 @@ public class ErrorCode { ...@@ -940,9 +972,46 @@ public class ErrorCode {
* </pre> * </pre>
*/ */
public static final int SAVEPOINT_IS_INVALID_1 = 90063; public static final int SAVEPOINT_IS_INVALID_1 = 90063;
/**
* The error with code <code>90064</code> is thrown when
* Savepoint.getSavepointName() is called on an unnamed savepoint.
* Example:
* <pre>
* Savepoint sp = conn.setSavepoint();
* sp.getSavepointName();
* </pre>
*/
public static final int SAVEPOINT_IS_UNNAMED = 90064; public static final int SAVEPOINT_IS_UNNAMED = 90064;
/**
* The error with code <code>90065</code> is thrown when
* Savepoint.getSavepointId() is called on a named savepoint.
* Example:
* <pre>
* Savepoint sp = conn.setSavepoint("Joe");
* sp.getSavepointId();
* </pre>
*/
public static final int SAVEPOINT_IS_NAMED = 90065; public static final int SAVEPOINT_IS_NAMED = 90065;
/**
* The error with code <code>90066</code> is thrown when
* the same property appears twice in the database URL or in
* the connection properties.
* Example:
* <pre>
* jdbc:h2:test;LOG=0;LOG=1
* </pre>
*/
public static final int DUPLICATE_PROPERTY_1 = 90066; public static final int DUPLICATE_PROPERTY_1 = 90066;
/**
* The error with code <code>90067</code> is thrown when
* the connection to the database is lost. A possible reason
* is that the connection has been closed due to a shutdown,
* or that the server is stopped.
*/
public static final int CONNECTION_BROKEN = 90067; public static final int CONNECTION_BROKEN = 90067;
/** /**
...@@ -961,11 +1030,69 @@ public class ErrorCode { ...@@ -961,11 +1030,69 @@ public class ErrorCode {
* </pre> * </pre>
*/ */
public static final int ORDER_BY_NOT_IN_RESULT = 90068; public static final int ORDER_BY_NOT_IN_RESULT = 90068;
/**
* The error with code <code>90069</code> is thrown when
* trying to create a role if an object with this name already exists.
* Example:
* <pre>
* CREATE ROLE TEST_ROLE;
* CREATE ROLE TEST_ROLE;
* </pre>
*/
public static final int ROLE_ALREADY_EXISTS_1 = 90069; public static final int ROLE_ALREADY_EXISTS_1 = 90069;
/**
* The error with code <code>90070</code> is thrown when
* trying to drop or grant a role that does not exists.
* Example:
* <pre>
* DROP ROLE TEST_ROLE_2;
* </pre>
*/
public static final int ROLE_NOT_FOUND_1 = 90070; public static final int ROLE_NOT_FOUND_1 = 90070;
/**
* The error with code <code>90071</code> is thrown when
* trying to grant or revoke if no role or user with that name exists.
* Example:
* <pre>
* GRANT SELECT ON TEST TO UNKNOWN;
* </pre>
*/
public static final int USER_OR_ROLE_NOT_FOUND_1 = 90071; public static final int USER_OR_ROLE_NOT_FOUND_1 = 90071;
/**
* The error with code <code>90072</code> is thrown when
* trying to grant or revoke if no role or user with that name exists.
* Example:
* <pre>
* GRANT SELECT, TEST_ROLE ON TEST TO SA;
* </pre>
*/
public static final int ROLES_AND_RIGHT_CANNOT_BE_MIXED = 90072; public static final int ROLES_AND_RIGHT_CANNOT_BE_MIXED = 90072;
/**
* The error with code <code>90073</code> is thrown when
* trying to revoke a right that does not or no longer exist.
* Example:
* <pre>
* CREATE USER TEST_USER PASSWORD 'abc';
* REVOKE SELECT ON TEST FROM TEST_USER;
* </pre>
*/
public static final int RIGHT_NOT_FOUND = 90073; public static final int RIGHT_NOT_FOUND = 90073;
/**
* The error with code <code>90074</code> is thrown when
* trying to grant a role that has already been granted.
* Example:
* <pre>
* CREATE ROLE TEST_ROLE;
* GRANT TEST_ROLE TO SA;
* GRANT TEST_ROLE TO SA;
* </pre>
*/
public static final int ROLE_ALREADY_GRANTED_1 = 90074; public static final int ROLE_ALREADY_GRANTED_1 = 90074;
/** /**
...@@ -990,6 +1117,9 @@ public class ErrorCode { ...@@ -990,6 +1117,9 @@ public class ErrorCode {
* </pre> * </pre>
*/ */
public static final int FUNCTION_ALIAS_ALREADY_EXISTS_1 = 90076; public static final int FUNCTION_ALIAS_ALREADY_EXISTS_1 = 90076;
private int todo44;
public static final int FUNCTION_ALIAS_NOT_FOUND_1 = 90077; public static final int FUNCTION_ALIAS_NOT_FOUND_1 = 90077;
public static final int SCHEMA_ALREADY_EXISTS_1 = 90078; public static final int SCHEMA_ALREADY_EXISTS_1 = 90078;
public static final int SCHEMA_NOT_FOUND_1 = 90079; public static final int SCHEMA_NOT_FOUND_1 = 90079;
...@@ -1240,6 +1370,8 @@ public class ErrorCode { ...@@ -1240,6 +1370,8 @@ public class ErrorCode {
*/ */
public static final int CAN_ONLY_ASSIGN_TO_VARIABLE_1 = 90137; public static final int CAN_ONLY_ASSIGN_TO_VARIABLE_1 = 90137;
// next is 90058
/** /**
* INTERNAL * INTERNAL
*/ */
......
...@@ -401,9 +401,6 @@ private int test; ...@@ -401,9 +401,6 @@ private int test;
* INTERNAL * INTERNAL
*/ */
public static int getLogFileDeleteDelay() { public static int getLogFileDeleteDelay() {
int test;
return getIntSetting(H2_LOG_DELETE_DELAY, 0); return getIntSetting(H2_LOG_DELETE_DELAY, 0);
// return getIntSetting(H2_LOG_DELETE_DELAY, 100);
// return getIntSetting(H2_LOG_DELETE_DELAY, Integer.MAX_VALUE);
} }
} }
...@@ -73,7 +73,7 @@ public class Constants { ...@@ -73,7 +73,7 @@ public class Constants {
public static final int BUILD_ID = 66; public static final int BUILD_ID = 66;
private static final String BUILD = "2008-02-02"; private static final String BUILD = "2008-02-02";
public static final int VERSION_MAJOR = 1; public static final int VERSION_MAJOR = 1;
public static final int VERSION_MINOR = 0; public static final int VERSION_MINOR = 0;
...@@ -172,8 +172,19 @@ public class Constants { ...@@ -172,8 +172,19 @@ public class Constants {
public static final int VIEW_COST_CACHE_MAX_AGE = 10000; // 10 seconds public static final int VIEW_COST_CACHE_MAX_AGE = 10000; // 10 seconds
public static final int MAX_PARAMETER_INDEX = 100000; public static final int MAX_PARAMETER_INDEX = 100000;
// to slow down dictionary attacks /**
* The password is hashed this many times
* to slow down dictionary attacks.
*/
public static final int ENCRYPTION_KEY_HASH_ITERATIONS = 1024; public static final int ENCRYPTION_KEY_HASH_ITERATIONS = 1024;
public static final String SCRIPT_SQL = "script.sql"; public static final String SCRIPT_SQL = "script.sql";
public static final int CACHE_MIN_RECORDS = 16; public static final int CACHE_MIN_RECORDS = 16;
/**
* The delay in milliseconds before an exception about
* a wrong user or password is thrown.
* This slows down dictionary attacks.
* An attacker can still open multiple connections.
*/
public static final long DELAY_WRONG_PASSWORD = 200;
} }
...@@ -160,6 +160,13 @@ public class Database implements DataHandler { ...@@ -160,6 +160,13 @@ public class Database implements DataHandler {
String lockMethodName = ci.removeProperty("FILE_LOCK", null); String lockMethodName = ci.removeProperty("FILE_LOCK", null);
this.accessModeLog = ci.removeProperty("ACCESS_MODE_LOG", "rw").toLowerCase(); this.accessModeLog = ci.removeProperty("ACCESS_MODE_LOG", "rw").toLowerCase();
this.accessModeData = ci.removeProperty("ACCESS_MODE_DATA", "rw").toLowerCase(); this.accessModeData = ci.removeProperty("ACCESS_MODE_DATA", "rw").toLowerCase();
int testing;
if ("r".equals(accessModeData)) {
readOnly = true;
accessModeLog = "r";
}
this.fileLockMethod = FileLock.getFileLockMethod(lockMethodName); this.fileLockMethod = FileLock.getFileLockMethod(lockMethodName);
this.textStorage = ci.getTextStorage(); this.textStorage = ci.getTextStorage();
this.databaseURL = ci.getURL(); this.databaseURL = ci.getURL();
...@@ -380,6 +387,11 @@ public class Database implements DataHandler { ...@@ -380,6 +387,11 @@ public class Database implements DataHandler {
public void checkFilePasswordHash(String c, byte[] hash) throws SQLException { public void checkFilePasswordHash(String c, byte[] hash) throws SQLException {
if (!ByteUtils.compareSecure(hash, filePasswordHash) || !StringUtils.equals(c, cipher)) { if (!ByteUtils.compareSecure(hash, filePasswordHash) || !StringUtils.equals(c, cipher)) {
try {
Thread.sleep(Constants.DELAY_WRONG_PASSWORD);
} catch (InterruptedException e) {
// ignore
}
throw Message.getSQLException(ErrorCode.WRONG_USER_OR_PASSWORD); throw Message.getSQLException(ErrorCode.WRONG_USER_OR_PASSWORD);
} }
} }
...@@ -419,7 +431,12 @@ public class Database implements DataHandler { ...@@ -419,7 +431,12 @@ public class Database implements DataHandler {
if (persistent) { if (persistent) {
String dataFileName = databaseName + Constants.SUFFIX_DATA_FILE; String dataFileName = databaseName + Constants.SUFFIX_DATA_FILE;
if (FileUtils.exists(dataFileName)) { if (FileUtils.exists(dataFileName)) {
readOnly = FileUtils.isReadOnly(dataFileName);
int testingReadOnly;
// if it is already read-only because ACCESS_MODE_DATA=r
readOnly = readOnly | FileUtils.isReadOnly(dataFileName);
// readOnly = FileUtils.isReadOnly(dataFileName);
textStorage = isTextStorage(dataFileName, textStorage); textStorage = isTextStorage(dataFileName, textStorage);
} }
} }
...@@ -767,6 +784,11 @@ public class Database implements DataHandler { ...@@ -767,6 +784,11 @@ public class Database implements DataHandler {
public User getUser(String name, SQLException notFound) throws SQLException { public User getUser(String name, SQLException notFound) throws SQLException {
User user = (User) users.get(name); User user = (User) users.get(name);
if (user == null) { if (user == null) {
try {
Thread.sleep(Constants.DELAY_WRONG_PASSWORD);
} catch (InterruptedException e) {
// ignore
}
throw notFound; throw notFound;
} }
return user; return user;
......
...@@ -126,6 +126,11 @@ public class User extends RightOwner { ...@@ -126,6 +126,11 @@ public class User extends RightOwner {
SHA256 sha = new SHA256(); SHA256 sha = new SHA256();
byte[] hash = sha.getHashWithSalt(buff, salt); byte[] hash = sha.getHashWithSalt(buff, salt);
if (!ByteUtils.compareSecure(hash, passwordHash)) { if (!ByteUtils.compareSecure(hash, passwordHash)) {
try {
Thread.sleep(Constants.DELAY_WRONG_PASSWORD);
} catch (InterruptedException e) {
// ignore
}
throw onError; throw onError;
} }
} }
......
...@@ -9,9 +9,11 @@ import java.util.Comparator; ...@@ -9,9 +9,11 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import org.h2.api.DatabaseEventListener; import org.h2.api.DatabaseEventListener;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.store.DataPage; import org.h2.store.DataPage;
import org.h2.store.DiskFile; import org.h2.store.DiskFile;
...@@ -257,6 +259,19 @@ public class LogSystem { ...@@ -257,6 +259,19 @@ public class LogSystem {
LogFile l = new LogFile(this, 0, fileNamePrefix); LogFile l = new LogFile(this, 0, fileNamePrefix);
activeLogs.add(l); activeLogs.add(l);
} }
int checkNoMissing;
if(SysProperties.getIntSetting(SysProperties.H2_LOG_DELETE_DELAY, 0) > 0) {
LogFile last = null;
for(int i=0; i<activeLogs.size();i++) {
LogFile current = (LogFile) activeLogs.get(i);
if(last != null && last.getId() + 1 != current.getId()) {
throw Message.getInternalError("Miissing log file: " + last.getId() + ", " + current.getId());
}
last = current;
}
}
currentLog = (LogFile) activeLogs.get(activeLogs.size() - 1); currentLog = (LogFile) activeLogs.get(activeLogs.size() - 1);
} }
......
...@@ -47,8 +47,10 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -47,8 +47,10 @@ public class TriggerObject extends SchemaObjectBase {
this.before = before; this.before = before;
} }
public void setTriggerClassName(Session session, String triggerClassName) throws SQLException { private synchronized void load(Session session) throws SQLException {
this.triggerClassName = triggerClassName; if (triggerCallback != null) {
return;
}
try { try {
Connection c2 = session.createConnection(false); Connection c2 = session.createConnection(false);
Object obj = session.getDatabase().loadUserClass(triggerClassName).newInstance(); Object obj = session.getDatabase().loadUserClass(triggerClassName).newInstance();
...@@ -60,10 +62,22 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -60,10 +62,22 @@ public class TriggerObject extends SchemaObjectBase {
} }
} }
public void setTriggerClassName(Session session, String triggerClassName, boolean force) throws SQLException {
this.triggerClassName = triggerClassName;
try {
load(session);
} catch (SQLException e) {
if (!force) {
throw e;
}
}
}
public void fire(Session session, boolean beforeAction) throws SQLException { public void fire(Session session, boolean beforeAction) throws SQLException {
if (rowBased || before != beforeAction) { if (rowBased || before != beforeAction) {
return; return;
} }
load(session);
Connection c2 = session.createConnection(false); Connection c2 = session.createConnection(false);
try { try {
triggerCallback.fire(c2, null, null); triggerCallback.fire(c2, null, null);
...@@ -170,7 +184,7 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -170,7 +184,7 @@ public class TriggerObject extends SchemaObjectBase {
public String getCreateSQLForCopy(Table table, String quotedName) { public String getCreateSQLForCopy(Table table, String quotedName) {
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
buff.append("CREATE TRIGGER "); buff.append("CREATE FORCE TRIGGER ");
buff.append(quotedName); buff.append(quotedName);
if (before) { if (before) {
buff.append(" BEFORE "); buff.append(" BEFORE ");
......
...@@ -155,13 +155,20 @@ java org.h2.test.TestAll timer ...@@ -155,13 +155,20 @@ java org.h2.test.TestAll timer
TestAll test = new TestAll(); TestAll test = new TestAll();
test.printSystem(); test.printSystem();
//System.setProperty(SysProperties.H2_LOG_DELETE_DELAY, "20"); int test2;
//TestRecover.main(new String[0]); // System.setProperty(SysProperties.H2_LOG_DELETE_DELAY, "20");
// TestRecover.main(new String[0]);
/* /*
out of memory tests valentine
add a 'kill process while altering tables' test case
create force trigger : test & document
read only databases without having to make the files read-only: test & document
TestSessionsLocks
...?
Automate real power off tests Automate real power off tests
Extend tests that simulate power off Extend tests that simulate power off
...@@ -171,8 +178,6 @@ Test delayed log files delete ...@@ -171,8 +178,6 @@ Test delayed log files delete
link to new changelog and roadmap, remove pages from google groups link to new changelog and roadmap, remove pages from google groups
check ValueByte memory usage
Adjust cache memory usage Adjust cache memory usage
// test with garbage at the end of the log file (must be consistently detected as such) // test with garbage at the end of the log file (must be consistently detected as such)
// TestRandomSQL is too random; most statements fails // TestRandomSQL is too random; most statements fails
...@@ -182,6 +187,8 @@ Adjust cache memory usage ...@@ -182,6 +187,8 @@ Adjust cache memory usage
Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes
History: History:
Security: The database now waits 200 ms before throwing an exception if
the user name or password don't match, to slow down dictionary attacks.
The value cache is now a soft reference cache. This should help save memory. The value cache is now a soft reference cache. This should help save memory.
Large result sets are now a bit faster. Large result sets are now a bit faster.
ALTER TABLE ALTER COLUMN RESTART and ALTER SEQUENCE now support an expressions. ALTER TABLE ALTER COLUMN RESTART and ALTER SEQUENCE now support an expressions.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.h2.test.bench; package org.h2.test.bench;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
...@@ -71,7 +72,9 @@ public class TestPerformance { ...@@ -71,7 +72,9 @@ public class TestPerformance {
openResults(init); openResults(init);
Properties prop = new Properties(); Properties prop = new Properties();
prop.load(getClass().getResourceAsStream("test.properties")); InputStream in = getClass().getResourceAsStream("test.properties");
prop.load(in);
in.close();
int size = Integer.parseInt(prop.getProperty("size")); int size = Integer.parseInt(prop.getProperty("size"));
ArrayList dbs = new ArrayList(); ArrayList dbs = new ArrayList();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
......
...@@ -24,6 +24,15 @@ public class TestReadOnly extends TestBase { ...@@ -24,6 +24,15 @@ public class TestReadOnly extends TestBase {
if (config.memory) { if (config.memory) {
return; return;
} }
testReadOnlyFileAccessMode();
testReadOnlyFiles();
}
private void testReadOnlyFileAccessMode() {
int todo;
}
private void testReadOnlyFiles() throws Exception {
File f = File.createTempFile("test", "temp"); File f = File.createTempFile("test", "temp");
check(f.canWrite()); check(f.canWrite());
......
...@@ -112,10 +112,9 @@ public class TestSessionsLocks extends TestBase { ...@@ -112,10 +112,9 @@ public class TestSessionsLocks extends TestBase {
check(done[0]); check(done[0]);
break; break;
} else { } else {
System.out.println("no statement is executing yet"); // no statement is executing yet
} }
} }
conn2.close(); conn2.close();
conn.close(); conn.close();
} }
......
...@@ -61,11 +61,11 @@ public class TestTriggersConstraints extends TestBase implements Trigger { ...@@ -61,11 +61,11 @@ public class TestTriggersConstraints extends TestBase implements Trigger {
ResultSet rs; ResultSet rs;
rs = stat.executeQuery("SCRIPT"); rs = stat.executeQuery("SCRIPT");
checkRows(rs, new String[] { checkRows(rs, new String[] {
"CREATE TRIGGER PUBLIC.INS_BEFORE BEFORE INSERT ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \"" "CREATE FORCE TRIGGER PUBLIC.INS_BEFORE BEFORE INSERT ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \""
+ getClass().getName() + "\";", + getClass().getName() + "\";",
"CREATE TRIGGER PUBLIC.INS_AFTER AFTER INSERT ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \"" "CREATE FORCE TRIGGER PUBLIC.INS_AFTER AFTER INSERT ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \""
+ getClass().getName() + "\";", + getClass().getName() + "\";",
"CREATE TRIGGER PUBLIC.UPD_BEFORE BEFORE UPDATE ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \"" "CREATE FORCE TRIGGER PUBLIC.UPD_BEFORE BEFORE UPDATE ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \""
+ getClass().getName() + "\";" }); + getClass().getName() + "\";" });
while (rs.next()) { while (rs.next()) {
String sql = rs.getString(1); String sql = rs.getString(1);
......
...@@ -9,6 +9,7 @@ import java.sql.Connection; ...@@ -9,6 +9,7 @@ import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Random; import java.util.Random;
...@@ -32,7 +33,7 @@ public class TestKillRestart extends TestBase { ...@@ -32,7 +33,7 @@ public class TestKillRestart extends TestBase {
String[] procDef = new String[] { "java", "-cp", "bin", getClass().getName(), "-url", url, "-user", user, String[] procDef = new String[] { "java", "-cp", "bin", getClass().getName(), "-url", url, "-user", user,
"-password", password }; "-password", password };
int len = getSize(1, 10); int len = getSize(2, 15);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Process p = Runtime.getRuntime().exec(procDef); Process p = Runtime.getRuntime().exec(procDef);
// InputStream err = p.getErrorStream(); // InputStream err = p.getErrorStream();
...@@ -97,8 +98,10 @@ public class TestKillRestart extends TestBase { ...@@ -97,8 +98,10 @@ public class TestKillRestart extends TestBase {
System.out.println("#Starting..."); System.out.println("#Starting...");
conn = DriverManager.getConnection(url, user, password); conn = DriverManager.getConnection(url, user, password);
stat = conn.createStatement(); stat = conn.createStatement();
stat.execute("DROP ALL OBJECTS");
stat.execute("CREATE TABLE TEST(ID IDENTITY, NAME VARCHAR)"); stat.execute("CREATE TABLE TEST(ID IDENTITY, NAME VARCHAR)");
stat.execute("CREATE TABLE TEST2(ID IDENTITY, NAME VARCHAR)"); stat.execute("CREATE TABLE TEST2(ID IDENTITY, NAME VARCHAR)");
stat.execute("CREATE TABLE TEST_META(ID INT)");
PreparedStatement prep = conn.prepareStatement("INSERT INTO TEST(NAME) VALUES(?)"); PreparedStatement prep = conn.prepareStatement("INSERT INTO TEST(NAME) VALUES(?)");
PreparedStatement prep2 = conn.prepareStatement("INSERT INTO TEST2(NAME) VALUES(?)"); PreparedStatement prep2 = conn.prepareStatement("INSERT INTO TEST2(NAME) VALUES(?)");
Random r = new Random(0); Random r = new Random(0);
...@@ -117,6 +120,9 @@ public class TestKillRestart extends TestBase { ...@@ -117,6 +120,9 @@ public class TestKillRestart extends TestBase {
if (i == 100) { if (i == 100) {
System.out.println("#Running..."); System.out.println("#Running...");
} }
if (r.nextInt(100) < 10) {
conn.createStatement().execute("ALTER TABLE TEST_META ALTER COLUMN ID INT DEFAULT 10");
}
if (r.nextBoolean()) { if (r.nextBoolean()) {
if (r.nextBoolean()) { if (r.nextBoolean()) {
prep.setString(1, new String(new char[r.nextInt(30) * 10])); prep.setString(1, new String(new char[r.nextInt(30) * 10]));
......
...@@ -2869,13 +2869,13 @@ create trigger test_trigger before insert on s.test call "org.h2.test.db.TestTri ...@@ -2869,13 +2869,13 @@ create trigger test_trigger before insert on s.test call "org.h2.test.db.TestTri
script NOPASSWORDS NOSETTINGS drop; script NOPASSWORDS NOSETTINGS drop;
> SCRIPT > SCRIPT
> --------------------------------------------------------------------------------------------------------------- > ---------------------------------------------------------------------------------------------------------------------
> -- 0 = SELECT COUNT(*) FROM S.TEST; > -- 0 = SELECT COUNT(*) FROM S.TEST;
> CREATE FORCE TRIGGER S.TEST_TRIGGER BEFORE INSERT ON S.TEST QUEUE 1024 CALL "org.h2.test.db.TestTriggersConstraints";
> CREATE INDEX S.INDEX_ID ON S.TEST(ID); > CREATE INDEX S.INDEX_ID ON S.TEST(ID);
> CREATE MEMORY TABLE S.TEST( ID INT ); > CREATE MEMORY TABLE S.TEST( ID INT );
> CREATE SCHEMA S AUTHORIZATION SA; > CREATE SCHEMA S AUTHORIZATION SA;
> CREATE SEQUENCE S.SEQ START WITH 10; > CREATE SEQUENCE S.SEQ START WITH 10;
> CREATE TRIGGER S.TEST_TRIGGER BEFORE INSERT ON S.TEST QUEUE 1024 CALL "org.h2.test.db.TestTriggersConstraints";
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN; > CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN;
> DROP SEQUENCE IF EXISTS S.SEQ; > DROP SEQUENCE IF EXISTS S.SEQ;
> DROP TABLE IF EXISTS S.TEST; > DROP TABLE IF EXISTS S.TEST;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论