| /*========================================================================= |
| * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * one or more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| /* |
| * InOperatorTest.java |
| * |
| * Created on March 24, 2005, 5:08 PM |
| */ |
| package com.gemstone.gemfire.cache.query.functional; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.fail; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| |
| import com.gemstone.gemfire.cache.AttributesFactory; |
| import com.gemstone.gemfire.cache.Cache; |
| import com.gemstone.gemfire.cache.Region; |
| import com.gemstone.gemfire.cache.RegionAttributes; |
| import com.gemstone.gemfire.cache.query.CacheUtils; |
| import com.gemstone.gemfire.cache.query.IndexType; |
| import com.gemstone.gemfire.cache.query.Query; |
| import com.gemstone.gemfire.cache.query.QueryService; |
| import com.gemstone.gemfire.cache.query.SelectResults; |
| import com.gemstone.gemfire.cache.query.Utils; |
| import com.gemstone.gemfire.test.junit.categories.IntegrationTest; |
| |
| /** |
| * |
| * @author vikramj |
| */ |
| @Category(IntegrationTest.class) |
| public class INOperatorJUnitTest { |
| |
| |
| @Before |
| public void setUp() throws Exception { |
| CacheUtils.startCache(); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| CacheUtils.closeCache(); |
| } |
| |
| // For decomposition of IN expressions, need to unit-test the following: |
| // 1) IN expr gets decomposed on indexed expression with func index (done) |
| // 2) index gets used on IN clause (done) |
| // 3) IN expr does not get decomposed on unindexed expression (not done) |
| // 4) Decomposed IN expr works with bind parameters (not done) |
| // 5) IN expr does get decomposed on indexed expression with pk index (not done) |
| // 6) pk index gets used with IN expression (not done) |
| // 7) decomposition (or not) of nested IN expressions (not done) |
| // 8) test IN clauses with: |
| // a) zero elements (should shortcircuit to return false ideally) (not done) |
| // b) one element (not done) |
| // c) more than one element (done) |
| |
| /** |
| * Test the decomposition of IN SET(..) that gets decomposed |
| * into ORs so an index can be used |
| * @author Eric Zoerner |
| */ |
| public void _testInDecompositionWithFunctionalIndex() throws Exception { |
| |
| } |
| |
| @Test |
| public void testRegionBulkGet() throws Exception { |
| Cache cache = CacheUtils.getCache(); |
| AttributesFactory attributesFactory = new AttributesFactory(); |
| RegionAttributes regionAttributes = attributesFactory.create(); |
| |
| Region region = cache.createRegion("pos",regionAttributes); |
| |
| region.put("6", new Integer(6)); |
| region.put("10", new Integer(10)); |
| region.put("12", new Integer(10)); |
| |
| QueryService qs = cache.getQueryService(); |
| |
| Query q; |
| SelectResults results; |
| Object[] keys; |
| Set expectedResults; |
| |
| q = qs.newQuery("SELECT e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "5", "6", "10", "45" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| expectedResults = new HashSet(); |
| expectedResults.add(new Integer(6)); |
| expectedResults.add(new Integer(10)); |
| assertEquals(expectedResults, results.asSet()); |
| |
| q = qs.newQuery("SELECT e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "42" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| expectedResults = new HashSet(); |
| assertEquals(expectedResults, results.asSet()); |
| |
| for (int i = 0; i < 1000; i++) { |
| region.put(String.valueOf(i), new Integer(i)); |
| } |
| q = qs.newQuery("SELECT e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "5", "6", "10", "45" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| expectedResults = new HashSet(); |
| expectedResults.add(new Integer(5)); |
| expectedResults.add(new Integer(6)); |
| expectedResults.add(new Integer(10)); |
| expectedResults.add(new Integer(45)); |
| assertEquals(expectedResults, results.asSet()); |
| |
| q = qs.newQuery("SELECT e.key, e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "5", "6", "10", "45" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| assertEquals(4, results.size()); |
| |
| region.destroyRegion(); |
| } |
| |
| |
| @Test |
| public void testIntSet() throws Exception { |
| |
| Query q = CacheUtils.getQueryService().newQuery("2 IN SET(1,2,3)"); |
| |
| Object result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for IN operator"); |
| } |
| @Test |
| public void testStringSet() throws Exception { |
| |
| Query q = CacheUtils.getQueryService().newQuery("'a' IN SET('x','y','z')"); |
| |
| Object result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.FALSE)) |
| fail("Failed for StringSet with IN operator"); |
| } |
| |
| @Test |
| public void testShortNumSet() throws Exception { |
| Short num = Short.valueOf("1"); |
| Object params[]=new Object[1]; |
| params[0]= num; |
| |
| Query q = CacheUtils.getQueryService().newQuery("$1 IN SET(1,2,3)"); |
| |
| Object result = q.execute(params); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for ShortNum with IN operator"); |
| } |
| |
| @Test |
| public void testCollection() throws Exception { |
| Object e1 = new Object(); |
| Object e2 = new Object(); |
| Object e3 = new Object(); |
| HashSet C1 = new HashSet(); |
| C1.add(e1); |
| C1.add(e2); |
| C1.add(e3); |
| Object params[]=new Object[3]; |
| params[0]= e1; |
| params[1]= C1; |
| params[2]= e2; |
| |
| Query q = CacheUtils.getQueryService().newQuery("$3 IN $2"); |
| Object result = q.execute(params); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for Collection with IN operator"); |
| } |
| |
| @Test |
| public void testWithSet() throws Exception { |
| String s1 = "Hello"; |
| String s2 = "World"; |
| HashSet H1 = new HashSet(); |
| H1.add(s1); |
| H1.add(s2); |
| Object params[]=new Object[2]; |
| params[0]= s1; |
| params[1]= H1; |
| Query q = CacheUtils.getQueryService().newQuery("$1 IN $2"); |
| Object result = q.execute(params); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for String set with IN operator"); |
| } |
| @Test |
| public void testArrayList() throws Exception { |
| String s1 = "sss"; |
| String s2 = "ddd"; |
| ArrayList AL1 = new ArrayList(); |
| AL1.add(s1); |
| AL1.add(s2); |
| Object params[]=new Object[3]; |
| params[0]= s1; |
| params[1]= s2; |
| params[2]= AL1; |
| Query q = CacheUtils.getQueryService().newQuery("$1 IN $3"); |
| Object result = q.execute(params); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for ArrayList with IN operator"); |
| } |
| |
| @Test |
| public void testNULL() throws Exception { |
| Query q = CacheUtils.getQueryService().newQuery(" null IN SET('x','y','z')"); |
| Object result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.FALSE)) |
| fail("Failed for NULL in IN operator Test"); |
| |
| q = CacheUtils.getQueryService().newQuery(" null IN SET(null)"); |
| result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for NULL in IN operator Test"); |
| |
| } |
| |
| @Test |
| public void testUNDEFINED() throws Exception { |
| Query q = CacheUtils.getQueryService().newQuery(" UNDEFINED IN SET(1,2,3)"); |
| Object result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.FALSE)) |
| fail("Failed for UNDEFINED with IN operator"); |
| |
| q = CacheUtils.getQueryService().newQuery(" UNDEFINED IN SET(UNDEFINED)"); |
| result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(QueryService.UNDEFINED)) |
| fail("Failed for UNDEFINED with IN operator"); |
| |
| q = CacheUtils.getQueryService().newQuery(" UNDEFINED IN SET(UNDEFINED,UNDEFINED)"); |
| result = q.execute(); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(QueryService.UNDEFINED)) |
| fail("Failed for UNDEFINED with IN operator"); |
| } |
| |
| @Test |
| public void testMiscSet() throws Exception { |
| Query q = CacheUtils.getQueryService().newQuery(" $1 IN SET(1, 'a', $2, $3, $4, $5)"); |
| Object params[] = {null, new Integer(0), "str", null, new Object()}; |
| |
| for(int i=1;i<params.length;i++){ |
| params[0] = params[i]; |
| Object result = q.execute(params); |
| CacheUtils.log(Utils.printResult(result)); |
| if(!result.equals(Boolean.TRUE)) |
| fail("Failed for Mix set with IN operator"); |
| } |
| |
| } |
| |
| @Test |
| public void testIndexUsageWithIn() throws Exception { |
| Cache cache = CacheUtils.getCache(); |
| AttributesFactory attributesFactory = new AttributesFactory(); |
| RegionAttributes regionAttributes = attributesFactory.create(); |
| |
| Region region = cache.createRegion("pos",regionAttributes); |
| |
| region.put("6", new Integer(6)); |
| region.put("10", new Integer(10)); |
| region.put("12", new Integer(10)); |
| |
| QueryService qs = cache.getQueryService(); |
| qs.createIndex("In Index", IndexType.FUNCTIONAL, "e.key","/pos.entrySet e"); |
| Query q; |
| SelectResults results; |
| Object[] keys; |
| Set expectedResults; |
| |
| q = qs.newQuery("SELECT e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "5", "6", "10", "45" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| expectedResults = new HashSet(); |
| expectedResults.add(new Integer(6)); |
| expectedResults.add(new Integer(10)); |
| assertEquals(expectedResults, results.asSet()); |
| |
| q = qs.newQuery("SELECT e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "42" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| expectedResults = new HashSet(); |
| assertEquals(expectedResults, results.asSet()); |
| |
| for (int i = 0; i < 1000; i++) { |
| region.put(String.valueOf(i), new Integer(i)); |
| } |
| q = qs.newQuery("SELECT e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "5", "6", "10", "45" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| expectedResults = new HashSet(); |
| expectedResults.add(new Integer(5)); |
| expectedResults.add(new Integer(6)); |
| expectedResults.add(new Integer(10)); |
| expectedResults.add(new Integer(45)); |
| assertEquals(expectedResults, results.asSet()); |
| |
| q = qs.newQuery("SELECT e.key, e.value FROM /pos.entrySet e WHERE e.key IN $1"); |
| keys = new Object[] { "5", "6", "10", "45" }; |
| results = (SelectResults)q.execute(new Object[] {keys}); |
| assertEquals(4, results.size()); |
| } |
| |
| |
| /** |
| * Tests optimization of compiled in where we no longer evaluate on every iteration |
| * The set is saved off into the query context and reused |
| * Each query should have it's own query context |
| * @throws Exception |
| */ |
| @Test |
| public void testCacheEvalCollnWithIn() throws Exception { |
| Cache cache = CacheUtils.getCache(); |
| AttributesFactory attributesFactory = new AttributesFactory(); |
| RegionAttributes regionAttributes = attributesFactory.create(); |
| QueryService qs = cache.getQueryService(); |
| Region customersRegion = cache.createRegionFactory(regionAttributes).create("customers"); |
| Region receiptsRegion = cache.createRegionFactory(regionAttributes).create("receipts"); |
| |
| qs.createIndex("receiptsByProduct", "i.productId", "/receipts r, r.items i"); |
| qs.createIndex("receiptsByCustomer", "r.productId", "/receipts r"); |
| qs.createIndex("customersByProfile", "c.profile", "/customers c"); |
| |
| int numReceiptsPerCustomer = 10; |
| for (int i = 0; i < 1000; i++) { |
| customersRegion.put(i, new Customer(i, i % 2 == 0 ? "PremiumIndividual": "AverageJoe")); |
| for (int j = 0; j < numReceiptsPerCustomer; j++) { |
| int receiptId = i * numReceiptsPerCustomer + j; |
| receiptsRegion.put(receiptId, new Receipt(receiptId, i)); |
| } |
| } |
| |
| Query q = qs.newQuery("<trace>select r from /receipts r, r.items i where i.productId = 8 and r.customerId in (select c.id from /customers c where c.profile = 'PremiumIndividual')"); |
| SelectResults results = (SelectResults) q.execute(); |
| assertEquals("Not the same size", 500, results.size()); |
| |
| for (int i = 1000; i < 1100; i++) { |
| customersRegion.put(i, new Customer(i, i % 2 == 0 ? "PremiumIndividual": "AverageJoe")); |
| for (int j = 0; j < numReceiptsPerCustomer; j++) { |
| int receiptId = i * numReceiptsPerCustomer + j; |
| receiptsRegion.put(receiptId, new Receipt(receiptId, i)); |
| } |
| } |
| results = (SelectResults)q.execute(); |
| assertEquals("Not the same size after new inserts", 550, results.size() ); |
| } |
| |
| /** |
| * Tests optimization of compiled in where we no longer evaluate on every iteration |
| * The set is saved off into the query context and reused |
| * Each query should have it's own query context |
| * @throws Exception |
| */ |
| @Test |
| public void testCacheEvalCollnWithInWithMultipleNestedIn() throws Exception { |
| Cache cache = CacheUtils.getCache(); |
| AttributesFactory attributesFactory = new AttributesFactory(); |
| RegionAttributes regionAttributes = attributesFactory.create(); |
| QueryService qs = cache.getQueryService(); |
| Region customersRegion = cache.createRegionFactory(regionAttributes).create("customers"); |
| Region receiptsRegion = cache.createRegionFactory(regionAttributes).create("receipts"); |
| |
| qs.createIndex("receiptsByProduct", "i.productId", "/receipts r, r.items i"); |
| qs.createIndex("receiptsByCustomer", "r.productId", "/receipts r"); |
| qs.createIndex("customersByProfile", "c.profile", "/customers c"); |
| |
| int numReceiptsPerCustomer = 10; |
| for (int i = 0; i < 1000; i++) { |
| customersRegion.put(i, new Customer(i, i % 2 == 0 ? "PremiumIndividual": "AverageJoe")); |
| for (int j = 0; j < numReceiptsPerCustomer; j++) { |
| int receiptId = i * numReceiptsPerCustomer + j; |
| receiptsRegion.put(receiptId, new Receipt(receiptId, i)); |
| } |
| } |
| |
| Query q = qs.newQuery("<trace>select r from /receipts r, r.items i where i.productId = 8 and r.customerId in (select c.id from /customers c where c.id in (select d.id from /customers d where d.profile='PremiumIndividual'))"); |
| SelectResults results = (SelectResults) q.execute(); |
| assertEquals("Not the same size", 500, results.size()); |
| |
| for (int i = 1000; i < 1100; i++) { |
| customersRegion.put(i, new Customer(i, i % 2 == 0 ? "PremiumIndividual": "AverageJoe")); |
| for (int j = 0; j < numReceiptsPerCustomer; j++) { |
| int receiptId = i * numReceiptsPerCustomer + j; |
| receiptsRegion.put(receiptId, new Receipt(receiptId, i)); |
| } |
| } |
| results = (SelectResults)q.execute(); |
| assertEquals("Not the same size after new inserts", 550, results.size() ); |
| } |
| |
| public class Customer { |
| public int id; |
| public String profile; |
| |
| public Customer(int id, String profile) { |
| this.id = id; |
| this.profile = profile; |
| } |
| |
| public int getId() { |
| return id; |
| } |
| |
| public String getProfile() { |
| return profile; |
| } |
| } |
| |
| public class Receipt { |
| public int customerId; |
| public Item[] items; |
| |
| public Receipt(int receiptId, int customerId) { |
| this.customerId = customerId; |
| items = new Item[] { new Item(receiptId % 10)}; |
| } |
| |
| public int getCustomerId() { |
| return customerId; |
| } |
| |
| public Item[] getItems() { |
| return items; |
| } |
| } |
| |
| public class Item { |
| public int productId; |
| |
| public Item(int productId) { |
| this.productId = productId; |
| } |
| |
| public int getProductId() { |
| return productId; |
| } |
| } |
| } |