From b1ba29c24f6c48c9b028bc8c4c5e9c729092f5ac Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Mon, 11 Sep 2006 01:33:12 +0000 Subject: Completed new query engine implementation. --- .../carbonado/qe/TestIndexedQueryAnalyzer.java | 106 ++++++++++++++++----- .../carbonado/qe/TestIndexedQueryExecutor.java | 44 +++++---- .../carbonado/qe/TestJoinedQueryExecutor.java | 19 ++-- .../carbonado/qe/TestSortedQueryExecutor.java | 4 +- .../carbonado/qe/TestUnionQueryAnalyzer.java | 20 ++-- .../carbonado/qe/TestUnionQueryExecutor.java | 4 +- .../com/amazon/carbonado/repo/toy/ToyStorage.java | 62 +++++++----- 7 files changed, 172 insertions(+), 87 deletions(-) (limited to 'src/test/java/com/amazon') diff --git a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java index dcc07ee..29e094d 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java +++ b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java @@ -26,8 +26,12 @@ import java.util.List; import junit.framework.TestCase; import junit.framework.TestSuite; +import com.amazon.carbonado.Cursor; import com.amazon.carbonado.Repository; import com.amazon.carbonado.Storable; +import com.amazon.carbonado.Storage; + +import com.amazon.carbonado.cursor.SortBuffer; import com.amazon.carbonado.info.StorableIndex; @@ -70,7 +74,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { // are performed by TestFilteringScore and TestOrderingScore. public void testFullScan() throws Exception { - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Address.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Address.class, RepoAccess.INSTANCE); Filter
filter = Filter.filterFor(Address.class, "addressZip = ?"); filter = filter.bind(); IndexedQueryAnalyzer.Result result = iqa.analyze(filter, null); @@ -83,7 +87,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { } public void testIndexScan() throws Exception { - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Address.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Address.class, RepoAccess.INSTANCE); Filter
filter = Filter.filterFor(Address.class, "addressID = ?"); filter = filter.bind(); IndexedQueryAnalyzer.Result result = iqa.analyze(filter, null); @@ -96,7 +100,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { } public void testBasic() throws Exception { - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID = ?"); filter = filter.bind(); IndexedQueryAnalyzer.Result result = iqa.analyze(filter, null); @@ -134,7 +138,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { } public void testSimpleJoin() throws Exception { - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "order.orderTotal >= ?"); filter = filter.bind(); IndexedQueryAnalyzer.Result result = iqa.analyze(filter, null); @@ -149,7 +153,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { public void testJoinPriority() throws Exception { // Selects foreign index because filter score is better. - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "shipmentNotes = ? & order.orderTotal >= ?"); filter = filter.bind(); @@ -168,7 +172,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { // Selects local index because filter score is just as good and local // indexes are preferred. - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "orderID >= ? & order.orderTotal >= ?"); filter = filter.bind(); @@ -184,7 +188,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { } public void testChainedJoin() throws Exception { - IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, IxProvider.INSTANCE); + IndexedQueryAnalyzer iqa = new IndexedQueryAnalyzer(Shipment.class, RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "order.address.addressState = ?"); filter = filter.bind(); @@ -201,7 +205,7 @@ public class TestIndexedQueryAnalyzer extends TestCase { Repository repo = new ToyRepository(); IndexedQueryAnalyzer iqa = - new IndexedQueryAnalyzer(Shipment.class, IxProvider.INSTANCE); + new IndexedQueryAnalyzer(Shipment.class, RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "order.address.addressState = ? & order.address.addressZip = ?"); FilterValues values = filter.initialFilterValues(); @@ -240,31 +244,55 @@ public class TestIndexedQueryAnalyzer extends TestCase { assertFalse(ixExec.mReverseOrder); } - static class IxProvider implements IndexProvider { - static final IxProvider INSTANCE = new IxProvider(); + static class RepoAccess implements RepositoryAccess { + static final RepoAccess INSTANCE = new RepoAccess(); + + public Repository getRootRepository() { + throw new UnsupportedOperationException(); + } + + public StorageAccess storageAccessFor(Class type) { + return new StoreAccess(type); + } + } + + /** + * Partially implemented StorageAccess which only supplies information + * about indexes. + */ + static class StoreAccess implements StorageAccess { + private final Class mType; + + StoreAccess(Class type) { + mType = type; + } + + public Class getStorableType() { + return mType; + } - public Collection> indexesFor(Class type) { + public Collection> getAllIndexes() { StorableIndex[] indexes; - if (Address.class.isAssignableFrom(type)) { + if (Address.class.isAssignableFrom(mType)) { indexes = new StorableIndex[] { - makeIndex(type, "addressID"), - makeIndex(type, "addressState") + makeIndex(mType, "addressID"), + makeIndex(mType, "addressState") }; - } else if (Order.class.isAssignableFrom(type)) { + } else if (Order.class.isAssignableFrom(mType)) { indexes = new StorableIndex[] { - makeIndex(type, "orderID"), - makeIndex(type, "orderTotal"), - makeIndex(type, "addressID") + makeIndex(mType, "orderID"), + makeIndex(mType, "orderTotal"), + makeIndex(mType, "addressID") }; - } else if (Shipment.class.isAssignableFrom(type)) { + } else if (Shipment.class.isAssignableFrom(mType)) { indexes = new StorableIndex[] { - makeIndex(type, "shipmentID"), - makeIndex(type, "orderID"), + makeIndex(mType, "shipmentID"), + makeIndex(mType, "orderID"), }; - } else if (Shipper.class.isAssignableFrom(type)) { + } else if (Shipper.class.isAssignableFrom(mType)) { indexes = new StorableIndex[] { - makeIndex(type, "shipperID") + makeIndex(mType, "shipperID") }; } else { indexes = new StorableIndex[0]; @@ -272,5 +300,37 @@ public class TestIndexedQueryAnalyzer extends TestCase { return Arrays.asList(indexes); } + + public Storage storageDelegate(StorableIndex index) { + return null; + } + + public SortBuffer createSortBuffer() { + throw new UnsupportedOperationException(); + } + + public Cursor fetch() { + throw new UnsupportedOperationException(); + } + + public Cursor fetch(StorableIndex index) { + throw new UnsupportedOperationException(); + } + + public Cursor fetch(StorableIndex index, Object[] identityValues) { + throw new UnsupportedOperationException(); + } + + public Cursor fetch(StorableIndex index, + Object[] identityValues, + BoundaryType rangeStartBoundary, + Object rangeStartValue, + BoundaryType rangeEndBoundary, + Object rangeEndValue, + boolean reverseRange, + boolean reverseOrder) + { + throw new UnsupportedOperationException(); + } } } diff --git a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryExecutor.java b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryExecutor.java index e8b3ba4..3226e13 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryExecutor.java +++ b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryExecutor.java @@ -697,26 +697,36 @@ public class TestIndexedQueryExecutor extends TestCase { boolean mReverseRange; boolean mReverseOrder; - public Mock(StorableIndex index, CompositeScore score) { - super(index, score); + Mock(StorableIndex index, CompositeScore score) { + this(index, score, new MockSupport[1]); } - protected Cursor fetch(StorableIndex index, - Object[] identityValues, - BoundaryType rangeStartBoundary, - Object rangeStartValue, - BoundaryType rangeEndBoundary, - Object rangeEndValue, - boolean reverseRange, - boolean reverseOrder) + Mock(StorableIndex index, CompositeScore score, MockSupport[] ref) { + // Extremely bizarre hack to allow support to know about us. + super(ref[0] = new MockSupport(), index, score); + ((MockSupport) ref[0]).mMock = this; + } + } + + static class MockSupport implements IndexedQueryExecutor.Support { + Mock mMock; + + public Cursor fetch(StorableIndex index, + Object[] identityValues, + BoundaryType rangeStartBoundary, + Object rangeStartValue, + BoundaryType rangeEndBoundary, + Object rangeEndValue, + boolean reverseRange, + boolean reverseOrder) { - mIdentityValues = identityValues; - mRangeStartBoundary = rangeStartBoundary; - mRangeStartValue = rangeStartValue; - mRangeEndBoundary = rangeEndBoundary; - mRangeEndValue = rangeEndValue; - mReverseRange = reverseRange; - mReverseOrder = reverseOrder; + mMock.mIdentityValues = identityValues; + mMock.mRangeStartBoundary = rangeStartBoundary; + mMock.mRangeStartValue = rangeStartValue; + mMock.mRangeEndBoundary = rangeEndBoundary; + mMock.mRangeEndValue = rangeEndValue; + mMock.mReverseRange = reverseRange; + mMock.mReverseOrder = reverseOrder; Collection empty = Collections.emptyList(); return new IteratorCursor(empty); diff --git a/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java b/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java index 7d352ed..ac4ebea 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java +++ b/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java @@ -169,29 +169,32 @@ public class TestJoinedQueryExecutor extends TestQueryExecutor { protected QueryExecutor addressExecutor() throws Exception { Storage addressStorage = mRepository.storageFor(UserAddress.class); - QueryExecutor addressExecutor = - new ScanQueryExecutor(addressStorage.query()); + QueryExecutor addressExecutor = new FullScanQueryExecutor + (new ScanQuerySupport(addressStorage.query())); addressExecutor = new FilteredQueryExecutor (addressExecutor, Filter.filterFor(UserAddress.class, "state = ?")); OrderingList ordering = OrderingList.get(UserAddress.class, "+country"); - addressExecutor = - new ArraySortedQueryExecutor(addressExecutor, null, ordering); + addressExecutor = new SortedQueryExecutor + (null, addressExecutor, null, ordering); return addressExecutor; } - static class ScanQueryExecutor extends FullScanQueryExecutor { + static class ScanQuerySupport implements FullScanQueryExecutor.Support { private final Query mQuery; - ScanQueryExecutor(Query query) { - super(query.getStorableType()); + ScanQuerySupport(Query query) { mQuery = query; } - protected Cursor fetch() throws FetchException { + public Class getStorableType() { + return mQuery.getStorableType(); + } + + public Cursor fetch() throws FetchException { return mQuery.fetch(); } } diff --git a/src/test/java/com/amazon/carbonado/qe/TestSortedQueryExecutor.java b/src/test/java/com/amazon/carbonado/qe/TestSortedQueryExecutor.java index 8e1eda2..53c47d6 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestSortedQueryExecutor.java +++ b/src/test/java/com/amazon/carbonado/qe/TestSortedQueryExecutor.java @@ -50,7 +50,7 @@ public class TestSortedQueryExecutor extends TestQueryExecutor { OrderingList
ordered = createOrdering("addressCountry"); QueryExecutor
executor = - new ArraySortedQueryExecutor
(unsorted, null, ordered); + new SortedQueryExecutor
(null, unsorted, null, ordered); assertEquals(filter, executor.getFilter()); @@ -69,7 +69,7 @@ public class TestSortedQueryExecutor extends TestQueryExecutor { OrderingList
finisher = createOrdering("addressState"); QueryExecutor
executor = - new ArraySortedQueryExecutor
(unsorted, handled, finisher); + new SortedQueryExecutor
(null, unsorted, handled, finisher); assertEquals(filter, executor.getFilter()); diff --git a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java index df2696d..7488c5b 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java +++ b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java @@ -70,7 +70,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testSingleSubResult() throws Exception { UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID = ?"); filter = filter.bind(); UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); @@ -81,7 +81,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testSingleSubResultUnspecifiedDirection() throws Exception { UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID > ?"); filter = filter.bind(); OrderingList orderings = @@ -98,7 +98,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testSimpleUnion() throws Exception { UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID = ? | orderID = ?"); filter = filter.bind(); @@ -129,7 +129,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testSimpleUnion2() throws Exception { UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID = ? | orderID > ?"); filter = filter.bind(); @@ -165,7 +165,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testSimpleUnion3() throws Exception { UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID = ? | orderID > ? & orderID <= ?"); filter = filter.bind(); @@ -206,7 +206,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testSimpleUnionUnspecifiedDirection() throws Exception { UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor(Shipment.class, "shipmentID > ? | orderID = ?"); filter = filter.bind(); @@ -251,7 +251,7 @@ public class TestUnionQueryAnalyzer extends TestCase { // split this into a union. After futher analysis, it should decide // that this offers no benefit and will merge them back. UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "shipmentID = ? & (shipmentID = ? | orderID = ?)"); @@ -276,7 +276,7 @@ public class TestUnionQueryAnalyzer extends TestCase { public void testFullScan() throws Exception { // Because no indexes were selected, there's no union to perform. UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "shipmentNotes = ? | shipperID = ?"); filter = filter.bind(); @@ -298,7 +298,7 @@ public class TestUnionQueryAnalyzer extends TestCase { // Because not all sub-results of union use an index, just fallback to // doing a full scan. UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "shipmentNotes = ? | orderID = ?"); filter = filter.bind(); @@ -320,7 +320,7 @@ public class TestUnionQueryAnalyzer extends TestCase { // Although not all sub-results use an index, one that does has a join // so it is exempt from folding into the full scan. UnionQueryAnalyzer uqa = - new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.IxProvider.INSTANCE); + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); Filter filter = Filter.filterFor (Shipment.class, "shipmentNotes = ? | orderID = ? & order.orderTotal > ?"); filter = filter.bind(); diff --git a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryExecutor.java b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryExecutor.java index 07716bb..9fccbc7 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryExecutor.java +++ b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryExecutor.java @@ -44,8 +44,8 @@ public class TestUnionQueryExecutor extends TestQueryExecutor { } public void testBasicUnion() throws Exception { - QueryExecutor
primary = new ArraySortedQueryExecutor
- (createExecutor(1, 2, 3, 4, 5, 6, 7, 8), null, createOrdering("addressID")); + QueryExecutor
primary = new SortedQueryExecutor
+ (null, createExecutor(1, 2, 3, 4, 5, 6, 7, 8), null, createOrdering("addressID")); Filter
filter_1 = Filter.filterFor(Address.class, "addressCountry > ?"); FilterValues
values_1 = filter_1.initialFilterValues(); diff --git a/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java index 84792ad..bafa244 100644 --- a/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java +++ b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java @@ -48,7 +48,9 @@ import com.amazon.carbonado.filter.FilterValues; import com.amazon.carbonado.info.OrderedProperty; import com.amazon.carbonado.info.StorableIntrospector; -import com.amazon.carbonado.qe.ArraySortedQueryExecutor; +import com.amazon.carbonado.qe.QueryExecutorFactory; +import com.amazon.carbonado.qe.QueryFactory; +import com.amazon.carbonado.qe.SortedQueryExecutor; import com.amazon.carbonado.qe.FilteredQueryExecutor; import com.amazon.carbonado.qe.IterableQueryExecutor; import com.amazon.carbonado.qe.OrderingList; @@ -59,7 +61,9 @@ import com.amazon.carbonado.qe.StandardQuery; * * @author Brian S O'Neill */ -public class ToyStorage implements Storage, MasterSupport { +public class ToyStorage + implements Storage, MasterSupport, QueryFactory, QueryExecutorFactory +{ final ToyRepository mRepo; final Class mType; @@ -89,18 +93,36 @@ public class ToyStorage implements Storage, MasterSupport return (S) mInstanceFactory.instantiate(this); } - public Query query() throws FetchException { + public Query query() { return new ToyQuery(null, null); } - public Query query(String filter) throws FetchException { + public Query query(String filter) { return query(Filter.filterFor(mType, filter)); } - public Query query(Filter filter) throws FetchException { + public Query query(Filter filter) { return new ToyQuery(filter.initialFilterValues(), null); } + public Query query(FilterValues values, OrderingList ordering) { + return new ToyQuery(values, ordering); + } + + public QueryExecutor executor(Filter filter, OrderingList ordering) { + QueryExecutor executor = new IterableQueryExecutor(mType, mData, mDataLock); + + if (filter != null) { + executor = new FilteredQueryExecutor(executor, filter); + } + + if (ordering.size() > 0) { + executor = new SortedQueryExecutor(null, executor, null, ordering); + } + + return executor; + } + public boolean addTrigger(Trigger trigger) { return false; } @@ -217,34 +239,24 @@ public class ToyStorage implements Storage, MasterSupport } private class ToyQuery extends StandardQuery { - ToyQuery(FilterValues values, OrderingList orderings) { - super(values, orderings); + ToyQuery(FilterValues values, OrderingList ordering) { + super(values, ordering); } - protected Storage getStorage() { - return ToyStorage.this; - } - - protected Transaction enterTransactionForDelete(IsolationLevel level) { + protected Transaction enterTransaction(IsolationLevel level) { return mRepo.enterTransaction(level); } - protected QueryExecutor getExecutor(FilterValues values, OrderingList orderings) { - QueryExecutor executor = new IterableQueryExecutor(mType, mData, mDataLock); - - if (values != null) { - executor = new FilteredQueryExecutor(executor, values.getFilter()); - } - - if (orderings.size() > 0) { - executor = new ArraySortedQueryExecutor(executor, null, orderings); - } + protected QueryFactory queryFactory() { + return ToyStorage.this; + } - return executor; + protected QueryExecutorFactory executorFactory() { + return ToyStorage.this; } - protected StandardQuery newInstance(FilterValues values, OrderingList orderings) { - return new ToyQuery(values, orderings); + protected StandardQuery newInstance(FilterValues values, OrderingList ordering) { + return new ToyQuery(values, ordering); } } } -- cgit v1.2.3