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