From 3df73d90a65115d9fdcf4b8596971e957c6bce2d Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sat, 14 Oct 2006 16:47:22 +0000 Subject: Moved tests to separate project. --- .../carbonado/qe/TestUnionQueryAnalyzer.java | 565 +++++++++++++++++++++ 1 file changed, 565 insertions(+) create mode 100644 src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java (limited to 'src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java') diff --git a/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java new file mode 100644 index 0000000..21d0b0c --- /dev/null +++ b/src/test/java/com/amazon/carbonado/qe/TestUnionQueryAnalyzer.java @@ -0,0 +1,565 @@ +/* + * Copyright 2006 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.carbonado.qe; + +import java.util.List; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.amazon.carbonado.Repository; +import com.amazon.carbonado.Storable; + +import com.amazon.carbonado.info.OrderedProperty; +import com.amazon.carbonado.info.StorableIndex; + +import com.amazon.carbonado.filter.Filter; +import com.amazon.carbonado.filter.FilterValues; +import com.amazon.carbonado.filter.PropertyFilter; + +import com.amazon.carbonado.repo.toy.ToyRepository; + +import com.amazon.carbonado.stored.Address; +import com.amazon.carbonado.stored.Order; +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; + +/** + * + * + * @author Brian S O'Neill + */ +public class TestUnionQueryAnalyzer extends TestCase { + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } + + public static TestSuite suite() { + return new TestSuite(TestUnionQueryAnalyzer.class); + } + + static StorableIndex makeIndex(Class type, String... props) { + return TestOrderingScore.makeIndex(type, props); + } + + static OrderingList makeOrdering(Class type, String... props) { + return TestOrderingScore.makeOrdering(type, props); + } + + public TestUnionQueryAnalyzer(String name) { + super(name); + } + + public void testNullFilter() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + UnionQueryAnalyzer.Result result = uqa.analyze(null, null); + List.Result> subResults = result.getSubResults(); + + assertEquals(1, subResults.size()); + } + + public void testSingleSubResult() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor(Shipment.class, "shipmentID = ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + List.Result> subResults = result.getSubResults(); + + assertEquals(1, subResults.size()); + } + + public void testSingleSubResultUnspecifiedDirection() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor(Shipment.class, "shipmentID > ?"); + filter = filter.bind(); + OrderingList orderings = + makeOrdering(Shipment.class, "~shipmentID", "~orderID"); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, orderings); + List.Result> subResults = result.getSubResults(); + + assertEquals(1, subResults.size()); + List> handled = + subResults.get(0).getCompositeScore().getOrderingScore().getHandledOrdering(); + assertEquals(1, handled.size()); + assertEquals("+shipmentID", handled.get(0).toString()); + } + + public void testSimpleUnion() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor(Shipment.class, + "shipmentID = ? | orderID = ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(Shipment.class, "+shipmentID"), result.getTotalOrdering()); + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + IndexedQueryAnalyzer.Result res_1 = subResults.get(1); + + assertTrue(res_0.handlesAnything()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentID = ?").bind(), + res_0.getCompositeScore().getFilteringScore().getIdentityFilter()); + assertEquals(makeIndex(Shipment.class, "shipmentID"), res_0.getLocalIndex()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(0, res_0.getRemainderOrdering().size()); + + assertTrue(res_1.handlesAnything()); + assertEquals(Filter.filterFor(Shipment.class, "orderID = ?").bind(), + res_1.getCompositeScore().getFilteringScore().getIdentityFilter()); + 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()); + assertEquals("+shipmentID", res_1.getRemainderOrdering().get(0).toString()); + } + + public void testSimpleUnion2() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor(Shipment.class, + "shipmentID = ? | orderID > ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(Shipment.class, "+shipmentID"), result.getTotalOrdering()); + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + IndexedQueryAnalyzer.Result res_1 = subResults.get(1); + + assertTrue(res_0.handlesAnything()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentID = ?").bind(), + res_0.getCompositeScore().getFilteringScore().getIdentityFilter()); + assertEquals(makeIndex(Shipment.class, "shipmentID"), res_0.getLocalIndex()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(0, res_0.getRemainderOrdering().size()); + + assertTrue(res_1.handlesAnything()); + assertTrue(res_1.getCompositeScore().getFilteringScore().hasRangeStart()); + assertFalse(res_1.getCompositeScore().getFilteringScore().hasRangeEnd()); + 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()); + assertEquals("+shipmentID", res_1.getRemainderOrdering().get(0).toString()); + } + + public void testSimpleUnion3() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor(Shipment.class, + "shipmentID = ? | orderID > ? & orderID <= ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(Shipment.class, "+shipmentID"), result.getTotalOrdering()); + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + IndexedQueryAnalyzer.Result res_1 = subResults.get(1); + + assertTrue(res_0.handlesAnything()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentID = ?").bind(), + res_0.getCompositeScore().getFilteringScore().getIdentityFilter()); + assertEquals(makeIndex(Shipment.class, "shipmentID"), res_0.getLocalIndex()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(0, res_0.getRemainderOrdering().size()); + + // Note: index that has proper filtering is preferred because + // "orderId > ? & orderID <= ?" filter specifies a complete range. + // We'll have to do a sort, but it isn't expected to be over that many records. + assertTrue(res_1.handlesAnything()); + assertTrue(res_1.getCompositeScore().getFilteringScore().hasRangeStart()); + assertTrue(res_1.getCompositeScore().getFilteringScore().hasRangeEnd()); + List> rangeFilters = + res_1.getCompositeScore().getFilteringScore().getRangeStartFilters(); + assertEquals(1, rangeFilters.size()); + assertEquals(Filter.filterFor(Shipment.class, "orderID > ?").bind(), rangeFilters.get(0)); + 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", "shipmentNotes"), res_1.getLocalIndex()); + assertEquals(null, res_1.getForeignIndex()); + assertEquals(null, res_1.getForeignProperty()); + // Sort operation required because the "shipmentID" index was not chosen. + assertEquals("+shipmentID", res_1.getRemainderOrdering().get(0).toString()); + } + + public void testSimpleUnionUnspecifiedDirection() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor(Shipment.class, + "shipmentID > ? | orderID = ?"); + filter = filter.bind(); + OrderingList orderings = + makeOrdering(Shipment.class, "~shipmentID", "~orderID"); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, orderings); + assertEquals(OrderingList.get(Shipment.class, "+shipmentID", "+orderID"), + result.getTotalOrdering()); + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + IndexedQueryAnalyzer.Result res_1 = subResults.get(1); + + List> handled = + res_0.getCompositeScore().getOrderingScore().getHandledOrdering(); + assertEquals(1, handled.size()); + assertEquals("+shipmentID", handled.get(0).toString()); + + handled = res_1.getCompositeScore().getOrderingScore().getHandledOrdering(); + assertEquals(0, handled.size()); + + assertTrue(res_0.handlesAnything()); + assertTrue(res_0.getCompositeScore().getFilteringScore().hasRangeStart()); + assertFalse(res_0.getCompositeScore().getFilteringScore().hasRangeEnd()); + assertEquals(makeIndex(Shipment.class, "shipmentID"), res_0.getLocalIndex()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(1, res_0.getRemainderOrdering().size()); + assertEquals("+orderID", res_0.getRemainderOrdering().get(0).toString()); + + assertTrue(res_1.handlesAnything()); + assertEquals(Filter.filterFor(Shipment.class, "orderID = ?").bind(), + res_1.getCompositeScore().getFilteringScore().getIdentityFilter()); + 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()); + assertEquals("+shipmentID", res_1.getRemainderOrdering().get(0).toString()); + } + + public void testSimpleMerge() throws Exception { + // Because query has an 'or' operation, the analyzer will initially + // 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.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (Shipment.class, + "shipmentID = ? & (shipmentID = ? | orderID = ?)"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + List.Result> subResults = result.getSubResults(); + + assertEquals(1, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + + assertTrue(res_0.handlesAnything()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentID = ?").bind(), + res_0.getCompositeScore().getFilteringScore().getIdentityFilter()); + assertEquals(makeIndex(Shipment.class, "shipmentID"), res_0.getLocalIndex()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(0, res_0.getRemainderOrdering().size()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentID = ? | orderID = ?"), + res_0.getRemainderFilter().unbind()); + } + + public void testFullScan() throws Exception { + // Because no indexes were selected, there's no union to perform. + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (Shipment.class, "shipmentNotes = ? | shipperID = ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + List.Result> subResults = result.getSubResults(); + + assertEquals(1, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + + assertFalse(res_0.handlesAnything()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(0, res_0.getRemainderOrdering().size()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentNotes = ? | shipperID = ?").bind(), + res_0.getRemainderFilter()); + } + + public void testFullScanFallback() throws Exception { + // Because not all sub-results of union use an index, just fallback to + // doing a full scan. + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(Shipment.class, TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (Shipment.class, "shipmentNotes = ? | orderID = ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + List.Result> subResults = result.getSubResults(); + + assertEquals(1, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + + assertFalse(res_0.handlesAnything()); + assertEquals(null, res_0.getForeignIndex()); + assertEquals(null, res_0.getForeignProperty()); + assertEquals(0, res_0.getRemainderOrdering().size()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentNotes = ? | orderID = ?").bind(), + res_0.getRemainderFilter()); + } + + public void testFullScanExempt() throws Exception { + // 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.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (Shipment.class, "shipmentNotes = ? | orderID = ? & order.orderTotal > ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + IndexedQueryAnalyzer.Result res_0 = subResults.get(0); + IndexedQueryAnalyzer.Result res_1 = subResults.get(1); + + assertTrue(res_0.handlesAnything()); + 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()); + assertEquals("+shipmentID", res_0.getRemainderOrdering().get(0).toString()); + assertEquals(Filter.filterFor(Shipment.class, "order.orderTotal > ?").bind(), + res_0.getRemainderFilter()); + + assertTrue(res_1.handlesAnything()); + assertEquals(makeIndex(Shipment.class, "shipmentID"), res_1.getLocalIndex()); + assertEquals(null, res_1.getForeignIndex()); + assertEquals(null, res_1.getForeignProperty()); + assertEquals(0, res_1.getRemainderOrdering().size()); + assertEquals(Filter.filterFor(Shipment.class, "shipmentNotes = ?").bind(), + res_1.getRemainderFilter()); + + } + + public void testComplexUnionPlan() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(StorableTestBasic.class, + TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (StorableTestBasic.class, "doubleProp = ? | (stringProp = ? & intProp = ?) | id > ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(StorableTestBasic.class, "+id"), result.getTotalOrdering()); + + QueryExecutor exec = result.createExecutor(); + + assertEquals(filter, exec.getFilter()); + assertEquals(OrderingList.get(StorableTestBasic.class, "+id"), exec.getOrdering()); + + List.Result> subResults = result.getSubResults(); + + assertEquals(3, subResults.size()); + + StringBuffer buf = new StringBuffer(); + exec.printPlan(buf, 0, null); + String plan = buf.toString(); + + String expected = + "union\n" + + " sort: [+id]\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[-doubleProp, +longProp, ~id], unique=true}\n" + + " ...identity filter: doubleProp = ?\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[-stringProp, -intProp, ~id], unique=true}\n" + + " ...identity filter: stringProp = ? & intProp = ?\n" + + " clustered index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+id], unique=true}\n" + + " ...range filter: id > ?\n"; + + // Test test will fail if the format of the plan changes. + assertEquals(expected, plan); + } + + public void testComplexUnionPlan2() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(StorableTestBasic.class, + TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (StorableTestBasic.class, "doubleProp = ? | stringProp = ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(StorableTestBasic.class, "+doubleProp", "+stringProp"), + result.getTotalOrdering()); + + QueryExecutor exec = result.createExecutor(); + + assertEquals(filter, exec.getFilter()); + assertEquals(OrderingList.get(StorableTestBasic.class, "+doubleProp", "+stringProp"), + exec.getOrdering()); + + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + + StringBuffer buf = new StringBuffer(); + exec.printPlan(buf, 0, null); + String plan = buf.toString(); + + String expected = + "union\n" + + " sort: [+stringProp]\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[-doubleProp, +longProp, ~id], unique=true}\n" + + " ...identity filter: doubleProp = ?\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+stringProp, +doubleProp], unique=true}\n" + + " ...identity filter: stringProp = ?\n"; + + // Test test will fail if the format of the plan changes. + assertEquals(expected, plan); + } + + public void testComplexUnionPlan3() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(StorableTestBasic.class, + TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (StorableTestBasic.class, "stringProp = ? | stringProp = ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(StorableTestBasic.class, "+stringProp", "+doubleProp"), + result.getTotalOrdering()); + + QueryExecutor exec = result.createExecutor(); + assertEquals(OrderingList.get(StorableTestBasic.class, "+stringProp", "+doubleProp"), + exec.getOrdering()); + + List.Result> subResults = result.getSubResults(); + + assertEquals(2, subResults.size()); + + StringBuffer buf = new StringBuffer(); + exec.printPlan(buf, 0, null); + String plan = buf.toString(); + + String expected = + "union\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+stringProp, +doubleProp], unique=true}\n" + + " ...identity filter: stringProp = ?\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+stringProp, +doubleProp], unique=true}\n" + + " ...identity filter: stringProp = ?[2]\n"; + + // Test test will fail if the format of the plan changes. + assertEquals(expected, plan); + } + + public void testComplexUnionPlan4() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(StorableTestBasic.class, + TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (StorableTestBasic.class, "doubleProp = ? | stringProp = ? | id > ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(StorableTestBasic.class, "+doubleProp", "+id"), + result.getTotalOrdering()); + + QueryExecutor exec = result.createExecutor(); + + assertEquals(filter, exec.getFilter()); + assertEquals(OrderingList.get(StorableTestBasic.class, "+doubleProp", "+id"), + exec.getOrdering()); + + List.Result> subResults = result.getSubResults(); + + assertEquals(3, subResults.size()); + + StringBuffer buf = new StringBuffer(); + exec.printPlan(buf, 0, null); + String plan = buf.toString(); + + String expected = + "union\n" + + " sort: [+id]\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[-doubleProp, +longProp, ~id], unique=true}\n" + + " ...identity filter: doubleProp = ?\n" + + " sort: [+doubleProp], [+id]\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+stringProp, +doubleProp], unique=true}\n" + + " ...identity filter: stringProp = ?\n" + + " sort: [+doubleProp, +id]\n" + + " clustered index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+id], unique=true}\n" + + " ...range filter: id > ?\n"; + + // Test test will fail if the format of the plan changes. + assertEquals(expected, plan); + } + + public void testComplexUnionPlan5() throws Exception { + UnionQueryAnalyzer uqa = + new UnionQueryAnalyzer(StorableTestBasic.class, + TestIndexedQueryAnalyzer.RepoAccess.INSTANCE); + Filter filter = Filter.filterFor + (StorableTestBasic.class, "stringProp = ? | stringProp = ? | id > ?"); + filter = filter.bind(); + UnionQueryAnalyzer.Result result = uqa.analyze(filter, null); + assertEquals(OrderingList.get(StorableTestBasic.class, "+stringProp", "+doubleProp"), + result.getTotalOrdering()); + + QueryExecutor exec = result.createExecutor(); + + assertEquals(filter, exec.getFilter()); + assertEquals(OrderingList.get(StorableTestBasic.class, "+stringProp", "+doubleProp"), + exec.getOrdering()); + + List.Result> subResults = result.getSubResults(); + + assertEquals(3, subResults.size()); + + StringBuffer buf = new StringBuffer(); + exec.printPlan(buf, 0, null); + String plan = buf.toString(); + + String expected = + "union\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+stringProp, +doubleProp], unique=true}\n" + + " ...identity filter: stringProp = ?\n" + + " index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+stringProp, +doubleProp], unique=true}\n" + + " ...identity filter: stringProp = ?[2]\n" + + " sort: [+stringProp, +doubleProp]\n" + + " clustered index scan: com.amazon.carbonado.stored.StorableTestBasic\n" + + " ...index: {properties=[+id], unique=true}\n" + + " ...range filter: id > ?\n"; + + // Test test will fail if the format of the plan changes. + assertEquals(expected, plan); + } +} -- cgit v1.2.3