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

wip

上级 8f467f15
...@@ -64,7 +64,7 @@ public final class JoinBatch { ...@@ -64,7 +64,7 @@ public final class JoinBatch {
} }
}; };
private ViewIndexLookupBatch viewIndexLookupBatch; private boolean batchedSubQuery;
private Future<Cursor> viewTopFutureCursor; private Future<Cursor> viewTopFutureCursor;
private JoinFilter[] filters; private JoinFilter[] filters;
...@@ -112,7 +112,7 @@ public final class JoinBatch { ...@@ -112,7 +112,7 @@ public final class JoinBatch {
public IndexLookupBatch getLookupBatch(int joinFilterId) { public IndexLookupBatch getLookupBatch(int joinFilterId) {
return filters[joinFilterId].lookupBatch; return filters[joinFilterId].lookupBatch;
} }
/** /**
* Reset state of this batch. * Reset state of this batch.
*/ */
...@@ -163,7 +163,7 @@ public final class JoinBatch { ...@@ -163,7 +163,7 @@ public final class JoinBatch {
current = new JoinRow(new Object[filters.length]); current = new JoinRow(new Object[filters.length]);
// initialize top cursor // initialize top cursor
Cursor cursor; Cursor cursor;
if (viewIndexLookupBatch == null) { if (!batchedSubQuery) {
// it is a top level batched query // it is a top level batched query
TableFilter f = top.filter; TableFilter f = top.filter;
IndexCursor indexCursor = f.getIndexCursor(); IndexCursor indexCursor = f.getIndexCursor();
...@@ -372,16 +372,22 @@ public final class JoinBatch { ...@@ -372,16 +372,22 @@ public final class JoinBatch {
* @return Adapter to allow joining to this batch in sub-queries and views. * @return Adapter to allow joining to this batch in sub-queries and views.
*/ */
private IndexLookupBatch viewIndexLookupBatch(ViewIndex viewIndex) { private IndexLookupBatch viewIndexLookupBatch(ViewIndex viewIndex) {
assert viewIndexLookupBatch == null; assert !batchedSubQuery;
return viewIndexLookupBatch = new ViewIndexLookupBatch(viewIndex); batchedSubQuery = true;
return new ViewIndexLookupBatch(viewIndex);
} }
/**
* Create index lookup batch for a view index.
*
* @param viewIndex view index
* @return index lookup batch or {@code null} if batching is not supported for this query
*/
public static IndexLookupBatch createViewIndexLookupBatch(ViewIndex viewIndex) { public static IndexLookupBatch createViewIndexLookupBatch(ViewIndex viewIndex) {
Query query = viewIndex.getQuery(); Query query = viewIndex.getQuery();
if (query.isUnion()) { if (query.isUnion()) {
SelectUnion union = (SelectUnion) query; ViewIndexLookupBatchUnion unionBatch = new ViewIndexLookupBatchUnion(viewIndex);
// TODO return unionBatch.initialize() ? unionBatch : null;
return null;
} else { } else {
Select select = (Select) query; Select select = (Select) query;
// here we have already prepared plan for our sub-query, // here we have already prepared plan for our sub-query,
...@@ -649,10 +655,7 @@ public final class JoinBatch { ...@@ -649,10 +655,7 @@ public final class JoinBatch {
private final List<Future<Cursor>> result = new SingletonList<Future<Cursor>>(); private final List<Future<Cursor>> result = new SingletonList<Future<Cursor>>();
/** private FakeLookupBatch(TableFilter filter) {
* @param index Index.
*/
public FakeLookupBatch(TableFilter filter) {
this.filter = filter; this.filter = filter;
} }
...@@ -716,22 +719,28 @@ public final class JoinBatch { ...@@ -716,22 +719,28 @@ public final class JoinBatch {
} }
/** /**
* Index lookup batch over this join batch for a sub-query or view. * Base class for SELECT and SELECT UNION view index lookup batches.
*/ */
private final class ViewIndexLookupBatch implements IndexLookupBatch { private abstract static class ViewIndexLookupBatchBase implements IndexLookupBatch {
private final ViewIndex viewIndex; protected final ViewIndex viewIndex;
private final ArrayList<Future<Cursor>> result = New.arrayList(); protected final ArrayList<Future<Cursor>> result = New.arrayList();
private int resultSize; protected int resultSize;
private ViewIndexLookupBatch(ViewIndex viewIndex) { protected ViewIndexLookupBatchBase(ViewIndex viewIndex) {
this.viewIndex = viewIndex; this.viewIndex = viewIndex;
} }
private boolean resetAfterFind() { protected abstract boolean collectSearchRows();
protected abstract QueryRunnerBase newQueryRunner();
protected abstract void startQueryRunners();
protected final boolean resetAfterFind() {
if (resultSize < 0) { if (resultSize < 0) {
// method find was called, we need to reset futures to initial state for reuse // method find was called, we need to reset futures to initial state for reuse
for (int i = 0, size = -resultSize; i < size; i++) { for (int i = 0, size = -resultSize; i < size; i++) {
((QueryRunner) result.get(i)).reset(); ((QueryRunnerBase) result.get(i)).reset();
} }
resultSize = 0; resultSize = 0;
return true; return true;
...@@ -740,25 +749,101 @@ public final class JoinBatch { ...@@ -740,25 +749,101 @@ public final class JoinBatch {
} }
@Override @Override
public boolean addSearchRows(SearchRow first, SearchRow last) { public final boolean addSearchRows(SearchRow first, SearchRow last) {
resetAfterFind(); resetAfterFind();
viewIndex.setupQueryParameters(viewIndex.getSession(), first, last, null); viewIndex.setupQueryParameters(viewIndex.getSession(), first, last, null);
if (!top.collectSearchRows()) { if (!collectSearchRows()) {
return false; return false;
} }
QueryRunner r; QueryRunnerBase r;
if (resultSize < result.size()) { if (resultSize < result.size()) {
// get reused runner // get reused runner
r = (QueryRunner) result.get(resultSize); r = (QueryRunnerBase) result.get(resultSize);
} else { } else {
// create new runner // create new runner
result.add(r = new QueryRunner()); result.add(r = newQueryRunner());
} }
r.first = first; r.first = first;
r.last = last; r.last = last;
resultSize++; resultSize++;
return true; return true;
} }
@Override
public void reset() {
if (resultSize != 0 && !resetAfterFind()) {
// find was not called, need to just clear runners
for (int i = 0; i < resultSize; i++) {
((QueryRunnerBase) result.get(i)).clear();
}
resultSize = 0;
}
}
@Override
public final List<Future<Cursor>> find() {
if (resultSize == 0) {
return Collections.emptyList();
}
startQueryRunners();
List<Future<Cursor>> list = resultSize == result.size() ?
result : result.subList(0, resultSize);
// mark that method find was called
resultSize = -resultSize;
return list;
}
}
/**
* Lazy query runner base.
*/
private abstract static class QueryRunnerBase extends LazyFuture<Cursor> {
protected final ViewIndex viewIndex;
protected SearchRow first;
protected SearchRow last;
public QueryRunnerBase(ViewIndex viewIndex) {
this.viewIndex = viewIndex;
}
protected void clear() {
first = last = null;
}
@Override
public final boolean reset() {
if (super.reset()) {
return true;
}
// this query runner was never executed, need to clear manually
clear();
return false;
}
protected final ViewCursor newCursor(LocalResult localResult) {
ViewCursor cursor = new ViewCursor(viewIndex, localResult, first, last);
clear();
return cursor;
}
}
/**
* View index lookup batch for a simple SELECT.
*/
private final class ViewIndexLookupBatch extends ViewIndexLookupBatchBase {
private ViewIndexLookupBatch(ViewIndex viewIndex) {
super(viewIndex);
}
@Override
protected QueryRunnerBase newQueryRunner() {
return new QueryRunner(viewIndex);
}
@Override
protected boolean collectSearchRows() {
return top.collectSearchRows();
}
@Override @Override
public boolean isBatchFull() { public boolean isBatchFull() {
...@@ -766,10 +851,13 @@ public final class JoinBatch { ...@@ -766,10 +851,13 @@ public final class JoinBatch {
} }
@Override @Override
public List<Future<Cursor>> find() { public void reset() {
if (resultSize == 0) { super.reset();
return Collections.emptyList(); JoinBatch.this.reset();
} }
@Override
protected void startQueryRunners() {
// we do batched find only for top table filter and then lazily run the ViewIndex query // we do batched find only for top table filter and then lazily run the ViewIndex query
// for each received top future cursor // for each received top future cursor
List<Future<Cursor>> topFutureCursors = top.find(); List<Future<Cursor>> topFutureCursors = top.find();
...@@ -781,48 +869,23 @@ public final class JoinBatch { ...@@ -781,48 +869,23 @@ public final class JoinBatch {
QueryRunner r = (QueryRunner) result.get(i); QueryRunner r = (QueryRunner) result.get(i);
r.topFutureCursor = topFutureCursors.get(i); r.topFutureCursor = topFutureCursors.get(i);
} }
List<Future<Cursor>> list = resultSize == result.size() ?
result : result.subList(0, resultSize);
// mark that method find was called
resultSize = -resultSize;
return list;
}
@Override
public void reset() {
if (resultSize != 0 && !resetAfterFind()) {
// find was not called, need to just clear runners
for (int i = 0; i < resultSize; i++) {
((QueryRunner) result.get(i)).clear();
}
resultSize = 0;
}
JoinBatch.this.reset();
} }
/** /**
* Lazy query runner. * Query runner.
*/ */
private class QueryRunner extends LazyFuture<Cursor> { private final class QueryRunner extends QueryRunnerBase {
private Future<Cursor> topFutureCursor; private Future<Cursor> topFutureCursor;
private SearchRow first;
private SearchRow last;
private void clear() { public QueryRunner(ViewIndex viewIndex) {
topFutureCursor = null; super(viewIndex);
first = last = null;
} }
@Override protected void clear() {
public boolean reset() { topFutureCursor = null;
if (super.reset()) { super.clear();
return true;
}
// this query runner was never executed, need to clear manually
clear();
return false;
} }
@Override @Override
protected Cursor run() throws Exception { protected Cursor run() throws Exception {
if (topFutureCursor == null) { if (topFutureCursor == null) {
...@@ -836,9 +899,94 @@ public final class JoinBatch { ...@@ -836,9 +899,94 @@ public final class JoinBatch {
} finally { } finally {
JoinBatch.this.viewTopFutureCursor = null; JoinBatch.this.viewTopFutureCursor = null;
} }
ViewCursor cursor = new ViewCursor(viewIndex, localResult, first, last); return newCursor(localResult);
clear(); }
return cursor; }
}
/**
* View index lookup batch for UNION queries.
*/
private static final class ViewIndexLookupBatchUnion extends ViewIndexLookupBatchBase {
private ArrayList<JoinFilter> tops = New.arrayList();
private ArrayList<JoinBatch> joinBatches = New.arrayList();
protected ViewIndexLookupBatchUnion(ViewIndex viewIndex) {
super(viewIndex);
}
/**
* @return {@code true} if initialized successfully
*/
private boolean initialize() {
return collectTopTableFilters(viewIndex.getQuery());
}
private boolean collectTopTableFilters(Query query) {
if (query.isUnion()) {
SelectUnion union = (SelectUnion) query;
return collectTopTableFilters(union.getLeft()) &&
collectTopTableFilters(union.getRight());
}
Select select = (Select) query;
JoinBatch jb = select.getJoinBatch();
if (jb == null) {
// if we've found non-batched select then we can't do batching at all here
return false;
}
tops.add(jb.filters[0]);
return true;
}
@Override
public boolean isBatchFull() {
// if at least one is full
for (int i = 0; i < tops.size(); i++) {
if (tops.get(i).isBatchFull()) {
return true;
}
}
return false;
}
@Override
protected boolean collectSearchRows() {
for (int i = 0; i < tops.size(); i++) {
if (tops.get(i).collectSearchRows()) {
// TODO
}
}
return true;
}
@Override
protected QueryRunnerBase newQueryRunner() {
return new QueryRunnerUnion();
}
@Override
protected void startQueryRunners() {
// TODO Auto-generated method stub
}
/**
* Query runner for UNION.
*/
private class QueryRunnerUnion extends QueryRunnerBase {
public QueryRunnerUnion() {
super(ViewIndexLookupBatchUnion.this.viewIndex);
}
@Override
protected void clear() {
super.clear();
// TODO
}
@Override
protected Cursor run() throws Exception {
// TODO Auto-generated method stub
return null;
} }
} }
} }
......
...@@ -101,6 +101,6 @@ public abstract class LazyFuture<T> implements Future<T> { ...@@ -101,6 +101,6 @@ public abstract class LazyFuture<T> implements Future<T> {
@Override @Override
public boolean isDone() { public boolean isDone() {
return state == S_DONE; return state != S_READY;
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论