From ecf73566b91313b61c06b104e45e24d89f4dd329 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sat, 4 Aug 2007 23:38:00 +0000 Subject: Add filtering short-circuit optimization. --- .../cursor/TestShortCircuitOptimizer.java | 217 +++++++++++++++++++++ .../amazon/carbonado/qe/TestFilteringScore.java | 35 ++-- 2 files changed, 237 insertions(+), 15 deletions(-) create mode 100644 src/test/java/com/amazon/carbonado/cursor/TestShortCircuitOptimizer.java (limited to 'src/test') diff --git a/src/test/java/com/amazon/carbonado/cursor/TestShortCircuitOptimizer.java b/src/test/java/com/amazon/carbonado/cursor/TestShortCircuitOptimizer.java new file mode 100644 index 0000000..4bfa78d --- /dev/null +++ b/src/test/java/com/amazon/carbonado/cursor/TestShortCircuitOptimizer.java @@ -0,0 +1,217 @@ +/* + * Copyright 2007 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.cursor; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.amazon.carbonado.filter.Filter; + +import com.amazon.carbonado.stored.*; + +/** + * + * + * @author Brian S O'Neill + */ +public class TestShortCircuitOptimizer extends TestCase { + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } + + public static TestSuite suite() { + return new TestSuite(TestShortCircuitOptimizer.class); + } + + public TestShortCircuitOptimizer(String name) { + super(name); + } + + protected void setUp() { + } + + protected void tearDown() { + } + + public void testBasic() throws Exception { + { + Filter filter = Filter.getOpenFilter(Order.class); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + + { + Filter filter = Filter.getClosedFilter(Order.class); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + + { + Filter filter = Filter.filterFor(Order.class, "orderNumber = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + } + + public void testNoJoins() throws Exception { + { + Filter filter = Filter + .filterFor(Order.class, "orderNumber = ? & orderTotal = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, "orderNumber = ? | orderTotal = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, "(orderNumber = ? | orderTotal = ?) & addressID != ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + } + + public void testManyToOneJoins() throws Exception { + { + Filter filter = Filter + .filterFor(Order.class, "orderNumber = ? & address.addressState = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, "address.addressState = ? & orderNumber = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + assertEquals(Filter.filterFor + (Order.class, "orderNumber = ? & address.addressState = ?"), + optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, + "(address.addressState = ? & orderNumber = ?) | orderTotal < ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + assertEquals(Filter.filterFor + (Order.class, + "orderTotal < ? | (orderNumber = ? & address.addressState = ?)"), + optimized); + } + + { + Filter filter = Filter + .filterFor(Shipment.class, + "order.address.addressState = ? | shipper.shipperName = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + assertEquals(Filter.filterFor + (Shipment.class, + "shipper.shipperName = ? | order.address.addressState = ?"), + optimized); + } + + { + Filter filter = Filter + .filterFor(Shipment.class, + "order.address.addressState = ? | shipper.address.addressCity = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + } + + public void testOneToManyJoins() throws Exception { + { + Filter filter = Filter + .filterFor(Order.class, "orderNumber = ? & orderItems.itemPrice = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, "orderItems.itemPrice = ? & orderNumber = ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + assertEquals(Filter.filterFor + (Order.class, "orderNumber = ? & orderItems.itemPrice = ?"), + optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, + "(orderItems.itemPrice = ? & orderNumber = ?) | orderTotal < ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + assertEquals(Filter.filterFor + (Order.class, + "orderTotal < ? | (orderNumber = ? & orderItems.itemPrice = ?)"), + optimized); + } + + { + Filter filter = Filter + .filterFor(Order.class, + "orderItems.shipment.shipmentDate > ? | shipments.shipmentDate < ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + assertEquals(Filter.filterFor + (Order.class, + "shipments.shipmentDate < ? | orderItems.shipment.shipmentDate > ?"), + optimized); + } + + { + Filter filter = Filter + .filterFor + (Order.class, + "orderItems.shipment.shipmentDate > ? | shipments.shipper.shipperName != ?"); + Filter optimized = ShortCircuitOptimizer.optimize(filter); + + // No change. + assertEquals(filter, optimized); + } + } +} diff --git a/src/test/java/com/amazon/carbonado/qe/TestFilteringScore.java b/src/test/java/com/amazon/carbonado/qe/TestFilteringScore.java index 25222a7..ecec5c0 100644 --- a/src/test/java/com/amazon/carbonado/qe/TestFilteringScore.java +++ b/src/test/java/com/amazon/carbonado/qe/TestFilteringScore.java @@ -624,9 +624,10 @@ public class TestFilteringScore extends TestCase { score_1 = FilteringScore.evaluate(ix_1, filter); score_2 = FilteringScore.evaluate(ix_2, filter); - // Second is better because it has fewer properties. - assertEquals(1, comp.compare(score_1, score_2)); - assertEquals(-1, comp.compare(score_2, score_1)); + // Same -- number of properties no longer considered except by + // OrderingScore and CompositeScore. + assertEquals(0, comp.compare(score_1, score_2)); + assertEquals(0, comp.compare(score_2, score_1)); score_1 = FilteringScore.evaluate(ix_1.clustered(true), filter); score_2 = FilteringScore.evaluate(ix_2, filter); @@ -637,9 +638,10 @@ public class TestFilteringScore extends TestCase { score_1 = FilteringScore.evaluate(ix_1, filter); score_2 = FilteringScore.evaluate(ix_2, filter); - // Although no property matches, second is better just because it has fewer properties. - assertEquals(1, comp.compare(score_1, score_2)); - assertEquals(-1, comp.compare(score_2, score_1)); + // No property matches and number of properties no longer considered + // except by OrderingScore and CompositeScore. + assertEquals(0, comp.compare(score_1, score_2)); + assertEquals(0, comp.compare(score_2, score_1)); filter = Filter.filterFor(StorableTestBasic.class, "stringProp = ?"); score_1 = FilteringScore.evaluate(ix_1.clustered(true), filter); @@ -660,9 +662,10 @@ public class TestFilteringScore extends TestCase { score_1 = FilteringScore.evaluate(ix_1, filter); score_2 = FilteringScore.evaluate(ix_2, filter); - // Second is better because it has fewer properties. - assertEquals(1, comp.compare(score_1, score_2)); - assertEquals(-1, comp.compare(score_2, score_1)); + // Same -- number of properties no longer considered except by + // OrderingScore and CompositeScore. + assertEquals(0, comp.compare(score_1, score_2)); + assertEquals(0, comp.compare(score_2, score_1)); filter = Filter.filterFor(StorableTestBasic.class, "id = ? & stringProp = ?"); score_1 = FilteringScore.evaluate(ix_1, filter); @@ -692,9 +695,10 @@ public class TestFilteringScore extends TestCase { score_1 = FilteringScore.evaluate(ix_1, filter); score_2 = FilteringScore.evaluate(ix_2, filter); - // Second is better because it has fewer properties. - assertEquals(1, comp.compare(score_1, score_2)); - assertEquals(-1, comp.compare(score_2, score_1)); + // Same -- number of properties no longer considered except by + // OrderingScore and CompositeScore. + assertEquals(0, comp.compare(score_1, score_2)); + assertEquals(0, comp.compare(score_2, score_1)); filter = Filter.filterFor(StorableTestBasic.class, "id >= ? & id < ?"); score_1 = FilteringScore.evaluate(ix_1.clustered(true), filter); @@ -709,9 +713,10 @@ public class TestFilteringScore extends TestCase { score_1 = FilteringScore.evaluate(ix_1.clustered(true), filter); score_2 = FilteringScore.evaluate(ix_2.clustered(true), filter); - // Second is better because it has fewer properties. - assertEquals(1, comp.compare(score_1, score_2)); - assertEquals(-1, comp.compare(score_2, score_1)); + // Same -- number of properties no longer considered except by + // OrderingScore and CompositeScore. + assertEquals(0, comp.compare(score_1, score_2)); + assertEquals(0, comp.compare(score_2, score_1)); } public void testArrangementFullComparator() throws Exception { -- cgit v1.2.3