diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2006-09-30 23:07:46 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2006-09-30 23:07:46 +0000 |
commit | f5a69fbf5e7e343d094687263604ce18b7b6dae5 (patch) | |
tree | 45e302cbdf1be177b1080b4227910f0052b7031c /src/test/java | |
parent | bddf5aea31f3ed34b43d26133de1671b2acbcc46 (diff) |
Finished join optimization.
Diffstat (limited to 'src/test/java')
5 files changed, 353 insertions, 101 deletions
diff --git a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java index ef1711f..6b1919a 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java +++ b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryAnalyzer.java @@ -27,12 +27,17 @@ import junit.framework.TestCase; import junit.framework.TestSuite;
import com.amazon.carbonado.Cursor;
+import com.amazon.carbonado.FetchException;
+import com.amazon.carbonado.Query;
import com.amazon.carbonado.Repository;
+import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storable;
import com.amazon.carbonado.Storage;
+import com.amazon.carbonado.cursor.ArraySortBuffer;
import com.amazon.carbonado.cursor.SortBuffer;
+import com.amazon.carbonado.info.OrderedProperty;
import com.amazon.carbonado.info.StorableIndex;
import com.amazon.carbonado.filter.Filter;
@@ -47,8 +52,6 @@ import com.amazon.carbonado.stored.Shipment; import com.amazon.carbonado.stored.Shipper;
import com.amazon.carbonado.stored.StorableTestBasic;
-import static com.amazon.carbonado.qe.TestIndexedQueryExecutor.Mock;
-
/**
*
*
@@ -118,7 +121,8 @@ public class TestIndexedQueryAnalyzer extends TestCase { assertTrue(result.handlesAnything());
assertEquals(filter, result.getCompositeScore().getFilteringScore().getIdentityFilter());
- assertEquals(makeIndex(Shipment.class, "orderID"), result.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"),
+ result.getLocalIndex());
assertEquals(null, result.getForeignIndex());
assertEquals(null, result.getForeignProperty());
@@ -133,7 +137,8 @@ public class TestIndexedQueryAnalyzer extends TestCase { result.getCompositeScore().getFilteringScore().getRangeStartFilters();
assertEquals(1, rangeFilters.size());
assertEquals(filter, rangeFilters.get(0));
- assertEquals(makeIndex(Shipment.class, "orderID"), result.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"),
+ result.getLocalIndex());
assertEquals(null, result.getForeignIndex());
assertEquals(null, result.getForeignProperty());
}
@@ -183,7 +188,8 @@ public class TestIndexedQueryAnalyzer extends TestCase { assertTrue(result.getCompositeScore().getFilteringScore().hasRangeStart());
assertEquals(Filter.filterFor(Shipment.class, "order.orderTotal >= ?").bind(),
result.getCompositeScore().getFilteringScore().getRemainderFilter());
- assertEquals(makeIndex(Shipment.class, "orderID"), result.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"),
+ result.getLocalIndex());
assertEquals(null, result.getForeignIndex());
assertEquals(null, result.getForeignProperty());
}
@@ -198,20 +204,19 @@ public class TestIndexedQueryAnalyzer extends TestCase { assertTrue(result.handlesAnything());
assertEquals(filter, result.getCompositeScore().getFilteringScore().getIdentityFilter());
assertEquals(null, result.getLocalIndex());
- assertEquals(makeIndex(Address.class, "addressState"), result.getForeignIndex());
+ assertEquals(makeIndex(Address.class, "addressState", "-addressCity"),
+ result.getForeignIndex());
assertEquals("order.address", result.getForeignProperty().toString());
}
public void testChainedJoinExecutor() throws Exception {
- Repository repo = new ToyRepository();
-
IndexedQueryAnalyzer<Shipment> iqa =
new IndexedQueryAnalyzer<Shipment>(Shipment.class, RepoAccess.INSTANCE);
Filter<Shipment> filter = Filter.filterFor
(Shipment.class, "order.address.addressState = ? & order.address.addressZip = ?");
FilterValues<Shipment> values = filter.initialFilterValues();
filter = values.getFilter();
- IndexedQueryAnalyzer.Result result = iqa.analyze(filter, null);
+ IndexedQueryAnalyzer<Shipment>.Result result = iqa.analyze(filter, null);
assertTrue(result.handlesAnything());
assertEquals(Filter.filterFor(Shipment.class, "order.address.addressState = ?").bind(),
@@ -219,30 +224,117 @@ public class TestIndexedQueryAnalyzer extends TestCase { assertEquals(Filter.filterFor(Shipment.class, "order.address.addressZip = ?").bind(),
result.getCompositeScore().getFilteringScore().getRemainderFilter());
assertEquals(null, result.getLocalIndex());
- assertEquals(makeIndex(Address.class, "addressState"), result.getForeignIndex());
+ assertEquals(makeIndex(Address.class, "addressState", "-addressCity"),
+ result.getForeignIndex());
assertEquals("order.address", result.getForeignProperty().toString());
- Mock ixExec = new Mock(result.getForeignIndex(), result.getCompositeScore());
+ QueryExecutor<Shipment> joinExec = JoinedQueryExecutor.build
+ (RepoAccess.INSTANCE,
+ result.getForeignProperty(), result.getFilter(), result.getOrdering());
+
+ FilterValues<Shipment> fv = values.with("WA").with("12345");
- QueryExecutor joinExec = new JoinedQueryExecutor
- (repo, result.getForeignProperty(), ixExec);
+ StringBuffer buf = new StringBuffer();
+ joinExec.printPlan(buf, 0, fv);
+ String plan = buf.toString();
- QueryExecutor filteredExec = new FilteredQueryExecutor
- (joinExec, result.getCompositeScore().getFilteringScore().getRemainderFilter());
+ // This is actually a pretty terrible plan due to the iterators. This
+ // is expected however, since we lied and said we had indexes.
+ String expected =
+ "join: com.amazon.carbonado.stored.Shipment\n" +
+ "...inner loop: order\n" +
+ " filter: orderID = ?\n" +
+ " collection iterator: com.amazon.carbonado.stored.Shipment\n" +
+ "...outer loop\n" +
+ " join: com.amazon.carbonado.stored.Order\n" +
+ " ...inner loop: address\n" +
+ " filter: addressID = ?\n" +
+ " collection iterator: com.amazon.carbonado.stored.Order\n" +
+ " ...outer loop\n" +
+ " filter: addressState = WA & addressZip = 12345\n" +
+ " collection iterator: com.amazon.carbonado.stored.Address\n";
- //System.out.println();
- //filteredExec.printPlan(System.out, 0, null);
+ assertEquals(expected, plan);
- joinExec.fetch(values.with("WA"));
+ joinExec.fetch(fv);
+
+ }
+
+ public void testComplexChainedJoinExecutor() throws Exception {
+ IndexedQueryAnalyzer<Shipment> iqa =
+ new IndexedQueryAnalyzer<Shipment>(Shipment.class, RepoAccess.INSTANCE);
+ Filter<Shipment> filter = Filter.filterFor
+ (Shipment.class,
+ "order.address.addressState = ? & order.address.addressID != ? " +
+ "& order.address.addressZip = ? & order.orderTotal > ? & shipmentNotes <= ? " +
+ "& order.addressID > ?");
+ FilterValues<Shipment> values = filter.initialFilterValues();
+ filter = values.getFilter();
+ OrderingList<Shipment> ordering = OrderingList
+ .get(Shipment.class, "order.address.addressCity", "shipmentNotes", "order.orderTotal");
+ IndexedQueryAnalyzer.Result result = iqa.analyze(filter, ordering);
+
+ assertTrue(result.handlesAnything());
+ assertEquals(Filter.filterFor(Shipment.class, "order.address.addressState = ?").bind(),
+ result.getCompositeScore().getFilteringScore().getIdentityFilter());
+ assertEquals(null, result.getLocalIndex());
+ assertEquals(makeIndex(Address.class, "addressState", "-addressCity"),
+ result.getForeignIndex());
+ assertEquals("order.address", result.getForeignProperty().toString());
- assertEquals(1, ixExec.mIdentityValues.length);
- assertEquals("WA", ixExec.mIdentityValues[0]);
- assertEquals(BoundaryType.OPEN, ixExec.mRangeStartBoundary);
- assertEquals(null, ixExec.mRangeStartValue);
- assertEquals(BoundaryType.OPEN, ixExec.mRangeEndBoundary);
- assertEquals(null, ixExec.mRangeEndValue);
- assertFalse(ixExec.mReverseRange);
- assertFalse(ixExec.mReverseOrder);
+ QueryExecutor<Shipment> joinExec = JoinedQueryExecutor.build
+ (RepoAccess.INSTANCE,
+ result.getForeignProperty(), result.getFilter(), result.getOrdering());
+
+ FilterValues<Shipment> fv =
+ values.with("WA").with(45).with("12345").with(100).with("Z").with(2);
+
+ StringBuffer buf = new StringBuffer();
+ joinExec.printPlan(buf, 0, fv);
+ String plan = buf.toString();
+
+ // This is actually a pretty terrible plan due to the iterators. This
+ // is expected however, since we lied and said we had indexes.
+ String expected =
+ "sort: [+order.address.addressCity, +shipmentNotes], [+order.orderTotal]\n" +
+ " join: com.amazon.carbonado.stored.Shipment\n" +
+ " ...inner loop: order\n" +
+ " sort: [+shipmentNotes]\n" +
+ " filter: shipmentNotes <= Z & orderID = ?\n" +
+ " collection iterator: com.amazon.carbonado.stored.Shipment\n" +
+ " ...outer loop\n" +
+ " join: com.amazon.carbonado.stored.Order\n" +
+ " ...inner loop: address\n" +
+ " filter: orderTotal > 100 & addressID > 2 & addressID = ?\n" +
+ " collection iterator: com.amazon.carbonado.stored.Order\n" +
+ " ...outer loop\n" +
+ " sort: [+addressCity]\n" +
+ " filter: addressState = WA & addressID != 45 & addressZip = 12345\n" +
+ " collection iterator: com.amazon.carbonado.stored.Address\n";
+
+ //System.out.println(plan);
+ assertEquals(expected, plan);
+
+ joinExec.fetch(fv);
+
+ // Now do it the easier way and compare plans.
+ QueryExecutor<Shipment> joinExec2 = result.createExecutor();
+
+ StringBuffer buf2 = new StringBuffer();
+ joinExec2.printPlan(buf2, 0, fv);
+ String plan2 = buf2.toString();
+
+ assertEquals(expected, plan2);
+
+ Filter<Shipment> expectedFilter = Filter.filterFor
+ (Shipment.class,
+ "order.address.addressState = ? & order.address.addressID != ? " +
+ "& order.address.addressZip = ? & order.orderTotal > ? " +
+ "& order.addressID > ?" +
+ "& shipmentNotes <= ? ");
+
+ assertEquals(expectedFilter.disjunctiveNormalForm(),
+ joinExec2.getFilter().unbind().disjunctiveNormalForm());
}
static class RepoAccess implements RepositoryAccess {
@@ -261,7 +353,9 @@ public class TestIndexedQueryAnalyzer extends TestCase { * Partially implemented StorageAccess which only supplies information
* about indexes.
*/
- static class StoreAccess<S extends Storable> implements StorageAccess<S> {
+ static class StoreAccess<S extends Storable>
+ implements StorageAccess<S>, QueryExecutorFactory<S>
+ {
private final Class<S> mType;
StoreAccess(Class<S> type) {
@@ -272,24 +366,45 @@ public class TestIndexedQueryAnalyzer extends TestCase { return mType;
}
+ public QueryExecutorFactory<S> getQueryExecutorFactory() {
+ return this;
+ }
+
+ public QueryExecutor<S> executor(Filter<S> filter, OrderingList<S> ordering) {
+ Iterable<S> iterable = Collections.emptyList();
+
+ QueryExecutor<S> exec = new IterableQueryExecutor<S>
+ (filter.getStorableType(), iterable);
+
+ if (filter != null) {
+ exec = new FilteredQueryExecutor<S>(exec, filter);
+ }
+
+ if (ordering != null && ordering.size() > 0) {
+ exec = new SortedQueryExecutor<S>(null, exec, null, ordering);
+ }
+
+ return exec;
+ }
+
public Collection<StorableIndex<S>> getAllIndexes() {
StorableIndex<S>[] indexes;
if (Address.class.isAssignableFrom(mType)) {
indexes = new StorableIndex[] {
makeIndex(mType, "addressID"),
- makeIndex(mType, "addressState")
+ makeIndex(mType, "addressState", "-addressCity")
};
} else if (Order.class.isAssignableFrom(mType)) {
indexes = new StorableIndex[] {
makeIndex(mType, "orderID"),
makeIndex(mType, "orderTotal"),
- makeIndex(mType, "addressID")
+ makeIndex(mType, "addressID", "orderTotal")
};
} else if (Shipment.class.isAssignableFrom(mType)) {
indexes = new StorableIndex[] {
makeIndex(mType, "shipmentID"),
- makeIndex(mType, "orderID"),
+ makeIndex(mType, "orderID", "shipmentNotes"),
};
} else if (Shipper.class.isAssignableFrom(mType)) {
indexes = new StorableIndex[] {
@@ -315,6 +430,10 @@ public class TestIndexedQueryAnalyzer extends TestCase { }
public SortBuffer<S> createSortBuffer() {
+ return new ArraySortBuffer<S>();
+ }
+
+ public long countAll() {
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 8908825..a68fbac 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryExecutor.java +++ b/src/test/java/com/amazon/carbonado/qe/TestIndexedQueryExecutor.java @@ -76,7 +76,7 @@ public class TestIndexedQueryExecutor extends TestCase { CompositeScore<StorableTestBasic> score = CompositeScore.evaluate(index, filter, null);
- Mock<StorableTestBasic> executor = new Mock(index, score);
+ Mock<StorableTestBasic> executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -96,7 +96,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100).with(5));
@@ -117,7 +117,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(200));
@@ -140,7 +140,7 @@ public class TestIndexedQueryExecutor extends TestCase { CompositeScore<StorableTestBasic> score = CompositeScore.evaluate(index, filter, null);
- Mock<StorableTestBasic> executor = new Mock(index, score);
+ Mock<StorableTestBasic> executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -159,7 +159,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -178,7 +178,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(30));
@@ -197,7 +197,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(30));
@@ -216,7 +216,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(10));
@@ -235,7 +235,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(30).with(10));
@@ -255,7 +255,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "-intProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100).with(30));
@@ -276,7 +276,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -296,7 +296,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "-intProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -316,7 +316,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "intProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -339,7 +339,7 @@ public class TestIndexedQueryExecutor extends TestCase { CompositeScore<StorableTestBasic> score = CompositeScore.evaluate(index, filter, null);
- Mock<StorableTestBasic> executor = new Mock(index, score);
+ Mock<StorableTestBasic> executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -358,7 +358,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -377,7 +377,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(30));
@@ -396,7 +396,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(30));
@@ -415,7 +415,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(10));
@@ -434,7 +434,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(30).with(10));
@@ -454,7 +454,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "-intProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100).with(30));
@@ -475,7 +475,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -495,7 +495,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "-intProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -515,7 +515,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "intProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100));
@@ -541,7 +541,7 @@ public class TestIndexedQueryExecutor extends TestCase { CompositeScore<StorableTestBasic> score = CompositeScore.evaluate(index, filter, null);
- Mock<StorableTestBasic> executor = new Mock(index, score);
+ Mock<StorableTestBasic> executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100).with(200));
@@ -560,7 +560,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(100).with(10));
@@ -580,7 +580,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(10).with(100).with(30));
@@ -612,7 +612,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter, null);
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(3).with(56.5).with(200.2));
@@ -628,7 +628,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "doubleProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(3).with(56.5).with(200.2));
@@ -644,7 +644,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "stringProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(3).with(56.5).with(200.2));
@@ -665,7 +665,7 @@ public class TestIndexedQueryExecutor extends TestCase { score = CompositeScore.evaluate(index, filter,
makeOrdering(StorableTestBasic.class, "-stringProp"));
- executor = new Mock(index, score);
+ executor = new Mock<StorableTestBasic>(index, score);
executor.fetch(values.with(3).with(56.5).with("foo"));
@@ -684,11 +684,40 @@ public class TestIndexedQueryExecutor extends TestCase { assertEquals(expectedOrdering, executor.getOrdering());
}
+ public void testHandledOrdering() throws Exception {
+ // Tests that ordering of executor only reveals what it actually uses.
+
+ StorableIndex<StorableTestBasic> index;
+ Filter<StorableTestBasic> filter;
+ FilterValues<StorableTestBasic> values;
+ CompositeScore<StorableTestBasic> score;
+ Mock<StorableTestBasic> executor;
+
+ index = makeIndex(StorableTestBasic.class, "intProp", "-doubleProp", "stringProp");
+
+ filter = Filter.filterFor(StorableTestBasic.class, "intProp = ?");
+ values = filter.initialFilterValues();
+ filter = values.getFilter();
+
+ score = CompositeScore.evaluate
+ (index, filter,
+ makeOrdering(StorableTestBasic.class, "intProp", "doubleProp"));
+
+ executor = new Mock<StorableTestBasic>(index, score);
+
+ assertEquals(values.getFilter(), executor.getFilter());
+ List<OrderedProperty<StorableTestBasic>> expectedOrdering =
+ makeOrdering(StorableTestBasic.class, "+doubleProp");
+ assertEquals(expectedOrdering, executor.getOrdering());
+ }
+
/**
* Mock object doesn't really open a cursor -- it just captures the passed
* parameters.
*/
- static class Mock<S extends Storable> extends IndexedQueryExecutor<S> {
+ static class Mock<S extends Storable> extends IndexedQueryExecutor<S>
+ implements IndexedQueryExecutor.Support<S>
+ {
Object[] mIdentityValues;
BoundaryType mRangeStartBoundary;
Object mRangeStartValue;
@@ -697,19 +726,9 @@ public class TestIndexedQueryExecutor extends TestCase { boolean mReverseRange;
boolean mReverseOrder;
- Mock(StorableIndex<S> index, CompositeScore<S> score) {
- this(index, score, new MockSupport[1]);
- }
-
- Mock(StorableIndex<S> index, CompositeScore<S> score, MockSupport[] ref) {
- // Extremely bizarre hack to allow support to know about us.
- super(ref[0] = new MockSupport(), index, score);
- ((MockSupport<S>) ref[0]).mMock = this;
+ public Mock(StorableIndex<S> index, CompositeScore<S> score) {
+ super(null, index, score);
}
- }
-
- static class MockSupport<S extends Storable> implements IndexedQueryExecutor.Support<S> {
- Mock<S> mMock;
public Cursor<S> fetchSubset(StorableIndex<S> index,
Object[] identityValues,
@@ -720,13 +739,13 @@ public class TestIndexedQueryExecutor extends TestCase { boolean reverseRange,
boolean reverseOrder)
{
- mMock.mIdentityValues = identityValues;
- mMock.mRangeStartBoundary = rangeStartBoundary;
- mMock.mRangeStartValue = rangeStartValue;
- mMock.mRangeEndBoundary = rangeEndBoundary;
- mMock.mRangeEndValue = rangeEndValue;
- mMock.mReverseRange = reverseRange;
- mMock.mReverseOrder = reverseOrder;
+ mIdentityValues = identityValues;
+ mRangeStartBoundary = rangeStartBoundary;
+ mRangeStartValue = rangeStartValue;
+ mRangeEndBoundary = rangeEndBoundary;
+ mRangeEndValue = rangeEndValue;
+ mReverseRange = reverseRange;
+ mReverseOrder = reverseOrder;
Collection<S> empty = Collections.emptyList();
return new IteratorCursor<S>(empty);
diff --git a/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java b/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java index 423cd74..e1abca9 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java +++ b/src/test/java/com/amazon/carbonado/qe/TestJoinedQueryExecutor.java @@ -18,8 +18,12 @@ package com.amazon.carbonado.qe;
+import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import junit.framework.TestSuite;
@@ -27,14 +31,21 @@ import com.amazon.carbonado.Cursor; import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.Query;
import com.amazon.carbonado.Repository;
+import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storable;
import com.amazon.carbonado.Storage;
+import com.amazon.carbonado.cursor.ArraySortBuffer;
+import com.amazon.carbonado.cursor.SortBuffer;
+
import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.FilterValues;
+import com.amazon.carbonado.info.ChainedProperty;
import com.amazon.carbonado.info.Direction;
import com.amazon.carbonado.info.OrderedProperty;
+import com.amazon.carbonado.info.StorableIndex;
+import com.amazon.carbonado.info.StorableInfo;
import com.amazon.carbonado.info.StorableIntrospector;
import com.amazon.carbonado.info.StorableProperty;
@@ -69,10 +80,23 @@ public class TestJoinedQueryExecutor extends TestQueryExecutor { }
public void testJoin() throws Exception {
- QueryExecutor<UserAddress> addressExecutor = addressExecutor();
+ StorableInfo<UserInfo> info = StorableIntrospector.examine(UserInfo.class);
+ Map<String, ? extends StorableProperty<UserInfo>> properties = info.getAllProperties();
+
+ RepositoryAccess repoAccess = new RepoAccess();
+
+ ChainedProperty<UserInfo> targetToSourceProperty =
+ ChainedProperty.get(properties.get("address"));
+
+ Filter<UserInfo> targetFilter = Filter.filterFor(UserInfo.class, "address.state = ?");
+ OrderingList<UserInfo> targetOrdering =
+ OrderingList.get(UserInfo.class, "+address.country");
+
+ QueryExecutor<UserInfo> userExecutor = JoinedQueryExecutor.build
+ (repoAccess, targetToSourceProperty, targetFilter, targetOrdering);
- QueryExecutor<UserInfo> userExecutor = new JoinedQueryExecutor<UserAddress, UserInfo>
- (mRepository, UserInfo.class, "address", addressExecutor);
+ //System.out.println();
+ //userExecutor.printPlan(System.out, 0, null);
assertEquals("address.state = ?", userExecutor.getFilter().toString());
assertEquals("+address.country", userExecutor.getOrdering().get(0).toString());
@@ -146,8 +170,13 @@ public class TestJoinedQueryExecutor extends TestQueryExecutor { // Now do a multi join, finding everyone with an explicit neighbor in IL.
- userExecutor = new JoinedQueryExecutor<UserAddress, UserInfo>
- (mRepository, UserInfo.class, "address.neighbor", addressExecutor);
+ targetToSourceProperty = ChainedProperty.parse(info, "address.neighbor");
+
+ targetFilter = Filter.filterFor(UserInfo.class, "address.neighbor.state = ?");
+ targetOrdering = OrderingList.get(UserInfo.class, "+address.neighbor.country");
+
+ userExecutor = JoinedQueryExecutor.build
+ (repoAccess, targetToSourceProperty, targetFilter, targetOrdering);
assertEquals("address.neighbor.state = ?", userExecutor.getFilter().toString());
assertEquals("+address.neighbor.country", userExecutor.getOrdering().get(0).toString());
@@ -163,24 +192,88 @@ public class TestJoinedQueryExecutor extends TestQueryExecutor { cursor.close();
assertEquals(1L, userExecutor.count(values));
-
}
- protected QueryExecutor<UserAddress> addressExecutor() throws Exception {
- Storage<UserAddress> addressStorage = mRepository.storageFor(UserAddress.class);
+ class RepoAccess implements RepositoryAccess {
+ public Repository getRootRepository() {
+ return mRepository;
+ }
- QueryExecutor<UserAddress> addressExecutor = new FullScanQueryExecutor<UserAddress>
- (new ScanQuerySupport<UserAddress>(addressStorage.query()));
+ public <S extends Storable> StorageAccess<S> storageAccessFor(Class<S> type) {
+ return new StoreAccess<S>(type);
+ }
+ }
+
+ class StoreAccess<S extends Storable> implements StorageAccess<S>, QueryExecutorFactory<S> {
+ private final Class<S> mType;
+
+ StoreAccess(Class<S> type) {
+ mType = type;
+ }
+
+ public Class<S> getStorableType() {
+ return mType;
+ }
+
+ public QueryExecutorFactory<S> getQueryExecutorFactory() {
+ return this;
+ }
- addressExecutor = new FilteredQueryExecutor<UserAddress>
- (addressExecutor, Filter.filterFor(UserAddress.class, "state = ?"));
+ public QueryExecutor<S> executor(Filter<S> filter, OrderingList<S> ordering)
+ throws RepositoryException
+ {
+ Storage<S> storage = mRepository.storageFor(mType);
- OrderingList<UserAddress> ordering = OrderingList.get(UserAddress.class, "+country");
+ QueryExecutor<S> exec = new FullScanQueryExecutor<S>
+ (new ScanQuerySupport<S>(storage.query()));
- addressExecutor = new SortedQueryExecutor<UserAddress>
- (null, addressExecutor, null, ordering);
+ if (filter != null) {
+ exec = new FilteredQueryExecutor<S>(exec, filter);
+ }
- return addressExecutor;
+ if (ordering != null && ordering.size() > 0) {
+ exec = new SortedQueryExecutor<S>(null, exec, null, ordering);
+ }
+
+ return exec;
+ }
+
+ public Collection<StorableIndex<S>> getAllIndexes() {
+ StorableIndex<S>[] indexes = new StorableIndex[0];
+ return Arrays.asList(indexes);
+ }
+
+ public Storage<S> storageDelegate(StorableIndex<S> index) {
+ return null;
+ }
+
+ public SortBuffer<S> createSortBuffer() {
+ return new ArraySortBuffer<S>();
+ }
+
+ public long countAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Cursor<S> fetchAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Cursor<S> fetchOne(StorableIndex<S> index, Object[] identityValues) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Cursor<S> fetchSubset(StorableIndex<S> index,
+ Object[] identityValues,
+ BoundaryType rangeStartBoundary,
+ Object rangeStartValue,
+ BoundaryType rangeEndBoundary,
+ Object rangeEndValue,
+ boolean reverseRange,
+ boolean reverseOrder)
+ {
+ throw new UnsupportedOperationException();
+ }
}
static class ScanQuerySupport<S extends Storable> implements FullScanQueryExecutor.Support<S> {
@@ -194,6 +287,10 @@ public class TestJoinedQueryExecutor extends TestQueryExecutor { return mQuery.getStorableType();
}
+ public long countAll() throws FetchException {
+ return mQuery.count();
+ }
+
public Cursor<S> fetchAll() throws FetchException {
return mQuery.fetch();
}
diff --git a/src/test/java/com/amazon/carbonado/qe/TestOrderingList.java b/src/test/java/com/amazon/carbonado/qe/TestOrderingList.java index ea9bc10..8af7a2e 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestOrderingList.java +++ b/src/test/java/com/amazon/carbonado/qe/TestOrderingList.java @@ -184,6 +184,21 @@ public class TestOrderingList extends TestCase { assertTrue(list_1 == list_2);
}
+ public void testSubList() throws Exception {
+ OrderingList<StorableTestBasic> list_1 =
+ OrderingList.get(StorableTestBasic.class, "date", "-intProp", "~stringProp");
+
+ assertEquals(0, list_1.subList(0, 0).size());
+ assertEquals(list_1, list_1.subList(0, 3));
+
+ OrderingList<StorableTestBasic> sub = list_1.subList(0, 1);
+ assertEquals(1, sub.size());
+ assertEquals("+date", sub.get(0).toString());
+
+ sub = list_1.subList(1, 3);
+ assertEquals(2, sub.size());
+ }
+
public void testAsArray() throws Exception {
OrderingList<StorableTestBasic> list =
OrderingList.get(StorableTestBasic.class, "date", "intProp", "stringProp");
diff --git a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java index e9cc8f9..7c92772 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java +++ b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java @@ -131,7 +131,8 @@ public class TestUnionQueryAnalyzer extends TestCase { assertTrue(res_1.handlesAnything());
assertEquals(Filter.filterFor(Shipment.class, "orderID = ?").bind(),
res_1.getCompositeScore().getFilteringScore().getIdentityFilter());
- assertEquals(makeIndex(Shipment.class, "orderID"), res_1.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"),
+ res_1.getLocalIndex());
assertEquals(null, res_1.getForeignIndex());
assertEquals(null, res_1.getForeignProperty());
assertEquals(1, res_1.getRemainderOrdering().size());
@@ -163,7 +164,8 @@ public class TestUnionQueryAnalyzer extends TestCase { assertTrue(res_1.handlesAnything());
assertTrue(res_1.getCompositeScore().getFilteringScore().hasRangeStart());
assertFalse(res_1.getCompositeScore().getFilteringScore().hasRangeEnd());
- assertEquals(makeIndex(Shipment.class, "orderID"), res_1.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"),
+ res_1.getLocalIndex());
assertEquals(null, res_1.getForeignIndex());
assertEquals(null, res_1.getForeignProperty());
assertEquals(1, res_1.getRemainderOrdering().size());
@@ -205,7 +207,7 @@ public class TestUnionQueryAnalyzer extends TestCase { rangeFilters = res_1.getCompositeScore().getFilteringScore().getRangeEndFilters();
assertEquals(1, rangeFilters.size());
assertEquals(Filter.filterFor(Shipment.class, "orderID <= ?").bind(), rangeFilters.get(0));
- assertEquals(makeIndex(Shipment.class, "orderID"), res_1.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"), res_1.getLocalIndex());
assertEquals(null, res_1.getForeignIndex());
assertEquals(null, res_1.getForeignProperty());
// Sort operation required because the "shipmentID" index was not chosen.
@@ -249,7 +251,7 @@ public class TestUnionQueryAnalyzer extends TestCase { assertTrue(res_1.handlesAnything());
assertEquals(Filter.filterFor(Shipment.class, "orderID = ?").bind(),
res_1.getCompositeScore().getFilteringScore().getIdentityFilter());
- assertEquals(makeIndex(Shipment.class, "orderID"), res_1.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"), res_1.getLocalIndex());
assertEquals(null, res_1.getForeignIndex());
assertEquals(null, res_1.getForeignProperty());
assertEquals(1, res_1.getRemainderOrdering().size());
@@ -342,7 +344,7 @@ public class TestUnionQueryAnalyzer extends TestCase { IndexedQueryAnalyzer<Shipment>.Result res_1 = subResults.get(1);
assertTrue(res_0.handlesAnything());
- assertEquals(makeIndex(Shipment.class, "orderID"), res_0.getLocalIndex());
+ assertEquals(makeIndex(Shipment.class, "orderID", "shipmentNotes"), res_0.getLocalIndex());
assertEquals(null, res_0.getForeignIndex());
assertEquals(null, res_0.getForeignProperty());
assertEquals(1, res_0.getRemainderOrdering().size());
|