提交 c266fa0a authored 作者: S.Vladykin's avatar S.Vladykin

WIP subquery batched join

上级 98b5eba7
...@@ -71,6 +71,8 @@ public abstract class Query extends Prepared { ...@@ -71,6 +71,8 @@ public abstract class Query extends Prepared {
super(session); super(session);
} }
public abstract boolean isUnion();
/** /**
* Execute the query without checking the cache. If a target is specified, * Execute the query without checking the cache. If a target is specified,
* the results are written to it, and the method returns null. If no target * the results are written to it, and the method returns null. If no target
......
...@@ -87,6 +87,11 @@ public class Select extends Query { ...@@ -87,6 +87,11 @@ public class Select extends Query {
super(session); super(session);
} }
@Override
public boolean isUnion() {
return false;
}
/** /**
* Add a table to the query. * Add a table to the query.
* *
...@@ -942,7 +947,9 @@ public class Select extends Query { ...@@ -942,7 +947,9 @@ public class Select extends Query {
} }
expressionArray = new Expression[expressions.size()]; expressionArray = new Expression[expressions.size()];
expressions.toArray(expressionArray); expressions.toArray(expressionArray);
topTableFilter.prepareBatch(0); if (!session.isParsingView()) {
topTableFilter.prepareBatch(0);
}
isPrepared = true; isPrepared = true;
} }
......
...@@ -7,7 +7,6 @@ package org.h2.command.dml; ...@@ -7,7 +7,6 @@ package org.h2.command.dml;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.engine.Session; import org.h2.engine.Session;
...@@ -72,6 +71,11 @@ public class SelectUnion extends Query { ...@@ -72,6 +71,11 @@ public class SelectUnion extends Query {
this.left = query; this.left = query;
} }
@Override
public boolean isUnion() {
return true;
}
public void setUnionType(int type) { public void setUnionType(int type) {
this.unionType = type; this.unionType = type;
} }
......
...@@ -6,9 +6,12 @@ ...@@ -6,9 +6,12 @@
package org.h2.index; package org.h2.index;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.command.dml.Query; import org.h2.command.dml.Query;
import org.h2.command.dml.Select;
import org.h2.command.dml.SelectUnion; import org.h2.command.dml.SelectUnion;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Session; import org.h2.engine.Session;
...@@ -21,6 +24,7 @@ import org.h2.result.SearchRow; ...@@ -21,6 +24,7 @@ import org.h2.result.SearchRow;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.IndexColumn; import org.h2.table.IndexColumn;
import org.h2.table.JoinBatch;
import org.h2.table.SubQueryInfo; import org.h2.table.SubQueryInfo;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.table.TableView; import org.h2.table.TableView;
...@@ -93,6 +97,46 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -93,6 +97,46 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
} }
} }
@Override
public IndexLookupBatch createLookupBatch(TableFilter filter) {
if (recursive) {
// we do not support batching for recursive queries
return null;
}
if (query.isUnion()) {
return createLookupBatchUnion((SelectUnion) query);
}
return createLookupBatchSimple((Select) query);
}
private IndexLookupBatch createLookupBatchSimple(Select select) {
// here we have already prepared plan for our sub-query,
// thus select already contains join batch for it (if it has to)
JoinBatch joinBatch = select.getJoinBatch();
if (joinBatch == null) {
// our sub-query itself is not batched, will run usual way
return null;
}
return joinBatch.getLookupBatch(0);
}
private IndexLookupBatch createLookupBatchUnion(SelectUnion union) {
Query left = union.getLeft();
IndexLookupBatch leftLookupBatch = left.isUnion() ?
createLookupBatchUnion((SelectUnion) left):
createLookupBatchSimple((Select) left);
Query right = union.getRight();
IndexLookupBatch rightLookupBatch = right.isUnion() ?
createLookupBatchUnion((SelectUnion) right) :
createLookupBatchSimple((Select) right);
if (leftLookupBatch == null && rightLookupBatch == null) {
return null;
}
return new UnionLookupBatch(leftLookupBatch, rightLookupBatch);
}
public Session getSession() { public Session getSession() {
return createSession; return createSession;
} }
...@@ -221,7 +265,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -221,7 +265,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
if (query == null) { if (query == null) {
query = (Query) createSession.prepare(querySQL, true); query = (Query) createSession.prepare(querySQL, true);
} }
if (!(query instanceof SelectUnion)) { if (!query.isUnion()) {
throw DbException.get(ErrorCode.SYNTAX_ERROR_2, throw DbException.get(ErrorCode.SYNTAX_ERROR_2,
"recursive queries without UNION ALL"); "recursive queries without UNION ALL");
} }
...@@ -454,4 +498,41 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -454,4 +498,41 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
return recursive; return recursive;
} }
/**
* Lookup batch for unions.
*/
private static final class UnionLookupBatch implements IndexLookupBatch {
private final IndexLookupBatch left;
private final IndexLookupBatch right;
private UnionLookupBatch(IndexLookupBatch left, IndexLookupBatch right) {
this.left = left;
this.right = right;
}
@Override
public void addSearchRows(SearchRow first, SearchRow last) {
assert !left.isBatchFull();
assert !right.isBatchFull();
left.addSearchRows(first, last);
right.addSearchRows(first, last);
}
@Override
public boolean isBatchFull() {
return left.isBatchFull() || right.isBatchFull();
}
@Override
public List<Future<Cursor>> find() {
// TODO Auto-generated method stub
return null;
}
@Override
public void reset() {
left.reset();
right.reset();
}
}
} }
...@@ -83,6 +83,8 @@ public final class JoinBatch { ...@@ -83,6 +83,8 @@ public final class JoinBatch {
} }
/** /**
* Check if the index at the given table filter really supports batching in this query.
*
* @param joinFilterId joined table filter id * @param joinFilterId joined table filter id
* @return {@code true} if index really supports batching in this query * @return {@code true} if index really supports batching in this query
*/ */
...@@ -90,6 +92,16 @@ public final class JoinBatch { ...@@ -90,6 +92,16 @@ public final class JoinBatch {
return filters[joinFilterId].isBatched(); return filters[joinFilterId].isBatched();
} }
/**
* Get the lookup batch for the given table filter.
*
* @param joinFilterId joined table filter id
* @return lookup batch
*/
public IndexLookupBatch getLookupBatch(int joinFilterId) {
return filters[joinFilterId].lookupBatch;
}
/** /**
* Reset state of this batch. * Reset state of this batch.
*/ */
......
...@@ -339,6 +339,23 @@ public class TableFilter implements ColumnResolver { ...@@ -339,6 +339,23 @@ public class TableFilter implements ColumnResolver {
foundOne = false; foundOne = false;
} }
private boolean isAlwaysTopTableFilter(int id) {
if (id != 0) {
return false;
}
// check if we are at the top table filters all the way up
SubQueryInfo info = session.getSubQueryInfo();
for (;;) {
if (info == null) {
return true;
}
if (info.getFilter() != 0) {
return false;
}
info = info.getUpper();
}
}
/** /**
* Attempt to initialize batched join. * Attempt to initialize batched join.
* *
...@@ -351,8 +368,7 @@ public class TableFilter implements ColumnResolver { ...@@ -351,8 +368,7 @@ public class TableFilter implements ColumnResolver {
batch = join.prepareBatch(id + 1); batch = join.prepareBatch(id + 1);
} }
IndexLookupBatch lookupBatch = null; IndexLookupBatch lookupBatch = null;
if (batch == null && select != null && id != 0) { if (batch == null && select != null && !isAlwaysTopTableFilter(id)) {
// TODO session.getSubQueryInfo() instead of id != 0 + use upper level sub-query info
lookupBatch = index.createLookupBatch(this); lookupBatch = index.createLookupBatch(this);
if (lookupBatch != null) { if (lookupBatch != null) {
batch = new JoinBatch(id + 1, join); batch = new JoinBatch(id + 1, join);
...@@ -362,12 +378,11 @@ public class TableFilter implements ColumnResolver { ...@@ -362,12 +378,11 @@ public class TableFilter implements ColumnResolver {
if (nestedJoin != null) { if (nestedJoin != null) {
throw DbException.getUnsupportedException("nested join with batched index"); throw DbException.getUnsupportedException("nested join with batched index");
} }
if (lookupBatch == null && id != 0) {
// TODO session.getSubQueryInfo() instead of id != 0 + use upper level sub-query info
lookupBatch = index.createLookupBatch(this);
}
joinBatch = batch; joinBatch = batch;
joinFilterId = id; joinFilterId = id;
if (lookupBatch == null && !isAlwaysTopTableFilter(id)) {
lookupBatch = index.createLookupBatch(this);
}
batch.register(this, lookupBatch); batch.register(this, lookupBatch);
} }
return batch; return batch;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论