提交 132e613f authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 58197110
#Wed Jan 16 10:26:35 CET 2008
#Thu Jan 17 08:51:17 CET 2008
javac=javac
benchmark.drivers.dir=C\:/data/java
path.servlet.jar=C\:/data/classpath/servlet-api.jar
......
......@@ -822,17 +822,28 @@ public class Select extends Query {
}
public boolean isEverything(ExpressionVisitor visitor) {
if (visitor.type == ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID) {
switch(visitor.type) {
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: {
for (int i = 0; i < filters.size(); i++) {
TableFilter f = (TableFilter) filters.get(i);
long m = f.getTable().getMaxDataModificationId();
visitor.addDataModificationId(m);
}
break;
}
if (visitor.type == ExpressionVisitor.EVALUATABLE) {
case ExpressionVisitor.EVALUATABLE: {
if (!SysProperties.OPTIMIZE_EVALUATABLE_SUBQUERIES) {
return false;
}
break;
}
case ExpressionVisitor.GET_DEPENDENCIES: {
for (int i = 0; i < filters.size(); i++) {
TableFilter filter = (TableFilter) filters.get(i);
filter.getTable().addDependencies(visitor.getDependencies());
}
break;
}
}
visitor.queryLevel(1);
boolean result = true;
......
......@@ -168,6 +168,17 @@ public class SysProperties {
* Maximum size of an object in the cache.
*/
public static final int OBJECT_CACHE_SIZE = getIntSetting("h2.objectCacheSize", 1024);
/**
* System property <code>h2.optimizeDropDependencies</code> (default: true).<br />
* Improve the performance of DROP and DROP ALL OBJECTS by quicker scanning if other objects depend on this object.
*/
public static final boolean OPTIMIZE_DROP_DEPENDENCIES = getBooleanSetting("h2.optimizeDropDependencies", true);
/**
* System property <code>h2.optimizeDistinct</code> (default: true).<br />
* Improve the performance of simple DISTINCT queries if an index is available for the given column.
*/
public static final boolean OPTIMIZE_DISTINCT = getBooleanSetting("h2.optimizeDistinct", true);
/**
......
......@@ -1188,6 +1188,29 @@ public class Database implements DataHandler {
removeMeta(session, id);
}
private String getDependentObject(SchemaObject obj) {
switch (obj.getType()) {
case DbObject.COMMENT:
case DbObject.CONSTRAINT:
case DbObject.INDEX:
case DbObject.RIGHT:
case DbObject.TRIGGER:
case DbObject.USER:
return null;
}
ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
HashSet set = new HashSet();
for (int i = 0; i < list.size(); i++) {
Table t = (Table) list.get(i);
set.clear();
t.addDependencies(set);
if (set.contains(obj)) {
return t.getSQL();
}
}
return null;
}
private String getFirstInvalidTable(Session session) {
String conflict = null;
try {
......@@ -1216,7 +1239,12 @@ public class Database implements DataHandler {
removeDatabaseObject(session, comment);
}
obj.getSchema().remove(session, obj);
String invalid = getFirstInvalidTable(session);
String invalid;
if (SysProperties.OPTIMIZE_DROP_DEPENDENCIES) {
invalid = getDependentObject(obj);
} else {
invalid = getFirstInvalidTable(session);
}
if (invalid != null) {
obj.getSchema().add(obj);
throw Message.getSQLException(ErrorCode.CANNOT_DROP_2, new String[] { obj.getSQL(), invalid });
......
......@@ -357,16 +357,14 @@ public class Aggregate extends Expression {
buff.append(on.getSQL());
if (orderList != null) {
buff.append(" ORDER BY ");
if (orderList != null) {
for (int i = 0; i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
if (i > 0) {
buff.append(", ");
}
buff.append(o.expression.getSQL());
if (o.descending) {
buff.append(" DESC");
}
for (int i = 0; i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
if (i > 0) {
buff.append(", ");
}
buff.append(o.expression.getSQL());
if (o.descending) {
buff.append(" DESC");
}
}
}
......@@ -457,7 +455,19 @@ public class Aggregate extends Expression {
return false;
}
}
return (on == null || on.isEverything(visitor)) && (separator == null || separator.isEverything(visitor));
if (on != null && !on.isEverything(visitor)) {
return false;
}
if (separator != null && !separator.isEverything(visitor)) {
return false;
}
for (int i = 0; orderList != null && i < orderList.size(); i++) {
SelectOrderBy o = (SelectOrderBy) orderList.get(i);
if (!o.expression.isEverything(visitor)) {
return false;
}
}
return true;
}
public int getCost() {
......
......@@ -297,4 +297,5 @@ public abstract class Expression {
public Expression optimizeInJoin(Session session, Select select) throws SQLException {
return this;
}
}
......@@ -246,6 +246,8 @@ public class ExpressionColumn extends Expression {
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return resolver != visitor.getResolver();
case ExpressionVisitor.GET_DEPENDENCIES:
return true;
default:
throw Message.getInternalError("type=" + visitor.type);
}
......
......@@ -4,6 +4,9 @@
*/
package org.h2.expression;
import java.util.HashSet;
import org.h2.engine.DbObject;
import org.h2.table.ColumnResolver;
import org.h2.table.Table;
......@@ -12,32 +15,53 @@ import org.h2.table.Table;
* to optimize a statement.
*/
public class ExpressionVisitor {
// Is the value independent on unset parameters or on columns of a higher level query, or sequence values (that means can it be evaluated right now)
/**
* Is the value independent on unset parameters or on columns of a higher level query,
* or sequence values (that means can it be evaluated right now)?
*/
public static final int INDEPENDENT = 0;
// Are all aggregates MIN(column), MAX(column), or COUNT(*)?
/**
* Are all aggregates MIN(column), MAX(column), or COUNT(*)?
*/
public static final int OPTIMIZABLE_MIN_MAX_COUNT_ALL = 1;
// Does the expression return the same results for the same parameters?
/**
* Does the expression return the same results for the same parameters?
*/
public static final int DETERMINISTIC = 2;
// Can the expression be evaluated, that means are all columns set to 'evaluatable'?
/**
* Can the expression be evaluated, that means are all columns set to 'evaluatable'?
*/
public static final int EVALUATABLE = 3;
// Request to set the latest modification id
/**
* Request to set the latest modification id.
*/
public static final int SET_MAX_DATA_MODIFICATION_ID = 4;
// Does the expression have no side effects (change the data)?
/**
* Does the expression have no side effects (change the data)?
*/
public static final int READONLY = 5;
// Does an expression have no relation to the given table filter?
/**
* Does an expression have no relation to the given table filter?
*/
public static final int NOT_FROM_RESOLVER = 6;
/**
* Request to get the set of dependencies.
*/
public static final int GET_DEPENDENCIES = 7;
int queryLevel;
public Table table;
public int type;
private long maxDataModificationId;
private ColumnResolver resolver;
private HashSet dependencies;
public static ExpressionVisitor get(int type) {
return new ExpressionVisitor(type);
......@@ -47,6 +71,18 @@ public class ExpressionVisitor {
return maxDataModificationId;
}
public void addDependency(DbObject obj) {
dependencies.add(obj);
}
public HashSet getDependencies() {
return dependencies;
}
public void setDependencies(HashSet dependencies) {
this.dependencies = dependencies;
}
private ExpressionVisitor(int type) {
this.type = type;
}
......
......@@ -80,10 +80,14 @@ public class JavaAggregate extends Expression {
}
public boolean isEverything(ExpressionVisitor visitor) {
if (visitor.type == ExpressionVisitor.DETERMINISTIC) {
switch(visitor.type) {
case ExpressionVisitor.DETERMINISTIC:
// TODO optimization: some functions are deterministic, but we don't
// know (no setting for that)
return false;
case ExpressionVisitor.GET_DEPENDENCIES:
visitor.addDependency(userAggregate);
break;
}
for (int i = 0; i < args.length; i++) {
Expression e = args[i];
......
......@@ -117,10 +117,14 @@ public class JavaFunction extends Expression implements FunctionCall {
}
public boolean isEverything(ExpressionVisitor visitor) {
if (visitor.type == ExpressionVisitor.DETERMINISTIC) {
switch(visitor.type) {
case ExpressionVisitor.DETERMINISTIC:
// TODO optimization: some functions are deterministic, but we don't
// know (no setting for that)
return false;
case ExpressionVisitor.GET_DEPENDENCIES:
visitor.addDependency(functionAlias);
break;
}
for (int i = 0; i < args.length; i++) {
Expression e = args[i];
......
......@@ -5,6 +5,7 @@
package org.h2.expression;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
import org.h2.message.Message;
......@@ -114,6 +115,8 @@ public class Parameter extends Expression implements ParameterInterface {
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES:
return true;
default:
throw Message.getInternalError("type="+visitor.type);
}
......
......@@ -79,6 +79,8 @@ public class Rownum extends Expression {
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES:
return true;
default:
throw Message.getInternalError("type="+visitor.type);
}
......
......@@ -88,6 +88,9 @@ public class SequenceValue extends Expression {
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES:
visitor.addDependency(sequence);
return true;
default:
throw Message.getInternalError("type="+visitor.type);
}
......
......@@ -230,4 +230,5 @@ public class TableFunction extends Expression implements FunctionCall {
public ValueResultSet getValueForColumnList(Session session, Expression[] nullArgs) throws SQLException {
return getTable(session, args, true, false);
}
}
......@@ -107,6 +107,8 @@ public class ValueExpression extends Expression {
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES:
return true;
default:
throw Message.getInternalError("type=" + visitor.type);
}
......
......@@ -73,6 +73,8 @@ public class Variable extends Expression {
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES:
return true;
default:
throw Message.getInternalError("type="+visitor.type);
}
......
......@@ -15,6 +15,7 @@ import org.h2.engine.Mode;
import org.h2.engine.Session;
import org.h2.expression.ConditionAndOr;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.SequenceValue;
import org.h2.expression.ValueExpression;
import org.h2.message.Message;
......@@ -490,4 +491,19 @@ public class Column {
this.primaryKey = primaryKey;
}
boolean isEverything(ExpressionVisitor visitor) {
if (visitor.type == ExpressionVisitor.GET_DEPENDENCIES) {
if (sequence != null) {
visitor.getDependencies().add(sequence);
}
}
if (defaultExpression != null && !defaultExpression.isEverything(visitor)) {
return false;
}
if (checkConstraint != null && !checkConstraint.isEverything(visitor)) {
return false;
}
return true;
}
}
......@@ -6,6 +6,7 @@ package org.h2.table;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import org.h2.command.Prepared;
import org.h2.constant.ErrorCode;
......@@ -14,6 +15,7 @@ import org.h2.engine.Constants;
import org.h2.engine.DbObject;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.ExpressionVisitor;
import org.h2.index.Index;
import org.h2.index.IndexType;
import org.h2.log.UndoLogRecord;
......@@ -211,6 +213,19 @@ public abstract class Table extends SchemaObjectBase {
throw Message.getInternalError();
}
public void addDependencies(HashSet dependencies) {
if (sequences != null) {
for (int i = 0; i < sequences.size(); i++) {
dependencies.add(sequences.get(i));
}
}
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.GET_DEPENDENCIES);
visitor.setDependencies(dependencies);
for (int i = 0; i < columns.length; i++) {
columns[i].isEverything(visitor);
}
}
public ObjectArray getChildren() {
ObjectArray children = new ObjectArray();
ObjectArray indexes = getIndexes();
......
......@@ -24,19 +24,19 @@ public class ChangePassword {
private String cipher;
private byte[] decrypt;
private byte[] encrypt;
// TODO security: maybe allow functions in the url
// jdbc:h2:test;action=[decrypt|encrypt|check|reindex|recover|compress...]
// and/or implement SQL commands that call this functions (only for the admin)
// and/or implement SQL commands that call this functions (only for the admin)
private void showUsage() {
System.out.println("java "+getClass().getName()
+ " [-dir <dir>] [-db <database>] [-cipher <cipher>] [-decrypt <pwd>] [-encrypt <pwd>] [-quiet]");
}
/**
* The command line interface for this tool.
* The options must be split into strings like this: "-db", "test",...
* The options must be split into strings like this: "-db", "test",...
* Options are case sensitive. The following options are supported:
* <ul>
* <li>-help or -? (print the list of options)
......@@ -47,10 +47,10 @@ public class ChangePassword {
* </li><li>-encrypt password (null if the database should not be encrypted)
* </li><li>-quiet does not print progress information
* </li></ul>
*
*
* @param args the command line arguments
* @throws SQLException
*/
*/
public static void main(String[] args) throws SQLException {
new ChangePassword().run(args);
}
......@@ -58,8 +58,8 @@ public class ChangePassword {
private void run(String[] args) throws SQLException {
String dir = ".";
String cipher = null;
byte[] decrypt = null;
byte[] encrypt = null;
char[] decryptPassword = null;
char[] encryptPassword = null;
String db = null;
boolean quiet = false;
for (int i = 0; args != null && i < args.length; i++) {
......@@ -70,9 +70,9 @@ public class ChangePassword {
} else if (args[i].equals("-db")) {
db = args[++i];
} else if (args[i].equals("-decrypt")) {
decrypt = getFileEncryptionKey(args[++i].toCharArray());
decryptPassword = args[++i].toCharArray();
} else if (args[i].equals("-encrypt")) {
encrypt = getFileEncryptionKey(args[++i].toCharArray());
encryptPassword = args[++i].toCharArray();
} else if (args[i].equals("-quiet")) {
quiet = true;
} else {
......@@ -80,27 +80,30 @@ public class ChangePassword {
return;
}
}
if (encrypt == null && decrypt == null) {
if (encryptPassword == null && decryptPassword == null) {
showUsage();
return;
}
execute(dir, db, cipher, decrypt, encrypt, quiet);
execute(dir, db, cipher, decryptPassword, encryptPassword, quiet);
}
/**
* Get the file encryption key for a given password.
*
* @param password
*
* @param password the password as a char array
* @return the encryption key
*/
public byte[] getFileEncryptionKey(char[] password) {
private static byte[] getFileEncryptionKey(char[] password) {
if (password == null) {
return null;
}
SHA256 sha = new SHA256();
return sha.getKeyPasswordHash("file", password);
}
/**
* Changes the password for a database.
*
*
* @param dir the directory (. for the current directory)
* @param db the database name (null for all databases)
* @param cipher the cipher (AES, XTEA)
......@@ -109,12 +112,12 @@ public class ChangePassword {
* @param quiet don't print progress information
* @throws SQLException
*/
public static void execute(String dir, String db, String cipher, byte[] decrypt, byte[] encrypt, boolean quiet) throws SQLException {
public static void execute(String dir, String db, String cipher, char[] decryptPassword, char[] encryptPassword, boolean quiet) throws SQLException {
ChangePassword change = new ChangePassword();
change.dir = dir;
change.cipher = cipher;
change.decrypt = decrypt;
change.encrypt = encrypt;
change.decrypt = getFileEncryptionKey(decryptPassword);
change.encrypt = getFileEncryptionKey(encryptPassword);
// first, test only if the file can be renamed (to find errors with locked files early)
ArrayList files = FileLister.getDatabaseFiles(dir, db, false);
......@@ -125,7 +128,7 @@ public class ChangePassword {
FileUtils.rename(fileName, temp);
FileUtils.rename(temp, fileName);
}
// if this worked, the operation will (hopefully) be successful
// if this worked, the operation will (hopefully) be successful
// TODO changePassword: this is a workaround! make the operation atomic (all files or none)
for (int i = 0; i < files.size(); i++) {
String fileName = (String) files.get(i);
......@@ -133,7 +136,7 @@ public class ChangePassword {
}
if (files.size() == 0 && !quiet) {
System.out.println("No database files found");
}
}
}
private void process(String fileName) throws SQLException {
......
......@@ -146,7 +146,7 @@ public class ObjectArray {
public void addAll(ObjectArray list) {
for (int i = 0; i < list.size; i++) {
add(list.get(i));
add(list.data[i]);
}
}
......
......@@ -150,6 +150,8 @@ java org.h2.test.TestAll timer
/*
where is base64 code?
Roadmap:
History:
......
......@@ -89,6 +89,15 @@ public class TestCrashAPI extends TestBase {
Statement stat = conn.createStatement();
stat.execute("SET LOCK_TIMEOUT 10");
stat.execute("SET WRITE_DELAY 0");
if (random.nextBoolean()) {
if (random.nextBoolean()) {
double g = random.nextGaussian();
int size = (int) Math.abs(10000 * g * g);
stat.execute("SET CACHE_SIZE " + size);
} else {
stat.execute("SET CACHE_SIZE 0");
}
}
stat.execute("SCRIPT NOPASSWORDS NOSETTINGS");
for (int i = start; i < end && i < statements.size(); i++) {
try {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论