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

--no commit message

--no commit message
上级 21b5d16e
......@@ -1036,6 +1036,11 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>Clustering: adding a node should be very fast and without interrupting clients (very short lock)
</li><li>Updatable result sets: DatabaseMetaData.ownUpdatesAreVisible = true
</li><li>Cache size should be in KB
</li><li>Ability to resize the cache array when resizing the cache
</li><li>Index usage for WHERE NOT FLAG (flag is a boolean column)
</li><li>Automatic conversion from WHERE ID=1 AND ID=2 to WHERE FALSE
</li><li>Automatic conversion from WHERE X=Y AND Y=Z to X=Y AND Y=Z AND X=Z
</li><li>Automatic conversion from WHERE X>10 AND X>20 to X>20
</li></ul>
<h3>Not Planned</h3>
......
......@@ -94,7 +94,7 @@ public class Delete extends Prepared {
if (condition != null) {
condition.mapColumns(tableFilter, 0);
condition = condition.optimize(session);
condition.createIndexConditions(tableFilter);
condition = condition.createIndexConditions(tableFilter);
}
PlanItem item = tableFilter.getBestPlanItem(session);
tableFilter.setPlanItem(item);
......
......@@ -476,7 +476,7 @@ public class Select extends Query {
condition = condition.optimize(session);
for (int j = 0; j < filters.size(); j++) {
TableFilter f = (TableFilter) filters.get(j);
condition.createIndexConditions(f);
condition = condition.createIndexConditions(f);
}
}
if(condition == null && isGroupQuery && groupIndex == null && havingIndex<0 && filters.size()==1) {
......
......@@ -144,7 +144,7 @@ public class Update extends Prepared {
if (condition != null) {
condition.mapColumns(tableFilter, 0);
condition = condition.optimize(session);
condition.createIndexConditions(tableFilter);
condition = condition.createIndexConditions(tableFilter);
}
for (int i = 0; i < expressions.length; i++) {
Expression expr = expressions[i];
......
......@@ -103,14 +103,14 @@ public class CompareLike extends Condition {
return esc;
}
public void createIndexConditions(TableFilter filter) throws SQLException {
public Expression createIndexConditions(TableFilter filter) throws SQLException {
Session session = filter.getSession();
if(!(left instanceof ExpressionColumn)) {
return;
return this;
}
ExpressionColumn l = (ExpressionColumn)left;
if(filter != l.getTableFilter()) {
return;
return this;
}
// parameters are always evaluatable, but
// we need to check the actual value now
......@@ -119,10 +119,10 @@ public class CompareLike extends Condition {
// which is maybe slower (but maybe not in this case!)
// TODO optimizer: like: check what other databases do!
if(!right.isConstant()) {
return;
return this;
}
if(escape != null && !escape.isConstant()) {
return;
return this;
}
String p = right.getValue(session).getString();
Value e = escape == null ? null : escape.getValue(session);
......@@ -133,12 +133,12 @@ public class CompareLike extends Condition {
initPattern(p, getEscapeChar(e));
if(patternLength <= 0 || types[0] != MATCH) {
// can't use an index
return;
return this;
}
int dataType = l.getColumn().getType();
if(dataType != Value.STRING && dataType != Value.STRING_IGNORECASE && dataType != Value.STRING_FIXED) {
// column is not a varchar - can't use the index
return;
return this;
}
int maxMatch = 0;
StringBuffer buff = new StringBuffer();
......@@ -146,24 +146,26 @@ public class CompareLike extends Condition {
buff.append(pattern[maxMatch++]);
}
String begin = buff.toString();
Expression condition = this;
if(maxMatch == patternLength) {
filter.addIndexCondition(new IndexCondition(Comparison.EQUAL, l, ValueExpression.get(ValueString.get(begin))));
condition = filter.addIndexCondition(condition, new IndexCondition(Comparison.EQUAL, l, ValueExpression.get(ValueString.get(begin))));
} else {
// TODO check if this is correct according to Unicode rules (code points)
String end;
if(begin.length()>0) {
filter.addIndexCondition(new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(ValueString.get(begin))));
condition = filter.addIndexCondition(condition, new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(ValueString.get(begin))));
char next = begin.charAt(begin.length()-1);
// search the 'next' unicode character (or at least a character that is higher)
for(int i=1; i<2000; i++) {
end = begin.substring(0, begin.length()-1) + (char)(next+i);
if(compareMode.compareString(begin, end, ignoreCase) == -1) {
filter.addIndexCondition(new IndexCondition(Comparison.SMALLER, l, ValueExpression.get(ValueString.get(end))));
condition = filter.addIndexCondition(condition, new IndexCondition(Comparison.SMALLER, l, ValueExpression.get(ValueString.get(end))));
break;
}
}
}
}
return condition;
}
public Value getValue(Session session) throws SQLException {
......
......@@ -199,10 +199,10 @@ public class Comparison extends Condition {
}
}
public void createIndexConditions(TableFilter filter) {
public Expression createIndexConditions(TableFilter filter) {
if(right==null) {
// TODO index usage: IS [NOT] NULL index usage is possible
return;
return this;
}
ExpressionColumn l = null;
if(left instanceof ExpressionColumn) {
......@@ -220,12 +220,12 @@ public class Comparison extends Condition {
}
// one side must be from the current filter
if(l==null && r==null) {
return;
return this;
}
// filter.addFilterCondition(this, join);
// if both sides are part of the same filter, it can't be used for index lookup
if(l!=null && r!=null) {
return;
return this;
}
boolean addIndex;
switch(compareType) {
......@@ -244,12 +244,13 @@ public class Comparison extends Condition {
}
if(addIndex) {
if(l!=null) {
filter.addIndexCondition(new IndexCondition(compareType, l, right));
return filter.addIndexCondition(this, new IndexCondition(compareType, l, right));
} else if(r!=null) {
int compareRev = getReversedCompareType(compareType);
filter.addIndexCondition(new IndexCondition(compareRev, r, left));
return filter.addIndexCondition(this, new IndexCondition(compareRev, r, left));
}
}
return this;
}
public void setEvaluatable(TableFilter tableFilter, boolean b) {
......
......@@ -51,11 +51,12 @@ public class ConditionAndOr extends Condition {
return "("+sql+")";
}
public void createIndexConditions(TableFilter filter) throws SQLException {
public Expression createIndexConditions(TableFilter filter) throws SQLException {
if (andOrType == AND) {
left.createIndexConditions(filter);
right.createIndexConditions(filter);
left = left.createIndexConditions(filter);
right = right.createIndexConditions(filter);
}
return this;
}
public Value getValue(Session session) throws SQLException {
......
......@@ -120,22 +120,24 @@ public class ConditionIn extends Condition {
return this;
}
public void createIndexConditions(TableFilter filter) {
public Expression createIndexConditions(TableFilter filter) {
if(!Constants.OPTIMIZE_IN) {
return;
return this;
}
if(min == null && max == null) {
return;
return this;
}
if(!(left instanceof ExpressionColumn)) {
return;
return this;
}
ExpressionColumn l = (ExpressionColumn)left;
if(filter != l.getTableFilter()) {
return;
return this;
}
filter.addIndexCondition(new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(min)));
filter.addIndexCondition(new IndexCondition(Comparison.SMALLER_EQUAL, l, ValueExpression.get(max)));
Expression result = this;
result = filter.addIndexCondition(result, new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(min)));
result = filter.addIndexCondition(result, new IndexCondition(Comparison.SMALLER_EQUAL, l, ValueExpression.get(max)));
return result;
}
public void setEvaluatable(TableFilter tableFilter, boolean b) {
......
......@@ -20,8 +20,9 @@ public class ConditionNot extends Condition {
this.condition = condition;
}
public void createIndexConditions(TableFilter filter) {
public Expression createIndexConditions(TableFilter filter) {
// TODO optimization: in some cases, index conditions can be created here
return this;
}
public Value getValue(Session session) throws SQLException {
......
......@@ -51,8 +51,9 @@ public abstract class Expression {
return getValue(session).getBoolean();
}
public void createIndexConditions(TableFilter filter) throws SQLException {
public Expression createIndexConditions(TableFilter filter) throws SQLException {
// default is do nothing
return this;
}
public String getColumnName() {
......
......@@ -11,6 +11,7 @@ import org.h2.command.Parser;
import org.h2.command.dml.Select;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.IndexCondition;
import org.h2.message.Message;
import org.h2.schema.Constant;
import org.h2.schema.Schema;
......@@ -19,6 +20,7 @@ import org.h2.table.ColumnResolver;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueBoolean;
/**
* @author Thomas
......@@ -243,4 +245,16 @@ public class ExpressionColumn extends Expression {
return 2;
}
public Expression createIndexConditions(TableFilter filter) {
TableFilter tf = getTableFilter();
if(filter != tf) {
return this;
}
if(column.getType() == Value.BOOLEAN) {
IndexCondition cond = new IndexCondition(Comparison.EQUAL, this, ValueExpression.get(ValueBoolean.get(true)));
return filter.addIndexCondition(this, cond);
}
return this;
}
}
......@@ -1405,7 +1405,6 @@ public class Function extends Expression implements FunctionCall {
}
public String getSQL() {
// TODO function: getSQL for some functions is not correct
StringBuffer buff = new StringBuffer();
buff.append(info.name);
buff.append('(');
......@@ -1424,6 +1423,18 @@ public class Function extends Expression implements FunctionCall {
buff.append(StringUtils.unEnclose(args[1].getSQL()));
break;
}
case TABLE: {
for (int i = 0; i < args.length; i++) {
if (i > 0) {
buff.append(", ");
}
buff.append(columnList[i].getCreateSQL());
buff.append("=");
Expression e = args[i];
buff.append(e.getSQL());
}
break;
}
default: {
for (int i = 0; i < args.length; i++) {
if (i > 0) {
......
......@@ -19,5 +19,6 @@ public interface FunctionCall {
Expression optimize(Session session) throws SQLException;
Value getValue(Session session) throws SQLException;
Expression[] getArgs();
String getSQL();
}
......@@ -39,13 +39,14 @@ public class ValueExpression extends Expression {
return value.getType();
}
public void createIndexConditions(TableFilter filter) {
public Expression createIndexConditions(TableFilter filter) {
if(value.getType() == Value.BOOLEAN) {
boolean v = ((ValueBoolean)value).getBoolean().booleanValue();
if(!v) {
filter.addIndexCondition(new IndexCondition(Comparison.FALSE, null, this));
return filter.addIndexCondition(this, new IndexCondition(Comparison.FALSE, null, this));
}
}
return this;
}
public void mapColumns(ColumnResolver resolver, int level) throws SQLException {
......
......@@ -112,5 +112,9 @@ public class IndexCondition {
public boolean isEvaluatable() {
return expression.isEverything(ExpressionVisitor.EVALUATABLE);
}
public Expression getExpression() {
return expression;
}
}
......@@ -141,6 +141,24 @@ public class FunctionTable extends Table {
public Index getUniqueIndex() {
return null;
}
public String getSQL() {
int todoDocument;
return function.getSQL();
// return super.getSQL();
// StringBuffer buff = new StringBuffer();
// buff.append(super.getSQL());
// buff.append('(');
// Expression[] args = function.getArgs();
// for (int i = 0; i < args.length; i++) {
// if (i > 0) {
// buff.append(", ");
// }
// buff.append(args[i].getSQL());
// }
// buff.append(')');
// return buff.toString();
}
}
......@@ -11,6 +11,7 @@ import org.h2.engine.Constants;
import org.h2.engine.Mode;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Comparison;
import org.h2.expression.ConditionAndOr;
import org.h2.expression.Expression;
import org.h2.index.Cursor;
......@@ -322,8 +323,21 @@ public class TableFilter implements ColumnResolver {
return table.getName();
}
public void addIndexCondition(IndexCondition condition) {
public Expression addIndexCondition(Expression expr, IndexCondition condition) {
for(int i=0; i<indexConditions.size(); i++) {
IndexCondition c = (IndexCondition) indexConditions.get(i);
if(c.getColumn() == condition.getColumn()) {
if(c.getMask() == IndexCondition.EQUALITY && condition.getMask() == IndexCondition.EQUALITY) {
Expression e1 = c.getExpression();
Expression e2 = condition.getExpression();
// Comparison comp = new Comparison();
System.out.println("add: " + e1.getSQL() + " = " + e2.getSQL());
}
}
}
indexConditions.add(condition);
return expr;
}
public void addFilterCondition(Expression condition, boolean join) {
......@@ -366,7 +380,7 @@ public class TableFilter implements ColumnResolver {
private void mapAndAddFilter(Expression on) throws SQLException {
on.mapColumns(this, 0);
addFilterCondition(on, true);
on.createIndexConditions(this);
on = on.createIndexConditions(this);
for(int i=0; joins != null && i<joins.size(); i++) {
TableFilter join = getTableFilter(i);
join.mapAndAddFilter(on);
......
......@@ -260,6 +260,7 @@ public class StringUtils {
}
public static String unEnclose(String s) {
int todoNotCorrectForArrays;
if(s.startsWith("(") && s.endsWith(")")) {
return s.substring(1, s.length()-1);
} else {
......
--- special grammar and test cases ---------------------------------------------------------------------------------------------
CREATE TABLE TEST(ID INT PRIMARY KEY, FLAG BOOLEAN, NAME VARCHAR);
> ok
CREATE INDEX IDXFLAG ON TEST(FLAG, NAME);
> ok
INSERT INTO TEST VALUES(1, TRUE, 'Hello'), (2, FALSE, 'World');
> ok
EXPLAIN SELECT * FROM TEST WHERE FLAG;
> ok
EXPLAIN SELECT * FROM TEST WHERE FLAG AND NAME>'I';
> ok
DROP TABLE TEST;
> ok
CREATE TABLE test_table (firstcol varchar(20), secondcol integer);
> ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论