Skip to content

Commit

Permalink
Improving search by compound indexes. (#3915)
Browse files Browse the repository at this point in the history
* Improving search by compound indexes.

* Fixing review findings.

* Fixing the index condition handling.

* Adjusting test cases.

* Fixing TableFilter.prepare().

* Adjusting test cases.

* Refactoring the constructors of the IndexCondition class.

* Removing unnecessary TODOs.

* Fixing review findings.

* Introducing the TestCompoundIndexSearch class.

* Preparing IndexCondition to deal with queries where the columns not used in the right order.

* Fixing test errors.
  • Loading branch information
kiss034 committed Nov 27, 2023
1 parent 426185a commit 539e8d6
Show file tree
Hide file tree
Showing 9 changed files with 646 additions and 53 deletions.
31 changes: 29 additions & 2 deletions h2/src/main/org/h2/expression/condition/ConditionIn.java
Expand Up @@ -6,6 +6,8 @@
package org.h2.expression.condition;

import java.util.ArrayList;
import java.util.List;

import org.h2.engine.SessionLocal;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
Expand Down Expand Up @@ -165,12 +167,37 @@ public void createIndexConditions(SessionLocal session, TableFilter filter) {
} else if (left instanceof ExpressionList) {
ExpressionList list = (ExpressionList) left;
if (!list.isArray()) {
createIndexConditions(filter, list);
// First we create a compound index condition.
createCompoundIndexCondition(filter);
// If there is no compound index, then the TableFilter#prepare() method will drop this condition.
// Then we create a unique index condition for each column.
createUniqueIndexConditions(filter, list);
// If there are two or more index conditions, IndexCursor will only use the first one.
// See: IndexCursor#canUseIndexForIn(Column)
}
}
}

private void createIndexConditions(TableFilter filter, ExpressionList list) {
/**
* Creates a compound index condition containing every item in the expression list.
* @see IndexCondition#getCompoundInList(ExpressionList, List)
*/
private void createCompoundIndexCondition(TableFilter filter) {
// We do not check filter here, because the IN condition can contain columns from multiple tables.
ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
for (Expression e : valueList) {
if (!e.isEverything(visitor)) {
return;
}
}
filter.addIndexCondition(IndexCondition.getCompoundInList((ExpressionList) left, valueList));
}

/**
* Creates a unique index condition for every item in the expression list.
* @see IndexCondition#getInList(ExpressionColumn, List)
*/
private void createUniqueIndexConditions(TableFilter filter, ExpressionList list) {
int c = list.getSubexpressionCount();
for (int i = 0; i < c; i++) {
Expression e = list.getSubexpression(i);
Expand Down
Expand Up @@ -6,6 +6,7 @@
package org.h2.expression.condition;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

import org.h2.engine.SessionLocal;
Expand Down Expand Up @@ -139,12 +140,37 @@ public void createIndexConditions(SessionLocal session, TableFilter filter) {
} else if (left instanceof ExpressionList) {
ExpressionList list = (ExpressionList) left;
if (!list.isArray()) {
createIndexConditions(filter, list);
// First we create a compound index condition.
createCompoundIndexCondition(filter);
// If there is no compound index, then the TableFilter#prepare() method will drop this condition.
// Then we create a unique index condition for each column.
createUniqueIndexConditions(filter, list);
// If there are two or more index conditions, IndexCursor will only use the first one.
// See: IndexCursor#canUseIndexForIn(Column)
}
}
}

private void createIndexConditions(TableFilter filter, ExpressionList list) {
/**
* Creates a compound index condition containing every item in the expression list.
* @see IndexCondition#getCompoundInList(ExpressionList, List)
*/
private void createCompoundIndexCondition(TableFilter filter) {
// We do not check filter here, because the IN condition can contain columns from multiple tables.
ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
for (Expression e : valueList) {
if (!e.isEverything(visitor)) {
return;
}
}
filter.addIndexCondition(IndexCondition.getCompoundInList((ExpressionList) left, valueList));
}

/**
* Creates a unique index condition for every item in the expression list.
* @see IndexCondition#getInList(ExpressionColumn, List)
*/
private void createUniqueIndexConditions(TableFilter filter, ExpressionList list) {
int c = list.getSubexpressionCount();
for (int i = 0; i < c; i++) {
Expression e = list.getSubexpression(i);
Expand Down

0 comments on commit 539e8d6

Please sign in to comment.